Skip to content

Commit

Permalink
Merge branch 'master' into issue-455
Browse files Browse the repository at this point in the history
  • Loading branch information
Yingxin-Jiang authored Feb 11, 2019
2 parents 70f9383 + f202b29 commit e00db9c
Show file tree
Hide file tree
Showing 20 changed files with 668 additions and 150 deletions.
18 changes: 18 additions & 0 deletions build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ GCP_BUCKET_CHARTS ?= agones-chart
MINIKUBE_PROFILE ?= agones
GO_BUILD_TAGS ?= none

# Specify stress test level 1..100
# STRESS_TEST_LEVEL=n requires capacity between 50*n up to 100*n simple-udp Game Servers.
STRESS_TEST_LEVEL=20

# kind cluster name to use
KIND_PROFILE ?= agones
KIND_CONTAINER_NAME=kind-$(KIND_PROFILE)-control-plane
Expand Down Expand Up @@ -217,6 +221,16 @@ test-e2e: $(ensure-build-image)
--gameserver-image=$(GS_TEST_IMAGE) \
--pullsecret=$(IMAGE_PULL_SECRET)

# Runs end-to-end stress tests on the current configured cluster
# For minikube user the minikube-stress-test-e2e targets
stress-test-e2e: $(ensure-build-image)
$(GO_TEST) $(agones_package)/test/e2e $(ARGS) $(GO_E2E_TEST_ARGS) \
-timeout 1h \
-run '.*StressTest.*' \
--gameserver-image=$(GS_TEST_IMAGE) \
--pullsecret=$(IMAGE_PULL_SECRET) \
--stress $(STRESS_TEST_LEVEL)

# Run test on install yaml - make sure there is no change
# mostly this is for CI
test-install-yaml:
Expand Down Expand Up @@ -610,6 +624,10 @@ minikube-transfer-image:
minikube-test-e2e: DOCKER_RUN_ARGS=--network=host -v $(minikube_cert_mount)
minikube-test-e2e: minikube-agones-profile test-e2e

# Runs stress tests against our minikube
minikube-stress-test-e2e: DOCKER_RUN_ARGS=--network=host -v $(minikube_cert_mount)
minikube-stress-test-e2e: minikube-agones-profile stress-test-e2e

# prometheus on minkube
# we have to disable PVC as it's not supported on minkube.
minikube-setup-prometheus:
Expand Down
4 changes: 2 additions & 2 deletions cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ func main() {

allocationMutex := &sync.Mutex{}

gsController := gameservers.NewController(wh, health, allocationMutex,
gsController := gameservers.NewController(wh, health,
ctlConf.MinPort, ctlConf.MaxPort, ctlConf.SidecarImage, ctlConf.AlwaysPullSidecar,
ctlConf.SidecarCPURequest, ctlConf.SidecarCPULimit,
kubeClient, kubeInformerFactory, extClient, agonesClient, agonesInformerFactory)
gsSetController := gameserversets.NewController(wh, health, allocationMutex,
gsSetController := gameserversets.NewController(wh, health,
kubeClient, extClient, agonesClient, agonesInformerFactory)
fleetController := fleets.NewController(wh, health, kubeClient, extClient, agonesClient, agonesInformerFactory)
faController := fleetallocation.NewController(wh, allocationMutex,
Expand Down
34 changes: 34 additions & 0 deletions examples/simple-udp/dev-gameserver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2019 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: "stable.agones.dev/v1alpha1"
kind: GameServer
metadata:
name: local-simple-udp
generateName: "simple-udp-"
annotations:
# Causes Agones to register your local game server at 192.1.1.2, replace with your server's IP address.
stable.agones.dev/dev-address: "192.1.1.2"
spec:
ports:
- name: default
portPolicy: "static"
hostPort: 17654
containerPort: 17654
# The following is ignored but required due to validation.
template:
spec:
containers:
- name: simple-udp
image: gcr.io/agones-images/udp-server:0.5
84 changes: 62 additions & 22 deletions pkg/apis/stable/v1alpha1/gameserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package v1alpha1
import (
"encoding/json"
"fmt"
"net"

"github.com/mattbaird/jsonpatch"

Expand Down Expand Up @@ -76,6 +77,9 @@ const (
GameServerContainerAnnotation = stable.GroupName + "/container"
// SidecarServiceAccountName is the default service account for managing access to get/update GameServers
SidecarServiceAccountName = "agones-sdk"
// DevAddressAnnotation is an annotation to indicate that a GameServer hosted outside of Agones.
// A locally hosted GameServer is not managed by Agones it is just simply registered.
DevAddressAnnotation = "stable.agones.dev/dev-address"
)

var (
Expand Down Expand Up @@ -247,40 +251,76 @@ func (gs *GameServer) applySchedulingDefaults() {
// the returned array
func (gs *GameServer) Validate() (bool, []metav1.StatusCause) {
var causes []metav1.StatusCause
// make sure the host port is specified if this is a development server
devAddress, hasDevAddress := gs.GetDevAddress()

// make sure a name is specified when there is multiple containers in the pod.
if len(gs.Spec.Container) == 0 && len(gs.Spec.Template.Spec.Containers) > 1 {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueInvalid,
Field: "container",
Message: "Container is required when using multiple containers in the pod template",
})
}
if hasDevAddress {
// verify that the value is a valid IP address.
if net.ParseIP(devAddress) == nil {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueInvalid,
Field: fmt.Sprintf("annotations.%s", DevAddressAnnotation),
Message: fmt.Sprintf("Value '%s' of annotation '%s' must be a valid IP address.", DevAddressAnnotation, devAddress),
})
}

// no host port when using dynamic PortPolicy
for _, p := range gs.Spec.Ports {
if p.HostPort > 0 && p.PortPolicy == Dynamic {
for _, p := range gs.Spec.Ports {
if p.HostPort == 0 {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueRequired,
Field: fmt.Sprintf("%s.hostPort", p.Name),
Message: fmt.Sprintf("HostPort is required if GameServer is annotated with %s", DevAddressAnnotation),
})
}
if p.PortPolicy != Static {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueRequired,
Field: fmt.Sprintf("%s.portPolicy", p.Name),
Message: fmt.Sprintf("PortPolicy must be Static"),
})
}
}
} else {
// make sure a name is specified when there is multiple containers in the pod.
if len(gs.Spec.Container) == 0 && len(gs.Spec.Template.Spec.Containers) > 1 {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueInvalid,
Field: fmt.Sprintf("%s.hostPort", p.Name),
Message: "HostPort cannot be specified with a Dynamic PortPolicy",
Field: "container",
Message: "Container is required when using multiple containers in the pod template",
})
}
}

