Kruise-Game init
Signed-off-by: ChrisLiu <chrisliu1995@163.com>
This commit is contained in:
parent
3aa9e5654b
commit
c98d68f919
|
|
@ -0,0 +1,4 @@
|
|||
# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file
|
||||
# Ignore build and test binaries.
|
||||
bin/
|
||||
testbin/
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
bin/
|
||||
testbin/
|
||||
.temp
|
||||
bin
|
||||
testbin/*
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
test/e2e/generated/bindata.go
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
|
@ -24,6 +23,3 @@ test/e2e/generated/bindata.go
|
|||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.vscode
|
||||
|
||||
.DS_Store
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
# Build the manager binary
|
||||
FROM golang:1.18 as builder
|
||||
|
||||
WORKDIR /workspace
|
||||
# Copy the Go Modules manifests
|
||||
COPY go.mod go.mod
|
||||
COPY go.sum go.sum
|
||||
# cache deps before building and copying source so that we don't need to re-download as much
|
||||
# and so that source changes don't invalidate our downloaded layer
|
||||
RUN go mod download
|
||||
|
||||
# Copy the go source
|
||||
COPY main.go main.go
|
||||
COPY apis/ apis/
|
||||
COPY pkg/ pkg/
|
||||
|
||||
# Build
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager main.go
|
||||
|
||||
# Use distroless as minimal base images to package the manager binary
|
||||
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||
FROM alpine:3.14
|
||||
WORKDIR /
|
||||
COPY --from=builder /workspace/manager .
|
||||
|
||||
ENTRYPOINT ["/manager"]
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
|
||||
# Image URL to use all building/pushing images targets
|
||||
IMG ?= kruise-game-manager:test
|
||||
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
|
||||
ENVTEST_K8S_VERSION = 1.24.1
|
||||
|
||||
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
|
||||
ifeq (,$(shell go env GOBIN))
|
||||
GOBIN=$(shell go env GOPATH)/bin
|
||||
else
|
||||
GOBIN=$(shell go env GOBIN)
|
||||
endif
|
||||
|
||||
# Setting SHELL to bash allows bash commands to be executed by recipes.
|
||||
# This is a requirement for 'setup-envtest.sh' in the test target.
|
||||
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
|
||||
SHELL = /usr/bin/env bash -o pipefail
|
||||
.SHELLFLAGS = -ec
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
##@ General
|
||||
|
||||
# The help target prints out all targets with their descriptions organized
|
||||
# beneath their categories. The categories are represented by '##@' and the
|
||||
# target descriptions by '##'. The awk commands is responsible for reading the
|
||||
# entire set of makefiles included in this invocation, looking for lines of the
|
||||
# file as xyz: ## something, and then pretty-format the target and help. Then,
|
||||
# if there's a line with ##@ something, that gets pretty-printed as a category.
|
||||
# More info on the usage of ANSI control characters for terminal formatting:
|
||||
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
|
||||
# More info on the awk command:
|
||||
# http://linuxcommand.org/lc3_adv_awk.php
|
||||
|
||||
.PHONY: help
|
||||
help: ## Display this help.
|
||||
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
|
||||
|
||||
##@ Development
|
||||
|
||||
.PHONY: manifests
|
||||
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
|
||||
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
|
||||
|
||||
.PHONY: generate
|
||||
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
|
||||
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Run go fmt against code.
|
||||
go fmt ./...
|
||||
|
||||
.PHONY: vet
|
||||
vet: ## Run go vet against code.
|
||||
go vet ./...
|
||||
|
||||
.PHONY: test
|
||||
test: manifests generate fmt vet envtest ## Run tests.
|
||||
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... -coverprofile cover.out
|
||||
|
||||
##@ Build
|
||||
|
||||
.PHONY: build
|
||||
build: generate fmt vet ## Build manager binary.
|
||||
go build -o bin/manager main.go
|
||||
|
||||
.PHONY: run
|
||||
run: manifests generate fmt vet ## Run a controller from your host.
|
||||
go run ./main.go
|
||||
|
||||
.PHONY: docker-build
|
||||
docker-build: ## Build docker images with the manager.
|
||||
docker build -t ${IMG} .
|
||||
|
||||
.PHONY: docker-push
|
||||
docker-push: ## Push docker images with the manager.
|
||||
docker push ${IMG}
|
||||
|
||||
##@ Deployment
|
||||
|
||||
ifndef ignore-not-found
|
||||
ignore-not-found = false
|
||||
endif
|
||||
|
||||
.PHONY: install
|
||||
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
|
||||
$(KUSTOMIZE) build config/crd | kubectl apply -f -
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
|
||||
$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
|
||||
|
||||
.PHONY: deploy
|
||||
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
|
||||
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
|
||||
$(KUSTOMIZE) build config/default | kubectl apply -f -
|
||||
|
||||
.PHONY: undeploy
|
||||
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
|
||||
$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
|
||||
|
||||
##@ Build Dependencies
|
||||
|
||||
## Location to install dependencies to
|
||||
LOCALBIN ?= $(shell pwd)/bin
|
||||
$(LOCALBIN):
|
||||
mkdir -p $(LOCALBIN)
|
||||
|
||||
## Tool Binaries
|
||||
KUSTOMIZE ?= $(LOCALBIN)/kustomize
|
||||
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
|
||||
ENVTEST ?= $(LOCALBIN)/setup-envtest
|
||||
|
||||
## Tool Versions
|
||||
KUSTOMIZE_VERSION ?= v4.5.5
|
||||
CONTROLLER_TOOLS_VERSION ?= v0.9.0
|
||||
|
||||
KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
|
||||
.PHONY: kustomize
|
||||
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
|
||||
$(KUSTOMIZE): $(LOCALBIN)
|
||||
curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN)
|
||||
|
||||
.PHONY: controller-gen
|
||||
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
|
||||
$(CONTROLLER_GEN): $(LOCALBIN)
|
||||
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
|
||||
|
||||
.PHONY: envtest
|
||||
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
|
||||
$(ENVTEST): $(LOCALBIN)
|
||||
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
domain: my.domain
|
||||
layout:
|
||||
- go.kubebuilder.io/v3
|
||||
projectName: kruise-game
|
||||
repo: github.com/openkruise/kruise-game
|
||||
resources:
|
||||
- api:
|
||||
crdVersion: v1
|
||||
namespaced: true
|
||||
controller: true
|
||||
domain: kruise.io
|
||||
group: game
|
||||
kind: GameServerSet
|
||||
path: github.com/openkruise/kruise-game/apis/v1alpha1
|
||||
version: v1alpha1
|
||||
- api:
|
||||
crdVersion: v1
|
||||
namespaced: true
|
||||
controller: true
|
||||
domain: kruise.io
|
||||
group: game
|
||||
kind: GameServer
|
||||
path: github.com/openkruise/kruise-game/apis/v1alpha1
|
||||
version: v1alpha1
|
||||
version: "3"
|
||||
49
README.md
49
README.md
|
|
@ -1 +1,48 @@
|
|||
# kruise-game
|
||||
# kruise-game
|
||||
|
||||
## Introduction
|
||||
`Kruise-Game` is an open source project based on OpenKruise, to solve the problem of game server landing in Kubernetes.
|
||||
|
||||
<img width="250px" src="./docs/images/logo.jpg" alt="OpenKruiseGame logo"/>
|
||||
|
||||
|
||||
## Why is Kruise-Game?
|
||||
Game servers are stateful services, and there are differences in the operation and maintenance of each game server, which also increases with time. In Kubernetes, general workloads manages a batch of game servers according to pod templates, which cannot take into account the differences in game server status. Batch management and directional management are in conflict in k8s. **Kruise-Game** was born to resolve that. Kruise-Game contains two CRDs, GameServer and GameServerSet:
|
||||
|
||||
- `GameServer` is responsible for the management of game server status. Users can customize the game server status to reflect the differences between game servers;
|
||||
- `GameServerSet` is responsible for batch management of game servers. Users can customize update/reduction strategies according to the status of game servers.
|
||||
|
||||
Features:
|
||||
- Game server status management
|
||||
- Mark game servers status without effecting to its lifecycle
|
||||
- Flexible scaling/deletion mechanism
|
||||
- Support scaling down by user-defined status & priority
|
||||
- Support specifying game server to delete directly
|
||||
- Flexible update mechanism
|
||||
- Support hot update (in-place update)
|
||||
- Support updating game server by user-defined priority
|
||||
- Can control the range of the game servers to be updated
|
||||
- Can control the pace of the entire update process
|
||||
- Custom service quality
|
||||
- Support probing game servers‘ containers and mark game servers status automatically
|
||||
|
||||
## Quick Start
|
||||
|
||||
- [Installation](./docs/getting_started/installation.md)
|
||||
- [Basic Usage](./docs/tutorials/basic_usage.md)
|
||||
|
||||
## License
|
||||
|
||||
Copyright 2022.
|
||||
|
||||
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.
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
// +groupName=game.kruise.io
|
||||
package v1alpha1
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
const (
|
||||
GameServerStateKey = "game.kruise.io/gs-state"
|
||||
GameServerOpsStateKey = "game.kruise.io/gs-opsState"
|
||||
GameServerUpdatePriorityKey = "game.kruise.io/gs-update-priority"
|
||||
GameServerDeletePriorityKey = "game.kruise.io/gs-delete-priority"
|
||||
)
|
||||
|
||||
// GameServerSpec defines the desired state of GameServer
|
||||
type GameServerSpec struct {
|
||||
OpsState OpsState `json:"opsState,omitempty"`
|
||||
UpdatePriority *intstr.IntOrString `json:"updatePriority,omitempty"`
|
||||
DeletionPriority *intstr.IntOrString `json:"deletionPriority,omitempty"`
|
||||
NetworkDisabled bool `json:"networkDisabled,omitempty"`
|
||||
}
|
||||
|
||||
type GameServerState string
|
||||
|
||||
const (
|
||||
Unknown GameServerState = "Unknown"
|
||||
Creating GameServerState = "Creating"
|
||||
Ready GameServerState = "Ready"
|
||||
NotReady GameServerState = "NotReady"
|
||||
Crash GameServerState = "Crash"
|
||||
Updating GameServerState = "Updating"
|
||||
Deleting GameServerState = "Deleting"
|
||||
)
|
||||
|
||||
type OpsState string
|
||||
|
||||
const (
|
||||
Maintaining OpsState = "Maintaining"
|
||||
WaitToDelete OpsState = "WaitToBeDeleted"
|
||||
None OpsState = "None"
|
||||
)
|
||||
|
||||
type ServiceQuality struct {
|
||||
corev1.Probe `json:",inline"`
|
||||
Name string `json:"name"`
|
||||
ContainerName string `json:"containerName,omitempty"`
|
||||
ServiceQualityAction []ServiceQualityAction `json:"serviceQualityAction,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceQualityCondition struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status,omitempty"`
|
||||
LastProbeTime metav1.Time `json:"lastProbeTime,omitempty"`
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
|
||||
LastActionTransitionTime metav1.Time `json:"lastActionTransitionTime,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceQualityAction struct {
|
||||
Permanent bool `json:"permanent,omitempty"` // default: true
|
||||
State bool `json:"state"`
|
||||
GameServerSpec `json:",inline"`
|
||||
}
|
||||
|
||||
// GameServerStatus defines the observed state of GameServer
|
||||
type GameServerStatus struct {
|
||||
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
DesiredState GameServerState `json:"desiredState,omitempty"`
|
||||
CurrentState GameServerState `json:"currentState,omitempty"`
|
||||
NetworkStatus NetworkStatus `json:"networkStatus,omitempty"`
|
||||
PodStatus corev1.PodStatus `json:"podStatus,omitempty"`
|
||||
ServiceQualitiesCondition []ServiceQualityCondition `json:"serviceQualitiesConditions,omitempty"`
|
||||
// Lifecycle defines the lifecycle hooks for Pods pre-delete, in-place update.
|
||||
UpdatePriority *intstr.IntOrString `json:"updatePriority,omitempty"`
|
||||
DeletionPriority *intstr.IntOrString `json:"deletionPriority,omitempty"`
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkStatus struct {
|
||||
NetworkType string `json:"networkType,omitempty"`
|
||||
InternalAddresses []NetworkAddress `json:"internalAddresses,omitempty"`
|
||||
ExternalAddresses []NetworkAddress `json:"externalAddresses,omitempty"`
|
||||
DesiredNetworkState NetworkState `json:"desiredNetworkState,omitempty"`
|
||||
CurrentNetworkState NetworkState `json:"currentNetworkState,omitempty"`
|
||||
CreateTime metav1.Time `json:"createTime,omitempty"`
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkState string
|
||||
|
||||
type NetworkAddress struct {
|
||||
IP string `json:"ip"`
|
||||
// TODO add IPv6
|
||||
Ports []NetworkPort `json:"ports,omitempty"`
|
||||
PortRange NetworkPortRange `json:"portRange,omitempty"`
|
||||
EndPoint string `json:"endPoint,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkPort struct {
|
||||
Name string `json:"name"`
|
||||
Protocol corev1.Protocol `json:"protocol,omitempty"`
|
||||
Port *intstr.IntOrString `json:"port,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkPortRange struct {
|
||||
Protocol corev1.Protocol `json:"protocol,omitempty"`
|
||||
PortRange string `json:"portRange,omitempty"`
|
||||
}
|
||||
|
||||
//+genclient
|
||||
//+kubebuilder:object:root=true
|
||||
//+kubebuilder:subresource:status
|
||||
//+kubebuilder:printcolumn:name="STATE",type="string",JSONPath=".status.currentState",description="The current state of GameServer"
|
||||
//+kubebuilder:printcolumn:name="OPSSTATE",type="string",JSONPath=".spec.opsState",description="The operations state of GameServer"
|
||||
//+kubebuilder:printcolumn:name="DP",type="string",JSONPath=".status.deletionPriority",description="The current deletionPriority of GameServer"
|
||||
//+kubebuilder:printcolumn:name="UP",type="string",JSONPath=".status.updatePriority",description="The current updatePriority of GameServer"
|
||||
//+kubebuilder:resource:shortName=gs
|
||||
|
||||
// GameServer is the Schema for the gameservers API
|
||||
type GameServer struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec GameServerSpec `json:"spec,omitempty"`
|
||||
Status GameServerStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
|
||||
// GameServerList contains a list of GameServer
|
||||
type GameServerList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []GameServer `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&GameServer{}, &GameServerList{})
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
appspub "github.com/openkruise/kruise-api/apps/pub"
|
||||
kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
||||
apps "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
|
||||
const (
|
||||
GameServerOwnerGssKey = "game.kruise.io/owner-gss"
|
||||
GameServerSetReserveIdsKey = "game.kruise.io/reserve-ids"
|
||||
GameServerSetNotExistIdsKey = "game.kruise.io/not-exist-ids"
|
||||
AstsHashKey = "game.kruise.io/asts-hash"
|
||||
)
|
||||
|
||||
// GameServerSetSpec defines the desired state of GameServerSet
|
||||
type GameServerSetSpec struct {
|
||||
// replicas is the desired number of replicas of the given Template.
|
||||
// These are replicas in the sense that they are instantiations of the
|
||||
// same Template, but individual replicas also have a consistent identity.
|
||||
//+kubebuilder:validation:Required
|
||||
//+kubebuilder:validation:Minimum=0
|
||||
Replicas *int32 `json:"replicas"`
|
||||
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
// Important: Run "make" to regenerate code after modifying this file
|
||||
GameServerTemplate GameServerTemplate `json:"gameServerTemplate,omitempty"`
|
||||
ReserveGameServerIds []int `json:"reserveGameServerIds,omitempty"`
|
||||
ServiceQualities []ServiceQuality `json:"serviceQualities,omitempty"`
|
||||
UpdateStrategy UpdateStrategy `json:"updateStrategy,omitempty"`
|
||||
ScaleStrategy ScaleStrategy `json:"scaleStrategy,omitempty"`
|
||||
Network *Network `json:"network,omitempty"`
|
||||
}
|
||||
|
||||
type GameServerTemplate struct {
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
// +kubebuilder:validation:Schemaless
|
||||
corev1.PodTemplateSpec `json:",inline"`
|
||||
VolumeClaimTemplates []corev1.PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty"`
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
NetworkType string `json:"networkType,omitempty"`
|
||||
NetworkConf []NetworkConfParams `json:"networkConf,omitempty"`
|
||||
}
|
||||
|
||||
type NetworkConfParams KVParams
|
||||
|
||||
type KVParams struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateStrategy struct {
|
||||
// Type indicates the type of the StatefulSetUpdateStrategy.
|
||||
// Default is RollingUpdate.
|
||||
// +optional
|
||||
Type apps.StatefulSetUpdateStrategyType `json:"type,omitempty"`
|
||||
// RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType.
|
||||
// +optional
|
||||
RollingUpdate *RollingUpdateStatefulSetStrategy `json:"rollingUpdate,omitempty"`
|
||||
}
|
||||
|
||||
type RollingUpdateStatefulSetStrategy struct {
|
||||
// Partition indicates the ordinal at which the StatefulSet should be partitioned by default.
|
||||
// But if unorderedUpdate has been set:
|
||||
// - Partition indicates the number of pods with non-updated revisions when rolling update.
|
||||
// - It means controller will update $(replicas - partition) number of pod.
|
||||
// Default value is 0.
|
||||
// +optional
|
||||
Partition *int32 `json:"partition,omitempty"`
|
||||
// The maximum number of pods that can be unavailable during the update.
|
||||
// Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%).
|
||||
// Absolute number is calculated from percentage by rounding down.
|
||||
// Also, maxUnavailable can just be allowed to work with Parallel podManagementPolicy.
|
||||
// Defaults to 1.
|
||||
// +optional
|
||||
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`
|
||||
// PodUpdatePolicy indicates how pods should be updated
|
||||
// Default value is "ReCreate"
|
||||
// +optional
|
||||
PodUpdatePolicy kruiseV1beta1.PodUpdateStrategyType `json:"podUpdatePolicy,omitempty"`
|
||||
// Paused indicates that the StatefulSet is paused.
|
||||
// Default value is false
|
||||
// +optional
|
||||
Paused bool `json:"paused,omitempty"`
|
||||
// UnorderedUpdate contains strategies for non-ordered update.
|
||||
// If it is not nil, pods will be updated with non-ordered sequence.
|
||||
// Noted that UnorderedUpdate can only be allowed to work with Parallel podManagementPolicy
|
||||
// +optional
|
||||
// UnorderedUpdate *kruiseV1beta1.UnorderedUpdateStrategy `json:"unorderedUpdate,omitempty"`
|
||||
// InPlaceUpdateStrategy contains strategies for in-place update.
|
||||
// +optional
|
||||
InPlaceUpdateStrategy *appspub.InPlaceUpdateStrategy `json:"inPlaceUpdateStrategy,omitempty"`
|
||||
// MinReadySeconds indicates how long will the pod be considered ready after it's updated.
|
||||
// MinReadySeconds works with both OrderedReady and Parallel podManagementPolicy.
|
||||
// It affects the pod scale up speed when the podManagementPolicy is set to be OrderedReady.
|
||||
// Combined with MaxUnavailable, it affects the pod update speed regardless of podManagementPolicy.
|
||||
// Default value is 0, max is 300.
|
||||
// +optional
|
||||
MinReadySeconds *int32 `json:"minReadySeconds,omitempty"`
|
||||
}
|
||||
|
||||
type ScaleStrategy struct {
|
||||
kruiseV1beta1.StatefulSetScaleStrategy `json:",inline"`
|
||||
}
|
||||
|
||||
// GameServerSetStatus defines the observed state of GameServerSet
|
||||
type GameServerSetStatus struct {
|
||||
// replicas from advancedStatefulSet
|
||||
Replicas int32 `json:"replicas"`
|
||||
ReadyReplicas int32 `json:"readyReplicas"`
|
||||
AvailableReplicas int32 `json:"availableReplicas"`
|
||||
CurrentReplicas int32 `json:"currentReplicas"`
|
||||
UpdatedReplicas int32 `json:"updatedReplicas"`
|
||||
UpdatedReadyReplicas int32 `json:"updatedReadyReplicas,omitempty"`
|
||||
MaintainingReplicas *int32 `json:"maintainingReplicas,omitempty"`
|
||||
WaitToBeDeletedReplicas *int32 `json:"waitToBeDeletedReplicas,omitempty"`
|
||||
// LabelSelector is label selectors for query over pods that should match the replica count used by HPA.
|
||||
LabelSelector string `json:"labelSelector,omitempty"`
|
||||
}
|
||||
|
||||
//+genclient
|
||||
//+kubebuilder:object:root=true
|
||||
//+kubebuilder:subresource:status
|
||||
//+kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.labelSelector
|
||||
//+kubebuilder:resource:shortName=gss
|
||||
|
||||
// GameServerSet is the Schema for the gameserversets API
|
||||
type GameServerSet struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec GameServerSetSpec `json:"spec,omitempty"`
|
||||
Status GameServerSetStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
|
||||
// GameServerSetList contains a list of GameServerSet
|
||||
type GameServerSetList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []GameServerSet `json:"items"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&GameServerSet{}, &GameServerSetList{})
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package v1alpha1 contains API Schema definitions for the game.kruise.io v1alpha1 API group
|
||||
//+kubebuilder:object:generate=true
|
||||
//+groupName=game.kruise.io
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/scheme"
|
||||
)
|
||||
|
||||
var (
|
||||
// GroupVersion is group version used to register these objects
|
||||
GroupVersion = schema.GroupVersion{Group: "game.kruise.io", Version: "v1alpha1"}
|
||||
|
||||
SchemeGroupVersion = GroupVersion
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||
|
||||
// AddToScheme adds the types in this group-version to the given scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Resource is required by pkg/client/listers/...
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
|
@ -0,0 +1,562 @@
|
|||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"github.com/openkruise/kruise-api/apps/pub"
|
||||
"k8s.io/api/core/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GameServer) DeepCopyInto(out *GameServer) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServer.
|
||||
func (in *GameServer) DeepCopy() *GameServer {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServer)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *GameServer) 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 *GameServerList) DeepCopyInto(out *GameServerList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]GameServer, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerList.
|
||||
func (in *GameServerList) DeepCopy() *GameServerList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *GameServerList) 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 *GameServerSet) DeepCopyInto(out *GameServerSet) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerSet.
|
||||
func (in *GameServerSet) DeepCopy() *GameServerSet {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerSet)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *GameServerSet) 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 *GameServerSetList) DeepCopyInto(out *GameServerSetList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]GameServerSet, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerSetList.
|
||||
func (in *GameServerSetList) DeepCopy() *GameServerSetList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerSetList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *GameServerSetList) 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 *GameServerSetSpec) DeepCopyInto(out *GameServerSetSpec) {
|
||||
*out = *in
|
||||
if in.Replicas != nil {
|
||||
in, out := &in.Replicas, &out.Replicas
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
in.GameServerTemplate.DeepCopyInto(&out.GameServerTemplate)
|
||||
if in.ReserveGameServerIds != nil {
|
||||
in, out := &in.ReserveGameServerIds, &out.ReserveGameServerIds
|
||||
*out = make([]int, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ServiceQualities != nil {
|
||||
in, out := &in.ServiceQualities, &out.ServiceQualities
|
||||
*out = make([]ServiceQuality, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.UpdateStrategy.DeepCopyInto(&out.UpdateStrategy)
|
||||
in.ScaleStrategy.DeepCopyInto(&out.ScaleStrategy)
|
||||
if in.Network != nil {
|
||||
in, out := &in.Network, &out.Network
|
||||
*out = new(Network)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerSetSpec.
|
||||
func (in *GameServerSetSpec) DeepCopy() *GameServerSetSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerSetSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GameServerSetStatus) DeepCopyInto(out *GameServerSetStatus) {
|
||||
*out = *in
|
||||
if in.MaintainingReplicas != nil {
|
||||
in, out := &in.MaintainingReplicas, &out.MaintainingReplicas
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.WaitToBeDeletedReplicas != nil {
|
||||
in, out := &in.WaitToBeDeletedReplicas, &out.WaitToBeDeletedReplicas
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerSetStatus.
|
||||
func (in *GameServerSetStatus) DeepCopy() *GameServerSetStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerSetStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GameServerSpec) DeepCopyInto(out *GameServerSpec) {
|
||||
*out = *in
|
||||
if in.UpdatePriority != nil {
|
||||
in, out := &in.UpdatePriority, &out.UpdatePriority
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
if in.DeletionPriority != nil {
|
||||
in, out := &in.DeletionPriority, &out.DeletionPriority
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerSpec.
|
||||
func (in *GameServerSpec) DeepCopy() *GameServerSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GameServerStatus) DeepCopyInto(out *GameServerStatus) {
|
||||
*out = *in
|
||||
in.NetworkStatus.DeepCopyInto(&out.NetworkStatus)
|
||||
in.PodStatus.DeepCopyInto(&out.PodStatus)
|
||||
if in.ServiceQualitiesCondition != nil {
|
||||
in, out := &in.ServiceQualitiesCondition, &out.ServiceQualitiesCondition
|
||||
*out = make([]ServiceQualityCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.UpdatePriority != nil {
|
||||
in, out := &in.UpdatePriority, &out.UpdatePriority
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
if in.DeletionPriority != nil {
|
||||
in, out := &in.DeletionPriority, &out.DeletionPriority
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerStatus.
|
||||
func (in *GameServerStatus) DeepCopy() *GameServerStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GameServerTemplate) DeepCopyInto(out *GameServerTemplate) {
|
||||
*out = *in
|
||||
in.PodTemplateSpec.DeepCopyInto(&out.PodTemplateSpec)
|
||||
if in.VolumeClaimTemplates != nil {
|
||||
in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
|
||||
*out = make([]v1.PersistentVolumeClaim, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GameServerTemplate.
|
||||
func (in *GameServerTemplate) DeepCopy() *GameServerTemplate {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(GameServerTemplate)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *KVParams) DeepCopyInto(out *KVParams) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KVParams.
|
||||
func (in *KVParams) DeepCopy() *KVParams {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(KVParams)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Network) DeepCopyInto(out *Network) {
|
||||
*out = *in
|
||||
if in.NetworkConf != nil {
|
||||
in, out := &in.NetworkConf, &out.NetworkConf
|
||||
*out = make([]NetworkConfParams, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Network.
|
||||
func (in *Network) DeepCopy() *Network {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Network)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkAddress) DeepCopyInto(out *NetworkAddress) {
|
||||
*out = *in
|
||||
if in.Ports != nil {
|
||||
in, out := &in.Ports, &out.Ports
|
||||
*out = make([]NetworkPort, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
out.PortRange = in.PortRange
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkAddress.
|
||||
func (in *NetworkAddress) DeepCopy() *NetworkAddress {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkAddress)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkConfParams) DeepCopyInto(out *NetworkConfParams) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkConfParams.
|
||||
func (in *NetworkConfParams) DeepCopy() *NetworkConfParams {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkConfParams)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPort) DeepCopyInto(out *NetworkPort) {
|
||||
*out = *in
|
||||
if in.Port != nil {
|
||||
in, out := &in.Port, &out.Port
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPort.
|
||||
func (in *NetworkPort) DeepCopy() *NetworkPort {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPort)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkPortRange) DeepCopyInto(out *NetworkPortRange) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkPortRange.
|
||||
func (in *NetworkPortRange) DeepCopy() *NetworkPortRange {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkPortRange)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkStatus) DeepCopyInto(out *NetworkStatus) {
|
||||
*out = *in
|
||||
if in.InternalAddresses != nil {
|
||||
in, out := &in.InternalAddresses, &out.InternalAddresses
|
||||
*out = make([]NetworkAddress, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.ExternalAddresses != nil {
|
||||
in, out := &in.ExternalAddresses, &out.ExternalAddresses
|
||||
*out = make([]NetworkAddress, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.CreateTime.DeepCopyInto(&out.CreateTime)
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkStatus.
|
||||
func (in *NetworkStatus) DeepCopy() *NetworkStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RollingUpdateStatefulSetStrategy) DeepCopyInto(out *RollingUpdateStatefulSetStrategy) {
|
||||
*out = *in
|
||||
if in.Partition != nil {
|
||||
in, out := &in.Partition, &out.Partition
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.MaxUnavailable != nil {
|
||||
in, out := &in.MaxUnavailable, &out.MaxUnavailable
|
||||
*out = new(intstr.IntOrString)
|
||||
**out = **in
|
||||
}
|
||||
if in.InPlaceUpdateStrategy != nil {
|
||||
in, out := &in.InPlaceUpdateStrategy, &out.InPlaceUpdateStrategy
|
||||
*out = new(pub.InPlaceUpdateStrategy)
|
||||
**out = **in
|
||||
}
|
||||
if in.MinReadySeconds != nil {
|
||||
in, out := &in.MinReadySeconds, &out.MinReadySeconds
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RollingUpdateStatefulSetStrategy.
|
||||
func (in *RollingUpdateStatefulSetStrategy) DeepCopy() *RollingUpdateStatefulSetStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RollingUpdateStatefulSetStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ScaleStrategy) DeepCopyInto(out *ScaleStrategy) {
|
||||
*out = *in
|
||||
in.StatefulSetScaleStrategy.DeepCopyInto(&out.StatefulSetScaleStrategy)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScaleStrategy.
|
||||
func (in *ScaleStrategy) DeepCopy() *ScaleStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ScaleStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceQuality) DeepCopyInto(out *ServiceQuality) {
|
||||
*out = *in
|
||||
in.Probe.DeepCopyInto(&out.Probe)
|
||||
if in.ServiceQualityAction != nil {
|
||||
in, out := &in.ServiceQualityAction, &out.ServiceQualityAction
|
||||
*out = make([]ServiceQualityAction, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceQuality.
|
||||
func (in *ServiceQuality) DeepCopy() *ServiceQuality {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceQuality)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceQualityAction) DeepCopyInto(out *ServiceQualityAction) {
|
||||
*out = *in
|
||||
in.GameServerSpec.DeepCopyInto(&out.GameServerSpec)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceQualityAction.
|
||||
func (in *ServiceQualityAction) DeepCopy() *ServiceQualityAction {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceQualityAction)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceQualityCondition) DeepCopyInto(out *ServiceQualityCondition) {
|
||||
*out = *in
|
||||
in.LastProbeTime.DeepCopyInto(&out.LastProbeTime)
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
in.LastActionTransitionTime.DeepCopyInto(&out.LastActionTransitionTime)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceQualityCondition.
|
||||
func (in *ServiceQualityCondition) DeepCopy() *ServiceQualityCondition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceQualityCondition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpdateStrategy) DeepCopyInto(out *UpdateStrategy) {
|
||||
*out = *in
|
||||
if in.RollingUpdate != nil {
|
||||
in, out := &in.RollingUpdate, &out.RollingUpdate
|
||||
*out = new(RollingUpdateStatefulSetStrategy)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateStrategy.
|
||||
func (in *UpdateStrategy) DeepCopy() *UpdateStrategy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpdateStrategy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
|
@ -0,0 +1,838 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.9.0
|
||||
creationTimestamp: null
|
||||
name: gameservers.game.kruise.io
|
||||
spec:
|
||||
group: game.kruise.io
|
||||
names:
|
||||
kind: GameServer
|
||||
listKind: GameServerList
|
||||
plural: gameservers
|
||||
shortNames:
|
||||
- gs
|
||||
singular: gameserver
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- description: The current state of GameServer
|
||||
jsonPath: .status.currentState
|
||||
name: STATE
|
||||
type: string
|
||||
- description: The operations state of GameServer
|
||||
jsonPath: .spec.opsState
|
||||
name: OPSSTATE
|
||||
type: string
|
||||
- description: The current deletionPriority of GameServer
|
||||
jsonPath: .status.deletionPriority
|
||||
name: DP
|
||||
type: string
|
||||
- description: The current updatePriority of GameServer
|
||||
jsonPath: .status.updatePriority
|
||||
name: UP
|
||||
type: string
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: GameServer is the Schema for the gameservers API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: GameServerSpec defines the desired state of GameServer
|
||||
properties:
|
||||
deletionPriority:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
x-kubernetes-int-or-string: true
|
||||
networkDisabled:
|
||||
type: boolean
|
||||
opsState:
|
||||
type: string
|
||||
updatePriority:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
x-kubernetes-int-or-string: true
|
||||
type: object
|
||||
status:
|
||||
description: GameServerStatus defines the observed state of GameServer
|
||||
properties:
|
||||
currentState:
|
||||
type: string
|
||||
deletionPriority:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
x-kubernetes-int-or-string: true
|
||||
desiredState:
|
||||
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
|
||||
of cluster Important: Run "make" to regenerate code after modifying
|
||||
this file'
|
||||
type: string
|
||||
lastTransitionTime:
|
||||
format: date-time
|
||||
type: string
|
||||
networkStatus:
|
||||
properties:
|
||||
createTime:
|
||||
format: date-time
|
||||
type: string
|
||||
currentNetworkState:
|
||||
type: string
|
||||
desiredNetworkState:
|
||||
type: string
|
||||
externalAddresses:
|
||||
items:
|
||||
properties:
|
||||
endPoint:
|
||||
type: string
|
||||
ip:
|
||||
type: string
|
||||
portRange:
|
||||
properties:
|
||||
portRange:
|
||||
type: string
|
||||
protocol:
|
||||
default: TCP
|
||||
type: string
|
||||
type: object
|
||||
ports:
|
||||
description: TODO add IPv6
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
x-kubernetes-int-or-string: true
|
||||
protocol:
|
||||
default: TCP
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- ip
|
||||
type: object
|
||||
type: array
|
||||
internalAddresses:
|
||||
items:
|
||||
properties:
|
||||
endPoint:
|
||||
type: string
|
||||
ip:
|
||||
type: string
|
||||
portRange:
|
||||
properties:
|
||||
portRange:
|
||||
type: string
|
||||
protocol:
|
||||
default: TCP
|
||||
type: string
|
||||
type: object
|
||||
ports:
|
||||
description: TODO add IPv6
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
x-kubernetes-int-or-string: true
|
||||
protocol:
|
||||
default: TCP
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- ip
|
||||
type: object
|
||||
type: array
|
||||
lastTransitionTime:
|
||||
format: date-time
|
||||
type: string
|
||||
networkType:
|
||||
type: string
|
||||
type: object
|
||||
podStatus:
|
||||
description: PodStatus represents information about the status of
|
||||
a pod. Status may trail the actual state of a system, especially
|
||||
if the node that hosts the pod cannot contact the control plane.
|
||||
properties:
|
||||
conditions:
|
||||
description: 'Current service state of pod. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions'
|
||||
items:
|
||||
description: PodCondition contains details for the current condition
|
||||
of this pod.
|
||||
properties:
|
||||
lastProbeTime:
|
||||
description: Last time we probed the condition.
|
||||
format: date-time
|
||||
type: string
|
||||
lastTransitionTime:
|
||||
description: Last time the condition transitioned from one
|
||||
status to another.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Human-readable message indicating details about
|
||||
last transition.
|
||||
type: string
|
||||
reason:
|
||||
description: Unique, one-word, CamelCase reason for the
|
||||
condition's last transition.
|
||||
type: string
|
||||
status:
|
||||
description: 'Status is the status of the condition. Can
|
||||
be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions'
|
||||
type: string
|
||||
type:
|
||||
description: 'Type is the type of the condition. More info:
|
||||
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions'
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
containerStatuses:
|
||||
description: 'The list has one entry per container in the manifest.
|
||||
More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status'
|
||||
items:
|
||||
description: ContainerStatus contains details for the current
|
||||
status of this container.
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'.
|
||||
type: string
|
||||
image:
|
||||
description: 'The image the container is running. More info:
|
||||
https://kubernetes.io/docs/concepts/containers/images.'
|
||||
type: string
|
||||
imageID:
|
||||
description: ImageID of the container's image.
|
||||
type: string
|
||||
lastState:
|
||||
description: Details about the container's last termination
|
||||
condition.
|
||||
properties:
|
||||
running:
|
||||
description: Details about a running container
|
||||
properties:
|
||||
startedAt:
|
||||
description: Time at which the container was last
|
||||
(re-)started
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
terminated:
|
||||
description: Details about a terminated container
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'
|
||||
type: string
|
||||
exitCode:
|
||||
description: Exit status from the last termination
|
||||
of the container
|
||||
format: int32
|
||||
type: integer
|
||||
finishedAt:
|
||||
description: Time at which the container last terminated
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message regarding the last termination
|
||||
of the container
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason from the last termination
|
||||
of the container
|
||||
type: string
|
||||
signal:
|
||||
description: Signal from the last termination of
|
||||
the container
|
||||
format: int32
|
||||
type: integer
|
||||
startedAt:
|
||||
description: Time at which previous execution of
|
||||
the container started
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- exitCode
|
||||
type: object
|
||||
waiting:
|
||||
description: Details about a waiting container
|
||||
properties:
|
||||
message:
|
||||
description: Message regarding why the container
|
||||
is not yet running.
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason the container is not
|
||||
yet running.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
name:
|
||||
description: This must be a DNS_LABEL. Each container in
|
||||
a pod must have a unique name. Cannot be updated.
|
||||
type: string
|
||||
ready:
|
||||
description: Specifies whether the container has passed
|
||||
its readiness probe.
|
||||
type: boolean
|
||||
restartCount:
|
||||
description: The number of times the container has been
|
||||
restarted.
|
||||
format: int32
|
||||
type: integer
|
||||
started:
|
||||
description: Specifies whether the container has passed
|
||||
its startup probe. Initialized as false, becomes true
|
||||
after startupProbe is considered successful. Resets to
|
||||
false when the container is restarted, or if kubelet loses
|
||||
state temporarily. Is always true when no startupProbe
|
||||
is defined.
|
||||
type: boolean
|
||||
state:
|
||||
description: Details about the container's current condition.
|
||||
properties:
|
||||
running:
|
||||
description: Details about a running container
|
||||
properties:
|
||||
startedAt:
|
||||
description: Time at which the container was last
|
||||
(re-)started
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
terminated:
|
||||
description: Details about a terminated container
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'
|
||||
type: string
|
||||
exitCode:
|
||||
description: Exit status from the last termination
|
||||
of the container
|
||||
format: int32
|
||||
type: integer
|
||||
finishedAt:
|
||||
description: Time at which the container last terminated
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message regarding the last termination
|
||||
of the container
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason from the last termination
|
||||
of the container
|
||||
type: string
|
||||
signal:
|
||||
description: Signal from the last termination of
|
||||
the container
|
||||
format: int32
|
||||
type: integer
|
||||
startedAt:
|
||||
description: Time at which previous execution of
|
||||
the container started
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- exitCode
|
||||
type: object
|
||||
waiting:
|
||||
description: Details about a waiting container
|
||||
properties:
|
||||
message:
|
||||
description: Message regarding why the container
|
||||
is not yet running.
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason the container is not
|
||||
yet running.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
required:
|
||||
- image
|
||||
- imageID
|
||||
- name
|
||||
- ready
|
||||
- restartCount
|
||||
type: object
|
||||
type: array
|
||||
ephemeralContainerStatuses:
|
||||
description: Status for any ephemeral containers that have run
|
||||
in this pod. This field is beta-level and available on clusters
|
||||
that haven't disabled the EphemeralContainers feature gate.
|
||||
items:
|
||||
description: ContainerStatus contains details for the current
|
||||
status of this container.
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'.
|
||||
type: string
|
||||
image:
|
||||
description: 'The image the container is running. More info:
|
||||
https://kubernetes.io/docs/concepts/containers/images.'
|
||||
type: string
|
||||
imageID:
|
||||
description: ImageID of the container's image.
|
||||
type: string
|
||||
lastState:
|
||||
description: Details about the container's last termination
|
||||
condition.
|
||||
properties:
|
||||
running:
|
||||
description: Details about a running container
|
||||
properties:
|
||||
startedAt:
|
||||
description: Time at which the container was last
|
||||
(re-)started
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
terminated:
|
||||
description: Details about a terminated container
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'
|
||||
type: string
|
||||
exitCode:
|
||||
description: Exit status from the last termination
|
||||
of the container
|
||||
format: int32
|
||||
type: integer
|
||||
finishedAt:
|
||||
description: Time at which the container last terminated
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message regarding the last termination
|
||||
of the container
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason from the last termination
|
||||
of the container
|
||||
type: string
|
||||
signal:
|
||||
description: Signal from the last termination of
|
||||
the container
|
||||
format: int32
|
||||
type: integer
|
||||
startedAt:
|
||||
description: Time at which previous execution of
|
||||
the container started
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- exitCode
|
||||
type: object
|
||||
waiting:
|
||||
description: Details about a waiting container
|
||||
properties:
|
||||
message:
|
||||
description: Message regarding why the container
|
||||
is not yet running.
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason the container is not
|
||||
yet running.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
name:
|
||||
description: This must be a DNS_LABEL. Each container in
|
||||
a pod must have a unique name. Cannot be updated.
|
||||
type: string
|
||||
ready:
|
||||
description: Specifies whether the container has passed
|
||||
its readiness probe.
|
||||
type: boolean
|
||||
restartCount:
|
||||
description: The number of times the container has been
|
||||
restarted.
|
||||
format: int32
|
||||
type: integer
|
||||
started:
|
||||
description: Specifies whether the container has passed
|
||||
its startup probe. Initialized as false, becomes true
|
||||
after startupProbe is considered successful. Resets to
|
||||
false when the container is restarted, or if kubelet loses
|
||||
state temporarily. Is always true when no startupProbe
|
||||
is defined.
|
||||
type: boolean
|
||||
state:
|
||||
description: Details about the container's current condition.
|
||||
properties:
|
||||
running:
|
||||
description: Details about a running container
|
||||
properties:
|
||||
startedAt:
|
||||
description: Time at which the container was last
|
||||
(re-)started
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
terminated:
|
||||
description: Details about a terminated container
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'
|
||||
type: string
|
||||
exitCode:
|
||||
description: Exit status from the last termination
|
||||
of the container
|
||||
format: int32
|
||||
type: integer
|
||||
finishedAt:
|
||||
description: Time at which the container last terminated
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message regarding the last termination
|
||||
of the container
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason from the last termination
|
||||
of the container
|
||||
type: string
|
||||
signal:
|
||||
description: Signal from the last termination of
|
||||
the container
|
||||
format: int32
|
||||
type: integer
|
||||
startedAt:
|
||||
description: Time at which previous execution of
|
||||
the container started
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- exitCode
|
||||
type: object
|
||||
waiting:
|
||||
description: Details about a waiting container
|
||||
properties:
|
||||
message:
|
||||
description: Message regarding why the container
|
||||
is not yet running.
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason the container is not
|
||||
yet running.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
required:
|
||||
- image
|
||||
- imageID
|
||||
- name
|
||||
- ready
|
||||
- restartCount
|
||||
type: object
|
||||
type: array
|
||||
hostIP:
|
||||
description: IP address of the host to which the pod is assigned.
|
||||
Empty if not yet scheduled.
|
||||
type: string
|
||||
initContainerStatuses:
|
||||
description: 'The list has one entry per init container in the
|
||||
manifest. The most recent successful init container will have
|
||||
ready = true, the most recently started container will have
|
||||
startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status'
|
||||
items:
|
||||
description: ContainerStatus contains details for the current
|
||||
status of this container.
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'.
|
||||
type: string
|
||||
image:
|
||||
description: 'The image the container is running. More info:
|
||||
https://kubernetes.io/docs/concepts/containers/images.'
|
||||
type: string
|
||||
imageID:
|
||||
description: ImageID of the container's image.
|
||||
type: string
|
||||
lastState:
|
||||
description: Details about the container's last termination
|
||||
condition.
|
||||
properties:
|
||||
running:
|
||||
description: Details about a running container
|
||||
properties:
|
||||
startedAt:
|
||||
description: Time at which the container was last
|
||||
(re-)started
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
terminated:
|
||||
description: Details about a terminated container
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'
|
||||
type: string
|
||||
exitCode:
|
||||
description: Exit status from the last termination
|
||||
of the container
|
||||
format: int32
|
||||
type: integer
|
||||
finishedAt:
|
||||
description: Time at which the container last terminated
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message regarding the last termination
|
||||
of the container
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason from the last termination
|
||||
of the container
|
||||
type: string
|
||||
signal:
|
||||
description: Signal from the last termination of
|
||||
the container
|
||||
format: int32
|
||||
type: integer
|
||||
startedAt:
|
||||
description: Time at which previous execution of
|
||||
the container started
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- exitCode
|
||||
type: object
|
||||
waiting:
|
||||
description: Details about a waiting container
|
||||
properties:
|
||||
message:
|
||||
description: Message regarding why the container
|
||||
is not yet running.
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason the container is not
|
||||
yet running.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
name:
|
||||
description: This must be a DNS_LABEL. Each container in
|
||||
a pod must have a unique name. Cannot be updated.
|
||||
type: string
|
||||
ready:
|
||||
description: Specifies whether the container has passed
|
||||
its readiness probe.
|
||||
type: boolean
|
||||
restartCount:
|
||||
description: The number of times the container has been
|
||||
restarted.
|
||||
format: int32
|
||||
type: integer
|
||||
started:
|
||||
description: Specifies whether the container has passed
|
||||
its startup probe. Initialized as false, becomes true
|
||||
after startupProbe is considered successful. Resets to
|
||||
false when the container is restarted, or if kubelet loses
|
||||
state temporarily. Is always true when no startupProbe
|
||||
is defined.
|
||||
type: boolean
|
||||
state:
|
||||
description: Details about the container's current condition.
|
||||
properties:
|
||||
running:
|
||||
description: Details about a running container
|
||||
properties:
|
||||
startedAt:
|
||||
description: Time at which the container was last
|
||||
(re-)started
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
terminated:
|
||||
description: Details about a terminated container
|
||||
properties:
|
||||
containerID:
|
||||
description: Container's ID in the format '<type>://<container_id>'
|
||||
type: string
|
||||
exitCode:
|
||||
description: Exit status from the last termination
|
||||
of the container
|
||||
format: int32
|
||||
type: integer
|
||||
finishedAt:
|
||||
description: Time at which the container last terminated
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message regarding the last termination
|
||||
of the container
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason from the last termination
|
||||
of the container
|
||||
type: string
|
||||
signal:
|
||||
description: Signal from the last termination of
|
||||
the container
|
||||
format: int32
|
||||
type: integer
|
||||
startedAt:
|
||||
description: Time at which previous execution of
|
||||
the container started
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- exitCode
|
||||
type: object
|
||||
waiting:
|
||||
description: Details about a waiting container
|
||||
properties:
|
||||
message:
|
||||
description: Message regarding why the container
|
||||
is not yet running.
|
||||
type: string
|
||||
reason:
|
||||
description: (brief) reason the container is not
|
||||
yet running.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
required:
|
||||
- image
|
||||
- imageID
|
||||
- name
|
||||
- ready
|
||||
- restartCount
|
||||
type: object
|
||||
type: array
|
||||
message:
|
||||
description: A human readable message indicating details about
|
||||
why the pod is in this condition.
|
||||
type: string
|
||||
nominatedNodeName:
|
||||
description: nominatedNodeName is set only when this pod preempts
|
||||
other pods on the node, but it cannot be scheduled right away
|
||||
as preemption victims receive their graceful termination periods.
|
||||
This field does not guarantee that the pod will be scheduled
|
||||
on this node. Scheduler may decide to place the pod elsewhere
|
||||
if other nodes become available sooner. Scheduler may also decide
|
||||
to give the resources on this node to a higher priority pod
|
||||
that is created after preemption. As a result, this field may
|
||||
be different than PodSpec.nodeName when the pod is scheduled.
|
||||
type: string
|
||||
phase:
|
||||
description: "The phase of a Pod is a simple, high-level summary
|
||||
of where the Pod is in its lifecycle. The conditions array,
|
||||
the reason and message fields, and the individual container
|
||||
status arrays contain more detail about the pod's status. There
|
||||
are five possible phase values: \n Pending: The pod has been
|
||||
accepted by the Kubernetes system, but one or more of the container
|
||||
images has not been created. This includes time before being
|
||||
scheduled as well as time spent downloading images over the
|
||||
network, which could take a while. Running: The pod has been
|
||||
bound to a node, and all of the containers have been created.
|
||||
At least one container is still running, or is in the process
|
||||
of starting or restarting. Succeeded: All containers in the
|
||||
pod have terminated in success, and will not be restarted. Failed:
|
||||
All containers in the pod have terminated, and at least one
|
||||
container has terminated in failure. The container either exited
|
||||
with non-zero status or was terminated by the system. Unknown:
|
||||
For some reason the state of the pod could not be obtained,
|
||||
typically due to an error in communicating with the host of
|
||||
the pod. \n More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-phase"
|
||||
type: string
|
||||
podIP:
|
||||
description: IP address allocated to the pod. Routable at least
|
||||
within the cluster. Empty if not yet allocated.
|
||||
type: string
|
||||
podIPs:
|
||||
description: podIPs holds the IP addresses allocated to the pod.
|
||||
If this field is specified, the 0th entry must match the podIP
|
||||
field. Pods may be allocated at most 1 value for each of IPv4
|
||||
and IPv6. This list is empty if no IPs have been allocated yet.
|
||||
items:
|
||||
description: 'IP address information for entries in the (plural)
|
||||
PodIPs field. Each entry includes: IP: An IP address allocated
|
||||
to the pod. Routable at least within the cluster.'
|
||||
properties:
|
||||
ip:
|
||||
description: ip is an IP address (IPv4 or IPv6) assigned
|
||||
to the pod
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
qosClass:
|
||||
description: 'The Quality of Service (QOS) classification assigned
|
||||
to the pod based on resource requirements See PodQOSClass type
|
||||
for available QOS classes More info: https://git.k8s.io/community/contributors/design-proposals/node/resource-qos.md'
|
||||
type: string
|
||||
reason:
|
||||
description: A brief CamelCase message indicating details about
|
||||
why the pod is in this state. e.g. 'Evicted'
|
||||
type: string
|
||||
startTime:
|
||||
description: RFC 3339 date and time at which the object was acknowledged
|
||||
by the Kubelet. This is before the Kubelet pulled the container
|
||||
image(s) for the pod.
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
serviceQualitiesConditions:
|
||||
items:
|
||||
properties:
|
||||
lastActionTransitionTime:
|
||||
format: date-time
|
||||
type: string
|
||||
lastProbeTime:
|
||||
format: date-time
|
||||
type: string
|
||||
lastTransitionTime:
|
||||
format: date-time
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
updatePriority:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Lifecycle defines the lifecycle hooks for Pods pre-delete,
|
||||
in-place update.
|
||||
x-kubernetes-int-or-string: true
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
|
|
@ -0,0 +1,665 @@
|
|||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.9.0
|
||||
creationTimestamp: null
|
||||
name: gameserversets.game.kruise.io
|
||||
spec:
|
||||
group: game.kruise.io
|
||||
names:
|
||||
kind: GameServerSet
|
||||
listKind: GameServerSetList
|
||||
plural: gameserversets
|
||||
shortNames:
|
||||
- gss
|
||||
singular: gameserverset
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: GameServerSet is the Schema for the gameserversets API
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: GameServerSetSpec defines the desired state of GameServerSet
|
||||
properties:
|
||||
gameServerTemplate:
|
||||
description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
Important: Run "make" to regenerate code after modifying this file'
|
||||
properties:
|
||||
volumeClaimTemplates:
|
||||
items:
|
||||
description: PersistentVolumeClaim is a user's request for and
|
||||
claim to a persistent volume
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of
|
||||
this representation of an object. Servers should convert
|
||||
recognized schemas to the latest internal value, and may
|
||||
reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST
|
||||
resource this object represents. Servers may infer this
|
||||
from the endpoint the client submits requests to. Cannot
|
||||
be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
|
||||
type: object
|
||||
spec:
|
||||
description: 'spec defines the desired characteristics of
|
||||
a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
|
||||
properties:
|
||||
accessModes:
|
||||
description: 'accessModes contains the desired access
|
||||
modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
dataSource:
|
||||
description: 'dataSource field can be used to specify
|
||||
either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
|
||||
* An existing PVC (PersistentVolumeClaim) If the provisioner
|
||||
or an external controller can support the specified
|
||||
data source, it will create a new volume based on
|
||||
the contents of the specified data source. If the
|
||||
AnyVolumeDataSource feature gate is enabled, this
|
||||
field will always have the same contents as the DataSourceRef
|
||||
field.'
|
||||
properties:
|
||||
apiGroup:
|
||||
description: APIGroup is the group for the resource
|
||||
being referenced. If APIGroup is not specified,
|
||||
the specified Kind must be in the core API group.
|
||||
For any other third-party types, APIGroup is required.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind is the type of resource being
|
||||
referenced
|
||||
type: string
|
||||
name:
|
||||
description: Name is the name of resource being
|
||||
referenced
|
||||
type: string
|
||||
required:
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
dataSourceRef:
|
||||
description: 'dataSourceRef specifies the object from
|
||||
which to populate the volume with data, if a non-empty
|
||||
volume is desired. This may be any local object from
|
||||
a non-empty API group (non core object) or a PersistentVolumeClaim
|
||||
object. When this field is specified, volume binding
|
||||
will only succeed if the type of the specified object
|
||||
matches some installed volume populator or dynamic
|
||||
provisioner. This field will replace the functionality
|
||||
of the DataSource field and as such if both fields
|
||||
are non-empty, they must have the same value. For
|
||||
backwards compatibility, both fields (DataSource and
|
||||
DataSourceRef) will be set to the same value automatically
|
||||
if one of them is empty and the other is non-empty.
|
||||
There are two important differences between DataSource
|
||||
and DataSourceRef: * While DataSource only allows
|
||||
two specific types of objects, DataSourceRef allows
|
||||
any non-core object, as well as PersistentVolumeClaim
|
||||
objects. * While DataSource ignores disallowed values
|
||||
(dropping them), DataSourceRef preserves all values,
|
||||
and generates an error if a disallowed value is specified.
|
||||
(Beta) Using this field requires the AnyVolumeDataSource
|
||||
feature gate to be enabled.'
|
||||
properties:
|
||||
apiGroup:
|
||||
description: APIGroup is the group for the resource
|
||||
being referenced. If APIGroup is not specified,
|
||||
the specified Kind must be in the core API group.
|
||||
For any other third-party types, APIGroup is required.
|
||||
type: string
|
||||
kind:
|
||||
description: Kind is the type of resource being
|
||||
referenced
|
||||
type: string
|
||||
name:
|
||||
description: Name is the name of resource being
|
||||
referenced
|
||||
type: string
|
||||
required:
|
||||
- kind
|
||||
- name
|
||||
type: object
|
||||
resources:
|
||||
description: 'resources represents the minimum resources
|
||||
the volume should have. If RecoverVolumeExpansionFailure
|
||||
feature is enabled users are allowed to specify resource
|
||||
requirements that are lower than previous value but
|
||||
must still be higher than capacity recorded in the
|
||||
status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
|
||||
properties:
|
||||
limits:
|
||||
additionalProperties:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
description: 'Limits describes the maximum amount
|
||||
of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
requests:
|
||||
additionalProperties:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
description: 'Requests describes the minimum amount
|
||||
of compute resources required. If Requests is
|
||||
omitted for a container, it defaults to Limits
|
||||
if that is explicitly specified, otherwise to
|
||||
an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
selector:
|
||||
description: selector is a label query over volumes
|
||||
to consider for binding.
|
||||
properties:
|
||||
matchExpressions:
|
||||
description: matchExpressions is a list of label
|
||||
selector requirements. The requirements are ANDed.
|
||||
items:
|
||||
description: A label selector requirement is a
|
||||
selector that contains values, a key, and an
|
||||
operator that relates the key and values.
|
||||
properties:
|
||||
key:
|
||||
description: key is the label key that the
|
||||
selector applies to.
|
||||
type: string
|
||||
operator:
|
||||
description: operator represents a key's relationship
|
||||
to a set of values. Valid operators are
|
||||
In, NotIn, Exists and DoesNotExist.
|
||||
type: string
|
||||
values:
|
||||
description: values is an array of string
|
||||
values. If the operator is In or NotIn,
|
||||
the values array must be non-empty. If the
|
||||
operator is Exists or DoesNotExist, the
|
||||
values array must be empty. This array is
|
||||
replaced during a strategic merge patch.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- key
|
||||
- operator
|
||||
type: object
|
||||
type: array
|
||||
matchLabels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: matchLabels is a map of {key,value}
|
||||
pairs. A single {key,value} in the matchLabels
|
||||
map is equivalent to an element of matchExpressions,
|
||||
whose key field is "key", the operator is "In",
|
||||
and the values array contains only "value". The
|
||||
requirements are ANDed.
|
||||
type: object
|
||||
type: object
|
||||
storageClassName:
|
||||
description: 'storageClassName is the name of the StorageClass
|
||||
required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
|
||||
type: string
|
||||
volumeMode:
|
||||
description: volumeMode defines what type of volume
|
||||
is required by the claim. Value of Filesystem is implied
|
||||
when not included in claim spec.
|
||||
type: string
|
||||
volumeName:
|
||||
description: volumeName is the binding reference to
|
||||
the PersistentVolume backing this claim.
|
||||
type: string
|
||||
type: object
|
||||
status:
|
||||
description: 'status represents the current information/status
|
||||
of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
|
||||
properties:
|
||||
accessModes:
|
||||
description: 'accessModes contains the actual access
|
||||
modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
allocatedResources:
|
||||
additionalProperties:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
description: allocatedResources is the storage resource
|
||||
within AllocatedResources tracks the capacity allocated
|
||||
to a PVC. It may be larger than the actual capacity
|
||||
when a volume expansion operation is requested. For
|
||||
storage quota, the larger value from allocatedResources
|
||||
and PVC.spec.resources is used. If allocatedResources
|
||||
is not set, PVC.spec.resources alone is used for quota
|
||||
calculation. If a volume expansion capacity request
|
||||
is lowered, allocatedResources is only lowered if
|
||||
there are no expansion operations in progress and
|
||||
if the actual volume capacity is equal or lower than
|
||||
the requested capacity. This is an alpha field and
|
||||
requires enabling RecoverVolumeExpansionFailure feature.
|
||||
type: object
|
||||
capacity:
|
||||
additionalProperties:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
description: capacity represents the actual resources
|
||||
of the underlying volume.
|
||||
type: object
|
||||
conditions:
|
||||
description: conditions is the current Condition of
|
||||
persistent volume claim. If underlying persistent
|
||||
volume is being resized then the Condition will be
|
||||
set to 'ResizeStarted'.
|
||||
items:
|
||||
description: PersistentVolumeClaimCondition contails
|
||||
details about state of pvc
|
||||
properties:
|
||||
lastProbeTime:
|
||||
description: lastProbeTime is the time we probed
|
||||
the condition.
|
||||
format: date-time
|
||||
type: string
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the time the
|
||||
condition transitioned from one status to another.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is the human-readable message
|
||||
indicating details about last transition.
|
||||
type: string
|
||||
reason:
|
||||
description: reason is a unique, this should be
|
||||
a short, machine understandable string that
|
||||
gives the reason for condition's last transition.
|
||||
If it reports "ResizeStarted" that means the
|
||||
underlying persistent volume is being resized.
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
type:
|
||||
description: PersistentVolumeClaimConditionType
|
||||
is a valid value of PersistentVolumeClaimCondition.Type
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
phase:
|
||||
description: phase represents the current phase of PersistentVolumeClaim.
|
||||
type: string
|
||||
resizeStatus:
|
||||
description: resizeStatus stores status of resize operation.
|
||||
ResizeStatus is not set by default but when expansion
|
||||
is complete resizeStatus is set to empty string by
|
||||
resize controller or kubelet. This is an alpha field
|
||||
and requires enabling RecoverVolumeExpansionFailure
|
||||
feature.
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
network:
|
||||
properties:
|
||||
networkConf:
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
networkType:
|
||||
type: string
|
||||
type: object
|
||||
replicas:
|
||||
description: replicas is the desired number of replicas of the given
|
||||
Template. These are replicas in the sense that they are instantiations
|
||||
of the same Template, but individual replicas also have a consistent
|
||||
identity.
|
||||
format: int32
|
||||
minimum: 0
|
||||
type: integer
|
||||
reserveGameServerIds:
|
||||
items:
|
||||
type: integer
|
||||
type: array
|
||||
scaleStrategy:
|
||||
properties:
|
||||
maxUnavailable:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: 'The maximum number of pods that can be unavailable
|
||||
during scaling. Value can be an absolute number (ex: 5) or a
|
||||
percentage of desired pods (ex: 10%). Absolute number is calculated
|
||||
from percentage by rounding down. It can just be allowed to
|
||||
work with Parallel podManagementPolicy.'
|
||||
x-kubernetes-int-or-string: true
|
||||
type: object
|
||||
serviceQualities:
|
||||
items:
|
||||
properties:
|
||||
containerName:
|
||||
type: string
|
||||
exec:
|
||||
description: Exec specifies the action to take.
|
||||
properties:
|
||||
command:
|
||||
description: Command is the command line to execute inside
|
||||
the container, the working directory for the command is
|
||||
root ('/') in the container's filesystem. The command
|
||||
is simply exec'd, it is not run inside a shell, so traditional
|
||||
shell instructions ('|', etc) won't work. To use a shell,
|
||||
you need to explicitly call out to that shell. Exit status
|
||||
of 0 is treated as live/healthy and non-zero is unhealthy.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
failureThreshold:
|
||||
description: Minimum consecutive failures for the probe to be
|
||||
considered failed after having succeeded. Defaults to 3. Minimum
|
||||
value is 1.
|
||||
format: int32
|
||||
type: integer
|
||||
grpc:
|
||||
description: GRPC specifies an action involving a GRPC port.
|
||||
This is a beta field and requires enabling GRPCContainerProbe
|
||||
feature gate.
|
||||
properties:
|
||||
port:
|
||||
description: Port number of the gRPC service. Number must
|
||||
be in the range 1 to 65535.
|
||||
format: int32
|
||||
type: integer
|
||||
service:
|
||||
description: "Service is the name of the service to place
|
||||
in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md).
|
||||
\n If this is not specified, the default behavior is defined
|
||||
by gRPC."
|
||||
type: string
|
||||
required:
|
||||
- port
|
||||
type: object
|
||||
httpGet:
|
||||
description: HTTPGet specifies the http request to perform.
|
||||
properties:
|
||||
host:
|
||||
description: Host name to connect to, defaults to the pod
|
||||
IP. You probably want to set "Host" in httpHeaders instead.
|
||||
type: string
|
||||
httpHeaders:
|
||||
description: Custom headers to set in the request. HTTP
|
||||
allows repeated headers.
|
||||
items:
|
||||
description: HTTPHeader describes a custom header to be
|
||||
used in HTTP probes
|
||||
properties:
|
||||
name:
|
||||
description: The header field name
|
||||
type: string
|
||||
value:
|
||||
description: The header field value
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- value
|
||||
type: object
|
||||
type: array
|
||||
path:
|
||||
description: Path to access on the HTTP server.
|
||||
type: string
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Name or number of the port to access on the
|
||||
container. Number must be in the range 1 to 65535. Name
|
||||
must be an IANA_SVC_NAME.
|
||||
x-kubernetes-int-or-string: true
|
||||
scheme:
|
||||
description: Scheme to use for connecting to the host. Defaults
|
||||
to HTTP.
|
||||
type: string
|
||||
required:
|
||||
- port
|
||||
type: object
|
||||
initialDelaySeconds:
|
||||
description: 'Number of seconds after the container has started
|
||||
before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'
|
||||
format: int32
|
||||
type: integer
|
||||
name:
|
||||
type: string
|
||||
periodSeconds:
|
||||
description: How often (in seconds) to perform the probe. Default
|
||||
to 10 seconds. Minimum value is 1.
|
||||
format: int32
|
||||
type: integer
|
||||
serviceQualityAction:
|
||||
items:
|
||||
properties:
|
||||
deletionPriority:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
x-kubernetes-int-or-string: true
|
||||
networkDisabled:
|
||||
type: boolean
|
||||
opsState:
|
||||
type: string
|
||||
permanent:
|
||||
type: boolean
|
||||
state:
|
||||
type: boolean
|
||||
updatePriority:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
x-kubernetes-int-or-string: true
|
||||
required:
|
||||
- state
|
||||
type: object
|
||||
type: array
|
||||
successThreshold:
|
||||
description: Minimum consecutive successes for the probe to
|
||||
be considered successful after having failed. Defaults to
|
||||
1. Must be 1 for liveness and startup. Minimum value is 1.
|
||||
format: int32
|
||||
type: integer
|
||||
tcpSocket:
|
||||
description: TCPSocket specifies an action involving a TCP port.
|
||||
properties:
|
||||
host:
|
||||
description: 'Optional: Host name to connect to, defaults
|
||||
to the pod IP.'
|
||||
type: string
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Number or name of the port to access on the
|
||||
container. Number must be in the range 1 to 65535. Name
|
||||
must be an IANA_SVC_NAME.
|
||||
x-kubernetes-int-or-string: true
|
||||
required:
|
||||
- port
|
||||
type: object
|
||||
terminationGracePeriodSeconds:
|
||||
description: Optional duration in seconds the pod needs to terminate
|
||||
gracefully upon probe failure. The grace period is the duration
|
||||
in seconds after the processes running in the pod are sent
|
||||
a termination signal and the time when the processes are forcibly
|
||||
halted with a kill signal. Set this value longer than the
|
||||
expected cleanup time for your process. If this value is nil,
|
||||
the pod's terminationGracePeriodSeconds will be used. Otherwise,
|
||||
this value overrides the value provided by the pod spec. Value
|
||||
must be non-negative integer. The value zero indicates stop
|
||||
immediately via the kill signal (no opportunity to shut down).
|
||||
This is a beta field and requires enabling ProbeTerminationGracePeriod
|
||||
feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds
|
||||
is used if unset.
|
||||
format: int64
|
||||
type: integer
|
||||
timeoutSeconds:
|
||||
description: 'Number of seconds after which the probe times
|
||||
out. Defaults to 1 second. Minimum value is 1. More info:
|
||||
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes'
|
||||
format: int32
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
updateStrategy:
|
||||
properties:
|
||||
rollingUpdate:
|
||||
description: RollingUpdate is used to communicate parameters when
|
||||
Type is RollingUpdateStatefulSetStrategyType.
|
||||
properties:
|
||||
inPlaceUpdateStrategy:
|
||||
description: UnorderedUpdate contains strategies for non-ordered
|
||||
update. If it is not nil, pods will be updated with non-ordered
|
||||
sequence. Noted that UnorderedUpdate can only be allowed
|
||||
to work with Parallel podManagementPolicy UnorderedUpdate
|
||||
*kruiseV1beta1.UnorderedUpdateStrategy `json:"unorderedUpdate,omitempty"`
|
||||
InPlaceUpdateStrategy contains strategies for in-place update.
|
||||
properties:
|
||||
gracePeriodSeconds:
|
||||
description: GracePeriodSeconds is the timespan between
|
||||
set Pod status to not-ready and update images in Pod
|
||||
spec when in-place update a Pod.
|
||||
format: int32
|
||||
type: integer
|
||||
type: object
|
||||
maxUnavailable:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: 'The maximum number of pods that can be unavailable
|
||||
during the update. Value can be an absolute number (ex:
|
||||
5) or a percentage of desired pods (ex: 10%). Absolute number
|
||||
is calculated from percentage by rounding down. Also, maxUnavailable
|
||||
can just be allowed to work with Parallel podManagementPolicy.
|
||||
Defaults to 1.'
|
||||
x-kubernetes-int-or-string: true
|
||||
minReadySeconds:
|
||||
description: MinReadySeconds indicates how long will the pod
|
||||
be considered ready after it's updated. MinReadySeconds
|
||||
works with both OrderedReady and Parallel podManagementPolicy.
|
||||
It affects the pod scale up speed when the podManagementPolicy
|
||||
is set to be OrderedReady. Combined with MaxUnavailable,
|
||||
it affects the pod update speed regardless of podManagementPolicy.
|
||||
Default value is 0, max is 300.
|
||||
format: int32
|
||||
type: integer
|
||||
partition:
|
||||
description: 'Partition indicates the ordinal at which the
|
||||
StatefulSet should be partitioned by default. But if unorderedUpdate
|
||||
has been set: - Partition indicates the number of pods with
|
||||
non-updated revisions when rolling update. - It means controller
|
||||
will update $(replicas - partition) number of pod. Default
|
||||
value is 0.'
|
||||
format: int32
|
||||
type: integer
|
||||
paused:
|
||||
description: Paused indicates that the StatefulSet is paused.
|
||||
Default value is false
|
||||
type: boolean
|
||||
podUpdatePolicy:
|
||||
description: PodUpdatePolicy indicates how pods should be
|
||||
updated Default value is "ReCreate"
|
||||
type: string
|
||||
type: object
|
||||
type:
|
||||
description: Type indicates the type of the StatefulSetUpdateStrategy.
|
||||
Default is RollingUpdate.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- replicas
|
||||
type: object
|
||||
status:
|
||||
description: GameServerSetStatus defines the observed state of GameServerSet
|
||||
properties:
|
||||
availableReplicas:
|
||||
format: int32
|
||||
type: integer
|
||||
currentReplicas:
|
||||
format: int32
|
||||
type: integer
|
||||
labelSelector:
|
||||
description: LabelSelector is label selectors for query over pods
|
||||
that should match the replica count used by HPA.
|
||||
type: string
|
||||
maintainingReplicas:
|
||||
format: int32
|
||||
type: integer
|
||||
readyReplicas:
|
||||
format: int32
|
||||
type: integer
|
||||
replicas:
|
||||
description: replicas from advancedStatefulSet
|
||||
format: int32
|
||||
type: integer
|
||||
updatedReadyReplicas:
|
||||
format: int32
|
||||
type: integer
|
||||
updatedReplicas:
|
||||
format: int32
|
||||
type: integer
|
||||
waitToBeDeletedReplicas:
|
||||
format: int32
|
||||
type: integer
|
||||
required:
|
||||
- availableReplicas
|
||||
- currentReplicas
|
||||
- readyReplicas
|
||||
- replicas
|
||||
- updatedReplicas
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
scale:
|
||||
labelSelectorPath: .status.labelSelector
|
||||
specReplicasPath: .spec.replicas
|
||||
statusReplicasPath: .status.replicas
|
||||
status: {}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# This kustomization.yaml is not intended to be run by itself,
|
||||
# since it depends on service name and namespace that are out of this kustomize package.
|
||||
# It should be run by config/default
|
||||
resources:
|
||||
- bases/game.kruise.io_gameserversets.yaml
|
||||
- bases/game.kruise.io_gameservers.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizeresource
|
||||
|
||||
patchesStrategicMerge:
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
|
||||
# patches here are for enabling the conversion webhook for each CRD
|
||||
#- patches/webhook_in_gameserversets.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizewebhookpatch
|
||||
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
|
||||
# patches here are for enabling the CA injection for each CRD
|
||||
#- patches/cainjection_in_gameserversets.yaml
|
||||
#- patches/cainjection_in_gameservers.yaml
|
||||
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
|
||||
|
||||
# the following config is for teaching kustomize how to do kustomization for CRDs.
|
||||
configurations:
|
||||
- kustomizeconfig.yaml
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# This file is for teaching kustomize how to substitute name and namespace reference in CRD
|
||||
nameReference:
|
||||
- kind: Service
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- kind: CustomResourceDefinition
|
||||
version: v1
|
||||
group: apiextensions.k8s.io
|
||||
path: spec/conversion/webhook/clientConfig/service/name
|
||||
|
||||
namespace:
|
||||
- kind: CustomResourceDefinition
|
||||
version: v1
|
||||
group: apiextensions.k8s.io
|
||||
path: spec/conversion/webhook/clientConfig/service/namespace
|
||||
create: false
|
||||
|
||||
varReference:
|
||||
- path: metadata/annotations
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# Adds namespace to all resources.
|
||||
namespace: kruise-game-system
|
||||
|
||||
# Value of this field is prepended to the
|
||||
# names of all resources, e.g. a deployment named
|
||||
# "wordpress" becomes "alices-wordpress".
|
||||
# Note that it should also match with the prefix (text before '-') of the namespace
|
||||
# field above.
|
||||
namePrefix: kruise-game-
|
||||
|
||||
# Labels to add to all resources and selectors.
|
||||
#commonLabels:
|
||||
# someName: someValue
|
||||
|
||||
bases:
|
||||
- ../crd
|
||||
- ../rbac
|
||||
- ../manager
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||
# crd/kustomization.yaml
|
||||
- ../webhook
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
|
||||
#- ../certmanager
|
||||
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
|
||||
# - ../prometheus
|
||||
|
||||
patchesStrategicMerge:
|
||||
# Protect the /metrics endpoint by putting it behind auth.
|
||||
# If you want your controller-manager to expose the /metrics
|
||||
# endpoint w/o any authn/z, please comment the following line.
|
||||
#- manager_auth_proxy_patch.yaml
|
||||
|
||||
# Mount the controller config file for loading manager configurations
|
||||
# through a ComponentConfig type
|
||||
#- manager_config_patch.yaml
|
||||
|
||||
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
|
||||
# crd/kustomization.yaml
|
||||
#- manager_webhook_patch.yaml
|
||||
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
|
||||
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
|
||||
# 'CERTMANAGER' needs to be enabled to use ca injection
|
||||
#- webhookcainjection_patch.yaml
|
||||
|
||||
# the following config is for teaching kustomize how to do var substitution
|
||||
vars:
|
||||
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
|
||||
#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
|
||||
# objref:
|
||||
# kind: Certificate
|
||||
# group: cert-manager.io
|
||||
# version: v1
|
||||
# name: serving-cert # this name should match the one in certificate.yaml
|
||||
# fieldref:
|
||||
# fieldpath: metadata.namespace
|
||||
#- name: CERTIFICATE_NAME
|
||||
# objref:
|
||||
# kind: Certificate
|
||||
# group: cert-manager.io
|
||||
# version: v1
|
||||
# name: serving-cert # this name should match the one in certificate.yaml
|
||||
#- name: SERVICE_NAMESPACE # namespace of the service
|
||||
# objref:
|
||||
# kind: Service
|
||||
# version: v1
|
||||
# name: webhook-service
|
||||
# fieldref:
|
||||
# fieldpath: metadata.namespace
|
||||
#- name: SERVICE_NAME
|
||||
# objref:
|
||||
# kind: Service
|
||||
# version: v1
|
||||
# name: webhook-service
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# This patch inject a sidecar container which is a HTTP proxy for the
|
||||
# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: kube-rbac-proxy
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- "ALL"
|
||||
image: ringtail/kube-rbac-proxy:v0.12.0
|
||||
args:
|
||||
- "--secure-listen-address=0.0.0.0:8443"
|
||||
- "--upstream=http://127.0.0.1:8080/"
|
||||
- "--logtostderr=true"
|
||||
- "--v=0"
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
protocol: TCP
|
||||
name: https
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 5m
|
||||
memory: 64Mi
|
||||
- name: manager
|
||||
args:
|
||||
- "--health-probe-bind-address=:8081"
|
||||
- "--metrics-bind-address=127.0.0.1:8080"
|
||||
- "--leader-elect"
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: manager
|
||||
ports:
|
||||
- containerPort: 9443
|
||||
name: webhook-server
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
name: cert
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: cert
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: webhook-server-cert
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# This patch add annotation to admission webhook config and
|
||||
# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize.
|
||||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
kind: MutatingWebhookConfiguration
|
||||
metadata:
|
||||
name: mutating-webhook-configuration
|
||||
annotations:
|
||||
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
|
||||
kind: ControllerManagerConfig
|
||||
health:
|
||||
healthProbeBindAddress: :8081
|
||||
metrics:
|
||||
bindAddress: 127.0.0.1:8080
|
||||
webhook:
|
||||
port: 9443
|
||||
leaderElection:
|
||||
leaderElect: true
|
||||
resourceName: c637bb1e.my.domain
|
||||
# leaderElectionReleaseOnCancel defines if the leader should step down volume
|
||||
# when the Manager ends. This requires the binary to immediately end when the
|
||||
# Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
|
||||
# speeds up voluntary leader transitions as the new leader don't have to wait
|
||||
# LeaseDuration time first.
|
||||
# In the default scaffold provided, the program ends immediately after
|
||||
# the manager stops, so would be fine to enable this option. However,
|
||||
# if you are doing or is intended to do any operation such as perform cleanups
|
||||
# after the manager stops then its usage might be unsafe.
|
||||
# leaderElectionReleaseOnCancel: true
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
resources:
|
||||
- manager.yaml
|
||||
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
|
||||
configMapGenerator:
|
||||
- files:
|
||||
- controller_manager_config.yaml
|
||||
name: manager-config
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: controller
|
||||
newName: kruise-game-manager
|
||||
newTag: test
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
name: system
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
control-plane: controller-manager
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
kubectl.kubernetes.io/default-container: manager
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
spec:
|
||||
# securityContext:
|
||||
# runAsNonRoot: true
|
||||
# TODO(user): For common cases that do not require escalating privileges
|
||||
# it is recommended to ensure that all your Pods/Containers are restrictive.
|
||||
# More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
|
||||
# Please uncomment the following code if your project does NOT have to work on old Kubernetes
|
||||
# versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).
|
||||
# seccompProfile:
|
||||
# type: RuntimeDefault
|
||||
containers:
|
||||
- command:
|
||||
- /manager
|
||||
args:
|
||||
- --leader-elect=false
|
||||
image: controller:latest
|
||||
name: manager
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- "ALL"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8082
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /readyz
|
||||
port: 8082
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
# TODO(user): Configure the resources accordingly based on the project requirements.
|
||||
# More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
|
||||
resources:
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 1024Mi
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 64Mi
|
||||
serviceAccountName: controller-manager
|
||||
terminationGracePeriodSeconds: 10
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
resources:
|
||||
- monitor.yaml
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
# Prometheus Monitor Service (Metrics)
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
name: controller-manager-metrics-monitor
|
||||
namespace: system
|
||||
spec:
|
||||
endpoints:
|
||||
- path: /metrics
|
||||
port: https
|
||||
scheme: https
|
||||
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
tlsConfig:
|
||||
insecureSkipVerify: true
|
||||
selector:
|
||||
matchLabels:
|
||||
control-plane: controller-manager
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: metrics-reader
|
||||
rules:
|
||||
- nonResourceURLs:
|
||||
- "/metrics"
|
||||
verbs:
|
||||
- get
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: proxy-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- authentication.k8s.io
|
||||
resources:
|
||||
- tokenreviews
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- authorization.k8s.io
|
||||
resources:
|
||||
- subjectaccessreviews
|
||||
verbs:
|
||||
- create
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: proxy-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: proxy-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
control-plane: controller-manager
|
||||
name: controller-manager-metrics-service
|
||||
namespace: system
|
||||
spec:
|
||||
ports:
|
||||
- name: https
|
||||
port: 8443
|
||||
protocol: TCP
|
||||
targetPort: https
|
||||
selector:
|
||||
control-plane: controller-manager
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# permissions for end users to edit gameservers.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: gameserver-editor-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameservers
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameservers/status
|
||||
verbs:
|
||||
- get
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# permissions for end users to view gameservers.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: gameserver-viewer-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameservers
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameservers/status
|
||||
verbs:
|
||||
- get
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# permissions for end users to edit gameserversets.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: gameserverset-editor-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameserversets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameserversets/status
|
||||
verbs:
|
||||
- get
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# permissions for end users to view gameserversets.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: gameserverset-viewer-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameserversets
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameserversets/status
|
||||
verbs:
|
||||
- get
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
resources:
|
||||
# All RBAC will be applied under this service account in
|
||||
# the deployment namespace. You may comment out this resource
|
||||
# if your manager will use a service account that exists at
|
||||
# runtime. Be sure to update RoleBinding and ClusterRoleBinding
|
||||
# subjects if changing service account names.
|
||||
- service_account.yaml
|
||||
- role.yaml
|
||||
- role_binding.yaml
|
||||
- leader_election_role.yaml
|
||||
- leader_election_role_binding.yaml
|
||||
# Comment the following 4 lines if you want to disable
|
||||
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
|
||||
# which protects your /metrics endpoint.
|
||||
- auth_proxy_service.yaml
|
||||
- auth_proxy_role.yaml
|
||||
- auth_proxy_role_binding.yaml
|
||||
- auth_proxy_client_clusterrole.yaml
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# permissions to do leader election.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: leader-election-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- coordination.k8s.io
|
||||
resources:
|
||||
- leases
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
- create
|
||||
- patch
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: leader-election-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: leader-election-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: manager-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- admissionregistration.k8s.io
|
||||
resources:
|
||||
- mutatingwebhookconfigurations
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- admissionregistration.k8s.io
|
||||
resources:
|
||||
- validatingwebhookconfigurations
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- apiextensions.k8s.io
|
||||
resources:
|
||||
- customresourcedefinitions
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- apps.kruise.io
|
||||
resources:
|
||||
- statefulsets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- apps.kruise.io
|
||||
resources:
|
||||
- statefulsets/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameservers
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameservers/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameservers/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameserversets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameserversets/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- game.kruise.io
|
||||
resources:
|
||||
- gameserversets/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: manager-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: manager-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: controller-manager
|
||||
namespace: system
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
resources:
|
||||
- service.yaml
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: webhook-service
|
||||
namespace: kruise-game-system
|
||||
spec:
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 9876
|
||||
selector:
|
||||
control-plane: controller-manager
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# Installation
|
||||
|
||||
## Install manually
|
||||
|
||||
### 0. Edit Makefile, changing {IMG}
|
||||
|
||||
### 1. Build docker image with the kruise-game controller manager.
|
||||
```shell
|
||||
make docker-build
|
||||
```
|
||||
|
||||
### 2. Push docker image with the kruise-game controller manager.
|
||||
```shell
|
||||
make docker-push
|
||||
```
|
||||
|
||||
### 3. Deploy kruise-game controller manager to the K8s cluster.
|
||||
```shell
|
||||
make deploy
|
||||
```
|
||||
|
||||
## Uninstall manually
|
||||
```shell
|
||||
make undeploy
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# Introduction
|
||||
|
||||
## What is Kruise-Game?
|
||||
Kruise-Game is an open source project based on OpenKruise, to solve the problem of game server landing in Kubernetes.
|
||||
|
||||
## Why is Kruise-Game?
|
||||
Game servers are stateful services, and there are differences in the operation and maintenance of each game server, which also increases with time. In Kubernetes, general workloads manages a batch of game servers according to pod templates, which cannot take into account the differences in game server status. Batch management and directional management are in conflict in k8s. **Kruise-Game** was born to resolve that. Kruise-Game contains two CRDs, GameServer and GameServerSet:
|
||||
|
||||
- `GameServer` is responsible for the management of game server status. Users can customize the game server status to reflect the differences between game servers;
|
||||
- `GameServerSet` is responsible for batch management of game servers. Users can customize update/reduction strategies according to the status of game servers.
|
||||
|
||||
## Features
|
||||
- Game server status management
|
||||
- Mark game servers status without effecting to its lifecycle
|
||||
- Flexible scaling/deletion mechanism
|
||||
- Support scaling down by user-defined status & priority
|
||||
- Support specifying game server to delete directly
|
||||
- Flexible update mechanism
|
||||
- Support hot update (in-place update)
|
||||
- Support updating game server by user-defined priority
|
||||
- Can control the range of the game servers to be updated
|
||||
- Can control the pace of the entire update process
|
||||
- Custom service quality
|
||||
- Support probing game servers‘ containers and mark game servers status automatically
|
||||
|
||||
## What's Next
|
||||
Here are some recommended next steps:
|
||||
|
||||
- Start to [Install kruise-game](./installation.md).
|
||||
- Learn Kruise-Game's [Basic Usage](../tutorials/basic_usage.md).
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
|
|
@ -0,0 +1,222 @@
|
|||
# Basic Usage
|
||||
|
||||
## Requirements
|
||||
- Installation of Kruise, Reference [Install OpenKruise](https://openkruise.io/zh/docs/installation/).
|
||||
- Installation of Kruise-Game, Reference [Install Kruise-Game](../getting_started/installation.md)
|
||||
|
||||
## Deploy GameServerSet
|
||||
This is an example of GameServerSet, which manages 3 game servers.
|
||||
```yaml
|
||||
apiVersion: game.kruise.io/v1alpha1
|
||||
kind: GameServerSet
|
||||
metadata:
|
||||
name: minecraft
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
updateStrategy:
|
||||
rollingUpdate:
|
||||
podUpdatePolicy: InPlaceIfPossible
|
||||
gameServerTemplate:
|
||||
spec:
|
||||
containers:
|
||||
- image: registry.cn-hangzhou.aliyuncs.com/acs/minecraft-demo:1.12.2
|
||||
name: minecraft
|
||||
```
|
||||
When the deployment is complete, the cluster will generate 1 GameServerset, 3 GameServers, and 3 Pods corresponding to GameServers
|
||||
```bash
|
||||
kubectl get gss
|
||||
NAME AGE
|
||||
minecraft 9s
|
||||
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-1 Ready None 0 0
|
||||
minecraft-2 Ready None 0 0
|
||||
|
||||
kubectl get pod
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
minecraft-0 1/1 Running 0 10s
|
||||
minecraft-1 1/1 Running 0 10s
|
||||
minecraft-2 1/1 Running 0 10s
|
||||
```
|
||||
|
||||
## Game servers scale up
|
||||
Directly adjust the number of replicas to the desired number
|
||||
```bash
|
||||
kubectl scale gss minecraft --replicas=5
|
||||
gameserverset.game.kruise.io/minecraft scaled
|
||||
```
|
||||
|
||||
The number of game servers eventually became 5
|
||||
```bash
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-1 Ready None 0 0
|
||||
minecraft-2 Ready None 0 0
|
||||
minecraft-3 Ready None 0 0
|
||||
minecraft-4 Ready None 0 0
|
||||
```
|
||||
|
||||
## Game servers scale down by deletion priority
|
||||
Manually set the GameServer deletionPriority (you can set the deletionPriority automatically through the ServiceQuality function)
|
||||
```yaml
|
||||
kubectl edit gs minecraft-2
|
||||
|
||||
...
|
||||
spec:
|
||||
deletionPriority: 10 #initial value is 0,turn it up to 10
|
||||
opsState: None
|
||||
updatePriority: 0
|
||||
...
|
||||
```
|
||||
Scale down
|
||||
```bash
|
||||
kubectl scale gss minecraft --replicas=4
|
||||
gameserverset.game.kruise.io/minecraft scale
|
||||
```
|
||||
|
||||
The numbers of game servers eventually became 4. It can be found that the No.2 gs with the highest deletionPriority has been deleted.
|
||||
```bash
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-1 Ready None 0 0
|
||||
minecraft-2 Deleting None 10 0
|
||||
minecraft-3 Ready None 0 0
|
||||
minecraft-4 Ready None 0 0
|
||||
|
||||
# After a while
|
||||
...
|
||||
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-1 Ready None 0 0
|
||||
minecraft-3 Ready None 0 0
|
||||
minecraft-4 Ready None 0 0
|
||||
```
|
||||
|
||||
## Game servers scale down by OpsState
|
||||
Manually set the GameServer OpsState to `WaitToBeDeleted` (you can set the OpsState automatically through the ServiceQuality function)
|
||||
|
||||
```yaml
|
||||
kubectl edit gs minecraft-3
|
||||
|
||||
...
|
||||
spec:
|
||||
deletionPriority: 0
|
||||
opsState: WaitToBeDeleted #Initialization is None, will be changed to WaitToBeDeleted
|
||||
updatePriority: 0
|
||||
...
|
||||
```
|
||||
Scale down
|
||||
```bash
|
||||
kubectl scale gss minecraft --replicas=3
|
||||
gameserverset.game.kruise.io/minecraft scaled
|
||||
```
|
||||
|
||||
The numbers of game servers eventually became 3. It can be found that the No.3 gs with WaitToBeDeleted OpsState has been deleted.
|
||||
```bash
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-1 Ready None 0 0
|
||||
minecraft-3 Deleting None 10 0
|
||||
minecraft-4 Ready None 0 0
|
||||
|
||||
# After a while
|
||||
...
|
||||
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-1 Ready None 0 0
|
||||
minecraft-4 Ready None 0 0
|
||||
```
|
||||
|
||||
## Specify game server offline
|
||||
Specify the game server with serial No.1 to go offline
|
||||
```yaml
|
||||
kubectl edit gss minecraft
|
||||
|
||||
...
|
||||
spec:
|
||||
replicas: 2 #replicas is reduced by 1, adjusted to 2
|
||||
reserveGameServerIds:
|
||||
- 1 #specify serial No.1
|
||||
...
|
||||
```
|
||||
|
||||
The numbers of game servers eventually became 2. It can be found that the No.1 gs has been deleted.
|
||||
```bash
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-1 Deleting None 0 0
|
||||
minecraft-4 Ready None 0 0
|
||||
|
||||
# After a while
|
||||
...
|
||||
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 0
|
||||
minecraft-4 Ready None 0 0
|
||||
```
|
||||
|
||||
## Game servers update by update priority
|
||||
|
||||
Manually set the GameServer updatePriority (you can set the updatePriority automatically through the ServiceQuality function)
|
||||
|
||||
```yaml
|
||||
kubectl edit gs minecraft-0
|
||||
|
||||
...
|
||||
spec:
|
||||
deletionPriority: 0
|
||||
opsState: None
|
||||
updatePriority: 10 #initial value is 0,turn it up to 10
|
||||
...
|
||||
```
|
||||
|
||||
Update game servers' image
|
||||
```yaml
|
||||
kubectl edit gss minecraft
|
||||
|
||||
...
|
||||
spec:
|
||||
gameServerTemplate:
|
||||
spec:
|
||||
containers:
|
||||
- image: registry.cn-hangzhou.aliyuncs.com/acs/minecraft-demo:1.13.0 #update images tag to 1.13.0
|
||||
name: minecraft
|
||||
...
|
||||
|
||||
```
|
||||
|
||||
Pay attention to the update process, you can find that the GameServer with a larger updatePriority is updated first
|
||||
```bash
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Updating None 0 10
|
||||
minecraft-4 Ready None 0 0
|
||||
|
||||
# After a while
|
||||
...
|
||||
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 10
|
||||
minecraft-4 Updating None 0 0
|
||||
|
||||
# After a while
|
||||
...
|
||||
|
||||
kubectl get gs
|
||||
NAME STATE OPSSTATE DP UP
|
||||
minecraft-0 Ready None 0 10
|
||||
minecraft-4 Ready None 0 0
|
||||
```
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
module github.com/openkruise/kruise-game
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/gomega v1.18.1
|
||||
github.com/openkruise/kruise-api v1.2.0
|
||||
k8s.io/api v0.24.0
|
||||
k8s.io/apimachinery v0.24.0
|
||||
k8s.io/client-go v0.24.0
|
||||
k8s.io/code-generator v0.24.0
|
||||
k8s.io/klog/v2 v2.60.1
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
|
||||
sigs.k8s.io/controller-runtime v0.12.1
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.81.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/go-logr/logr v1.2.0 // indirect
|
||||
github.com/go-logr/zapr v1.2.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/google/uuid v1.1.2 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.12.1 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.19.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/apiextensions-apiserver v0.24.0 // indirect
|
||||
k8s.io/component-base v0.24.0 // indirect
|
||||
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2018 Google LLC
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Generates a CA certificate, a server key, and a server certificate signed by the CA.
|
||||
|
||||
set -e
|
||||
SCRIPT=`basename ${BASH_SOURCE[0]}`
|
||||
|
||||
function usage {
|
||||
cat<< EOF
|
||||
Usage: $SCRIPT
|
||||
Options:
|
||||
-h | --help Display help information.
|
||||
-n | --namespace <namespace> The namespace where the Spark operator is installed.
|
||||
-s | --service <service> The name of the webhook service.
|
||||
-p | --in-pod Whether the script is running inside a pod or not.
|
||||
EOF
|
||||
}
|
||||
|
||||
function parse_arguments {
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
case "$1" in
|
||||
-n|--namespace)
|
||||
if [[ -n "$2" ]]; then
|
||||
NAMESPACE="$2"
|
||||
else
|
||||
echo "-n or --namespace requires a value."
|
||||
exit 1
|
||||
fi
|
||||
shift 2
|
||||
continue
|
||||
;;
|
||||
-s|--service)
|
||||
if [[ -n "$2" ]]; then
|
||||
SERVICE="$2"
|
||||
else
|
||||
echo "-s or --service requires a value."
|
||||
exit 1
|
||||
fi
|
||||
shift 2
|
||||
continue
|
||||
;;
|
||||
-p|--in-pod)
|
||||
export IN_POD=true
|
||||
shift 1
|
||||
continue
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--) # End of all options.
|
||||
shift
|
||||
break
|
||||
;;
|
||||
'') # End of all options.
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Unrecognized option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Set the namespace to "kruise-game-system" by default if not provided.
|
||||
# Set the webhook service name to "kruise-game-webhook" by default if not provided.
|
||||
IN_POD=false
|
||||
SERVICE="kruise-game-webhook"
|
||||
NAMESPACE="kruise-game-system"
|
||||
parse_arguments "$@"
|
||||
|
||||
TMP_DIR="/tmp/kruise-pod-webhook-certs"
|
||||
|
||||
echo "Generating certs for the kruise-game pod admission webhook in ${TMP_DIR}."
|
||||
mkdir -p ${TMP_DIR}
|
||||
cat > ${TMP_DIR}/server.conf << EOF
|
||||
[req]
|
||||
req_extensions = v3_req
|
||||
distinguished_name = req_distinguished_name
|
||||
[req_distinguished_name]
|
||||
[ v3_req ]
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
extendedKeyUsage = clientAuth, serverAuth
|
||||
subjectAltName = DNS:kruise-game-webhook.kruise-game-system.svc
|
||||
EOF
|
||||
|
||||
# Create a certificate authority.
|
||||
touch ${TMP_DIR}/.rnd
|
||||
export RANDFILE=${TMP_DIR}/.rnd
|
||||
openssl genrsa -out ${TMP_DIR}/ca-key.pem 2048
|
||||
openssl req -x509 -new -nodes -key ${TMP_DIR}/ca-key.pem -days 100000 -out ${TMP_DIR}/ca-cert.pem -subj "/CN=${SERVICE}_ca" -addext "subjectAltName = DNS:${SERVICE}_ca"
|
||||
|
||||
# Create a server certificate.
|
||||
openssl genrsa -out ${TMP_DIR}/server-key.pem 2048
|
||||
# Note the CN is the DNS name of the service of the webhook.
|
||||
openssl req -new -key ${TMP_DIR}/server-key.pem -out ${TMP_DIR}/server.csr -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -config ${TMP_DIR}/server.conf -addext "subjectAltName = DNS:kruise-game-webhook.kruise-game-system.svc"
|
||||
openssl x509 -req -in ${TMP_DIR}/server.csr -CA ${TMP_DIR}/ca-cert.pem -CAkey ${TMP_DIR}/ca-key.pem -CAcreateserial -out ${TMP_DIR}/server-cert.pem -days 100000 -extensions v3_req -extfile ${TMP_DIR}/server.conf
|
||||
|
||||
if [[ "$IN_POD" == "true" ]]; then
|
||||
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
|
||||
# Base64 encode secrets and then remove the trailing newline to avoid issues in the curl command
|
||||
ca_cert=$(cat ${TMP_DIR}/ca-cert.pem | base64 | tr -d '\n')
|
||||
ca_key=$(cat ${TMP_DIR}/ca-key.pem | base64 | tr -d '\n')
|
||||
server_cert=$(cat ${TMP_DIR}/server-cert.pem | base64 | tr -d '\n')
|
||||
server_key=$(cat ${TMP_DIR}/server-key.pem | base64 | tr -d '\n')
|
||||
|
||||
# Create the secret resource
|
||||
echo "Creating a secret for the certificate and keys"
|
||||
STATUS=$(curl -ik \
|
||||
-o ${TMP_DIR}/output \
|
||||
-w "%{http_code}" \
|
||||
-X POST \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"kind": "Secret",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "kruise-game-webhook-certs",
|
||||
"namespace": "'"$NAMESPACE"'"
|
||||
},
|
||||
"data": {
|
||||
"ca-cert.pem": "'"$ca_cert"'",
|
||||
"ca-key.pem": "'"$ca_key"'",
|
||||
"server-cert.pem": "'"$server_cert"'",
|
||||
"server-key.pem": "'"$server_key"'"
|
||||
}
|
||||
}' \
|
||||
https://kubernetes.default.svc/api/v1/namespaces/${NAMESPACE}/secrets)
|
||||
|
||||
cat ${TMP_DIR}/output
|
||||
|
||||
case "$STATUS" in
|
||||
201)
|
||||
printf "\nSuccess - secret created.\n"
|
||||
;;
|
||||
409)
|
||||
printf "\nSuccess - secret already exists.\n"
|
||||
;;
|
||||
*)
|
||||
printf "\nFailed creating secret.\n"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
kubectl create secret --namespace=${NAMESPACE} generic kruise-game-webhook-certs --from-file=${TMP_DIR}/ca-key.pem --from-file=${TMP_DIR}/ca-cert.pem --from-file=${TMP_DIR}/server-key.pem --from-file=${TMP_DIR}/server-cert.pem
|
||||
fi
|
||||
|
||||
# Clean up after we're done.
|
||||
printf "\nDeleting ${TMP_DIR}.\n"
|
||||
rm -rf ${TMP_DIR}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//go:build tools
|
||||
// +build tools
|
||||
|
||||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This package imports things required by build scripts, to force `go mod` to see them as dependencies
|
||||
package hack
|
||||
|
||||
import (
|
||||
_ "k8s.io/code-generator"
|
||||
)
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
||||
controller "github.com/openkruise/kruise-game/pkg/controllers"
|
||||
"github.com/openkruise/kruise-game/pkg/webhook"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
|
||||
// to ensure that exec-entrypoint and run can make use of them.
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log/zap"
|
||||
|
||||
gamekruiseiov1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
utilclient "github.com/openkruise/kruise-game/pkg/util/client"
|
||||
//+kubebuilder:scaffold:imports
|
||||
)
|
||||
|
||||
var (
|
||||
scheme = runtime.NewScheme()
|
||||
setupLog = ctrl.Log.WithName("setup")
|
||||
)
|
||||
|
||||
func init() {
|
||||
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
|
||||
|
||||
utilruntime.Must(gamekruiseiov1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(kruiseV1beta1.AddToScheme(scheme))
|
||||
//+kubebuilder:scaffold:scheme
|
||||
}
|
||||
|
||||
func main() {
|
||||
var metricsAddr string
|
||||
var enableLeaderElection bool
|
||||
var probeAddr string
|
||||
var namespace string
|
||||
var syncPeriodStr string
|
||||
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
|
||||
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8082", "The address the probe endpoint binds to.")
|
||||
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
|
||||
"Enable leader election for controller manager. "+
|
||||
"Enabling this will ensure there is only one active controller manager.")
|
||||
flag.StringVar(&namespace, "namespace", "",
|
||||
"Namespace if specified restricts the manager's cache to watch objects in the desired namespace. Defaults to all namespaces.")
|
||||
flag.StringVar(&syncPeriodStr, "sync-period", "", "Determines the minimum frequency at which watched resources are reconciled.")
|
||||
|
||||
opts := zap.Options{
|
||||
Development: true,
|
||||
}
|
||||
opts.BindFlags(flag.CommandLine)
|
||||
flag.Parse()
|
||||
|
||||
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
|
||||
|
||||
// syncPeriod parsed
|
||||
var syncPeriod *time.Duration
|
||||
if syncPeriodStr != "" {
|
||||
d, err := time.ParseDuration(syncPeriodStr)
|
||||
if err != nil {
|
||||
setupLog.Error(err, "invalid sync period flag")
|
||||
} else {
|
||||
syncPeriod = &d
|
||||
}
|
||||
}
|
||||
|
||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||
Scheme: scheme,
|
||||
MetricsBindAddress: metricsAddr,
|
||||
Port: 9443,
|
||||
HealthProbeBindAddress: probeAddr,
|
||||
LeaderElection: enableLeaderElection,
|
||||
LeaderElectionID: "game-kruise-manager",
|
||||
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
|
||||
// when the Manager ends. This requires the binary to immediately end when the
|
||||
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
|
||||
// speeds up voluntary leader transitions as the new leader don't have to wait
|
||||
// LeaseDuration time first.
|
||||
//
|
||||
// In the default scaffold provided, the program ends immediately after
|
||||
// the manager stops, so would be fine to enable this option. However,
|
||||
// if you are doing or is intended to do any operation such as perform cleanups
|
||||
// after the manager stops then its usage might be unsafe.
|
||||
// LeaderElectionReleaseOnCancel: true,
|
||||
Namespace: namespace,
|
||||
SyncPeriod: syncPeriod,
|
||||
NewClient: utilclient.NewClient,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
setupLog.Error(err, "unable to start kruise-game-manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// create webhook server
|
||||
wss := webhook.NewWebhookServer(mgr)
|
||||
// validate webhook server
|
||||
if err := wss.SetupWithManager(mgr).Initialize(mgr.GetConfig()); err != nil {
|
||||
setupLog.Error(err, "unable to set up webhook server")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
//+kubebuilder:scaffold:builder
|
||||
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up health check")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
|
||||
setupLog.Error(err, "unable to set up ready check")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
go func() {
|
||||
setupLog.Info("setup controllers")
|
||||
if err = controller.SetupWithManager(mgr); err != nil {
|
||||
setupLog.Error(err, "unable to setup controllers")
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
setupLog.Info("starting kruise-game-manager")
|
||||
|
||||
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
|
||||
setupLog.Error(err, "problem running manager")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package versioned
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
gamev1alpha1 "github.com/openkruise/kruise-game/pkg/client/clientset/versioned/typed/apis/v1alpha1"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
GameV1alpha1() gamev1alpha1.GameV1alpha1Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
gameV1alpha1 *gamev1alpha1.GameV1alpha1Client
|
||||
}
|
||||
|
||||
// GameV1alpha1 retrieves the GameV1alpha1Client
|
||||
func (c *Clientset) GameV1alpha1() gamev1alpha1.GameV1alpha1Interface {
|
||||
return c.gameV1alpha1
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
||||
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
|
||||
if configShallowCopy.UserAgent == "" {
|
||||
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
// share the transport between all clients
|
||||
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||
}
|
||||
|
||||
// NewForConfigAndClient creates a new Clientset for the given config and http client.
|
||||
// Note the http client provided takes precedence over the configured transport values.
|
||||
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||
// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
|
||||
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
if configShallowCopy.Burst <= 0 {
|
||||
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
||||
}
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.gameV1alpha1, err = gamev1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
cs, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.gameV1alpha1 = gamev1alpha1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package versioned
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
clientset "github.com/openkruise/kruise-game/pkg/client/clientset/versioned"
|
||||
gamev1alpha1 "github.com/openkruise/kruise-game/pkg/client/clientset/versioned/typed/apis/v1alpha1"
|
||||
fakegamev1alpha1 "github.com/openkruise/kruise-game/pkg/client/clientset/versioned/typed/apis/v1alpha1/fake"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{tracker: o}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
tracker testing.ObjectTracker
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Tracker() testing.ObjectTracker {
|
||||
return c.tracker
|
||||
}
|
||||
|
||||
var (
|
||||
_ clientset.Interface = &Clientset{}
|
||||
_ testing.FakeClient = &Clientset{}
|
||||
)
|
||||
|
||||
// GameV1alpha1 retrieves the GameV1alpha1Client
|
||||
func (c *Clientset) GameV1alpha1() gamev1alpha1.GameV1alpha1Interface {
|
||||
return &fakegamev1alpha1.FakeGameV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
gamev1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
gamev1alpha1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(scheme))
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
gamev1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
gamev1alpha1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(Scheme))
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
"github.com/openkruise/kruise-game/pkg/client/clientset/versioned/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type GameV1alpha1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
GameServersGetter
|
||||
GameServerSetsGetter
|
||||
}
|
||||
|
||||
// GameV1alpha1Client is used to interact with features provided by the game.kruise.io group.
|
||||
type GameV1alpha1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *GameV1alpha1Client) GameServers(namespace string) GameServerInterface {
|
||||
return newGameServers(c, namespace)
|
||||
}
|
||||
|
||||
func (c *GameV1alpha1Client) GameServerSets(namespace string) GameServerSetInterface {
|
||||
return newGameServerSets(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new GameV1alpha1Client for the given config.
|
||||
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||
func NewForConfig(c *rest.Config) (*GameV1alpha1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
httpClient, err := rest.HTTPClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewForConfigAndClient(&config, httpClient)
|
||||
}
|
||||
|
||||
// NewForConfigAndClient creates a new GameV1alpha1Client for the given config and http client.
|
||||
// Note the http client provided takes precedence over the configured transport values.
|
||||
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GameV1alpha1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &GameV1alpha1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new GameV1alpha1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *GameV1alpha1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new GameV1alpha1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *GameV1alpha1Client {
|
||||
return &GameV1alpha1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1alpha1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
||||
|
||||
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 *GameV1alpha1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1alpha1
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/openkruise/kruise-game/pkg/client/clientset/versioned/typed/apis/v1alpha1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeGameV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeGameV1alpha1) GameServers(namespace string) v1alpha1.GameServerInterface {
|
||||
return &FakeGameServers{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeGameV1alpha1) GameServerSets(namespace string) v1alpha1.GameServerSetInterface {
|
||||
return &FakeGameServerSets{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeGameV1alpha1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/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"
|
||||
)
|
||||
|
||||
// FakeGameServers implements GameServerInterface
|
||||
type FakeGameServers struct {
|
||||
Fake *FakeGameV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var gameserversResource = schema.GroupVersionResource{Group: "game.kruise.io", Version: "v1alpha1", Resource: "gameservers"}
|
||||
|
||||
var gameserversKind = schema.GroupVersionKind{Group: "game.kruise.io", Version: "v1alpha1", Kind: "GameServer"}
|
||||
|
||||
// Get takes name of the gameServer, and returns the corresponding gameServer object, and an error if there is any.
|
||||
func (c *FakeGameServers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.GameServer, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(gameserversResource, c.ns, name), &v1alpha1.GameServer{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServer), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of GameServers that match those selectors.
|
||||
func (c *FakeGameServers) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.GameServerList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(gameserversResource, gameserversKind, c.ns, opts), &v1alpha1.GameServerList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.GameServerList{ListMeta: obj.(*v1alpha1.GameServerList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.GameServerList).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 gameServers.
|
||||
func (c *FakeGameServers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(gameserversResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a gameServer and creates it. Returns the server's representation of the gameServer, and an error, if there is any.
|
||||
func (c *FakeGameServers) Create(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.CreateOptions) (result *v1alpha1.GameServer, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(gameserversResource, c.ns, gameServer), &v1alpha1.GameServer{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServer), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a gameServer and updates it. Returns the server's representation of the gameServer, and an error, if there is any.
|
||||
func (c *FakeGameServers) Update(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.UpdateOptions) (result *v1alpha1.GameServer, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(gameserversResource, c.ns, gameServer), &v1alpha1.GameServer{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServer), 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 *FakeGameServers) UpdateStatus(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.UpdateOptions) (*v1alpha1.GameServer, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(gameserversResource, "status", c.ns, gameServer), &v1alpha1.GameServer{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServer), err
|
||||
}
|
||||
|
||||
// Delete takes name of the gameServer and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeGameServers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteActionWithOptions(gameserversResource, c.ns, name, opts), &v1alpha1.GameServer{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeGameServers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(gameserversResource, c.ns, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.GameServerList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched gameServer.
|
||||
func (c *FakeGameServers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.GameServer, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(gameserversResource, c.ns, name, pt, data, subresources...), &v1alpha1.GameServer{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServer), err
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/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"
|
||||
)
|
||||
|
||||
// FakeGameServerSets implements GameServerSetInterface
|
||||
type FakeGameServerSets struct {
|
||||
Fake *FakeGameV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var gameserversetsResource = schema.GroupVersionResource{Group: "game.kruise.io", Version: "v1alpha1", Resource: "gameserversets"}
|
||||
|
||||
var gameserversetsKind = schema.GroupVersionKind{Group: "game.kruise.io", Version: "v1alpha1", Kind: "GameServerSet"}
|
||||
|
||||
// Get takes name of the gameServerSet, and returns the corresponding gameServerSet object, and an error if there is any.
|
||||
func (c *FakeGameServerSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.GameServerSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(gameserversetsResource, c.ns, name), &v1alpha1.GameServerSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServerSet), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of GameServerSets that match those selectors.
|
||||
func (c *FakeGameServerSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.GameServerSetList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(gameserversetsResource, gameserversetsKind, c.ns, opts), &v1alpha1.GameServerSetList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.GameServerSetList{ListMeta: obj.(*v1alpha1.GameServerSetList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.GameServerSetList).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 gameServerSets.
|
||||
func (c *FakeGameServerSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(gameserversetsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a gameServerSet and creates it. Returns the server's representation of the gameServerSet, and an error, if there is any.
|
||||
func (c *FakeGameServerSets) Create(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.CreateOptions) (result *v1alpha1.GameServerSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(gameserversetsResource, c.ns, gameServerSet), &v1alpha1.GameServerSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServerSet), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a gameServerSet and updates it. Returns the server's representation of the gameServerSet, and an error, if there is any.
|
||||
func (c *FakeGameServerSets) Update(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.UpdateOptions) (result *v1alpha1.GameServerSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(gameserversetsResource, c.ns, gameServerSet), &v1alpha1.GameServerSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServerSet), 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 *FakeGameServerSets) UpdateStatus(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.UpdateOptions) (*v1alpha1.GameServerSet, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(gameserversetsResource, "status", c.ns, gameServerSet), &v1alpha1.GameServerSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServerSet), err
|
||||
}
|
||||
|
||||
// Delete takes name of the gameServerSet and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeGameServerSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteActionWithOptions(gameserversetsResource, c.ns, name, opts), &v1alpha1.GameServerSet{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeGameServerSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(gameserversetsResource, c.ns, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.GameServerSetList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched gameServerSet.
|
||||
func (c *FakeGameServerSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.GameServerSet, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(gameserversetsResource, c.ns, name, pt, data, subresources...), &v1alpha1.GameServerSet{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.GameServerSet), err
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
scheme "github.com/openkruise/kruise-game/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"
|
||||
)
|
||||
|
||||
// GameServersGetter has a method to return a GameServerInterface.
|
||||
// A group's client should implement this interface.
|
||||
type GameServersGetter interface {
|
||||
GameServers(namespace string) GameServerInterface
|
||||
}
|
||||
|
||||
// GameServerInterface has methods to work with GameServer resources.
|
||||
type GameServerInterface interface {
|
||||
Create(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.CreateOptions) (*v1alpha1.GameServer, error)
|
||||
Update(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.UpdateOptions) (*v1alpha1.GameServer, error)
|
||||
UpdateStatus(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.UpdateOptions) (*v1alpha1.GameServer, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.GameServer, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.GameServerList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.GameServer, err error)
|
||||
GameServerExpansion
|
||||
}
|
||||
|
||||
// gameServers implements GameServerInterface
|
||||
type gameServers struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newGameServers returns a GameServers
|
||||
func newGameServers(c *GameV1alpha1Client, namespace string) *gameServers {
|
||||
return &gameServers{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the gameServer, and returns the corresponding gameServer object, and an error if there is any.
|
||||
func (c *gameServers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.GameServer, err error) {
|
||||
result = &v1alpha1.GameServer{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of GameServers that match those selectors.
|
||||
func (c *gameServers) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.GameServerList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1alpha1.GameServerList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested gameServers.
|
||||
func (c *gameServers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a gameServer and creates it. Returns the server's representation of the gameServer, and an error, if there is any.
|
||||
func (c *gameServers) Create(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.CreateOptions) (result *v1alpha1.GameServer, err error) {
|
||||
result = &v1alpha1.GameServer{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(gameServer).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a gameServer and updates it. Returns the server's representation of the gameServer, and an error, if there is any.
|
||||
func (c *gameServers) Update(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.UpdateOptions) (result *v1alpha1.GameServer, err error) {
|
||||
result = &v1alpha1.GameServer{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
Name(gameServer.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(gameServer).
|
||||
Do(ctx).
|
||||
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 *gameServers) UpdateStatus(ctx context.Context, gameServer *v1alpha1.GameServer, opts v1.UpdateOptions) (result *v1alpha1.GameServer, err error) {
|
||||
result = &v1alpha1.GameServer{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
Name(gameServer.Name).
|
||||
SubResource("status").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(gameServer).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the gameServer and deletes it. Returns an error if one occurs.
|
||||
func (c *gameServers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *gameServers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched gameServer.
|
||||
func (c *gameServers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.GameServer, err error) {
|
||||
result = &v1alpha1.GameServer{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("gameservers").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
scheme "github.com/openkruise/kruise-game/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"
|
||||
)
|
||||
|
||||
// GameServerSetsGetter has a method to return a GameServerSetInterface.
|
||||
// A group's client should implement this interface.
|
||||
type GameServerSetsGetter interface {
|
||||
GameServerSets(namespace string) GameServerSetInterface
|
||||
}
|
||||
|
||||
// GameServerSetInterface has methods to work with GameServerSet resources.
|
||||
type GameServerSetInterface interface {
|
||||
Create(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.CreateOptions) (*v1alpha1.GameServerSet, error)
|
||||
Update(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.UpdateOptions) (*v1alpha1.GameServerSet, error)
|
||||
UpdateStatus(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.UpdateOptions) (*v1alpha1.GameServerSet, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.GameServerSet, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.GameServerSetList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.GameServerSet, err error)
|
||||
GameServerSetExpansion
|
||||
}
|
||||
|
||||
// gameServerSets implements GameServerSetInterface
|
||||
type gameServerSets struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newGameServerSets returns a GameServerSets
|
||||
func newGameServerSets(c *GameV1alpha1Client, namespace string) *gameServerSets {
|
||||
return &gameServerSets{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the gameServerSet, and returns the corresponding gameServerSet object, and an error if there is any.
|
||||
func (c *gameServerSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.GameServerSet, err error) {
|
||||
result = &v1alpha1.GameServerSet{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of GameServerSets that match those selectors.
|
||||
func (c *gameServerSets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.GameServerSetList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1alpha1.GameServerSetList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested gameServerSets.
|
||||
func (c *gameServerSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a gameServerSet and creates it. Returns the server's representation of the gameServerSet, and an error, if there is any.
|
||||
func (c *gameServerSets) Create(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.CreateOptions) (result *v1alpha1.GameServerSet, err error) {
|
||||
result = &v1alpha1.GameServerSet{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(gameServerSet).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a gameServerSet and updates it. Returns the server's representation of the gameServerSet, and an error, if there is any.
|
||||
func (c *gameServerSets) Update(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.UpdateOptions) (result *v1alpha1.GameServerSet, err error) {
|
||||
result = &v1alpha1.GameServerSet{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
Name(gameServerSet.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(gameServerSet).
|
||||
Do(ctx).
|
||||
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 *gameServerSets) UpdateStatus(ctx context.Context, gameServerSet *v1alpha1.GameServerSet, opts v1.UpdateOptions) (result *v1alpha1.GameServerSet, err error) {
|
||||
result = &v1alpha1.GameServerSet{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
Name(gameServerSet.Name).
|
||||
SubResource("status").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(gameServerSet).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the gameServerSet and deletes it. Returns an error if one occurs.
|
||||
func (c *gameServerSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *gameServerSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched gameServerSet.
|
||||
func (c *gameServerSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.GameServerSet, err error) {
|
||||
result = &v1alpha1.GameServerSet{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("gameserversets").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
type GameServerExpansion interface{}
|
||||
|
||||
type GameServerSetExpansion interface{}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
kruiseclientset "github.com/openkruise/kruise-game/pkg/client/clientset/versioned"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/discovery"
|
||||
kubeclientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// GenericClientset defines a generic client
|
||||
type GenericClientset struct {
|
||||
DiscoveryClient discovery.DiscoveryInterface
|
||||
KubeClient kubeclientset.Interface
|
||||
KruiseGameClient kruiseclientset.Interface
|
||||
}
|
||||
|
||||
// newForConfig creates a new Clientset for the given config.
|
||||
func newForConfig(c *rest.Config) (*GenericClientset, error) {
|
||||
cWithProtobuf := rest.CopyConfig(c)
|
||||
cWithProtobuf.ContentType = runtime.ContentTypeProtobuf
|
||||
discoveryClient, err := discovery.NewDiscoveryClientForConfig(cWithProtobuf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kubeClient, err := kubeclientset.NewForConfig(cWithProtobuf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kruiseClient, err := kruiseclientset.NewForConfig(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &GenericClientset{
|
||||
DiscoveryClient: discoveryClient,
|
||||
KubeClient: kubeClient,
|
||||
KruiseGameClient: kruiseClient,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// newForConfig creates a new Clientset for the given config.
|
||||
func newForConfigOrDie(c *rest.Config) *GenericClientset {
|
||||
gc, err := newForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gc
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package apis
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/openkruise/kruise-game/pkg/client/informers/externalversions/apis/v1alpha1"
|
||||
internalinterfaces "github.com/openkruise/kruise-game/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1alpha1 provides access to shared informers for resources in V1alpha1.
|
||||
V1alpha1() v1alpha1.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1alpha1 returns a new v1alpha1.Interface.
|
||||
func (g *group) V1alpha1() v1alpha1.Interface {
|
||||
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
time "time"
|
||||
|
||||
apisv1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
versioned "github.com/openkruise/kruise-game/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/openkruise/kruise-game/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "github.com/openkruise/kruise-game/pkg/client/listers/apis/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"
|
||||
)
|
||||
|
||||
// GameServerInformer provides access to a shared informer and lister for
|
||||
// GameServers.
|
||||
type GameServerInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha1.GameServerLister
|
||||
}
|
||||
|
||||
type gameServerInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewGameServerInformer constructs a new informer for GameServer 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 NewGameServerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredGameServerInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredGameServerInformer constructs a new informer for GameServer 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 NewFilteredGameServerInformer(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.GameV1alpha1().GameServers(namespace).List(context.TODO(), options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.GameV1alpha1().GameServers(namespace).Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&apisv1alpha1.GameServer{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *gameServerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredGameServerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *gameServerInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&apisv1alpha1.GameServer{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *gameServerInformer) Lister() v1alpha1.GameServerLister {
|
||||
return v1alpha1.NewGameServerLister(f.Informer().GetIndexer())
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
time "time"
|
||||
|
||||
apisv1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
versioned "github.com/openkruise/kruise-game/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/openkruise/kruise-game/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "github.com/openkruise/kruise-game/pkg/client/listers/apis/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"
|
||||
)
|
||||
|
||||
// GameServerSetInformer provides access to a shared informer and lister for
|
||||
// GameServerSets.
|
||||
type GameServerSetInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha1.GameServerSetLister
|
||||
}
|
||||
|
||||
type gameServerSetInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewGameServerSetInformer constructs a new informer for GameServerSet 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 NewGameServerSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredGameServerSetInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredGameServerSetInformer constructs a new informer for GameServerSet 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 NewFilteredGameServerSetInformer(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.GameV1alpha1().GameServerSets(namespace).List(context.TODO(), options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.GameV1alpha1().GameServerSets(namespace).Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&apisv1alpha1.GameServerSet{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *gameServerSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredGameServerSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *gameServerSetInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&apisv1alpha1.GameServerSet{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *gameServerSetInformer) Lister() v1alpha1.GameServerSetLister {
|
||||
return v1alpha1.NewGameServerSetLister(f.Informer().GetIndexer())
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/openkruise/kruise-game/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// GameServers returns a GameServerInformer.
|
||||
GameServers() GameServerInformer
|
||||
// GameServerSets returns a GameServerSetInformer.
|
||||
GameServerSets() GameServerSetInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// GameServers returns a GameServerInformer.
|
||||
func (v *version) GameServers() GameServerInformer {
|
||||
return &gameServerInformer{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}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
versioned "github.com/openkruise/kruise-game/pkg/client/clientset/versioned"
|
||||
apis "github.com/openkruise/kruise-game/pkg/client/informers/externalversions/apis"
|
||||
internalinterfaces "github.com/openkruise/kruise-game/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client versioned.Interface
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
customResync map[reflect.Type]time.Duration
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
customResync: make(map[reflect.Type]time.Duration),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
Game() apis.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Game() apis.Interface {
|
||||
return apis.New(f, f.namespace, f.tweakListOptions)
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=game.kruise.io, Version=v1alpha1
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("gameservers"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Game().V1alpha1().GameServers().Informer()}, nil
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("gameserversets"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Game().V1alpha1().GameServerSets().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
versioned "github.com/openkruise/kruise-game/pkg/client/clientset/versioned"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
|
||||
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
|
||||
type TweakListOptionsFunc func(*v1.ListOptions)
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// GameServerListerExpansion allows custom methods to be added to
|
||||
// GameServerLister.
|
||||
type GameServerListerExpansion interface{}
|
||||
|
||||
// GameServerNamespaceListerExpansion allows custom methods to be added to
|
||||
// GameServerNamespaceLister.
|
||||
type GameServerNamespaceListerExpansion interface{}
|
||||
|
||||
// GameServerSetListerExpansion allows custom methods to be added to
|
||||
// GameServerSetLister.
|
||||
type GameServerSetListerExpansion interface{}
|
||||
|
||||
// GameServerSetNamespaceListerExpansion allows custom methods to be added to
|
||||
// GameServerSetNamespaceLister.
|
||||
type GameServerSetNamespaceListerExpansion interface{}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GameServerLister helps list GameServers.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type GameServerLister interface {
|
||||
// List lists all GameServers in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.GameServer, err error)
|
||||
// GameServers returns an object that can list and get GameServers.
|
||||
GameServers(namespace string) GameServerNamespaceLister
|
||||
GameServerListerExpansion
|
||||
}
|
||||
|
||||
// gameServerLister implements the GameServerLister interface.
|
||||
type gameServerLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewGameServerLister returns a new GameServerLister.
|
||||
func NewGameServerLister(indexer cache.Indexer) GameServerLister {
|
||||
return &gameServerLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all GameServers in the indexer.
|
||||
func (s *gameServerLister) List(selector labels.Selector) (ret []*v1alpha1.GameServer, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha1.GameServer))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// GameServers returns an object that can list and get GameServers.
|
||||
func (s *gameServerLister) GameServers(namespace string) GameServerNamespaceLister {
|
||||
return gameServerNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// GameServerNamespaceLister helps list and get GameServers.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type GameServerNamespaceLister interface {
|
||||
// List lists all GameServers in the indexer for a given namespace.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.GameServer, err error)
|
||||
// Get retrieves the GameServer from the indexer for a given namespace and name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1alpha1.GameServer, error)
|
||||
GameServerNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// gameServerNamespaceLister implements the GameServerNamespaceLister
|
||||
// interface.
|
||||
type gameServerNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all GameServers in the indexer for a given namespace.
|
||||
func (s gameServerNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.GameServer, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha1.GameServer))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the GameServer from the indexer for a given namespace and name.
|
||||
func (s gameServerNamespaceLister) Get(name string) (*v1alpha1.GameServer, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1alpha1.Resource("gameserver"), name)
|
||||
}
|
||||
return obj.(*v1alpha1.GameServer), nil
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GameServerSetLister helps list GameServerSets.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type GameServerSetLister interface {
|
||||
// List lists all GameServerSets in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.GameServerSet, err error)
|
||||
// GameServerSets returns an object that can list and get GameServerSets.
|
||||
GameServerSets(namespace string) GameServerSetNamespaceLister
|
||||
GameServerSetListerExpansion
|
||||
}
|
||||
|
||||
// gameServerSetLister implements the GameServerSetLister interface.
|
||||
type gameServerSetLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewGameServerSetLister returns a new GameServerSetLister.
|
||||
func NewGameServerSetLister(indexer cache.Indexer) GameServerSetLister {
|
||||
return &gameServerSetLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all GameServerSets in the indexer.
|
||||
func (s *gameServerSetLister) List(selector labels.Selector) (ret []*v1alpha1.GameServerSet, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha1.GameServerSet))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// GameServerSets returns an object that can list and get GameServerSets.
|
||||
func (s *gameServerSetLister) GameServerSets(namespace string) GameServerSetNamespaceLister {
|
||||
return gameServerSetNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// GameServerSetNamespaceLister helps list and get GameServerSets.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type GameServerSetNamespaceLister interface {
|
||||
// List lists all GameServerSets in the indexer for a given namespace.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.GameServerSet, err error)
|
||||
// Get retrieves the GameServerSet from the indexer for a given namespace and name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1alpha1.GameServerSet, error)
|
||||
GameServerSetNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// gameServerSetNamespaceLister implements the GameServerSetNamespaceLister
|
||||
// interface.
|
||||
type gameServerSetNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all GameServerSets in the indexer for a given namespace.
|
||||
func (s gameServerSetNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.GameServerSet, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha1.GameServerSet))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the GameServerSet from the indexer for a given namespace and name.
|
||||
func (s gameServerSetNamespaceLister) Get(name string) (*v1alpha1.GameServerSet, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1alpha1.Resource("gameserverset"), name)
|
||||
}
|
||||
return obj.(*v1alpha1.GameServerSet), nil
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg *rest.Config
|
||||
|
||||
defaultGenericClient *GenericClientset
|
||||
)
|
||||
|
||||
// NewRegistry creates clientset by client-go
|
||||
func NewRegistry(c *rest.Config) error {
|
||||
var err error
|
||||
defaultGenericClient, err = newForConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgCopy := *c
|
||||
cfg = &cfgCopy
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetGenericClient returns default clientset
|
||||
func GetGenericClient() *GenericClientset {
|
||||
return defaultGenericClient
|
||||
}
|
||||
|
||||
// GetGenericClientWithName returns clientset with given name as user-agent
|
||||
func GetGenericClientWithName(name string) *GenericClientset {
|
||||
if cfg == nil {
|
||||
return nil
|
||||
}
|
||||
newCfg := *cfg
|
||||
newCfg.UserAgent = fmt.Sprintf("%s/%s", cfg.UserAgent, name)
|
||||
return newForConfigOrDie(&newCfg)
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package versioned
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package versioned
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
Copyright 2022.
|
||||
|
||||
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.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
Copyright 2022.
|
||||
|
||||
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.
|
||||
*/
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/openkruise/kruise-game/pkg/controllers/gameserver"
|
||||
"github.com/openkruise/kruise-game/pkg/controllers/gameserverset"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
)
|
||||
|
||||
var controllerAddFuncs []func(manager.Manager) error
|
||||
|
||||
func init() {
|
||||
controllerAddFuncs = append(controllerAddFuncs, gameserver.Add)
|
||||
controllerAddFuncs = append(controllerAddFuncs, gameserverset.Add)
|
||||
}
|
||||
|
||||
func SetupWithManager(m manager.Manager) error {
|
||||
for _, f := range controllerAddFuncs {
|
||||
if err := f(m); err != nil {
|
||||
if kindMatchErr, ok := err.(*meta.NoKindMatchError); ok {
|
||||
klog.Infof("CRD %v is not installed, its controller will perform noops!", kindMatchErr.GroupKind)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package gameserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
gamekruiseiov1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
utildiscovery "github.com/openkruise/kruise-game/pkg/util/discovery"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/pointer"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
)
|
||||
|
||||
var (
|
||||
controllerKind = gamekruiseiov1alpha1.SchemeGroupVersion.WithKind("GameServer")
|
||||
// leave it to batch size
|
||||
concurrentReconciles = 10
|
||||
)
|
||||
|
||||
func Add(mgr manager.Manager) error {
|
||||
if !utildiscovery.DiscoverGVK(controllerKind) {
|
||||
return nil
|
||||
}
|
||||
return add(mgr, newReconciler(mgr))
|
||||
}
|
||||
|
||||
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
|
||||
recorder := mgr.GetEventRecorderFor("gameserver-controller")
|
||||
return &GameServerReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
recorder: recorder,
|
||||
}
|
||||
}
|
||||
|
||||
func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
||||
// Create a new controller
|
||||
klog.Info("Starting GameServer Controller")
|
||||
c, err := controller.New("gameserver-controller", mgr, controller.Options{Reconciler: r, MaxConcurrentReconciles: concurrentReconciles})
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
if err = c.Watch(&source.Kind{Type: &gamekruiseiov1alpha1.GameServer{}}, &handler.EnqueueRequestForOwner{
|
||||
OwnerType: &corev1.Pod{},
|
||||
IsController: true,
|
||||
}); err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
if err = watchPod(c); err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GameServerReconciler reconciles a GameServer object
|
||||
type GameServerReconciler struct {
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
recorder record.EventRecorder
|
||||
}
|
||||
|
||||
func watchPod(c controller.Controller) error {
|
||||
if err := c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.Funcs{
|
||||
CreateFunc: func(createEvent event.CreateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
pod := createEvent.Object.(*corev1.Pod)
|
||||
if _, exist := pod.GetLabels()[gamekruiseiov1alpha1.GameServerOwnerGssKey]; exist {
|
||||
limitingInterface.Add(reconcile.Request{NamespacedName: types.NamespacedName{
|
||||
Name: pod.GetName(),
|
||||
Namespace: pod.GetNamespace(),
|
||||
}})
|
||||
}
|
||||
},
|
||||
UpdateFunc: func(updateEvent event.UpdateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
newPod := updateEvent.ObjectNew.(*corev1.Pod)
|
||||
if _, exist := newPod.GetLabels()[gamekruiseiov1alpha1.GameServerOwnerGssKey]; exist {
|
||||
limitingInterface.Add(reconcile.Request{NamespacedName: types.NamespacedName{
|
||||
Name: newPod.GetName(),
|
||||
Namespace: newPod.GetNamespace(),
|
||||
}})
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(deleteEvent event.DeleteEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
pod := deleteEvent.Object.(*corev1.Pod)
|
||||
if _, exist := pod.GetLabels()[gamekruiseiov1alpha1.GameServerOwnerGssKey]; exist {
|
||||
limitingInterface.Add(reconcile.Request{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Namespace: deleteEvent.Object.GetNamespace(),
|
||||
Name: deleteEvent.Object.GetName(),
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//+kubebuilder:rbac:groups=game.kruise.io,resources=gameservers,verbs=get;list;watch;create;update;patch;delete
|
||||
//+kubebuilder:rbac:groups=game.kruise.io,resources=gameservers/status,verbs=get;update;patch
|
||||
//+kubebuilder:rbac:groups=game.kruise.io,resources=gameservers/finalizers,verbs=update
|
||||
|
||||
// Reconcile is part of the main kubernetes reconciliation loop which aims to
|
||||
// move the current state of the cluster closer to the desired state.
|
||||
// TODO(user): Modify the Reconcile function to compare the state specified by
|
||||
// the GameServer object against the actual cluster state, and then
|
||||
// perform operations to make the cluster state reflect the state specified by
|
||||
// the user.
|
||||
//
|
||||
// For more details, check Reconcile and its Result here:
|
||||
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.1/pkg/reconcile
|
||||
func (r *GameServerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
_ = log.FromContext(ctx)
|
||||
namespacedName := req.NamespacedName
|
||||
|
||||
// get pod
|
||||
pod := &corev1.Pod{}
|
||||
err := r.Get(ctx, namespacedName, pod)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
klog.Errorf("failed to find pod %s in %s, because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// get GameServer
|
||||
gs := &gamekruiseiov1alpha1.GameServer{}
|
||||
err = r.Get(ctx, namespacedName, gs)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
err := r.initGameServer(pod)
|
||||
if err != nil && !errors.IsAlreadyExists(err) && !errors.IsNotFound(err) {
|
||||
klog.Errorf("failed to create GameServer %s in %s, because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
klog.Errorf("failed to find GameServer %s in %s, because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
gsm := NewGameServerManager(gs, pod, r.Client)
|
||||
|
||||
gss, err := r.getGameServerSet(pod)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
klog.Errorf("failed to get GameServerSet for GameServer %s in %s, because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
podUpdated, err := gsm.SyncToPod()
|
||||
if err != nil || podUpdated {
|
||||
return reconcile.Result{Requeue: podUpdated}, err
|
||||
}
|
||||
|
||||
err = gsm.SyncToGs(gss.Spec.ServiceQualities)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// SetupWithManager sets up the controller with the Manager.
|
||||
func (r *GameServerReconciler) SetupWithManager(mgr ctrl.Manager) (c controller.Controller, err error) {
|
||||
c, err = ctrl.NewControllerManagedBy(mgr).
|
||||
For(&gamekruiseiov1alpha1.GameServer{}).Build(r)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (r *GameServerReconciler) getGameServerSet(pod *corev1.Pod) (*gamekruiseiov1alpha1.GameServerSet, error) {
|
||||
gssName := pod.GetLabels()[gamekruiseiov1alpha1.GameServerOwnerGssKey]
|
||||
gss := &gamekruiseiov1alpha1.GameServerSet{}
|
||||
err := r.Client.Get(context.Background(), types.NamespacedName{
|
||||
Namespace: pod.GetNamespace(),
|
||||
Name: gssName,
|
||||
}, gss)
|
||||
return gss, err
|
||||
}
|
||||
|
||||
func (r *GameServerReconciler) initGameServer(pod *corev1.Pod) error {
|
||||
gs := &gamekruiseiov1alpha1.GameServer{}
|
||||
gs.Name = pod.GetName()
|
||||
gs.Namespace = pod.GetNamespace()
|
||||
|
||||
// set owner reference
|
||||
ors := make([]metav1.OwnerReference, 0)
|
||||
or := metav1.OwnerReference{
|
||||
APIVersion: pod.APIVersion,
|
||||
Kind: pod.Kind,
|
||||
Name: pod.GetName(),
|
||||
UID: pod.GetUID(),
|
||||
Controller: pointer.BoolPtr(true),
|
||||
BlockOwnerDeletion: pointer.BoolPtr(true),
|
||||
}
|
||||
ors = append(ors, or)
|
||||
gs.OwnerReferences = ors
|
||||
|
||||
// set NetWork
|
||||
gs.Spec.NetworkDisabled = false
|
||||
|
||||
// set OpsState
|
||||
gs.Spec.OpsState = gamekruiseiov1alpha1.None
|
||||
|
||||
// set UpdatePriority
|
||||
updatePriority := intstr.FromInt(0)
|
||||
gs.Spec.UpdatePriority = &updatePriority
|
||||
|
||||
// set deletionPriority
|
||||
deletionPriority := intstr.FromInt(0)
|
||||
gs.Spec.DeletionPriority = &deletionPriority
|
||||
|
||||
return r.Client.Create(context.Background(), gs)
|
||||
}
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package gameserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
kruisePub "github.com/openkruise/kruise-api/apps/pub"
|
||||
gameKruiseV1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
"github.com/openkruise/kruise-game/pkg/util"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
type Control interface {
|
||||
SyncToPod() (bool, error)
|
||||
SyncToGs(qualities []gameKruiseV1alpha1.ServiceQuality) error
|
||||
}
|
||||
|
||||
type GameServerManager struct {
|
||||
gameServer *gameKruiseV1alpha1.GameServer
|
||||
pod *corev1.Pod
|
||||
client client.Client
|
||||
}
|
||||
|
||||
func (manager GameServerManager) SyncToPod() (bool, error) {
|
||||
// compare GameServer Spec With Pod
|
||||
pod := manager.pod
|
||||
gs := manager.gameServer
|
||||
podLabels := pod.GetLabels()
|
||||
podDeletePriority := podLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey]
|
||||
podUpdatePriority := podLabels[gameKruiseV1alpha1.GameServerUpdatePriorityKey]
|
||||
podGsOpsState := podLabels[gameKruiseV1alpha1.GameServerOpsStateKey]
|
||||
podGsState := podLabels[gameKruiseV1alpha1.GameServerStateKey]
|
||||
|
||||
updated := false
|
||||
newLabels := make(map[string]string)
|
||||
if gs.Spec.DeletionPriority.String() != podDeletePriority {
|
||||
newLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey] = gs.Spec.DeletionPriority.String()
|
||||
updated = true
|
||||
}
|
||||
if gs.Spec.UpdatePriority.String() != podUpdatePriority {
|
||||
newLabels[gameKruiseV1alpha1.GameServerUpdatePriorityKey] = gs.Spec.UpdatePriority.String()
|
||||
updated = true
|
||||
}
|
||||
if string(gs.Spec.OpsState) != podGsOpsState {
|
||||
newLabels[gameKruiseV1alpha1.GameServerOpsStateKey] = string(gs.Spec.OpsState)
|
||||
updated = true
|
||||
}
|
||||
|
||||
var gsState gameKruiseV1alpha1.GameServerState
|
||||
switch pod.Status.Phase {
|
||||
case corev1.PodRunning:
|
||||
// GameServer Updating
|
||||
lifecycleState, exist := pod.GetLabels()[kruisePub.LifecycleStateKey]
|
||||
if exist && (lifecycleState == string(kruisePub.LifecycleStateUpdating) || lifecycleState == string(kruisePub.LifecycleStatePreparingUpdate)) {
|
||||
gsState = gameKruiseV1alpha1.Updating
|
||||
break
|
||||
}
|
||||
// GameServer Deleting
|
||||
if !pod.DeletionTimestamp.IsZero() {
|
||||
gsState = gameKruiseV1alpha1.Deleting
|
||||
break
|
||||
}
|
||||
// GameServer Ready / NotReady
|
||||
for _, con := range pod.Status.Conditions {
|
||||
if con.Type == corev1.PodReady {
|
||||
if con.Status == corev1.ConditionTrue {
|
||||
gsState = gameKruiseV1alpha1.Ready
|
||||
} else {
|
||||
gsState = gameKruiseV1alpha1.NotReady
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
case corev1.PodFailed:
|
||||
gsState = gameKruiseV1alpha1.Crash
|
||||
case corev1.PodPending:
|
||||
gsState = gameKruiseV1alpha1.Creating
|
||||
default:
|
||||
gsState = gameKruiseV1alpha1.Unknown
|
||||
}
|
||||
if string(gsState) != podGsState {
|
||||
newLabels[gameKruiseV1alpha1.GameServerStateKey] = string(gsState)
|
||||
updated = true
|
||||
}
|
||||
|
||||
if updated {
|
||||
patchPod := map[string]interface{}{"metadata": map[string]map[string]string{"labels": newLabels}}
|
||||
patchPodBytes, err := json.Marshal(patchPod)
|
||||
if err != nil {
|
||||
return updated, err
|
||||
}
|
||||
err = manager.client.Patch(context.TODO(), pod, client.RawPatch(types.StrategicMergePatchType, patchPodBytes))
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
klog.Errorf("failed to patch Pod %s in %s,because of %s.", pod.GetName(), pod.GetNamespace(), err.Error())
|
||||
return updated, err
|
||||
}
|
||||
}
|
||||
|
||||
return updated, nil
|
||||
}
|
||||
|
||||
func (manager GameServerManager) SyncToGs(qualities []gameKruiseV1alpha1.ServiceQuality) error {
|
||||
gs := manager.gameServer
|
||||
pod := manager.pod
|
||||
podLabels := pod.GetLabels()
|
||||
podDeletePriority := intstr.FromString(podLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey])
|
||||
podUpdatePriority := intstr.FromString(podLabels[gameKruiseV1alpha1.GameServerUpdatePriorityKey])
|
||||
podGsState := gameKruiseV1alpha1.GameServerState(podLabels[gameKruiseV1alpha1.GameServerStateKey])
|
||||
|
||||
gsConditions := gs.Status.ServiceQualitiesCondition
|
||||
podConditions := pod.Status.Conditions
|
||||
var sqNames []string
|
||||
for _, sq := range qualities {
|
||||
sqNames = append(sqNames, sq.Name)
|
||||
}
|
||||
var toExec map[string]string
|
||||
var newGsConditions []gameKruiseV1alpha1.ServiceQualityCondition
|
||||
for _, pc := range podConditions {
|
||||
if util.IsStringInList(string(pc.Type), sqNames) {
|
||||
toExecAction := true
|
||||
lastActionTransitionTime := metav1.Now()
|
||||
for _, gsc := range gsConditions {
|
||||
if gsc.Name == string(pc.Type) && gsc.Status == string(pc.Status) {
|
||||
toExecAction = false
|
||||
lastActionTransitionTime = gsc.LastActionTransitionTime
|
||||
break
|
||||
}
|
||||
}
|
||||
serviceQualityCondition := gameKruiseV1alpha1.ServiceQualityCondition{
|
||||
Name: string(pc.Type),
|
||||
Status: string(pc.Status),
|
||||
LastProbeTime: pc.LastProbeTime,
|
||||
LastTransitionTime: pc.LastTransitionTime,
|
||||
LastActionTransitionTime: lastActionTransitionTime,
|
||||
}
|
||||
newGsConditions = append(newGsConditions, serviceQualityCondition)
|
||||
if toExecAction {
|
||||
toExec[string(pc.Type)] = string(pc.Status)
|
||||
}
|
||||
}
|
||||
}
|
||||
if toExec != nil {
|
||||
var spec gameKruiseV1alpha1.GameServerSpec
|
||||
for _, sq := range qualities {
|
||||
for name := range toExec {
|
||||
if sq.Name == name {
|
||||
// TODO exec action
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patchSpec := map[string]interface{}{"spec": spec}
|
||||
jsonPatchSpec, err := json.Marshal(patchSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = manager.client.Patch(context.TODO(), gs, client.RawPatch(types.MergePatchType, jsonPatchSpec))
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
klog.Errorf("failed to patch GameServer spec %s in %s,because of %s.", gs.GetName(), gs.GetNamespace(), err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
status := gameKruiseV1alpha1.GameServerStatus{
|
||||
PodStatus: pod.Status,
|
||||
CurrentState: podGsState,
|
||||
DesiredState: gameKruiseV1alpha1.Ready,
|
||||
UpdatePriority: &podUpdatePriority,
|
||||
DeletionPriority: &podDeletePriority,
|
||||
ServiceQualitiesCondition: newGsConditions,
|
||||
LastTransitionTime: metav1.Now(),
|
||||
}
|
||||
patchStatus := map[string]interface{}{"status": status}
|
||||
jsonPatchStatus, err := json.Marshal(patchStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = manager.client.Status().Patch(context.TODO(), gs, client.RawPatch(types.MergePatchType, jsonPatchStatus))
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
klog.Errorf("failed to patch GameServer Status %s in %s,because of %s.", gs.GetName(), gs.GetNamespace(), err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewGameServerManager(gs *gameKruiseV1alpha1.GameServer, pod *corev1.Pod, c client.Client) Control {
|
||||
return &GameServerManager{
|
||||
gameServer: gs,
|
||||
pod: pod,
|
||||
client: c,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package gameserverset
|
||||
|
||||
import (
|
||||
"context"
|
||||
kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
||||
gamekruiseiov1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
"github.com/openkruise/kruise-game/pkg/util"
|
||||
utildiscovery "github.com/openkruise/kruise-game/pkg/util/discovery"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/pointer"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller"
|
||||
"sigs.k8s.io/controller-runtime/pkg/event"
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
)
|
||||
|
||||
var (
|
||||
controllerKind = gamekruiseiov1alpha1.SchemeGroupVersion.WithKind("GameServerSet")
|
||||
// leave it to batch size
|
||||
concurrentReconciles = 10
|
||||
)
|
||||
|
||||
func Add(mgr manager.Manager) error {
|
||||
if !utildiscovery.DiscoverGVK(controllerKind) {
|
||||
return nil
|
||||
}
|
||||
return add(mgr, newReconciler(mgr))
|
||||
}
|
||||
|
||||
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
|
||||
recorder := mgr.GetEventRecorderFor("gameserverset-controller")
|
||||
return &GameServerSetReconciler{
|
||||
Client: mgr.GetClient(),
|
||||
Scheme: mgr.GetScheme(),
|
||||
recorder: recorder,
|
||||
}
|
||||
}
|
||||
|
||||
func add(mgr manager.Manager, r reconcile.Reconciler) error {
|
||||
// Create a new controller
|
||||
klog.Info("Starting GameServerSet Controller")
|
||||
c, err := controller.New("gameserverset-controller", mgr, controller.Options{Reconciler: r, MaxConcurrentReconciles: concurrentReconciles})
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = c.Watch(&source.Kind{Type: &gamekruiseiov1alpha1.GameServerSet{}}, &handler.EnqueueRequestForObject{}); err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = watchPod(c); err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err = watchWorkloads(c); err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// watch pod
|
||||
func watchPod(c controller.Controller) (err error) {
|
||||
|
||||
if err := c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.Funcs{
|
||||
CreateFunc: func(createEvent event.CreateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
pod := createEvent.Object.(*corev1.Pod)
|
||||
if gssName, exist := pod.GetLabels()[gamekruiseiov1alpha1.GameServerOwnerGssKey]; exist {
|
||||
limitingInterface.Add(reconcile.Request{NamespacedName: types.NamespacedName{
|
||||
Name: gssName,
|
||||
Namespace: pod.GetNamespace(),
|
||||
}})
|
||||
}
|
||||
},
|
||||
UpdateFunc: func(updateEvent event.UpdateEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
pod := updateEvent.ObjectNew.(*corev1.Pod)
|
||||
if gssName, exist := pod.GetLabels()[gamekruiseiov1alpha1.GameServerOwnerGssKey]; exist {
|
||||
limitingInterface.Add(reconcile.Request{NamespacedName: types.NamespacedName{
|
||||
Name: gssName,
|
||||
Namespace: pod.GetNamespace(),
|
||||
}})
|
||||
}
|
||||
},
|
||||
DeleteFunc: func(deleteEvent event.DeleteEvent, limitingInterface workqueue.RateLimitingInterface) {
|
||||
pod := deleteEvent.Object.(*corev1.Pod)
|
||||
if gssName, exist := pod.GetLabels()[gamekruiseiov1alpha1.GameServerOwnerGssKey]; exist {
|
||||
limitingInterface.Add(reconcile.Request{NamespacedName: types.NamespacedName{
|
||||
Name: gssName,
|
||||
Namespace: pod.GetNamespace(),
|
||||
}})
|
||||
}
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// watch workloads
|
||||
func watchWorkloads(c controller.Controller) (err error) {
|
||||
if err := c.Watch(&source.Kind{Type: &kruiseV1beta1.StatefulSet{}}, &handler.EnqueueRequestForOwner{
|
||||
IsController: true,
|
||||
OwnerType: &gamekruiseiov1alpha1.GameServerSet{},
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GameServerSetReconciler reconciles a GameServerSet object
|
||||
type GameServerSetReconciler struct {
|
||||
client.Client
|
||||
Scheme *runtime.Scheme
|
||||
recorder record.EventRecorder
|
||||
}
|
||||
|
||||
//+kubebuilder:rbac:groups=game.kruise.io,resources=gameserversets,verbs=get;list;watch;create;update;patch;delete
|
||||
//+kubebuilder:rbac:groups=game.kruise.io,resources=gameserversets/status,verbs=get;update;patch
|
||||
//+kubebuilder:rbac:groups=game.kruise.io,resources=gameserversets/finalizers,verbs=update
|
||||
|
||||
// Reconcile is part of the main kubernetes reconciliation loop which aims to
|
||||
// move the current state of the cluster closer to the desired state.
|
||||
// TODO(user): Modify the Reconcile function to compare the state specified by
|
||||
// the GameServerSet object against the actual cluster state, and then
|
||||
// perform operations to make the cluster state reflect the state specified by
|
||||
// the user.
|
||||
//
|
||||
// For more details, check Reconcile and its Result here:
|
||||
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.1/pkg/reconcile
|
||||
func (r *GameServerSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
_ = log.FromContext(ctx)
|
||||
namespacedName := req.NamespacedName
|
||||
|
||||
// get GameServerSet
|
||||
gss := &gamekruiseiov1alpha1.GameServerSet{}
|
||||
err := r.Get(ctx, namespacedName, gss)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
klog.Errorf("Failed to find GameServerSet %s in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// get advanced statefulset
|
||||
asts := &kruiseV1beta1.StatefulSet{}
|
||||
err = r.Get(ctx, namespacedName, asts)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
err = r.initAsts(gss)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to create advanced statefulset %s in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
klog.Errorf("failed to find advanced statefulset %s in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// get actual Pod list
|
||||
podList := &corev1.PodList{}
|
||||
err = r.List(ctx, podList, &client.ListOptions{
|
||||
Namespace: gss.GetNamespace(),
|
||||
LabelSelector: labels.SelectorFromSet(map[string]string{
|
||||
gamekruiseiov1alpha1.GameServerOwnerGssKey: gss.GetName(),
|
||||
})})
|
||||
if err != nil {
|
||||
klog.Errorf("failed to list GameServers of GameServerSet %s in %s.", gss.GetName(), gss.GetNamespace())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
gsm := NewGameServerSetManager(gss, asts, podList.Items, r.Client)
|
||||
|
||||
// scale game servers
|
||||
if gsm.IsNeedToScale() {
|
||||
err = gsm.GameServerScale()
|
||||
if err != nil {
|
||||
klog.Errorf("GameServerSet %s failed to scale GameServers in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
// update workload
|
||||
if gsm.IsNeedToUpdateWorkload() {
|
||||
err = gsm.UpdateWorkload()
|
||||
if err != nil {
|
||||
klog.Errorf("GameServerSet %s failed to synchronize workload in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
// TODO sync PodProbeMarker
|
||||
err = gsm.SyncPodProbeMarker()
|
||||
if err != nil {
|
||||
klog.Errorf("GameServerSet %s failed to synchronize PodProbeMarker in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
// sync GameServerSet Status
|
||||
err = gsm.SyncStatus()
|
||||
if err != nil {
|
||||
klog.Errorf("GameServerSet %s failed to synchronize its status in %s,because of %s.", namespacedName.Name, namespacedName.Namespace, err.Error())
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// SetupWithManager sets up the controller with the Manager.
|
||||
func (r *GameServerSetReconciler) SetupWithManager(mgr ctrl.Manager) (c controller.Controller, err error) {
|
||||
c, err = ctrl.NewControllerManagedBy(mgr).
|
||||
For(&gamekruiseiov1alpha1.GameServerSet{}).Build(r)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (r *GameServerSetReconciler) initAsts(gss *gamekruiseiov1alpha1.GameServerSet) error {
|
||||
asts := &kruiseV1beta1.StatefulSet{}
|
||||
asts.Namespace = gss.GetNamespace()
|
||||
asts.Name = gss.GetName()
|
||||
|
||||
// set owner reference
|
||||
ors := make([]metav1.OwnerReference, 0)
|
||||
or := metav1.OwnerReference{
|
||||
APIVersion: gss.APIVersion,
|
||||
Kind: gss.Kind,
|
||||
Name: gss.GetName(),
|
||||
UID: gss.GetUID(),
|
||||
Controller: pointer.BoolPtr(true),
|
||||
BlockOwnerDeletion: pointer.BoolPtr(true),
|
||||
}
|
||||
ors = append(ors, or)
|
||||
asts.SetOwnerReferences(ors)
|
||||
|
||||
// set label
|
||||
astsLabels := make(map[string]string)
|
||||
astsLabels[gamekruiseiov1alpha1.AstsHashKey] = util.GetAstsHash(gss)
|
||||
asts.SetLabels(astsLabels)
|
||||
|
||||
// set label selector
|
||||
asts.Spec.Selector = &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{gamekruiseiov1alpha1.GameServerOwnerGssKey: gss.GetName()},
|
||||
}
|
||||
|
||||
// set replicas
|
||||
asts.Spec.Replicas = gss.Spec.Replicas
|
||||
|
||||
asts = util.GetNewAstsFromGss(gss, asts)
|
||||
|
||||
return r.Client.Create(context.Background(), asts)
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package gameserverset
|
||||
|
||||
import (
|
||||
"context"
|
||||
kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
||||
gameKruiseV1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
"github.com/openkruise/kruise-game/pkg/util"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Control interface {
|
||||
GameServerScale() error
|
||||
UpdateWorkload() error
|
||||
SyncStatus() error
|
||||
IsNeedToScale() bool
|
||||
IsNeedToUpdateWorkload() bool
|
||||
SyncPodProbeMarker() error
|
||||
}
|
||||
|
||||
type GameServerSetManager struct {
|
||||
gameServerSet *gameKruiseV1alpha1.GameServerSet
|
||||
asts *kruiseV1beta1.StatefulSet
|
||||
podList []corev1.Pod
|
||||
client client.Client
|
||||
}
|
||||
|
||||
func NewGameServerSetManager(gss *gameKruiseV1alpha1.GameServerSet, asts *kruiseV1beta1.StatefulSet, gsList []corev1.Pod, c client.Client) Control {
|
||||
return &GameServerSetManager{
|
||||
gameServerSet: gss,
|
||||
asts: asts,
|
||||
podList: gsList,
|
||||
client: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *GameServerSetManager) IsNeedToScale() bool {
|
||||
gss := manager.gameServerSet
|
||||
asts := manager.asts
|
||||
gsList := manager.podList
|
||||
|
||||
currentReplicas := len(gsList)
|
||||
workloadReplicas := int(*asts.Spec.Replicas)
|
||||
expectedReplicas := int(*gss.Spec.Replicas)
|
||||
|
||||
// workload is reconciling its replicas, don't interrupt
|
||||
if currentReplicas != workloadReplicas {
|
||||
return false
|
||||
}
|
||||
|
||||
// no need to scale
|
||||
return !(expectedReplicas == currentReplicas && util.IsSliceEqual(util.StringToIntSlice(gss.GetAnnotations()[gameKruiseV1alpha1.GameServerSetReserveIdsKey], ","), gss.Spec.ReserveGameServerIds))
|
||||
}
|
||||
|
||||
func (manager *GameServerSetManager) GameServerScale() error {
|
||||
gss := manager.gameServerSet
|
||||
asts := manager.asts
|
||||
gsList := manager.podList
|
||||
c := manager.client
|
||||
ctx := context.Background()
|
||||
|
||||
currentReplicas := len(gsList)
|
||||
expectedReplicas := int(*gss.Spec.Replicas)
|
||||
as := gss.GetAnnotations()
|
||||
reserveIds := util.StringToIntSlice(as[gameKruiseV1alpha1.GameServerSetReserveIdsKey], ",")
|
||||
notExistIds := util.StringToIntSlice(as[gameKruiseV1alpha1.GameServerSetNotExistIdsKey], ",")
|
||||
gssReserveIds := gss.Spec.ReserveGameServerIds
|
||||
|
||||
klog.Infof("GameServers %s/%s already has %d replicas, expect to have %d replicas.", gss.GetNamespace(), gss.GetName(), currentReplicas, expectedReplicas)
|
||||
|
||||
newNotExistIds := computeToScaleGs(gssReserveIds, reserveIds, notExistIds, expectedReplicas, gsList)
|
||||
|
||||
asts.Spec.ReserveOrdinals = append(gssReserveIds, newNotExistIds...)
|
||||
asts.Spec.Replicas = gss.Spec.Replicas
|
||||
asts.Spec.ScaleStrategy = &kruiseV1beta1.StatefulSetScaleStrategy{
|
||||
MaxUnavailable: gss.Spec.ScaleStrategy.MaxUnavailable,
|
||||
}
|
||||
err := c.Update(ctx, asts)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to update workload replicas %s in %s,because of %s.", gss.GetName(), gss.GetNamespace(), err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
gssAnnotations := make(map[string]string)
|
||||
gssAnnotations[gameKruiseV1alpha1.GameServerSetReserveIdsKey] = util.IntSliceToString(gssReserveIds, ",")
|
||||
gssAnnotations[gameKruiseV1alpha1.GameServerSetNotExistIdsKey] = util.IntSliceToString(newNotExistIds, ",")
|
||||
patchGss := map[string]interface{}{"metadata": map[string]map[string]string{"annotations": gssAnnotations}}
|
||||
patchGssBytes, _ := json.Marshal(patchGss)
|
||||
err = c.Patch(ctx, gss, client.RawPatch(types.MergePatchType, patchGssBytes))
|
||||
if err != nil {
|
||||
klog.Errorf("failed to patch GameServerSet %s in %s,because of %s.", gss.GetName(), gss.GetNamespace(), err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func computeToScaleGs(gssReserveIds, reserveIds, notExistIds []int, expectedReplicas int, pods []corev1.Pod) []int {
|
||||
workloadManageIds := util.GetIndexListFromPodList(pods)
|
||||
|
||||
var toAdd []int
|
||||
var toDelete []int
|
||||
|
||||
// 1. compute reserved GameServerIds, firstly
|
||||
|
||||
// 1.a. to delete those new reserved GameServers already in workloadManageIds
|
||||
toDelete = util.GetSliceInAandInB(util.GetSliceInANotInB(gssReserveIds, reserveIds), workloadManageIds)
|
||||
|
||||
// 1.b. to add those remove-reserved GameServers already in workloadManageIds
|
||||
existLastIndex := -1
|
||||
if len(workloadManageIds) != 0 {
|
||||
sort.Ints(workloadManageIds)
|
||||
existLastIndex = workloadManageIds[len(workloadManageIds)-1]
|
||||
}
|
||||
for _, id := range util.GetSliceInANotInB(reserveIds, gssReserveIds) {
|
||||
if existLastIndex > id {
|
||||
toAdd = append(toAdd, id)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. compute remain GameServerIds, secondly
|
||||
|
||||
numToAdd := expectedReplicas - len(pods) + len(toDelete) - len(toAdd)
|
||||
if numToAdd < 0 {
|
||||
|
||||
// 2.a to delete GameServers according to DeleteSequence
|
||||
sortedGs := util.DeleteSequenceGs(pods)
|
||||
sort.Sort(sortedGs)
|
||||
toDelete = append(toDelete, util.GetIndexListFromPodList(sortedGs[:-numToAdd])...)
|
||||
} else {
|
||||
|
||||
// 2.b to add GameServers, firstly add those in add notExistIds, secondly add those in future sequence
|
||||
numNotExist := len(notExistIds)
|
||||
if numNotExist < numToAdd {
|
||||
toAdd = append(toAdd, notExistIds...)
|
||||
times := 0
|
||||
for i := existLastIndex + 1; times < numToAdd-numNotExist; i++ {
|
||||
if !util.IsNumInList(i, gssReserveIds) {
|
||||
toAdd = append(toAdd, i)
|
||||
times++
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toAdd = append(toAdd, notExistIds[:numToAdd]...)
|
||||
}
|
||||
}
|
||||
|
||||
newManageIds := append(workloadManageIds, util.GetSliceInANotInB(toAdd, workloadManageIds)...)
|
||||
newManageIds = util.GetSliceInANotInB(newManageIds, toDelete)
|
||||
var newNotExistIds []int
|
||||
if len(newManageIds) != 0 {
|
||||
sort.Ints(newManageIds)
|
||||
for i := 0; i < newManageIds[len(newManageIds)-1]; i++ {
|
||||
if !util.IsNumInList(i, newManageIds) && !util.IsNumInList(i, gssReserveIds) {
|
||||
newNotExistIds = append(newNotExistIds, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newNotExistIds
|
||||
}
|
||||
|
||||
func (manager *GameServerSetManager) IsNeedToUpdateWorkload() bool {
|
||||
return manager.asts.GetLabels()[gameKruiseV1alpha1.AstsHashKey] != util.GetAstsHash(manager.gameServerSet)
|
||||
}
|
||||
|
||||
func (manager *GameServerSetManager) UpdateWorkload() error {
|
||||
gss := manager.gameServerSet
|
||||
asts := manager.asts
|
||||
|
||||
// sync with Advanced StatefulSet
|
||||
asts = util.GetNewAstsFromGss(gss, asts)
|
||||
astsLabels := asts.GetLabels()
|
||||
astsLabels[gameKruiseV1alpha1.AstsHashKey] = util.GetAstsHash(manager.gameServerSet)
|
||||
asts.SetLabels(astsLabels)
|
||||
return manager.client.Update(context.Background(), asts)
|
||||
}
|
||||
|
||||
func (manager *GameServerSetManager) SyncPodProbeMarker() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *GameServerSetManager) SyncStatus() error {
|
||||
gss := manager.gameServerSet
|
||||
asts := manager.asts
|
||||
c := manager.client
|
||||
ctx := context.Background()
|
||||
podList := manager.podList
|
||||
|
||||
maintainingGs := 0
|
||||
waitToBeDeletedGs := 0
|
||||
|
||||
for _, pod := range podList {
|
||||
|
||||
podLabels := pod.GetLabels()
|
||||
opsState := podLabels[gameKruiseV1alpha1.GameServerOpsStateKey]
|
||||
|
||||
// ops state
|
||||
switch opsState {
|
||||
case string(gameKruiseV1alpha1.WaitToDelete):
|
||||
waitToBeDeletedGs++
|
||||
case string(gameKruiseV1alpha1.Maintaining):
|
||||
maintainingGs++
|
||||
}
|
||||
}
|
||||
|
||||
status := gameKruiseV1alpha1.GameServerSetStatus{
|
||||
Replicas: *gss.Spec.Replicas,
|
||||
CurrentReplicas: int32(len(podList)),
|
||||
AvailableReplicas: asts.Status.AvailableReplicas,
|
||||
ReadyReplicas: asts.Status.ReadyReplicas,
|
||||
UpdatedReplicas: asts.Status.UpdatedReplicas,
|
||||
UpdatedReadyReplicas: asts.Status.UpdatedReadyReplicas,
|
||||
MaintainingReplicas: pointer.Int32Ptr(int32(maintainingGs)),
|
||||
WaitToBeDeletedReplicas: pointer.Int32Ptr(int32(waitToBeDeletedGs)),
|
||||
LabelSelector: asts.Status.LabelSelector,
|
||||
}
|
||||
|
||||
patchStatus := map[string]interface{}{"status": status}
|
||||
jsonPatch, err := json.Marshal(patchStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Status().Patch(ctx, gss, client.RawPatch(types.MergePatchType, jsonPatch))
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||
)
|
||||
|
||||
var (
|
||||
disableNoDeepCopy bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&disableNoDeepCopy, "disable-no-deepcopy", false, "If you are going to disable NoDeepCopy List in some controllers and webhooks.")
|
||||
}
|
||||
|
||||
// NewClient creates the default caching client with disable deepcopy list from cache.
|
||||
func NewClient(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) {
|
||||
c, err := client.New(config, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uncachedGVKs := map[schema.GroupVersionKind]struct{}{}
|
||||
for _, obj := range uncachedObjects {
|
||||
gvk, err := apiutil.GVKForObject(obj, c.Scheme())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uncachedGVKs[gvk] = struct{}{}
|
||||
}
|
||||
|
||||
return &delegatingClient{
|
||||
scheme: c.Scheme(),
|
||||
mapper: c.RESTMapper(),
|
||||
Reader: &delegatingReader{
|
||||
CacheReader: cache,
|
||||
ClientReader: c,
|
||||
noDeepCopyLister: &noDeepCopyLister{cache: cache, scheme: c.Scheme()},
|
||||
scheme: c.Scheme(),
|
||||
uncachedGVKs: uncachedGVKs,
|
||||
},
|
||||
Writer: c,
|
||||
StatusClient: c,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type delegatingClient struct {
|
||||
client.Reader
|
||||
client.Writer
|
||||
client.StatusClient
|
||||
|
||||
scheme *runtime.Scheme
|
||||
mapper meta.RESTMapper
|
||||
}
|
||||
|
||||
// Scheme returns the scheme this client is using.
|
||||
func (d *delegatingClient) Scheme() *runtime.Scheme {
|
||||
return d.scheme
|
||||
}
|
||||
|
||||
// RESTMapper returns the rest mapper this client is using.
|
||||
func (d *delegatingClient) RESTMapper() meta.RESTMapper {
|
||||
return d.mapper
|
||||
}
|
||||
|
||||
// delegatingReader forms a Reader that will cause Get and List requests for
|
||||
// unstructured types to use the ClientReader while requests for any other type
|
||||
// of object with use the CacheReader. This avoids accidentally caching the
|
||||
// entire cluster in the common case of loading arbitrary unstructured objects
|
||||
// (e.g. from OwnerReferences).
|
||||
type delegatingReader struct {
|
||||
CacheReader client.Reader
|
||||
ClientReader client.Reader
|
||||
|
||||
noDeepCopyLister *noDeepCopyLister
|
||||
|
||||
uncachedGVKs map[schema.GroupVersionKind]struct{}
|
||||
scheme *runtime.Scheme
|
||||
cacheUnstructured bool
|
||||
}
|
||||
|
||||
func (d *delegatingReader) shouldBypassCache(obj runtime.Object) (bool, error) {
|
||||
gvk, err := apiutil.GVKForObject(obj, d.scheme)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// TODO: this is producing unsafe guesses that don't actually work,
|
||||
// but it matches ~99% of the cases out there.
|
||||
if meta.IsListType(obj) {
|
||||
gvk.Kind = strings.TrimSuffix(gvk.Kind, "List")
|
||||
}
|
||||
if _, isUncached := d.uncachedGVKs[gvk]; isUncached {
|
||||
return true, nil
|
||||
}
|
||||
if !d.cacheUnstructured {
|
||||
_, isUnstructured := obj.(*unstructured.Unstructured)
|
||||
_, isUnstructuredList := obj.(*unstructured.UnstructuredList)
|
||||
return isUnstructured || isUnstructuredList, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Get retrieves an obj for a given object key from the Kubernetes Cluster.
|
||||
func (d *delegatingReader) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error {
|
||||
if isUncached, err := d.shouldBypassCache(obj); err != nil {
|
||||
return err
|
||||
} else if isUncached {
|
||||
return d.ClientReader.Get(ctx, key, obj)
|
||||
}
|
||||
return d.CacheReader.Get(ctx, key, obj)
|
||||
}
|
||||
|
||||
// List retrieves list of objects for a given namespace and list options.
|
||||
func (d *delegatingReader) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {
|
||||
if isUncached, err := d.shouldBypassCache(list); err != nil {
|
||||
return err
|
||||
} else if isUncached {
|
||||
return d.ClientReader.List(ctx, list, opts...)
|
||||
}
|
||||
if !disableNoDeepCopy && isDisableDeepCopy(opts) {
|
||||
return d.noDeepCopyLister.List(ctx, list, opts...)
|
||||
}
|
||||
return d.CacheReader.List(ctx, list, opts...)
|
||||
}
|
||||
|
||||
var DisableDeepCopy = disableDeepCopy{}
|
||||
|
||||
type disableDeepCopy struct{}
|
||||
|
||||
func (_ disableDeepCopy) ApplyToList(_ *client.ListOptions) {
|
||||
}
|
||||
|
||||
func isDisableDeepCopy(opts []client.ListOption) bool {
|
||||
for _, opt := range opts {
|
||||
if opt == DisableDeepCopy {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
apimeta "k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
toolscache "k8s.io/client-go/tools/cache"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||
)
|
||||
|
||||
type noDeepCopyLister struct {
|
||||
cache cache.Cache
|
||||
scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
func (r *noDeepCopyLister) List(ctx context.Context, out client.ObjectList, opts ...client.ListOption) error {
|
||||
startTime := time.Now()
|
||||
gvk, _, err := r.objectTypeForListObject(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indexer, err := r.getIndexerByGVK(ctx, *gvk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
listOpts := client.ListOptions{}
|
||||
listOpts.ApplyOptions(opts)
|
||||
|
||||
var objs []interface{}
|
||||
switch {
|
||||
case listOpts.FieldSelector != nil:
|
||||
field, val, requiresExact := requiresExactMatch(listOpts.FieldSelector)
|
||||
if !requiresExact {
|
||||
return fmt.Errorf("non-exact field matches are not supported by the cache")
|
||||
}
|
||||
// list all objects by the field selector. If this is namespaced and we have one, ask for the
|
||||
// namespaced index key. Otherwise, ask for the non-namespaced variant by using the fake "all namespaces"
|
||||
// namespace.
|
||||
objs, err = indexer.ByIndex(FieldIndexName(field), KeyToNamespacedKey(listOpts.Namespace, val))
|
||||
case listOpts.Namespace != "":
|
||||
objs, err = indexer.ByIndex(toolscache.NamespaceIndex, listOpts.Namespace)
|
||||
default:
|
||||
objs = indexer.List()
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var labelSel labels.Selector
|
||||
if listOpts.LabelSelector != nil {
|
||||
labelSel = listOpts.LabelSelector
|
||||
}
|
||||
limitSet := listOpts.Limit > 0
|
||||
|
||||
runtimeObjs := make([]runtime.Object, 0, len(objs))
|
||||
for _, item := range objs {
|
||||
// if the Limit option is set and the number of items
|
||||
// listed exceeds this limit, then stop reading.
|
||||
if limitSet && int64(len(runtimeObjs)) >= listOpts.Limit {
|
||||
break
|
||||
}
|
||||
obj, isObj := item.(runtime.Object)
|
||||
if !isObj {
|
||||
return fmt.Errorf("cache contained %T, which is not an Object", obj)
|
||||
}
|
||||
meta, err := apimeta.Accessor(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if labelSel != nil {
|
||||
lbls := labels.Set(meta.GetLabels())
|
||||
if !labelSel.Matches(lbls) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
runtimeObjs = append(runtimeObjs, obj)
|
||||
}
|
||||
defer func() {
|
||||
klog.V(6).Infof("Listed %v %v objects %v without DeepCopy, cost %v", gvk.GroupVersion(), gvk.Kind, len(runtimeObjs), time.Since(startTime))
|
||||
}()
|
||||
return apimeta.SetList(out, runtimeObjs)
|
||||
}
|
||||
|
||||
func (r *noDeepCopyLister) getIndexerByGVK(ctx context.Context, gvk schema.GroupVersionKind) (toolscache.Indexer, error) {
|
||||
informer, err := r.cache.GetInformerForKind(ctx, gvk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sharedInformer, ok := informer.(toolscache.SharedIndexInformer)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("informer %T from cache is not a SharedIndexInformer", informer)
|
||||
}
|
||||
return sharedInformer.GetIndexer(), nil
|
||||
}
|
||||
|
||||
// objectTypeForListObject tries to find the runtime.Object and associated GVK
|
||||
// for a single object corresponding to the passed-in list type. We need them
|
||||
// because they are used as cache map key.
|
||||
func (r *noDeepCopyLister) objectTypeForListObject(list client.ObjectList) (*schema.GroupVersionKind, runtime.Object, error) {
|
||||
gvk, err := apiutil.GVKForObject(list, r.scheme)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(gvk.Kind, "List") {
|
||||
return nil, nil, fmt.Errorf("non-list type %T (kind %q) passed as output", list, gvk)
|
||||
}
|
||||
// we need the non-list GVK, so chop off the "List" from the end of the kind
|
||||
gvk.Kind = gvk.Kind[:len(gvk.Kind)-4]
|
||||
_, isUnstructured := list.(*unstructured.UnstructuredList)
|
||||
var cacheTypeObj runtime.Object
|
||||
if isUnstructured {
|
||||
u := &unstructured.Unstructured{}
|
||||
u.SetGroupVersionKind(gvk)
|
||||
cacheTypeObj = u
|
||||
} else {
|
||||
itemsPtr, err := apimeta.GetItemsPtr(list)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// http://knowyourmeme.com/memes/this-is-fine
|
||||
elemType := reflect.Indirect(reflect.ValueOf(itemsPtr)).Type().Elem()
|
||||
if elemType.Kind() != reflect.Ptr {
|
||||
elemType = reflect.PtrTo(elemType)
|
||||
}
|
||||
|
||||
cacheTypeValue := reflect.Zero(elemType)
|
||||
var ok bool
|
||||
cacheTypeObj, ok = cacheTypeValue.Interface().(runtime.Object)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("cannot get cache for %T, its element %T is not a runtime.Object", list, cacheTypeValue.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
return &gvk, cacheTypeObj, nil
|
||||
}
|
||||
|
||||
// requiresExactMatch checks if the given field selector is of the form `k=v` or `k==v`.
|
||||
func requiresExactMatch(sel fields.Selector) (field, val string, required bool) {
|
||||
reqs := sel.Requirements()
|
||||
if len(reqs) != 1 {
|
||||
return "", "", false
|
||||
}
|
||||
req := reqs[0]
|
||||
if req.Operator != selection.Equals && req.Operator != selection.DoubleEquals {
|
||||
return "", "", false
|
||||
}
|
||||
return req.Field, req.Value, true
|
||||
}
|
||||
|
||||
// FieldIndexName constructs the name of the index over the given field,
|
||||
// for use with an indexer.
|
||||
func FieldIndexName(field string) string {
|
||||
return "field:" + field
|
||||
}
|
||||
|
||||
// noNamespaceNamespace is used as the "namespace" when we want to list across all namespaces.
|
||||
const allNamespacesNamespace = "__all_namespaces"
|
||||
|
||||
// KeyToNamespacedKey prefixes the given index key with a namespace
|
||||
// for use in field selector indexes.
|
||||
func KeyToNamespacedKey(ns string, baseKey string) string {
|
||||
if ns != "" {
|
||||
return ns + "/" + baseKey
|
||||
}
|
||||
return allNamespacesNamespace + "/" + baseKey
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/klog/v2"
|
||||
"time"
|
||||
|
||||
"github.com/openkruise/kruise-game/pkg/client"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||
)
|
||||
|
||||
var (
|
||||
internalScheme = runtime.NewScheme()
|
||||
|
||||
errKindNotFound = fmt.Errorf("kind not found in group version resources")
|
||||
backOff = wait.Backoff{
|
||||
Steps: 4,
|
||||
Duration: 500 * time.Millisecond,
|
||||
Factor: 5.0,
|
||||
Jitter: 0.1,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = AddToScheme(internalScheme)
|
||||
}
|
||||
|
||||
func DiscoverGVK(gvk schema.GroupVersionKind) bool {
|
||||
genericClient := client.GetGenericClient()
|
||||
if genericClient == nil {
|
||||
return true
|
||||
}
|
||||
discoveryClient := genericClient.DiscoveryClient
|
||||
|
||||
startTime := time.Now()
|
||||
err := retry.OnError(backOff, func(err error) bool { return true }, func() error {
|
||||
resourceList, err := discoveryClient.ServerResourcesForGroupVersion(gvk.GroupVersion().String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range resourceList.APIResources {
|
||||
if r.Kind == gvk.Kind {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errKindNotFound
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if err == errKindNotFound {
|
||||
klog.Warningf("Not found kind %s in group version %s, waiting time %s", gvk.Kind, gvk.GroupVersion().String(), time.Since(startTime))
|
||||
return false
|
||||
}
|
||||
|
||||
// This might be caused by abnormal apiserver or etcd, ignore it
|
||||
klog.Errorf("Failed to find resources in group version %s: %v, waiting time %s", gvk.GroupVersion().String(), err, time.Since(startTime))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func DiscoverObject(obj runtime.Object) bool {
|
||||
gvk, err := apiutil.GVKForObject(obj, internalScheme)
|
||||
if err != nil {
|
||||
klog.Warningf("Not recognized object %T in scheme: %v", obj, err)
|
||||
return false
|
||||
}
|
||||
return DiscoverGVK(gvk)
|
||||
}
|
||||
|
||||
// AddToSchemes may be used to add all resources defined in the project to a Scheme
|
||||
var AddToSchemes runtime.SchemeBuilder
|
||||
|
||||
// AddToScheme adds all Resources to the Scheme
|
||||
func AddToScheme(s *runtime.Scheme) error {
|
||||
return AddToSchemes.AddToScheme(s)
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
appspub "github.com/openkruise/kruise-api/apps/pub"
|
||||
kruiseV1beta1 "github.com/openkruise/kruise-api/apps/v1beta1"
|
||||
gameKruiseV1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
apps "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DeleteSequenceGs []corev1.Pod
|
||||
|
||||
func (dg DeleteSequenceGs) Len() int {
|
||||
return len(dg)
|
||||
}
|
||||
|
||||
func (dg DeleteSequenceGs) Swap(i, j int) {
|
||||
dg[i], dg[j] = dg[j], dg[i]
|
||||
}
|
||||
|
||||
func (dg DeleteSequenceGs) Less(i, j int) bool {
|
||||
iLabels := dg[i].GetLabels()
|
||||
jLabels := dg[j].GetLabels()
|
||||
iOpsState := iLabels[gameKruiseV1alpha1.GameServerOpsStateKey]
|
||||
jOpsState := jLabels[gameKruiseV1alpha1.GameServerOpsStateKey]
|
||||
iDeletionPriority := iLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey]
|
||||
jDeletionPriority := jLabels[gameKruiseV1alpha1.GameServerDeletePriorityKey]
|
||||
|
||||
// OpsState
|
||||
if iOpsState != jOpsState {
|
||||
return opsStateDeletePrority(iOpsState) > opsStateDeletePrority(jOpsState)
|
||||
}
|
||||
// Deletion Priority
|
||||
if iDeletionPriority != jDeletionPriority {
|
||||
iDeletionPriorityInt, _ := strconv.Atoi(iDeletionPriority)
|
||||
jDeletionPriorityInt, _ := strconv.Atoi(jDeletionPriority)
|
||||
return iDeletionPriorityInt > jDeletionPriorityInt
|
||||
}
|
||||
// Index Number
|
||||
return GetIndexFromGsName(dg[i].GetName()) > GetIndexFromGsName(dg[j].GetName())
|
||||
}
|
||||
|
||||
func opsStateDeletePrority(opsState string) int {
|
||||
switch opsState {
|
||||
case string(gameKruiseV1alpha1.WaitToDelete):
|
||||
return 1
|
||||
case string(gameKruiseV1alpha1.None):
|
||||
return 0
|
||||
case string(gameKruiseV1alpha1.Maintaining):
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetIndexFromGsName(gsName string) int {
|
||||
temp := strings.Split(gsName, "-")
|
||||
index, _ := strconv.Atoi(temp[len(temp)-1])
|
||||
return index
|
||||
}
|
||||
|
||||
func GetIndexListFromPodList(podList []corev1.Pod) []int {
|
||||
var indexList []int
|
||||
for i := 0; i < len(podList); i++ {
|
||||
indexList = append(indexList, GetIndexFromGsName(podList[i].GetName()))
|
||||
}
|
||||
return indexList
|
||||
}
|
||||
|
||||
func GetIndexListFromGsList(gsList []gameKruiseV1alpha1.GameServer) []int {
|
||||
var indexList []int
|
||||
for i := 0; i < len(gsList); i++ {
|
||||
indexList = append(indexList, GetIndexFromGsName(gsList[i].GetName()))
|
||||
}
|
||||
return indexList
|
||||
}
|
||||
|
||||
func GetNewAstsFromGss(gss *gameKruiseV1alpha1.GameServerSet, asts *kruiseV1beta1.StatefulSet) *kruiseV1beta1.StatefulSet {
|
||||
// default: set ParallelPodManagement
|
||||
asts.Spec.PodManagementPolicy = apps.ParallelPodManagement
|
||||
|
||||
// set pod labels
|
||||
podLabels := gss.Spec.GameServerTemplate.GetLabels()
|
||||
if podLabels == nil {
|
||||
podLabels = make(map[string]string)
|
||||
}
|
||||
podLabels[gameKruiseV1alpha1.GameServerOwnerGssKey] = gss.GetName()
|
||||
asts.Spec.Template.SetLabels(podLabels)
|
||||
|
||||
// set pod annotations
|
||||
podAnnotations := gss.Spec.GameServerTemplate.GetAnnotations()
|
||||
asts.Spec.Template.SetAnnotations(podAnnotations)
|
||||
|
||||
// set template spec
|
||||
asts.Spec.Template.Spec = gss.Spec.GameServerTemplate.Spec
|
||||
// default: add InPlaceUpdateReady condition
|
||||
readinessGates := gss.Spec.GameServerTemplate.Spec.ReadinessGates
|
||||
readinessGates = append(readinessGates, corev1.PodReadinessGate{ConditionType: appspub.InPlaceUpdateReady})
|
||||
asts.Spec.Template.Spec.ReadinessGates = readinessGates
|
||||
|
||||
// set VolumeClaimTemplates
|
||||
asts.Spec.VolumeClaimTemplates = gss.Spec.GameServerTemplate.VolumeClaimTemplates
|
||||
|
||||
// set ScaleStrategy
|
||||
asts.Spec.ScaleStrategy = &kruiseV1beta1.StatefulSetScaleStrategy{
|
||||
MaxUnavailable: gss.Spec.ScaleStrategy.MaxUnavailable,
|
||||
}
|
||||
|
||||
// set UpdateStrategy
|
||||
asts.Spec.UpdateStrategy.Type = gss.Spec.UpdateStrategy.Type
|
||||
var rollingUpdateStatefulSetStrategy *kruiseV1beta1.RollingUpdateStatefulSetStrategy
|
||||
if gss.Spec.UpdateStrategy.RollingUpdate != nil {
|
||||
asts.Spec.UpdateStrategy.Type = apps.RollingUpdateStatefulSetStrategyType
|
||||
rollingUpdateStatefulSetStrategy = &kruiseV1beta1.RollingUpdateStatefulSetStrategy{
|
||||
Partition: gss.Spec.UpdateStrategy.RollingUpdate.Partition,
|
||||
MaxUnavailable: gss.Spec.UpdateStrategy.RollingUpdate.MaxUnavailable,
|
||||
PodUpdatePolicy: gss.Spec.UpdateStrategy.RollingUpdate.PodUpdatePolicy,
|
||||
Paused: gss.Spec.UpdateStrategy.RollingUpdate.Paused,
|
||||
InPlaceUpdateStrategy: gss.Spec.UpdateStrategy.RollingUpdate.InPlaceUpdateStrategy,
|
||||
MinReadySeconds: gss.Spec.UpdateStrategy.RollingUpdate.MinReadySeconds,
|
||||
UnorderedUpdate: &kruiseV1beta1.UnorderedUpdateStrategy{
|
||||
PriorityStrategy: &appspub.UpdatePriorityStrategy{
|
||||
OrderPriority: []appspub.UpdatePriorityOrderTerm{
|
||||
{
|
||||
OrderedKey: gameKruiseV1alpha1.GameServerUpdatePriorityKey,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
asts.Spec.UpdateStrategy.RollingUpdate = rollingUpdateStatefulSetStrategy
|
||||
|
||||
return asts
|
||||
}
|
||||
|
||||
type astsToUpdate struct {
|
||||
UpdateStrategy gameKruiseV1alpha1.UpdateStrategy
|
||||
Template gameKruiseV1alpha1.GameServerTemplate
|
||||
}
|
||||
|
||||
func GetAstsHash(gss *gameKruiseV1alpha1.GameServerSet) string {
|
||||
return GetHash(astsToUpdate{
|
||||
UpdateStrategy: gss.Spec.UpdateStrategy,
|
||||
Template: gss.Spec.GameServerTemplate,
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
gameKruiseV1alpha1 "github.com/openkruise/kruise-game/apis/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetIndexFromGsName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
result int
|
||||
}{
|
||||
{
|
||||
name: "xxx-23-3",
|
||||
result: 3,
|
||||
},
|
||||
{
|
||||
name: "www_3-12",
|
||||
result: 12,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
actual := GetIndexFromGsName(test.name)
|
||||
expect := test.result
|
||||
if expect != actual {
|
||||
t.Errorf("expect %v but got %v", expect, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteSequenceGs(t *testing.T) {
|
||||
tests := []struct {
|
||||
before []corev1.Pod
|
||||
after []int
|
||||
}{
|
||||
{
|
||||
before: []corev1.Pod{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "xxx-0",
|
||||
Labels: map[string]string{
|
||||
gameKruiseV1alpha1.GameServerOpsStateKey: string(gameKruiseV1alpha1.None),
|
||||
gameKruiseV1alpha1.GameServerDeletePriorityKey: "10",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "xxx-1",
|
||||
Labels: map[string]string{
|
||||
gameKruiseV1alpha1.GameServerOpsStateKey: string(gameKruiseV1alpha1.Maintaining),
|
||||
gameKruiseV1alpha1.GameServerDeletePriorityKey: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "xxx-2",
|
||||
Labels: map[string]string{
|
||||
gameKruiseV1alpha1.GameServerOpsStateKey: string(gameKruiseV1alpha1.WaitToDelete),
|
||||
gameKruiseV1alpha1.GameServerDeletePriorityKey: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "xxx-3",
|
||||
Labels: map[string]string{
|
||||
gameKruiseV1alpha1.GameServerOpsStateKey: string(gameKruiseV1alpha1.None),
|
||||
gameKruiseV1alpha1.GameServerDeletePriorityKey: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
after: []int{2, 0, 3, 1},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
after := DeleteSequenceGs(test.before)
|
||||
sort.Sort(after)
|
||||
expect := test.after
|
||||
actual := GetIndexListFromPodList(after)
|
||||
for i := 0; i < len(actual); i++ {
|
||||
if expect[i] != actual[i] {
|
||||
t.Errorf("expect %v but got %v", expect, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"hash"
|
||||
"hash/fnv"
|
||||
)
|
||||
|
||||
func GetHash(objectToWrite interface{}) string {
|
||||
hf := fnv.New32()
|
||||
DeepHashObject(hf, objectToWrite)
|
||||
return fmt.Sprint(hf.Sum32())
|
||||
}
|
||||
|
||||
// DeepHashObject writes specified object to hash using the spew library
|
||||
// which follows pointers and prints actual values of the nested objects
|
||||
// ensuring the hash does not change when a pointer changes.
|
||||
func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) {
|
||||
hasher.Reset()
|
||||
printer := spew.ConfigState{
|
||||
Indent: " ",
|
||||
SortKeys: true,
|
||||
DisableMethods: true,
|
||||
SpewKeys: true,
|
||||
}
|
||||
printer.Fprintf(hasher, "%#v", objectToWrite)
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetHash(t *testing.T) {
|
||||
tests := []struct {
|
||||
objectA interface{}
|
||||
objectB interface{}
|
||||
result bool
|
||||
}{
|
||||
{
|
||||
objectA: corev1.PodTemplateSpec{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "containerA",
|
||||
Image: "nginx:latest",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
objectB: corev1.PodTemplateSpec{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "containerB",
|
||||
Image: "nginx:latest",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
actual := GetHash(test.objectA) == GetHash(test.objectB)
|
||||
expect := test.result
|
||||
if expect != actual {
|
||||
t.Errorf("expect %v but got %v", expect, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
Copyright 2022 The Kruise Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func IsNumInList(num int, list []int) bool {
|
||||
for _, n := range list {
|
||||
if num == n {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsStringInList(str string, list []string) bool {
|
||||
for _, s := range list {
|
||||
if s == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetSliceInANotInB(a, b []int) []int {
|
||||
var ret []int
|
||||
for _, aa := range a {
|
||||
if !IsNumInList(aa, b) {
|
||||
ret = append(ret, aa)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetSliceInAandInB(a, b []int) []int {
|
||||
var ret []int
|
||||
for _, aa := range a {
|
||||
if IsNumInList(aa, b) {
|
||||
ret = append(ret, aa)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func IntSliceToString(number []int, delimiter string) string {
|
||||
return strings.Trim(strings.Replace(fmt.Sprint(number), " ", delimiter, -1), "[]")
|
||||
}
|
||||
|
||||
func StringToIntSlice(str string, delimiter string) []int {
|
||||
if str == "" {
|
||||
return nil
|
||||
}
|
||||
strList := strings.Split(str, delimiter)
|
||||
if len(strList) == 0 {
|
||||
return nil
|
||||
}
|
||||
var retSlice []int
|
||||
for _, item := range strList {
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
val, err := strconv.Atoi(item)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
retSlice = append(retSlice, val)
|
||||
}
|
||||
return retSlice
|
||||
}
|
||||
|
||||
func IsSliceEqual(a, b []int) bool {
|
||||
if (a == nil) != (b == nil) {
|
||||
return false
|
||||
}
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
sort.Ints(a)
|
||||
sort.Ints(b)
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func RemoveRepeat(nums []int) []int {
|
||||
var result []int
|
||||
tempMap := map[int]byte{}
|
||||
for _, num := range nums {
|
||||
beforeLen := len(tempMap)
|
||||
tempMap[num] = 0
|
||||
if len(tempMap) == beforeLen {
|
||||
continue
|
||||
}
|
||||
result = append(result, num)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func IsRepeat(nums []int) bool {
|
||||
tempMap := map[int]byte{}
|
||||
for _, num := range nums {
|
||||
beforeLen := len(tempMap)
|
||||
tempMap[num] = 0
|
||||
if len(tempMap) == beforeLen {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsHasNegativeNum(nums []int) bool {
|
||||
for _, num := range nums {
|
||||
if num < 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue