From fb11d704bbe537280190c8b9cba7d2e15a5db493 Mon Sep 17 00:00:00 2001 From: Mark Mandel Date: Wed, 6 Dec 2017 15:34:55 -0800 Subject: [PATCH] install.yaml to install Agon. Install CRD and Controller via yaml is cleaner, and also make it far easier to uninstall (kubectl delete -f) Added some documentation around installation, etc. Closes #17 --- README.md | 13 +++++ build/Makefile | 2 +- build/README.md | 46 +++++++++++----- gameservers/controller/controller.go | 27 ++-------- gameservers/controller/controller_test.go | 54 +++---------------- .../deployment.yaml => install.yaml | 22 ++++++-- pkg/apis/stable/v1alpha1/crd.go | 45 ---------------- 7 files changed, 76 insertions(+), 133 deletions(-) rename gameservers/controller/deployment.yaml => install.yaml (63%) delete mode 100644 pkg/apis/stable/v1alpha1/crd.go diff --git a/README.md b/README.md index 573bc57593..b769cd9416 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,19 @@ This software is currenty alpha, and subject to change. Not to be used in produc - Simple example code - Documentation of the above +## Requirements +- Requires a Kubernetes cluster of version 1.8+ +- Open the firewall access for the range of ports that Game Servers can be connected to in the cluster. + +## Installation +`kubectl apply -f install.yaml` + +If you are running your own Docker repository, make a local copy of install.yaml +and edit to match your settings. + +## Usage +See the [examples](./examples) directory + ## Development See the tools in the [build](build/README.md) directory for testing and building Agon. diff --git a/build/Makefile b/build/Makefile index 221d1eac24..6ff0420392 100644 --- a/build/Makefile +++ b/build/Makefile @@ -76,7 +76,7 @@ build-gameservers-sidecar-binary: ensure-image build-gameservers-sidecar-image: ensure-image build-gameservers-sidecar-binary docker build $(agon_path)/gameservers/sidecar/ --tag=$(sidecar_tag) -# Generate the gRPC sidecar Server +# Generate the gRPC sidecar Server and Client gen-gameservers-sidecar-grpc: ensure-image docker run --rm $(common_mounts) --entrypoint="/root/gen-grpc-go.sh" $(TAG) diff --git a/build/README.md b/build/README.md index 38bc66af63..392687863c 100644 --- a/build/README.md +++ b/build/README.md @@ -1,34 +1,52 @@ # Build -Tooling for building and developing against Agon, with only dependency being [Docker](https://www.docker.com). +Tooling for building and developing against Agon, with only dependencies being +[Make](https://www.gnu.org/software/make/) and [Docker](https://www.docker.com) -Rather than installing all the dependencies locally, you can test and build Agon using the Docker image that can -be build from the Dockerfile based image in this directory. There is an accompanying Makefile for all the common +Rather than installing all the dependencies locally, you can test and build Agon using the Docker image is +built from the Dockerfile based image in this directory. There is an accompanying Makefile for all the common tasks you may wish to accomplish. +## GOPATH + +This project should be cloned to the directory `$GOPATH/src/github.com/agonio/agon` +for when you are developing locally, and require package resolution in your IDE. + +This is not required if you are simply building using the `make` targets + ## Make Targets -## Development Targets +All targets will create the build image if it is not present. + +### Development Targets Targets for developing with the build image -### `make build-gameservers-controller-image` +#### `make build` +Build all the images required for Agon + +#### `make test` +Run all tests + +### `make shell` +Run a bash shell with the developer tools (go tooling, kubectl, etc) and source code in it. + +### `make godoc` +Run a container with godoc (search index enabled) + +#### `make build-gameservers-controller-image` Compile the gameserver controller and then build the docker image -### `make build-gameservers-sidecar-image` +#### `make build-gameservers-sidecar-image` Compile the gameserver sidecar and then build the docker image -### `make test` -Run all tests - -### `make gen-client` +#### `make gen-crd-client` Generate the Custom Resource Definition client(s) -### `make shell` -Run a bash shell with the developer tools ad source code in it. -Also creates the image if it doesn't exist +#### `make gen-gameservers-sidecar-grpc` +Generate the gRPC sidecar Server and Client -## Build Image Targets +### Build Image Targets Targets for building the build image diff --git a/gameservers/controller/controller.go b/gameservers/controller/controller.go index 942c88bb80..1ac56f8e1b 100644 --- a/gameservers/controller/controller.go +++ b/gameservers/controller/controller.go @@ -110,11 +110,7 @@ func NewController(sidecarImage string, func (c Controller) Run(threadiness int, stop <-chan struct{}) error { defer c.queue.ShutDown() - err := c.createCRDIfDoesntExist() - if err != nil { - return err - } - err = c.waitForEstablishedCRD() + err := c.waitForEstablishedCRD() if err != nil { return err } @@ -383,28 +379,11 @@ func (c Controller) externalIP(pod *corev1.Pod) (string, error) { return "", errors.Errorf("Could not find an external ip for Node: #%s", node.ObjectMeta.Name) } -// createCRDIfDoesntExist creates the GameServer CRD if it doesn't exist. -// only returns an error if something goes wrong -func (c Controller) createCRDIfDoesntExist() error { - crd, err := c.crdGetter.Create(stablev1alpha1.GameServerCRD()) - if err != nil { - if !k8serrors.IsAlreadyExists(err) { - return errors.Wrap(err, "error creating gameserver custom resource definition") - } - logrus.Info("gameserver custom resource definition already exists.") - } else { - logrus.WithField("crd", crd).Info("gameserver custom resource definition created successfully") - } - - return nil -} - // waitForEstablishedCRD blocks until CRD comes to an Established state. // Has a deadline of 60 seconds for this to occur. func (c Controller) waitForEstablishedCRD() error { - crdName := stablev1alpha1.GameServerCRD().ObjectMeta.Name return wait.PollImmediate(500*time.Millisecond, 60*time.Second, func() (done bool, err error) { - crd, err := c.crdGetter.Get(crdName, metav1.GetOptions{}) + crd, err := c.crdGetter.Get("gameservers.stable.agon.io", metav1.GetOptions{}) if err != nil { return false, err } @@ -413,7 +392,7 @@ func (c Controller) waitForEstablishedCRD() error { switch cond.Type { case apiv1beta1.Established: if cond.Status == apiv1beta1.ConditionTrue { - logrus.WithField("crd", crd).Info("gameserver custom resource definition is established") + logrus.WithField("crd", crd).Info("GameServer custom resource definition is established") return true, err } } diff --git a/gameservers/controller/controller_test.go b/gameservers/controller/controller_test.go index 161cdcae8f..90543c8955 100644 --- a/gameservers/controller/controller_test.go +++ b/gameservers/controller/controller_test.go @@ -15,7 +15,6 @@ package main import ( - "errors" "sync" "testing" "time" @@ -43,44 +42,6 @@ import ( "k8s.io/client-go/tools/cache" ) -func TestControllerCreateCRDIfDoesntExist(t *testing.T) { - t.Parallel() - - t.Run("CRD doesn't exist", func(t *testing.T) { - con, mocks := newFakeController() - var crd *v1beta1.CustomResourceDefinition - mocks.extClient.AddReactor("create", "customresourcedefinitions", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { - a := action.(k8stesting.CreateAction) - crd = a.GetObject().(*v1beta1.CustomResourceDefinition) - return true, nil, nil - }) - - err := con.createCRDIfDoesntExist() - assert.Nil(t, err, "CRD Should be created: %v", err) - assert.Equal(t, v1alpha1.GameServerCRD(), crd) - }) - - t.Run("CRD does exist", func(t *testing.T) { - con, mocks := newFakeController() - mocks.extClient.AddReactor("create", "customresourcedefinitions", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { - err = k8serrors.NewAlreadyExists(schema.GroupResource{Group: stable.GroupName, Resource: "gameserver"}, "Foo") - return true, nil, err - }) - err := con.createCRDIfDoesntExist() - assert.Nil(t, err, "CRD Should not be created, but not throw an error: %v", err) - }) - - t.Run("Something bad happens", func(t *testing.T) { - con, mocks := newFakeController() - fixture := errors.New("this is a custom error") - mocks.extClient.AddReactor("create", "customresourcedefinitions", func(action k8stesting.Action) (bool, runtime.Object, error) { - return true, nil, fixture - }) - err := con.createCRDIfDoesntExist() - assert.NotNil(t, err, "Custom error should be returned") - }) -} - func TestControllerWaitForEstablishedCRD(t *testing.T) { t.Parallel() crd := newEstablishedCRD() @@ -579,13 +540,14 @@ func newSingeContainerSpec() v1alpha1.GameServerSpec { } func newEstablishedCRD() *v1beta1.CustomResourceDefinition { - crd := v1alpha1.GameServerCRD() - crd.Status.Conditions = []v1beta1.CustomResourceDefinitionCondition{{ - Type: v1beta1.Established, - Status: v1beta1.ConditionTrue, - }} - - return crd + return &v1beta1.CustomResourceDefinition{ + Status: v1beta1.CustomResourceDefinitionStatus{ + Conditions: []v1beta1.CustomResourceDefinitionCondition{{ + Type: v1beta1.Established, + Status: v1beta1.ConditionTrue, + }}, + }, + } } func startInformers(c *Controller, mocks mocks) chan struct{} { diff --git a/gameservers/controller/deployment.yaml b/install.yaml similarity index 63% rename from gameservers/controller/deployment.yaml rename to install.yaml index 4bed2fa8ed..24c1b6ff97 100644 --- a/gameservers/controller/deployment.yaml +++ b/install.yaml @@ -11,7 +11,21 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: gameservers.stable.agon.io +spec: + group: stable.agon.io + version: v1alpha1 + scope: Namespaced + names: + kind: GameServer + plural: gameservers + shortNames: + - gs + singular: gameserver +--- apiVersion: extensions/v1beta1 kind: Deployment metadata: @@ -28,7 +42,9 @@ spec: containers: - name: gameservers-controller image: gcr.io/agon-images/gameservers-controller:0.1 - imagePullPolicy: Always + imagePullPolicy: Always # remove/set to IfNotPresent for production env: - name: ALWAYS_PULL_SIDECAR - value: "true" + value: "true" # set to false for production + # - name: SIDECAR # overwrite the GameServer sidecar image that is used + # value: gcr.io/agon-images/gameservers-sidecar:0.1 diff --git a/pkg/apis/stable/v1alpha1/crd.go b/pkg/apis/stable/v1alpha1/crd.go deleted file mode 100644 index 256ed356da..0000000000 --- a/pkg/apis/stable/v1alpha1/crd.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2017 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1alpha1 - -import ( - "github.com/agonio/agon/pkg/apis/stable" - "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// GameServerCRD returns the Custom Resource Definition for a GameServer -func GameServerCRD() *v1beta1.CustomResourceDefinition { - return &v1beta1.CustomResourceDefinition{ - TypeMeta: v1.TypeMeta{ - APIVersion: "apiextensions.k8s.io/v1beta1", - Kind: "CustomResourceDefinition", - }, - ObjectMeta: v1.ObjectMeta{ - Name: "gameservers." + stable.GroupName, - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: stable.GroupName, - Version: "v1alpha1", - Scope: v1beta1.NamespaceScoped, - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "gameservers", - Singular: "gameserver", - Kind: "GameServer", - ShortNames: []string{"gs"}, - }, - }, - } -}