diff --git a/Makefile b/Makefile index 34cd2cd217..44347e5e4b 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ GO=go # Sources and Targets EXECUTABLES :=$(APP_NAME) # Build Binaries setting main.version and main.build vars -LDFLAGS :=-ldflags "-X main.HEKETI_VERSION=$(VERSION)" +LDFLAGS :=-ldflags "-X main.HEKETI_VERSION=$(VERSION) -extldflags '-z relro -z now'" # Package target PACKAGE :=$(DIR)/dist/$(APP_NAME)-$(VERSION).$(GOOS).$(ARCH).tar.gz CLIENT_PACKAGE :=$(DIR)/dist/$(APP_NAME)-client-$(VERSION).$(GOOS).$(ARCH).tar.gz @@ -84,9 +84,12 @@ $(PACKAGE): all $(CLIENT_PACKAGE): all @echo Packaging client Binaries... @mkdir -p tmp/$(CLIENT_PKG_NAME)/bin - @mkdir -p tmp/$(CLIENT_PKG_NAME)/share/heketi/templates + @mkdir -p tmp/$(CLIENT_PKG_NAME)/share/heketi/openshift/templates + @mkdir -p tmp/$(CLIENT_PKG_NAME)/share/heketi/kubernetes + @cp client/cli/go/topology-sample.json tmp/$(CLIENT_PKG_NAME)/share/heketi @cp client/cli/go/heketi-cli tmp/$(CLIENT_PKG_NAME)/bin - @cp extras/openshift/templates/* tmp/$(CLIENT_PKG_NAME)/share/heketi/templates + @cp extras/openshift/templates/* tmp/$(CLIENT_PKG_NAME)/share/heketi/openshift/templates + @cp extras/kubernetes/* tmp/$(CLIENT_PKG_NAME)/share/heketi/kubernetes @mkdir -p $(DIR)/dist/ tar -czf $@ -C tmp $(CLIENT_PKG_NAME); @rm -rf tmp diff --git a/apps/glusterfs/app.go b/apps/glusterfs/app.go index 705f0f68f4..2a1aa24d14 100644 --- a/apps/glusterfs/app.go +++ b/apps/glusterfs/app.go @@ -346,8 +346,10 @@ func (a *App) SetRoutes(router *mux.Router) error { } - return nil + // Set default error handler + router.NotFoundHandler = http.HandlerFunc(a.NotFoundHandler) + return nil } func (a *App) Close() { @@ -389,3 +391,8 @@ func (a *App) Backup(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) } } + +func (a *App) NotFoundHandler(w http.ResponseWriter, r *http.Request) { + logger.Warning("Invalid path or request %v", r.URL.Path) + http.Error(w, "Invalid path or request", http.StatusNotFound) +} diff --git a/apps/glusterfs/app_test.go b/apps/glusterfs/app_test.go index 4d5c643dcc..a1e6587453 100644 --- a/apps/glusterfs/app_test.go +++ b/apps/glusterfs/app_test.go @@ -18,10 +18,14 @@ package glusterfs import ( "bytes" + "net/http/httptest" "os" + "strings" "testing" "github.com/boltdb/bolt" + "github.com/gorilla/mux" + client "github.com/heketi/heketi/client/api/go-client" "github.com/heketi/heketi/pkg/utils" "github.com/heketi/tests" ) @@ -193,3 +197,31 @@ func TestAppReadOnlyDb(t *testing.T) { tests.Assert(t, app != nil) tests.Assert(t, app.dbReadOnly == true) } + +func TestAppPathNotFound(t *testing.T) { + dbfile := tests.Tempfile() + defer os.Remove(dbfile) + + app := NewTestApp(dbfile) + tests.Assert(t, app != nil) + defer app.Close() + router := mux.NewRouter() + app.SetRoutes(router) + + // Setup the server + ts := httptest.NewServer(router) + defer ts.Close() + + // Setup a new client + c := client.NewClientNoAuth(ts.URL) + + // Test paths which do not match the hexadecimal id + _, err := c.ClusterInfo("xxx") + tests.Assert(t, strings.Contains(err.Error(), "Invalid path or request")) + + _, err = c.NodeInfo("xxx") + tests.Assert(t, strings.Contains(err.Error(), "Invalid path or request")) + + _, err = c.VolumeInfo("xxx") + tests.Assert(t, strings.Contains(err.Error(), "Invalid path or request")) +} diff --git a/client/api/python/setup.cfg b/client/api/python/setup.cfg new file mode 100644 index 0000000000..3480374bc2 --- /dev/null +++ b/client/api/python/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal=1 \ No newline at end of file diff --git a/client/api/python/setup.py b/client/api/python/setup.py index 369088c1d5..f0f750cd1c 100644 --- a/client/api/python/setup.py +++ b/client/api/python/setup.py @@ -27,12 +27,14 @@ test_suite='nose.collector', install_requires=['pyjwt', 'requests'], classifiers=[ - 'Development Status :: 5 - Production/Stable' - 'Intended Audience :: Information Technology' - 'Intended Audience :: System Administrators' - 'License :: OSI Approved :: Apache Software License' - 'Operating System :: POSIX :: Linux' - 'Programming Language :: Python' - 'Programming Language :: Python :: 2.7' + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Information Technology', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2.7', + 'Topic :: System :: Filesystems', + 'Topic :: System :: Distributed Computing', ], ) diff --git a/client/cli/go/Makefile b/client/cli/go/Makefile index a0c78531aa..105ce1c756 100644 --- a/client/cli/go/Makefile +++ b/client/cli/go/Makefile @@ -29,7 +29,7 @@ TEST="go test" # Sources and Targets EXECUTABLES :=$(APP_NAME) # Build Binaries setting main.version and main.build vars -LDFLAGS :=-ldflags "-X main.HEKETI_CLI_VERSION=$(VERSION)" +LDFLAGS :=-ldflags "-X main.HEKETI_CLI_VERSION=$(VERSION) -extldflags '-z relro -z now'" # Package target PACKAGE :=$(DIR)/dist/$(APP_NAME)-$(VERSION).$(GOOS).$(ARCH).tar.gz diff --git a/executors/kubeexec/config.go b/executors/kubeexec/config.go index 708c141279..538fe933bf 100644 --- a/executors/kubeexec/config.go +++ b/executors/kubeexec/config.go @@ -27,10 +27,13 @@ type KubeConfig struct { Insecure bool `json:"insecure"` User string `json:"user"` Password string `json:"password"` + Token string `json:"token"` Namespace string `json:"namespace"` // Use Secrets to get the Bearerkey - UseSecrets bool `json:"use_secrets"` - TokenFile string `json:"token"` + UseSecrets bool `json:"use_secrets"` + + TokenFile string `json:"token_file"` + NamespaceFile string `json:"namespace_file"` // Use POD name instead of using label // to access POD diff --git a/executors/kubeexec/kubeexec.go b/executors/kubeexec/kubeexec.go index c1c83c7d3b..5b4cb79286 100644 --- a/executors/kubeexec/kubeexec.go +++ b/executors/kubeexec/kubeexec.go @@ -39,15 +39,6 @@ import ( "github.com/heketi/heketi/pkg/utils" ) -type KubernetesClient interface { -} - -type KubernetesRemoteCommand interface { -} - -type KubernetesRemoteCommandStream interface { -} - const ( KubeGlusterFSPodLabelKey = "glusterfs-node" ) @@ -139,6 +130,11 @@ func setWithEnvVariables(config *KubeConfig) { config.TokenFile = env } + env = os.Getenv("HEKETI_KUBE_NAMESPACEFILE") + if "" != env { + config.NamespaceFile = env + } + // Use POD names env = os.Getenv("HEKETI_KUBE_USE_POD_NAMES") if "" != env { @@ -168,6 +164,13 @@ func NewKubeExecutor(config *KubeConfig) (*KubeExecutor, error) { } // Check required values + if k.config.NamespaceFile != "" { + var err error + k.config.Namespace, err = k.readAllLinesFromFile(k.config.NamespaceFile) + if err != nil { + return nil, err + } + } if k.config.Namespace == "" { return nil, fmt.Errorf("Namespace must be provided in configuration") } @@ -193,13 +196,12 @@ func (k *KubeExecutor) RemoteCommandExecute(host string, // Execute return k.ConnectAndExec(host, - k.config.Namespace, "pods", commands, timeoutMinutes) } -func (k *KubeExecutor) ConnectAndExec(host, namespace, resource string, +func (k *KubeExecutor) ConnectAndExec(host, resource string, commands []string, timeoutMinutes int) ([]string, error) { @@ -213,7 +215,10 @@ func (k *KubeExecutor) ConnectAndExec(host, namespace, resource string, clientConfig.Insecure = k.config.Insecure // Login - if k.config.User != "" && k.config.Password != "" { + if k.config.UseSecrets == false && + k.config.User != "" && + k.config.Password != "" { + token, err := tokenCreator(clientConfig, nil, k.config.User, @@ -224,12 +229,11 @@ func (k *KubeExecutor) ConnectAndExec(host, namespace, resource string, } clientConfig.BearerToken = token } else if k.config.UseSecrets { - tokenBytes, err := ioutil.ReadFile(k.config.TokenFile) + var err error + clientConfig.BearerToken, err = k.readAllLinesFromFile(k.config.TokenFile) if err != nil { - logger.Err(err) - return nil, logger.LogError("Secret token not found in %v", k.config.TokenFile) + return nil, err } - clientConfig.BearerToken = string(tokenBytes) } // Get a client @@ -254,7 +258,7 @@ func (k *KubeExecutor) ConnectAndExec(host, namespace, resource string, } // Get a list of pods - pods, err := conn.Pods(namespace).List(api.ListOptions{ + pods, err := conn.Pods(k.config.Namespace).List(api.ListOptions{ LabelSelector: selector, FieldSelector: fields.Everything(), }) @@ -294,7 +298,7 @@ func (k *KubeExecutor) ConnectAndExec(host, namespace, resource string, req := conn.RESTClient.Post(). Resource(resource). Name(podName). - Namespace(namespace). + Namespace(k.config.Namespace). SubResource("exec") req.VersionedParams(&api.PodExecOptions{ Command: []string{"/bin/bash", "-c", command}, @@ -339,3 +343,11 @@ func (k *KubeExecutor) RebalanceOnExpansion() bool { func (k *KubeExecutor) SnapShotLimit() int { return k.config.SnapShotLimit } + +func (k *KubeExecutor) readAllLinesFromFile(filename string) (string, error) { + fileBytes, err := ioutil.ReadFile(filename) + if err != nil { + return "", logger.LogError("Error reading %v file: %v", filename, err.Error()) + } + return string(fileBytes), nil +} diff --git a/extras/docker/unstable/README.md b/extras/docker/unstable/README.md index 11b4f963f8..72b9bcdf1c 100644 --- a/extras/docker/unstable/README.md +++ b/extras/docker/unstable/README.md @@ -9,7 +9,7 @@ First you will need to download the latest development container: # docker pull heketi/heketi:dev -> NOTE: Must likely you will always need to do a new pull before staring your tests since the container changes so often. +> NOTE: Most likely you will always need to do a new pull before staring your tests since the container changes so often. ## Server Setup You will need to create a directory which has a directory containing configuraiton and any private key if necessary, and an empty directory used for storing the database. Directory and files must be read/write by user with id 1000 and if an ssh private key is used, it must also have a mod of 0600. diff --git a/extras/kubernetes/README.md b/extras/kubernetes/README.md new file mode 100644 index 0000000000..fb8ece37d1 --- /dev/null +++ b/extras/kubernetes/README.md @@ -0,0 +1,50 @@ +# Overview +Kubernetes templates for Heketi and Gluster. The following documentation is setup +to deploy the containers in Kubernetes. It is not a full setup. For full +documentation, please visit the Heketi wiki page. + +# Usage + +## Deploy Gluster + +* Get node name by running: + +``` +$ kubectl get nodes +``` + +* Deploy gluster container onto specified node: + +``` +$ sed -e \ + 's##..type your node name here..#' \ + glusterfs-deployment.json | kubectl create -f - +``` + +Repeat as needed. + +## Deploy Heketi + +* Create a service account for Heketi + +``` +$ kubectl create -f heketi-service-account.json +``` + +* Note the secret for the service account + +``` +$ heketi_secret=$(kubectl get sa heketi-service-account -o="go-template" --template="{{(index .secrets 0).name}}") +``` + +* Deploy deploy-heketi. Before deploying you will need to determine the Kubernetes API endpoint and namespace. + +In this example, we will use `https://1.1.1.1:443` as our Kubernetes API endpoint + +``` +$ sed -e "s##\"$heketi_secret\"#" \ + -e "s##\"http://1.1.1.1:443\"#" deploy-heketi-deployment.json | kubectl create -f - +``` + +Please refer to the wiki Kubernetes Deployment page for more information + diff --git a/extras/kubernetes/deploy-heketi-deployment.json b/extras/kubernetes/deploy-heketi-deployment.json index db90dc6f87..0985680bdb 100644 --- a/extras/kubernetes/deploy-heketi-deployment.json +++ b/extras/kubernetes/deploy-heketi-deployment.json @@ -30,7 +30,8 @@ "metadata": { "name": "deploy-heketi", "labels": { - "glusterfs": "heketi-deployment" + "glusterfs": "heketi-deployment", + "deploy-heketi": "heketi-deployment" }, "annotations": { "description": "Defines how to deploy Heketi" @@ -53,26 +54,22 @@ "imagePullPolicy": "Always", "name": "deploy-heketi", "env": [ - { - "name": "HEKETI_USER_KEY", - "value": "" - }, - { - "name": "HEKETI_ADMIN_KEY", - "value": "" - }, { "name": "HEKETI_EXECUTOR", "value": "kubernetes" }, { "name": "HEKETI_KUBE_USE_SECRET", - "value": "" + "value": "y" }, { "name": "HEKETI_KUBE_TOKENFILE", "value": "/var/lib/heketi/secret/token" }, + { + "name": "HEKETI_KUBE_NAMESPACEFILE", + "value": "/var/lib/heketi/secret/namespace" + }, { "name": "HEKETI_FSTAB", "value": "/var/lib/heketi/fstab" @@ -81,29 +78,13 @@ "name": "HEKETI_SNAPSHOT_LIMIT", "value": "14" }, - { - "name": "HEKETI_KUBE_CERTFILE", - "value": "" - }, { "name": "HEKETI_KUBE_INSECURE", - "value": "" - }, - { - "name": "HEKETI_KUBE_USER", - "value": "" - }, - { - "name": "HEKETI_KUBE_PASSWORD", - "value": "" - }, - { - "name": "HEKETI_KUBE_NAMESPACE", - "value": "" + "value": "y" }, { "name": "HEKETI_KUBE_APIHOST", - "value": "" + "value": } ], "ports": [ @@ -146,7 +127,7 @@ { "name": "secret", "secret": { - "secretName": "" + "secretName": } } ] diff --git a/extras/kubernetes/glusterfs-deployment.json b/extras/kubernetes/glusterfs-deployment.json index c4f62d1978..02e2e590c2 100644 --- a/extras/kubernetes/glusterfs-deployment.json +++ b/extras/kubernetes/glusterfs-deployment.json @@ -2,10 +2,10 @@ "kind": "Deployment", "apiVersion": "extensions/v1beta1", "metadata": { - "name": "glusterfs-", + "name": "glusterfs-", "labels": { "glusterfs": "deployment", - "glusterfs-node": "" + "glusterfs-node": "" }, "annotations": { "description": "GlusterFS container deployment template", @@ -20,12 +20,12 @@ "labels": { "name": "glusterfs", "glusterfs": "pod", - "glusterfs-node": "" + "glusterfs-node": "" } }, "spec": { "nodeSelector": { - "kubernetes.io/hostname": "" + "kubernetes.io/hostname": "" }, "hostNetwork": true, "containers": [ diff --git a/extras/kubernetes/heketi-deployment.json b/extras/kubernetes/heketi-deployment.json index 6b7d45b20e..c06d6fa0ef 100644 --- a/extras/kubernetes/heketi-deployment.json +++ b/extras/kubernetes/heketi-deployment.json @@ -53,26 +53,22 @@ "imagePullPolicy": "Always", "name": "heketi", "env": [ - { - "name": "HEKETI_USER_KEY", - "value": "" - }, - { - "name": "HEKETI_ADMIN_KEY", - "value": "" - }, { "name": "HEKETI_EXECUTOR", "value": "kubernetes" }, { "name": "HEKETI_KUBE_USE_SECRET", - "value": "" + "value": "y" }, { "name": "HEKETI_KUBE_TOKENFILE", "value": "/var/lib/heketi/secret/token" }, + { + "name": "HEKETI_KUBE_NAMESPACEFILE", + "value": "/var/lib/heketi/secret/namespace" + }, { "name": "HEKETI_FSTAB", "value": "/var/lib/heketi/fstab" @@ -81,29 +77,13 @@ "name": "HEKETI_SNAPSHOT_LIMIT", "value": "14" }, - { - "name": "HEKETI_KUBE_CERTFILE", - "value": "" - }, { "name": "HEKETI_KUBE_INSECURE", - "value": "" - }, - { - "name": "HEKETI_KUBE_USER", - "value": "" - }, - { - "name": "HEKETI_KUBE_PASSWORD", - "value": "" - }, - { - "name": "HEKETI_KUBE_NAMESPACE", - "value": "" + "value": "y" }, { "name": "HEKETI_KUBE_APIHOST", - "value": "" + "value": } ], "ports": [ @@ -150,7 +130,7 @@ { "name": "secret", "secret": { - "secretName": "" + "secretName": } } ] diff --git a/tests/functional/TestKubeSmokeTest/ServiceAccount.yaml b/extras/kubernetes/heketi-service-account.yaml similarity index 59% rename from tests/functional/TestKubeSmokeTest/ServiceAccount.yaml rename to extras/kubernetes/heketi-service-account.yaml index 28bf5f9f06..40a65d1a71 100644 --- a/tests/functional/TestKubeSmokeTest/ServiceAccount.yaml +++ b/extras/kubernetes/heketi-service-account.yaml @@ -1,4 +1,4 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: seracc.test + name: heketi-service-account diff --git a/pkg/heketitest/heketitest.go b/pkg/heketitest/heketitest.go new file mode 100644 index 0000000000..6bdcf4fa2b --- /dev/null +++ b/pkg/heketitest/heketitest.go @@ -0,0 +1,153 @@ +// +// Copyright (c) 2016 The heketi 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 heketitest + +import ( + "bytes" + "net/http/httptest" + "os" + + "github.com/codegangsta/negroni" + "github.com/gorilla/mux" + "github.com/heketi/heketi/apps/glusterfs" + "github.com/heketi/heketi/middleware" + "github.com/heketi/tests" + "github.com/lpabon/godbc" +) + +// Heketi test server configuration +type HeketiMockTestServerConfig struct { + Auth bool + AdminKey string + UserKey string + Logging bool +} + +// Heketi test service metadata +type HeketiMockTestServer struct { + DbFile string + Ts *httptest.Server + App *glusterfs.App +} + +// Create a simple Heketi mock server +// +// Example: +// h := heketitest.NewHeketiMockTestServerDefault() +// defer h.Close() +// +func NewHeketiMockTestServerDefault() *HeketiMockTestServer { + return NewHeketiMockTestServer(nil) +} + +// Create a Heketi mock server +// +// Example: +// c := &heketitest.HeketiMockTestServerConfig{ +// Auth: true, +// AdminKey: "admin", +// UserKey: "user", +// Logging: false, +// } +// +// h := heketitest.NewHeketiMockTestServer(c) +// defer h.Close() +// +func NewHeketiMockTestServer( + config *HeketiMockTestServerConfig) *HeketiMockTestServer { + + if config == nil { + config = &HeketiMockTestServerConfig{} + } + + h := &HeketiMockTestServer{} + h.DbFile = tests.Tempfile() + + // Set loglevel + var loglevel string + if config.Logging { + loglevel = "debug" + } else { + loglevel = "none" + } + + // Create simple configuration for unit tests + appConfig := bytes.NewBuffer([]byte(`{ + "glusterfs" : { + "executor" : "mock", + "allocator" : "simple", + "loglevel" : "` + loglevel + `", + "db" : "` + h.DbFile + `" + } + }`)) + h.App = glusterfs.NewApp(appConfig) + if h.App == nil { + return nil + } + + // Initialize REST service + h.Ts = h.setupHeketiServer(config) + if h.Ts == nil { + return nil + } + + return h +} + +// Get http test service struct +func (h *HeketiMockTestServer) HttpServer() *httptest.Server { + return h.Ts +} + +// Get URL to test server +func (h *HeketiMockTestServer) URL() string { + return h.Ts.URL +} + +// Close database and other services +func (h *HeketiMockTestServer) Close() { + os.Remove(h.DbFile) + h.App.Close() + h.Ts.Close() +} + +func (h *HeketiMockTestServer) setupHeketiServer( + config *HeketiMockTestServerConfig) *httptest.Server { + + godbc.Require(h.App != nil) + + router := mux.NewRouter() + h.App.SetRoutes(router) + n := negroni.New() + + // Add authentication + if config.Auth { + jwtconfig := &middleware.JwtAuthConfig{} + jwtconfig.Admin.PrivateKey = config.AdminKey + jwtconfig.User.PrivateKey = config.UserKey + + // Setup middleware + n.Use(middleware.NewJwtAuth(jwtconfig)) + n.UseFunc(h.App.Auth) + } + + // Add App + n.UseHandler(router) + + // Create server + return httptest.NewServer(n) +} diff --git a/pkg/heketitest/heketitest_test.go b/pkg/heketitest/heketitest_test.go new file mode 100644 index 0000000000..ea6177afbe --- /dev/null +++ b/pkg/heketitest/heketitest_test.go @@ -0,0 +1,72 @@ +// +// Copyright (c) 2016 The heketi 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 heketitest + +import ( + "testing" + + client "github.com/heketi/heketi/client/api/go-client" + "github.com/heketi/tests" +) + +func TestNewHeketiMockTestServer(t *testing.T) { + c := &HeketiMockTestServerConfig{ + Auth: true, + AdminKey: "admin", + UserKey: "user", + Logging: true, + } + + h := NewHeketiMockTestServer(c) + tests.Assert(t, h != nil) + tests.Assert(t, h.Ts != nil) + tests.Assert(t, h.DbFile != "") + tests.Assert(t, h.App != nil) + h.Close() + + h = NewHeketiMockTestServerDefault() + tests.Assert(t, h != nil) + tests.Assert(t, h.Ts != nil) + tests.Assert(t, h.DbFile != "") + tests.Assert(t, h.App != nil) +} + +func TestHeketiMockTestServer(t *testing.T) { + c := &HeketiMockTestServerConfig{ + Auth: true, + AdminKey: "admin", + UserKey: "user", + } + + h := NewHeketiMockTestServer(c) + defer h.Close() + + api := client.NewClient(h.URL(), "admin", "admin") + tests.Assert(t, api != nil) + + cluster, err := api.ClusterCreate() + tests.Assert(t, err == nil) + tests.Assert(t, cluster != nil) + tests.Assert(t, len(cluster.Nodes) == 0) + tests.Assert(t, len(cluster.Volumes) == 0) + + info, err := api.ClusterInfo(cluster.Id) + tests.Assert(t, err == nil) + tests.Assert(t, info.Id == cluster.Id) + tests.Assert(t, len(info.Nodes) == 0) + tests.Assert(t, len(info.Volumes) == 0) +} diff --git a/tests/functional/TestKubeSmokeTest/run.sh b/tests/functional/TestKubeSmokeTest/run.sh index cd9947c834..367097a1ed 100755 --- a/tests/functional/TestKubeSmokeTest/run.sh +++ b/tests/functional/TestKubeSmokeTest/run.sh @@ -11,7 +11,7 @@ CLIENTDIR=$TOP/client/cli/go source ${FUNCTIONAL_DIR}/lib.sh ### VERSIONS ### -KUBEVERSION=v1.4.0-beta.1 +KUBEVERSION=v1.4.3 docker_set_env() { @@ -59,6 +59,7 @@ build_heketi() { copy_client_files() { cp $CLIENTDIR/heketi-cli $RESOURCES_DIR || fail "Unable to copy client files" + cp $TOP/extras/kubernetes/* $RESOURCES_DIR || fail "Unable to copy kubernetes deployment files" } teardown() { @@ -75,7 +76,7 @@ setup_minikube() { fi echo -e "\nGet docker-machine" - curl -Lo docker-machine https://github.com/docker/machine/releases/download/v0.8.1/docker-machine-Linux-x86_64 || fail "Unable to get docker-machine" + curl -Lo docker-machine https://github.com/docker/machine/releases/download/v0.8.2/docker-machine-Linux-x86_64 || fail "Unable to get docker-machine" chmod +x docker-machine _sudo mv docker-machine /usr/local/bin @@ -90,7 +91,7 @@ setup_minikube() { echo -e "\nGet minikube" curl -Lo minikube \ - https://storage.googleapis.com/minikube/releases/v0.9.0/minikube-linux-amd64 || fail "Unable to get minikube" + https://storage.googleapis.com/minikube/releases/v0.12.0/minikube-linux-amd64 || fail "Unable to get minikube" chmod +x minikube _sudo mv minikube /usr/local/bin @@ -104,7 +105,6 @@ setup_minikube() { start_minikube() { minikube start \ - --iso-url=https://github.com/kubernetes/minikube/releases/download/v0.9.0/minikube.iso \ --cpus=2 \ --memory=2048 \ --vm-driver=kvm \ @@ -133,7 +133,6 @@ teardown setup ### TESTS ### -# test the Authentication using the token for kubetest in test*.sh ; do test_setup println "TEST $kubetest" diff --git a/tests/functional/TestKubeSmokeTest/test-heketi-deployment.json b/tests/functional/TestKubeSmokeTest/test-heketi-deployment.json deleted file mode 100644 index 2a19a64d4d..0000000000 --- a/tests/functional/TestKubeSmokeTest/test-heketi-deployment.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "kind": "Deployment", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "heketi", - "labels": { - "glusterfs": "heketi-deployment" - }, - "annotations": { - "description": "Defines how to deploy Heketi" - } - }, - "spec": { - "replicas":1, - "template": { - "metadata": { - "name": "heketi", - "labels": { - "name": "heketi", - "glusterfs": "heketi-pod" - } - }, - "spec": { - "containers": [ - { - "image": "heketi/heketi:ci", - "imagePullPolicy": "IfNotPresent", - "name": "heketi", - "env": [ - { - "name": "HEKETI_EXECUTOR", - "value": "kubernetes" - }, - { - "name": "HEKETI_KUBE_USE_SECRET", - "value": "y" - }, - { - "name": "HEKETI_KUBE_TOKENFILE", - "value": "/var/lib/heketi/secret/token" - }, - { - "name": "HEKETI_FSTAB", - "value": "/var/lib/heketi/fstab" - }, - { - "name": "HEKETI_SNAPSHOT_LIMIT", - "value": "14" - }, - { - "name": "HEKETI_KUBE_INSECURE", - "value": "y" - }, - { - "name": "HEKETI_KUBE_NAMESPACE", - "value": "default" - }, - { - "name": "HEKETI_KUBE_APIHOST", - "value": "" - } - ], - "ports": [ - { - "containerPort": 8080 - } - ], - "volumeMounts": [ - { - "name": "db", - "mountPath": "/var/lib/heketi" - }, - { - "name": "secret", - "mountPath": "/var/lib/heketi/secret" - } - ], - "readinessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 3, - "httpGet": { - "path": "/hello", - "port": 8080 - } - }, - "livenessProbe": { - "timeoutSeconds": 3, - "initialDelaySeconds": 30, - "httpGet": { - "path": "/hello", - "port": 8080 - } - } - } - ], - "volumes": [ - { - "name": "db" - }, - { - "name": "secret", - "secret": { - "secretName": "" - } - } - ] - } - } - } -} diff --git a/tests/functional/TestKubeSmokeTest/testHeketiRpc.sh b/tests/functional/TestKubeSmokeTest/testHeketiRpc.sh index a20601f392..c445dda140 100755 --- a/tests/functional/TestKubeSmokeTest/testHeketiRpc.sh +++ b/tests/functional/TestKubeSmokeTest/testHeketiRpc.sh @@ -50,45 +50,59 @@ start_mock_gluster_container() { setup_all_pods() { - kubectl get nodes --show-labels + kubectl get nodes --show-labels - echo -e "\nCreate a ServiceAccount" - kubectl create -f ServiceAccount.yaml || fail "Unable to create a serviceAccount" - - KUBESEC=$(kubectl get secrets | grep seracc | awk 'NR==1{print $1}') + echo -e "\nCreate a ServiceAccount" + kubectl create -f $RESOURCES_DIR/heketi-service-account.yaml || fail "Unable to create a serviceAccount" + KUBESEC=$(kubectl get sa heketi-service-account -o="go-template" --template="{{range .secrets}}{{.name}}{{end}}") KUBEAPI=https://$(minikube ip):8443 + echo -e "\nSecret is = $KUBESEC" + if [ -z "$KUBESEC" ] ; then + fail "Secret is empty" + fi + # Start Heketi echo -e "\nStart Heketi container" - sed 's\\'"$KUBEAPI"'\g; s\\'"$KUBESEC"'\g' test-heketi-deployment.json | kubectl create -f - --validate=false || fail "Unable to start heketi container" + sed -e "s#heketi/heketi#heketi/heketi:ci#" \ + -e "s#Always#IfNotPresent#" \ + -e "s##\"$KUBESEC\"#" \ + -e "s##\"$KUBEAPI\"#" \ + $RESOURCES_DIR/deploy-heketi-deployment.json | kubectl create -f - # Wait until it is running + echo "Wait until deploy-heketi is ready" while ! kubectl get pods | grep heketi | grep "1/1" > /dev/null ; do + echo -n "." sleep 1 done - # This blocks until ready - kubectl expose deployment heketi --type=NodePort || fail "Unable to expose heketi service" + + echo "Delete the cluster service because it cannot be used in minikube" + kubectl delete service deploy-heketi + + echo "Create a service for deploy-heketi" + kubectl expose deployment deploy-heketi --port=8080 --type=NodePort || fail "Unable to expose heketi service" echo -e "\nShow Topology" - export HEKETI_CLI_SERVER=$(minikube service heketi --url) + export HEKETI_CLI_SERVER=$(minikube service deploy-heketi --url) heketi-cli topology info - echo -e "\nStart gluster mock container" - start_mock_gluster_container 1 + echo -e "\nStart gluster mock container" + start_mock_gluster_container 1 start_mock_gluster_container 2 } test_peer_probe() { - echo -e "\nGet the Heketi server connection" + echo -e "\nGet the Heketi server connection" heketi-cli cluster create || fail "Unable to create cluster" - CLUSTERID=$(heketi-cli cluster list | sed -e '$!d') + CLUSTERID=$(heketi-cli cluster list | sed -e '$!d') - echo -e "\nAdd First Node" + echo -e "\nAdd First Node" heketi-cli node add --zone=1 --cluster=$CLUSTERID --management-host-name=gluster1 --storage-host-name=gluster1 || fail "Unable to add gluster1" - echo -e "\nAdd Second Node" + echo -e "\nAdd Second Node" heketi-cli node add --zone=2 --cluster=$CLUSTERID --management-host-name=gluster2 --storage-host-name=gluster2 || fail "Unable to add gluster2" echo -e "\nShow Topology"