// make sure the container value points to a valid container
_, _, err := gs.FindGameServerContainer()
if err != nil {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueInvalid,
Field: "container",
Message: err.Error(),
})
// no host port when using dynamic PortPolicy
for _, p := range gs.Spec.Ports {
if p.HostPort > 0 && p.PortPolicy == Dynamic {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueInvalid,
Field: fmt.Sprintf("%s.hostPort", p.Name),
Message: "HostPort cannot be specified with a Dynamic PortPolicy",
})
}
}

// make sure the container value points to a valid container
_, _, err := gs.FindGameServerContainer()
if err != nil {
causes = append(causes, metav1.StatusCause{
Type: metav1.CauseTypeFieldValueInvalid,
Field: "container",
Message: err.Error(),
})
}
}

return len(causes) == 0, causes
}

// GetDevAddress returns the address for game server.
func (gs *GameServer) GetDevAddress() (string, bool) {
devAddress, hasDevAddress := gs.ObjectMeta.Annotations[DevAddressAnnotation]
return devAddress, hasDevAddress
}

// FindGameServerContainer returns the container that is specified in
// spec.gameServer.container. Returns the index and the value.
// Returns an error if not found
Expand Down
51 changes: 51 additions & 0 deletions pkg/apis/stable/v1alpha1/gameserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package v1alpha1

import (
"fmt"
"testing"

"agones.dev/agones/pkg/apis/stable"
Expand All @@ -23,6 +24,10 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
ipFixture = "127.1.1.1"
)

func TestGameServerFindGameServerContainer(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -239,6 +244,26 @@ func TestGameServerValidate(t *testing.T) {
assert.Contains(t, fields, "container")
assert.Contains(t, fields, "main.hostPort")
assert.Equal(t, causes[0].Type, metav1.CauseTypeFieldValueInvalid)

gs = GameServer{
ObjectMeta: metav1.ObjectMeta{
Name: "dev-game",
Namespace: "default",
Annotations: map[string]string{DevAddressAnnotation: "invalid-ip"},
},
Spec: GameServerSpec{
Ports: []GameServerPort{{Name: "main", ContainerPort: 7777, PortPolicy: Static}},
},
}
ok, causes = gs.Validate()
for _, f := range causes {
fields = append(fields, f.Field)
}
assert.False(t, ok)
assert.Len(t, causes, 2)
assert.Contains(t, fields, fmt.Sprintf("annotations.%s", DevAddressAnnotation))
assert.Contains(t, fields, "main.hostPort")
assert.Equal(t, causes[1].Type, metav1.CauseTypeFieldValueRequired)
}

func TestGameServerPod(t *testing.T) {
Expand Down Expand Up @@ -369,3 +394,29 @@ func TestGameServerPatch(t *testing.T) {

assert.Contains(t, string(patch), `{"op":"replace","path":"/spec/container","value":"bear"}`)
}
func TestGetDevAddress(t *testing.T) {
devGs := &GameServer{
ObjectMeta: metav1.ObjectMeta{
Name: "dev-game",
Namespace: "default",
Annotations: map[string]string{DevAddressAnnotation: ipFixture},
},
Spec: GameServerSpec{
Ports: []GameServerPort{{HostPort: 7777, PortPolicy: Static}},
Template: corev1.PodTemplateSpec{Spec: corev1.PodSpec{
Containers: []corev1.Container{{Name: "container", Image: "container/image"}},
},
},
},
}

devAddress, isDev := devGs.GetDevAddress()
assert.True(t, isDev, "dev-game should had a dev-address")
assert.Equal(t, ipFixture, devAddress, "dev-address IP address should be 127.1.1.1")

regularGs := devGs.DeepCopy()
regularGs.ObjectMeta.Annotations = map[string]string{}
devAddress, isDev = regularGs.GetDevAddress()
assert.False(t, isDev, "dev-game should NOT have a dev-address")
assert.Equal(t, "", devAddress, "dev-address IP address should be 127.1.1.1")
}
Loading

0 comments on commit e00db9c

Please sign in to comment.