diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 70c78a2bf..f89d5c711 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,6 +1,7 @@ { "ImportPath": "k8s.io/contrib/ingress", - "GoVersion": "go1.6", + "GoVersion": "go1.5", + "GodepVersion": "v65", "Packages": [ "./..." ], @@ -43,6 +44,41 @@ "Comment": "v0.3.1-62-g3d72d39", "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" }, + { + "ImportPath": "github.com/docker/engine-api/types/blkiodev", + "Comment": "v0.3.1-62-g3d72d39", + "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" + }, + { + "ImportPath": "github.com/docker/engine-api/types/container", + "Comment": "v0.3.1-62-g3d72d39", + "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" + }, + { + "ImportPath": "github.com/docker/engine-api/types/filters", + "Comment": "v0.3.1-62-g3d72d39", + "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" + }, + { + "ImportPath": "github.com/docker/engine-api/types/network", + "Comment": "v0.3.1-62-g3d72d39", + "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" + }, + { + "ImportPath": "github.com/docker/engine-api/types/registry", + "Comment": "v0.3.1-62-g3d72d39", + "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" + }, + { + "ImportPath": "github.com/docker/engine-api/types/strslice", + "Comment": "v0.3.1-62-g3d72d39", + "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" + }, + { + "ImportPath": "github.com/docker/engine-api/types/versions", + "Comment": "v0.3.1-62-g3d72d39", + "Rev": "3d72d392d07bece8d7d7b2a3b6b2e57c2df376a2" + }, { "ImportPath": "github.com/docker/go-connections/nat", "Comment": "v0.2.0-2-gf549a93", @@ -58,6 +94,16 @@ "Comment": "v1.2-34-g496d495", "Rev": "496d495156da218b9912f03dfa7df7f80fbd8cc3" }, + { + "ImportPath": "github.com/emicklei/go-restful/log", + "Comment": "v1.2-34-g496d495", + "Rev": "496d495156da218b9912f03dfa7df7f80fbd8cc3" + }, + { + "ImportPath": "github.com/emicklei/go-restful/swagger", + "Comment": "v1.2-34-g496d495", + "Rev": "496d495156da218b9912f03dfa7df7f80fbd8cc3" + }, { "ImportPath": "github.com/evanphx/json-patch", "Rev": "7dd4489c2eb6073e5a9d7746c3274c5b5f0387df" @@ -101,6 +147,10 @@ "Comment": "0.1.3-8-g6633656", "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" }, + { + "ImportPath": "github.com/inconshreveable/mousetrap", + "Rev": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + }, { "ImportPath": "github.com/juju/ratelimit", "Rev": "77ed1c8a01217656d2080ad51981f6e99adaa177" @@ -118,6 +168,11 @@ "Comment": "v0.0.7", "Rev": "7ca2aa4873aea7cb4265b1726acb24b90d8726c6" }, + { + "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/fs", + "Comment": "v0.0.7", + "Rev": "7ca2aa4873aea7cb4265b1726acb24b90d8726c6" + }, { "ImportPath": "github.com/opencontainers/runc/libcontainer/configs", "Comment": "v0.0.7", @@ -170,10 +225,30 @@ "ImportPath": "golang.org/x/net/context", "Rev": "c2528b2dd8352441850638a8bb678c2ad056fd3e" }, + { + "ImportPath": "golang.org/x/net/context/ctxhttp", + "Rev": "c2528b2dd8352441850638a8bb678c2ad056fd3e" + }, { "ImportPath": "golang.org/x/oauth2", "Rev": "b5adcc2dcdf009d0391547edc6ecbaff889f5bb9" }, + { + "ImportPath": "golang.org/x/oauth2/google", + "Rev": "b5adcc2dcdf009d0391547edc6ecbaff889f5bb9" + }, + { + "ImportPath": "golang.org/x/oauth2/internal", + "Rev": "b5adcc2dcdf009d0391547edc6ecbaff889f5bb9" + }, + { + "ImportPath": "golang.org/x/oauth2/jws", + "Rev": "b5adcc2dcdf009d0391547edc6ecbaff889f5bb9" + }, + { + "ImportPath": "golang.org/x/oauth2/jwt", + "Rev": "b5adcc2dcdf009d0391547edc6ecbaff889f5bb9" + }, { "ImportPath": "google.golang.org/api/compute/v1", "Rev": "77e7d383beb96054547729f49c372b3d01e196ff" @@ -190,6 +265,10 @@ "ImportPath": "google.golang.org/api/googleapi", "Rev": "77e7d383beb96054547729f49c372b3d01e196ff" }, + { + "ImportPath": "google.golang.org/api/googleapi/internal/uritemplates", + "Rev": "77e7d383beb96054547729f49c372b3d01e196ff" + }, { "ImportPath": "google.golang.org/cloud/compute/metadata", "Rev": "eb47ba841d53d93506cfbfbc03927daf9cc48f88" @@ -202,6 +281,18 @@ "ImportPath": "gopkg.in/gcfg.v1", "Rev": "083575c3955c85df16fe9590cceab64d03f5eb6e" }, + { + "ImportPath": "gopkg.in/gcfg.v1/scanner", + "Rev": "083575c3955c85df16fe9590cceab64d03f5eb6e" + }, + { + "ImportPath": "gopkg.in/gcfg.v1/token", + "Rev": "083575c3955c85df16fe9590cceab64d03f5eb6e" + }, + { + "ImportPath": "gopkg.in/gcfg.v1/types", + "Rev": "083575c3955c85df16fe9590cceab64d03f5eb6e" + }, { "ImportPath": "gopkg.in/yaml.v2", "Rev": "a83829b6f1293c91addabc89d0571c246397bbf4" @@ -213,223 +304,648 @@ }, { "ImportPath": "k8s.io/kubernetes/federation/apis/federation", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/federation/apis/federation/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/federation/apis/federation/v1alpha1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/api", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/endpoints", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/errors", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/meta", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/pod", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/resource", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/rest", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/service", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/testapi", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/unversioned", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/unversioned/validation", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/util", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/v1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/api/validation", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apimachinery", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apimachinery/registered", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/apps", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/apps/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/apps/v1alpha1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/authorization", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/authorization/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/authorization/v1beta1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/autoscaling", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/autoscaling/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/autoscaling/v1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/batch", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/batch/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/batch/v1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/componentconfig", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/componentconfig/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/extensions", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/extensions/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/extensions/v1beta1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/extensions/validation", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/metrics", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/metrics/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/metrics/v1alpha1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/apis/policy", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/policy/install", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/apis/policy/v1alpha1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/auth/user", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/capabilities", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/cache", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/metrics", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/record", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/restclient", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/transport", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/typed/discovery", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned/auth", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned/clientcmd", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/latest", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/v1", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/cloudprovider", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/cloudprovider/providers/gce", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/controller", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/controller/framework", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/controller/podautoscaler", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/conversion", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/conversion/queryparams", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/credentialprovider", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/fieldpath", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/fields", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/healthz", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/kubectl", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/kubectl/cmd/util", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/kubectl/resource", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/kubelet/qos", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/kubelet/qos/util", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/labels", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/master/ports", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/registry/generic", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/runtime", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/runtime/serializer", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/runtime/serializer/json", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/runtime/serializer/protobuf", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/runtime/serializer/recognizer", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/runtime/serializer/streaming", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/runtime/serializer/versioning", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/storage", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/types", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/util", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/crypto", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/deployment", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/errors", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/flag", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/flowcontrol", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/framer", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/hash", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/homedir", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/integer", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/intstr", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/json", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/jsonpath", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/labels", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/net", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/net/sets", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/parsers", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/pod", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/rand", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/runtime", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/sets", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/strategicpatch", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/validation", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/validation/field", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/wait", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/workqueue", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/util/yaml", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/version", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/pkg/watch", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/pkg/watch/versioned", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/plugin/pkg/client/auth", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, + { + "ImportPath": "k8s.io/kubernetes/plugin/pkg/client/auth/gcp", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/third_party/forked/json", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/third_party/forked/reflect", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "k8s.io/kubernetes/third_party/golang/template", - "Comment": "v1.3.0-alpha.3-473-g41b7b04", - "Rev": "41b7b04fafecd22127a96fc51a87b2ea34418ffc" + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, { "ImportPath": "speter.net/go/exp/math/dec/inf", diff --git a/Godeps/_workspace/.gitignore b/Godeps/_workspace/.gitignore deleted file mode 100644 index f037d684e..000000000 --- a/Godeps/_workspace/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/pkg -/bin diff --git a/Godeps/_workspace/src/bitbucket.org/ww/goautoneg/autoneg_test.go b/Godeps/_workspace/src/bitbucket.org/ww/goautoneg/autoneg_test.go deleted file mode 100644 index 41d328f1d..000000000 --- a/Godeps/_workspace/src/bitbucket.org/ww/goautoneg/autoneg_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package goautoneg - -import ( - "testing" -) - -var chrome = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" - -func TestParseAccept(t *testing.T) { - alternatives := []string{"text/html", "image/png"} - content_type := Negotiate(chrome, alternatives) - if content_type != "image/png" { - t.Errorf("got %s expected image/png", content_type) - } - - alternatives = []string{"text/html", "text/plain", "text/n3"} - content_type = Negotiate(chrome, alternatives) - if content_type != "text/html" { - t.Errorf("got %s expected text/html", content_type) - } - - alternatives = []string{"text/n3", "text/plain"} - content_type = Negotiate(chrome, alternatives) - if content_type != "text/plain" { - t.Errorf("got %s expected text/plain", content_type) - } - - alternatives = []string{"text/n3", "application/rdf+xml"} - content_type = Negotiate(chrome, alternatives) - if content_type != "text/n3" { - t.Errorf("got %s expected text/n3", content_type) - } -} diff --git a/Godeps/_workspace/src/github.com/beorn7/perks/quantile/bench_test.go b/Godeps/_workspace/src/github.com/beorn7/perks/quantile/bench_test.go deleted file mode 100644 index 0bd0e4e77..000000000 --- a/Godeps/_workspace/src/github.com/beorn7/perks/quantile/bench_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package quantile - -import ( - "testing" -) - -func BenchmarkInsertTargeted(b *testing.B) { - b.ReportAllocs() - - s := NewTargeted(Targets) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertTargetedSmallEpsilon(b *testing.B) { - s := NewTargeted(TargetsSmallEpsilon) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertBiased(b *testing.B) { - s := NewLowBiased(0.01) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkInsertBiasedSmallEpsilon(b *testing.B) { - s := NewLowBiased(0.0001) - b.ResetTimer() - for i := float64(0); i < float64(b.N); i++ { - s.Insert(i) - } -} - -func BenchmarkQuery(b *testing.B) { - s := NewTargeted(Targets) - for i := float64(0); i < 1e6; i++ { - s.Insert(i) - } - b.ResetTimer() - n := float64(b.N) - for i := float64(0); i < n; i++ { - s.Query(i / n) - } -} - -func BenchmarkQuerySmallEpsilon(b *testing.B) { - s := NewTargeted(TargetsSmallEpsilon) - for i := float64(0); i < 1e6; i++ { - s.Insert(i) - } - b.ResetTimer() - n := float64(b.N) - for i := float64(0); i < n; i++ { - s.Query(i / n) - } -} diff --git a/Godeps/_workspace/src/github.com/beorn7/perks/quantile/example_test.go b/Godeps/_workspace/src/github.com/beorn7/perks/quantile/example_test.go deleted file mode 100644 index ab3293aaf..000000000 --- a/Godeps/_workspace/src/github.com/beorn7/perks/quantile/example_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// +build go1.1 - -package quantile_test - -import ( - "bufio" - "fmt" - "log" - "os" - "strconv" - "time" - - "github.com/beorn7/perks/quantile" -) - -func Example_simple() { - ch := make(chan float64) - go sendFloats(ch) - - // Compute the 50th, 90th, and 99th percentile. - q := quantile.NewTargeted(map[float64]float64{ - 0.50: 0.005, - 0.90: 0.001, - 0.99: 0.0001, - }) - for v := range ch { - q.Insert(v) - } - - fmt.Println("perc50:", q.Query(0.50)) - fmt.Println("perc90:", q.Query(0.90)) - fmt.Println("perc99:", q.Query(0.99)) - fmt.Println("count:", q.Count()) - // Output: - // perc50: 5 - // perc90: 16 - // perc99: 223 - // count: 2388 -} - -func Example_mergeMultipleStreams() { - // Scenario: - // We have multiple database shards. On each shard, there is a process - // collecting query response times from the database logs and inserting - // them into a Stream (created via NewTargeted(0.90)), much like the - // Simple example. These processes expose a network interface for us to - // ask them to serialize and send us the results of their - // Stream.Samples so we may Merge and Query them. - // - // NOTES: - // * These sample sets are small, allowing us to get them - // across the network much faster than sending the entire list of data - // points. - // - // * For this to work correctly, we must supply the same quantiles - // a priori the process collecting the samples supplied to NewTargeted, - // even if we do not plan to query them all here. - ch := make(chan quantile.Samples) - getDBQuerySamples(ch) - q := quantile.NewTargeted(map[float64]float64{0.90: 0.001}) - for samples := range ch { - q.Merge(samples) - } - fmt.Println("perc90:", q.Query(0.90)) -} - -func Example_window() { - // Scenario: We want the 90th, 95th, and 99th percentiles for each - // minute. - - ch := make(chan float64) - go sendStreamValues(ch) - - tick := time.NewTicker(1 * time.Minute) - q := quantile.NewTargeted(map[float64]float64{ - 0.90: 0.001, - 0.95: 0.0005, - 0.99: 0.0001, - }) - for { - select { - case t := <-tick.C: - flushToDB(t, q.Samples()) - q.Reset() - case v := <-ch: - q.Insert(v) - } - } -} - -func sendStreamValues(ch chan float64) { - // Use your imagination -} - -func flushToDB(t time.Time, samples quantile.Samples) { - // Use your imagination -} - -// This is a stub for the above example. In reality this would hit the remote -// servers via http or something like it. -func getDBQuerySamples(ch chan quantile.Samples) {} - -func sendFloats(ch chan<- float64) { - f, err := os.Open("exampledata.txt") - if err != nil { - log.Fatal(err) - } - sc := bufio.NewScanner(f) - for sc.Scan() { - b := sc.Bytes() - v, err := strconv.ParseFloat(string(b), 64) - if err != nil { - log.Fatal(err) - } - ch <- v - } - if sc.Err() != nil { - log.Fatal(sc.Err()) - } - close(ch) -} diff --git a/Godeps/_workspace/src/github.com/beorn7/perks/quantile/stream_test.go b/Godeps/_workspace/src/github.com/beorn7/perks/quantile/stream_test.go deleted file mode 100644 index 4dba05449..000000000 --- a/Godeps/_workspace/src/github.com/beorn7/perks/quantile/stream_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package quantile - -import ( - "math" - "math/rand" - "sort" - "testing" -) - -var ( - Targets = map[float64]float64{ - 0.01: 0.001, - 0.10: 0.01, - 0.50: 0.05, - 0.90: 0.01, - 0.99: 0.001, - } - TargetsSmallEpsilon = map[float64]float64{ - 0.01: 0.0001, - 0.10: 0.001, - 0.50: 0.005, - 0.90: 0.001, - 0.99: 0.0001, - } - LowQuantiles = []float64{0.01, 0.1, 0.5} - HighQuantiles = []float64{0.99, 0.9, 0.5} -) - -const RelativeEpsilon = 0.01 - -func verifyPercsWithAbsoluteEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for quantile, epsilon := range Targets { - n := float64(len(a)) - k := int(quantile * n) - lower := int((quantile - epsilon) * n) - if lower < 1 { - lower = 1 - } - upper := int(math.Ceil((quantile + epsilon) * n)) - if upper > len(a) { - upper = len(a) - } - w, min, max := a[k-1], a[lower-1], a[upper-1] - if g := s.Query(quantile); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", quantile, w, min, max, g) - } - } -} - -func verifyLowPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for _, qu := range LowQuantiles { - n := float64(len(a)) - k := int(qu * n) - - lowerRank := int((1 - RelativeEpsilon) * qu * n) - upperRank := int(math.Ceil((1 + RelativeEpsilon) * qu * n)) - w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] - if g := s.Query(qu); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) - } - } -} - -func verifyHighPercsWithRelativeEpsilon(t *testing.T, a []float64, s *Stream) { - sort.Float64s(a) - for _, qu := range HighQuantiles { - n := float64(len(a)) - k := int(qu * n) - - lowerRank := int((1 - (1+RelativeEpsilon)*(1-qu)) * n) - upperRank := int(math.Ceil((1 - (1-RelativeEpsilon)*(1-qu)) * n)) - w, min, max := a[k-1], a[lowerRank-1], a[upperRank-1] - if g := s.Query(qu); g < min || g > max { - t.Errorf("q=%f: want %v [%f,%f], got %v", qu, w, min, max, g) - } - } -} - -func populateStream(s *Stream) []float64 { - a := make([]float64, 0, 1e5+100) - for i := 0; i < cap(a); i++ { - v := rand.NormFloat64() - // Add 5% asymmetric outliers. - if i%20 == 0 { - v = v*v + 1 - } - s.Insert(v) - a = append(a, v) - } - return a -} - -func TestTargetedQuery(t *testing.T) { - rand.Seed(42) - s := NewTargeted(Targets) - a := populateStream(s) - verifyPercsWithAbsoluteEpsilon(t, a, s) -} - -func TestLowBiasedQuery(t *testing.T) { - rand.Seed(42) - s := NewLowBiased(RelativeEpsilon) - a := populateStream(s) - verifyLowPercsWithRelativeEpsilon(t, a, s) -} - -func TestHighBiasedQuery(t *testing.T) { - rand.Seed(42) - s := NewHighBiased(RelativeEpsilon) - a := populateStream(s) - verifyHighPercsWithRelativeEpsilon(t, a, s) -} - -// BrokenTestTargetedMerge is broken, see Merge doc comment. -func BrokenTestTargetedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewTargeted(Targets) - s2 := NewTargeted(Targets) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyPercsWithAbsoluteEpsilon(t, a, s1) -} - -// BrokenTestLowBiasedMerge is broken, see Merge doc comment. -func BrokenTestLowBiasedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewLowBiased(RelativeEpsilon) - s2 := NewLowBiased(RelativeEpsilon) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyLowPercsWithRelativeEpsilon(t, a, s2) -} - -// BrokenTestHighBiasedMerge is broken, see Merge doc comment. -func BrokenTestHighBiasedMerge(t *testing.T) { - rand.Seed(42) - s1 := NewHighBiased(RelativeEpsilon) - s2 := NewHighBiased(RelativeEpsilon) - a := populateStream(s1) - a = append(a, populateStream(s2)...) - s1.Merge(s2.Samples()) - verifyHighPercsWithRelativeEpsilon(t, a, s2) -} - -func TestUncompressed(t *testing.T) { - q := NewTargeted(Targets) - for i := 100; i > 0; i-- { - q.Insert(float64(i)) - } - if g := q.Count(); g != 100 { - t.Errorf("want count 100, got %d", g) - } - // Before compression, Query should have 100% accuracy. - for quantile := range Targets { - w := quantile * 100 - if g := q.Query(quantile); g != w { - t.Errorf("want %f, got %f", w, g) - } - } -} - -func TestUncompressedSamples(t *testing.T) { - q := NewTargeted(map[float64]float64{0.99: 0.001}) - for i := 1; i <= 100; i++ { - q.Insert(float64(i)) - } - if g := q.Samples().Len(); g != 100 { - t.Errorf("want count 100, got %d", g) - } -} - -func TestUncompressedOne(t *testing.T) { - q := NewTargeted(map[float64]float64{0.99: 0.01}) - q.Insert(3.14) - if g := q.Query(0.90); g != 3.14 { - t.Error("want PI, got", g) - } -} - -func TestDefaults(t *testing.T) { - if g := NewTargeted(map[float64]float64{0.99: 0.001}).Query(0.99); g != 0 { - t.Errorf("want 0, got %f", g) - } -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/examples/main.go b/Godeps/_workspace/src/github.com/blang/semver/examples/main.go deleted file mode 100644 index f36c983d9..000000000 --- a/Godeps/_workspace/src/github.com/blang/semver/examples/main.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -import ( - "fmt" - "github.com/blang/semver" -) - -func main() { - v, err := semver.Parse("0.0.1-alpha.preview.222+123.github") - if err != nil { - fmt.Printf("Error while parsing (not valid): %q", err) - } - fmt.Printf("Version to string: %q\n", v) - - fmt.Printf("Major: %d\n", v.Major) - fmt.Printf("Minor: %d\n", v.Minor) - fmt.Printf("Patch: %d\n", v.Patch) - - // Prerelease versions - if len(v.Pre) > 0 { - fmt.Println("Prerelease versions:") - for i, pre := range v.Pre { - fmt.Printf("%d: %q\n", i, pre) - } - } - - // Build meta data - if len(v.Build) > 0 { - fmt.Println("Build meta data:") - for i, build := range v.Build { - fmt.Printf("%d: %q\n", i, build) - } - } - - // Make == Parse (Value), New for Pointer - v001, err := semver.Make("0.0.1") - - fmt.Println("\nUse Version.Compare for comparisons (-1, 0, 1):") - fmt.Printf("%q is greater than %q: Compare == %d\n", v001, v, v001.Compare(v)) - fmt.Printf("%q is less than %q: Compare == %d\n", v, v001, v.Compare(v001)) - fmt.Printf("%q is equal to %q: Compare == %d\n", v, v, v.Compare(v)) - - fmt.Println("\nUse comparison helpers returning booleans:") - fmt.Printf("%q is greater than %q: %t\n", v001, v, v001.GT(v)) - fmt.Printf("%q is greater than equal %q: %t\n", v001, v, v001.GTE(v)) - fmt.Printf("%q is greater than equal %q: %t\n", v, v, v.GTE(v)) - fmt.Printf("%q is less than %q: %t\n", v, v001, v.LT(v001)) - fmt.Printf("%q is less than equal %q: %t\n", v, v001, v.LTE(v001)) - fmt.Printf("%q is less than equal %q: %t\n", v, v, v.LTE(v)) - - fmt.Println("\nManipulate Version in place:") - v.Pre[0], err = semver.NewPRVersion("beta") - if err != nil { - fmt.Printf("Error parsing pre release version: %q", err) - } - fmt.Printf("Version to string: %q\n", v) - - fmt.Println("\nCompare Prerelease versions:") - pre1, _ := semver.NewPRVersion("123") - pre2, _ := semver.NewPRVersion("alpha") - pre3, _ := semver.NewPRVersion("124") - fmt.Printf("%q is less than %q: Compare == %d\n", pre1, pre2, pre1.Compare(pre2)) - fmt.Printf("%q is greater than %q: Compare == %d\n", pre3, pre1, pre3.Compare(pre1)) - fmt.Printf("%q is equal to %q: Compare == %d\n", pre1, pre1, pre1.Compare(pre1)) - - fmt.Println("\nValidate versions:") - v.Build[0] = "?" - - err = v.Validate() - if err != nil { - fmt.Printf("Validation failed: %s\n", err) - } - - fmt.Println("Create valid build meta data:") - b1, _ := semver.NewBuildVersion("build123") - v.Build[0] = b1 - fmt.Printf("Version with new build version %q\n", v) - - _, err = semver.NewBuildVersion("build?123") - if err != nil { - fmt.Printf("Create build version failed: %s\n", err) - } -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/json_test.go b/Godeps/_workspace/src/github.com/blang/semver/json_test.go deleted file mode 100644 index 039117da9..000000000 --- a/Godeps/_workspace/src/github.com/blang/semver/json_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package semver - -import ( - "encoding/json" - "strconv" - "testing" -) - -func TestJSONMarshal(t *testing.T) { - versionString := "3.1.4-alpha.1.5.9+build.2.6.5" - v, err := Parse(versionString) - if err != nil { - t.Fatal(err) - } - - versionJSON, err := json.Marshal(v) - if err != nil { - t.Fatal(err) - } - - quotedVersionString := strconv.Quote(versionString) - - if string(versionJSON) != quotedVersionString { - t.Fatalf("JSON marshaled semantic version not equal: expected %q, got %q", quotedVersionString, string(versionJSON)) - } -} - -func TestJSONUnmarshal(t *testing.T) { - versionString := "3.1.4-alpha.1.5.9+build.2.6.5" - quotedVersionString := strconv.Quote(versionString) - - var v Version - if err := json.Unmarshal([]byte(quotedVersionString), &v); err != nil { - t.Fatal(err) - } - - if v.String() != versionString { - t.Fatalf("JSON unmarshaled semantic version not equal: expected %q, got %q", versionString, v.String()) - } - - badVersionString := strconv.Quote("3.1.4.1.5.9.2.6.5-other-digits-of-pi") - if err := json.Unmarshal([]byte(badVersionString), &v); err == nil { - t.Fatal("expected JSON unmarshal error, got nil") - } -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/semver_test.go b/Godeps/_workspace/src/github.com/blang/semver/semver_test.go deleted file mode 100644 index e56ebce05..000000000 --- a/Godeps/_workspace/src/github.com/blang/semver/semver_test.go +++ /dev/null @@ -1,417 +0,0 @@ -package semver - -import ( - "testing" -) - -func prstr(s string) PRVersion { - return PRVersion{s, 0, false} -} - -func prnum(i uint64) PRVersion { - return PRVersion{"", i, true} -} - -type formatTest struct { - v Version - result string -} - -var formatTests = []formatTest{ - {Version{1, 2, 3, nil, nil}, "1.2.3"}, - {Version{0, 0, 1, nil, nil}, "0.0.1"}, - {Version{0, 0, 1, []PRVersion{prstr("alpha"), prstr("preview")}, []string{"123", "456"}}, "0.0.1-alpha.preview+123.456"}, - {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, []string{"123", "456"}}, "1.2.3-alpha.1+123.456"}, - {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, nil}, "1.2.3-alpha.1"}, - {Version{1, 2, 3, nil, []string{"123", "456"}}, "1.2.3+123.456"}, - // Prereleases and build metadata hyphens - {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, []string{"123", "b-uild"}}, "1.2.3-alpha.b-eta+123.b-uild"}, - {Version{1, 2, 3, nil, []string{"123", "b-uild"}}, "1.2.3+123.b-uild"}, - {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, nil}, "1.2.3-alpha.b-eta"}, -} - -func TestStringer(t *testing.T) { - for _, test := range formatTests { - if res := test.v.String(); res != test.result { - t.Errorf("Stringer, expected %q but got %q", test.result, res) - } - } -} - -func TestParse(t *testing.T) { - for _, test := range formatTests { - if v, err := Parse(test.result); err != nil { - t.Errorf("Error parsing %q: %q", test.result, err) - } else if comp := v.Compare(test.v); comp != 0 { - t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp) - } else if err := v.Validate(); err != nil { - t.Errorf("Error validating parsed version %q: %q", test.v, err) - } - } -} - -func TestMustParse(t *testing.T) { - _ = MustParse("32.2.1-alpha") -} - -func TestMustParse_panic(t *testing.T) { - defer func() { - if recover() == nil { - t.Errorf("Should have panicked") - } - }() - _ = MustParse("invalid version") -} - -func TestValidate(t *testing.T) { - for _, test := range formatTests { - if err := test.v.Validate(); err != nil { - t.Errorf("Error validating %q: %q", test.v, err) - } - } -} - -type compareTest struct { - v1 Version - v2 Version - result int -} - -var compareTests = []compareTest{ - {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 0}, - {Version{2, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 1}, - {Version{0, 1, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 0}, - {Version{0, 2, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 1}, - {Version{0, 0, 1, nil, nil}, Version{0, 0, 1, nil, nil}, 0}, - {Version{0, 0, 2, nil, nil}, Version{0, 0, 1, nil, nil}, 1}, - {Version{1, 2, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 0}, - {Version{2, 2, 4, nil, nil}, Version{1, 2, 4, nil, nil}, 1}, - {Version{1, 3, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 1}, - {Version{1, 2, 4, nil, nil}, Version{1, 2, 3, nil, nil}, 1}, - - // Spec Examples #11 - {Version{1, 0, 0, nil, nil}, Version{2, 0, 0, nil, nil}, -1}, - {Version{2, 0, 0, nil, nil}, Version{2, 1, 0, nil, nil}, -1}, - {Version{2, 1, 0, nil, nil}, Version{2, 1, 1, nil, nil}, -1}, - - // Spec Examples #9 - {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, 1}, - {Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, -1}, - {Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, -1}, - {Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, -1}, - {Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, -1}, - {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, -1}, - {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, -1}, - {Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, Version{1, 0, 0, nil, nil}, -1}, - - // Ignore Build metadata - {Version{1, 0, 0, nil, []string{"1", "2", "3"}}, Version{1, 0, 0, nil, nil}, 0}, -} - -func TestCompare(t *testing.T) { - for _, test := range compareTests { - if res := test.v1.Compare(test.v2); res != test.result { - t.Errorf("Comparing %q : %q, expected %d but got %d", test.v1, test.v2, test.result, res) - } - //Test counterpart - if res := test.v2.Compare(test.v1); res != -test.result { - t.Errorf("Comparing %q : %q, expected %d but got %d", test.v2, test.v1, -test.result, res) - } - } -} - -type wrongformatTest struct { - v *Version - str string -} - -var wrongformatTests = []wrongformatTest{ - {nil, ""}, - {nil, "."}, - {nil, "1."}, - {nil, ".1"}, - {nil, "a.b.c"}, - {nil, "1.a.b"}, - {nil, "1.1.a"}, - {nil, "1.a.1"}, - {nil, "a.1.1"}, - {nil, ".."}, - {nil, "1.."}, - {nil, "1.1."}, - {nil, "1..1"}, - {nil, "1.1.+123"}, - {nil, "1.1.-beta"}, - {nil, "-1.1.1"}, - {nil, "1.-1.1"}, - {nil, "1.1.-1"}, - // giant numbers - {nil, "20000000000000000000.1.1"}, - {nil, "1.20000000000000000000.1"}, - {nil, "1.1.20000000000000000000"}, - {nil, "1.1.1-20000000000000000000"}, - // Leading zeroes - {nil, "01.1.1"}, - {nil, "001.1.1"}, - {nil, "1.01.1"}, - {nil, "1.001.1"}, - {nil, "1.1.01"}, - {nil, "1.1.001"}, - {nil, "1.1.1-01"}, - {nil, "1.1.1-001"}, - {nil, "1.1.1-beta.01"}, - {nil, "1.1.1-beta.001"}, - {&Version{0, 0, 0, []PRVersion{prstr("!")}, nil}, "0.0.0-!"}, - {&Version{0, 0, 0, nil, []string{"!"}}, "0.0.0+!"}, - // empty prversion - {&Version{0, 0, 0, []PRVersion{prstr(""), prstr("alpha")}, nil}, "0.0.0-.alpha"}, - // empty build meta data - {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{""}}, "0.0.0-alpha+"}, - {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{"test", ""}}, "0.0.0-alpha+test."}, -} - -func TestWrongFormat(t *testing.T) { - for _, test := range wrongformatTests { - - if res, err := Parse(test.str); err == nil { - t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res) - } - - if test.v != nil { - if err := test.v.Validate(); err == nil { - t.Errorf("Validating wrong format version %q (%q), expected error", test.v, test.str) - } - } - } -} - -func TestCompareHelper(t *testing.T) { - v := Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil} - v1 := Version{1, 0, 0, nil, nil} - if !v.EQ(v) { - t.Errorf("%q should be equal to %q", v, v) - } - if !v.Equals(v) { - t.Errorf("%q should be equal to %q", v, v) - } - if !v1.NE(v) { - t.Errorf("%q should not be equal to %q", v1, v) - } - if !v.GTE(v) { - t.Errorf("%q should be greater than or equal to %q", v, v) - } - if !v.LTE(v) { - t.Errorf("%q should be less than or equal to %q", v, v) - } - if !v.LT(v1) { - t.Errorf("%q should be less than %q", v, v1) - } - if !v.LTE(v1) { - t.Errorf("%q should be less than or equal %q", v, v1) - } - if !v.LE(v1) { - t.Errorf("%q should be less than or equal %q", v, v1) - } - if !v1.GT(v) { - t.Errorf("%q should be greater than %q", v1, v) - } - if !v1.GTE(v) { - t.Errorf("%q should be greater than or equal %q", v1, v) - } - if !v1.GE(v) { - t.Errorf("%q should be greater than or equal %q", v1, v) - } -} - -func TestPreReleaseVersions(t *testing.T) { - p1, err := NewPRVersion("123") - if !p1.IsNumeric() { - t.Errorf("Expected numeric prversion, got %q", p1) - } - if p1.VersionNum != 123 { - t.Error("Wrong prversion number") - } - if err != nil { - t.Errorf("Not expected error %q", err) - } - p2, err := NewPRVersion("alpha") - if p2.IsNumeric() { - t.Errorf("Expected non-numeric prversion, got %q", p2) - } - if p2.VersionStr != "alpha" { - t.Error("Wrong prversion string") - } - if err != nil { - t.Errorf("Not expected error %q", err) - } -} - -func TestBuildMetaDataVersions(t *testing.T) { - _, err := NewBuildVersion("123") - if err != nil { - t.Errorf("Unexpected error %q", err) - } - - _, err = NewBuildVersion("build") - if err != nil { - t.Errorf("Unexpected error %q", err) - } - - _, err = NewBuildVersion("test?") - if err == nil { - t.Error("Expected error, got none") - } - - _, err = NewBuildVersion("") - if err == nil { - t.Error("Expected error, got none") - } -} - -func TestNewHelper(t *testing.T) { - v, err := New("1.2.3") - if err != nil { - t.Fatalf("Unexpected error %q", err) - } - - // New returns pointer - if v == nil { - t.Fatal("Version is nil") - } - if v.Compare(Version{1, 2, 3, nil, nil}) != 0 { - t.Fatal("Unexpected comparison problem") - } -} - -func TestMakeHelper(t *testing.T) { - v, err := Make("1.2.3") - if err != nil { - t.Fatalf("Unexpected error %q", err) - } - if v.Compare(Version{1, 2, 3, nil, nil}) != 0 { - t.Fatal("Unexpected comparison problem") - } -} - -func BenchmarkParseSimple(b *testing.B) { - const VERSION = "0.0.1" - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - Parse(VERSION) - } -} - -func BenchmarkParseComplex(b *testing.B) { - const VERSION = "0.0.1-alpha.preview+123.456" - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - Parse(VERSION) - } -} - -func BenchmarkParseAverage(b *testing.B) { - l := len(formatTests) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - Parse(formatTests[n%l].result) - } -} - -func BenchmarkStringSimple(b *testing.B) { - const VERSION = "0.0.1" - v, _ := Parse(VERSION) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - v.String() - } -} - -func BenchmarkStringLarger(b *testing.B) { - const VERSION = "11.15.2012" - v, _ := Parse(VERSION) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - v.String() - } -} - -func BenchmarkStringComplex(b *testing.B) { - const VERSION = "0.0.1-alpha.preview+123.456" - v, _ := Parse(VERSION) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - v.String() - } -} - -func BenchmarkStringAverage(b *testing.B) { - l := len(formatTests) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - formatTests[n%l].v.String() - } -} - -func BenchmarkValidateSimple(b *testing.B) { - const VERSION = "0.0.1" - v, _ := Parse(VERSION) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - v.Validate() - } -} - -func BenchmarkValidateComplex(b *testing.B) { - const VERSION = "0.0.1-alpha.preview+123.456" - v, _ := Parse(VERSION) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - v.Validate() - } -} - -func BenchmarkValidateAverage(b *testing.B) { - l := len(formatTests) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - formatTests[n%l].v.Validate() - } -} - -func BenchmarkCompareSimple(b *testing.B) { - const VERSION = "0.0.1" - v, _ := Parse(VERSION) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - v.Compare(v) - } -} - -func BenchmarkCompareComplex(b *testing.B) { - const VERSION = "0.0.1-alpha.preview+123.456" - v, _ := Parse(VERSION) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - v.Compare(v) - } -} - -func BenchmarkCompareAverage(b *testing.B) { - l := len(compareTests) - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - compareTests[n%l].v1.Compare((compareTests[n%l].v2)) - } -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/sort_test.go b/Godeps/_workspace/src/github.com/blang/semver/sort_test.go deleted file mode 100644 index 68893972a..000000000 --- a/Godeps/_workspace/src/github.com/blang/semver/sort_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package semver - -import ( - "reflect" - "testing" -) - -func TestSort(t *testing.T) { - v100, _ := Parse("1.0.0") - v010, _ := Parse("0.1.0") - v001, _ := Parse("0.0.1") - versions := []Version{v010, v100, v001} - Sort(versions) - - correct := []Version{v001, v010, v100} - if !reflect.DeepEqual(versions, correct) { - t.Fatalf("Sort returned wrong order: %s", versions) - } -} - -func BenchmarkSort(b *testing.B) { - v100, _ := Parse("1.0.0") - v010, _ := Parse("0.1.0") - v001, _ := Parse("0.0.1") - b.ReportAllocs() - b.ResetTimer() - for n := 0; n < b.N; n++ { - Sort([]Version{v010, v100, v001}) - } -} diff --git a/Godeps/_workspace/src/github.com/blang/semver/sql_test.go b/Godeps/_workspace/src/github.com/blang/semver/sql_test.go deleted file mode 100644 index ebf48b584..000000000 --- a/Godeps/_workspace/src/github.com/blang/semver/sql_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package semver - -import ( - "testing" -) - -type scanTest struct { - val interface{} - shouldError bool - expected string -} - -var scanTests = []scanTest{ - {"1.2.3", false, "1.2.3"}, - {[]byte("1.2.3"), false, "1.2.3"}, - {7, true, ""}, - {7e4, true, ""}, - {true, true, ""}, -} - -func TestScanString(t *testing.T) { - for _, tc := range scanTests { - s := &Version{} - err := s.Scan(tc.val) - if tc.shouldError { - if err == nil { - t.Fatalf("Scan did not return an error on %v (%T)", tc.val, tc.val) - } - } else { - if err != nil { - t.Fatalf("Scan returned an unexpected error: %s (%T) on %v (%T)", tc.val, tc.val, tc.val, tc.val) - } - if val, _ := s.Value(); val != tc.expected { - t.Errorf("Wrong Value returned, expected %q, got %q", tc.expected, val) - } - } - } -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go deleted file mode 100644 index 39b7525b3..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2013 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" -) - -// custom type to test Stinger interface on non-pointer receiver. -type stringer string - -// String implements the Stringer interface for testing invocation of custom -// stringers on types with non-pointer receivers. -func (s stringer) String() string { - return "stringer " + string(s) -} - -// custom type to test Stinger interface on pointer receiver. -type pstringer string - -// String implements the Stringer interface for testing invocation of custom -// stringers on types with only pointer receivers. -func (s *pstringer) String() string { - return "stringer " + string(*s) -} - -// xref1 and xref2 are cross referencing structs for testing circular reference -// detection. -type xref1 struct { - ps2 *xref2 -} -type xref2 struct { - ps1 *xref1 -} - -// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular -// reference for testing detection. -type indirCir1 struct { - ps2 *indirCir2 -} -type indirCir2 struct { - ps3 *indirCir3 -} -type indirCir3 struct { - ps1 *indirCir1 -} - -// embed is used to test embedded structures. -type embed struct { - a string -} - -// embedwrap is used to test embedded structures. -type embedwrap struct { - *embed - e *embed -} - -// panicer is used to intentionally cause a panic for testing spew properly -// handles them -type panicer int - -func (p panicer) String() string { - panic("test panic") -} - -// customError is used to test custom error interface invocation. -type customError int - -func (e customError) Error() string { - return fmt.Sprintf("error: %d", int(e)) -} - -// stringizeWants converts a slice of wanted test output into a format suitable -// for a test error message. -func stringizeWants(wants []string) string { - s := "" - for i, want := range wants { - if i > 0 { - s += fmt.Sprintf("want%d: %s", i+1, want) - } else { - s += "want: " + want - } - } - return s -} - -// testFailed returns whether or not a test failed by checking if the result -// of the test is in the slice of wanted strings. -func testFailed(result string, wants []string) bool { - for _, want := range wants { - if result == want { - return false - } - } - return true -} - -type sortableStruct struct { - x int -} - -func (ss sortableStruct) String() string { - return fmt.Sprintf("ss.%d", ss.x) -} - -type unsortableStruct struct { - x int -} - -type sortTestCase struct { - input []reflect.Value - expected []reflect.Value -} - -func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) { - getInterfaces := func(values []reflect.Value) []interface{} { - interfaces := []interface{}{} - for _, v := range values { - interfaces = append(interfaces, v.Interface()) - } - return interfaces - } - - for _, test := range tests { - spew.SortValues(test.input, cs) - // reflect.DeepEqual cannot really make sense of reflect.Value, - // probably because of all the pointer tricks. For instance, - // v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{} - // instead. - input := getInterfaces(test.input) - expected := getInterfaces(test.expected) - if !reflect.DeepEqual(input, expected) { - t.Errorf("Sort mismatch:\n %v != %v", input, expected) - } - } -} - -// TestSortValues ensures the sort functionality for relect.Value based sorting -// works as intended. -func TestSortValues(t *testing.T) { - v := reflect.ValueOf - - a := v("a") - b := v("b") - c := v("c") - embedA := v(embed{"a"}) - embedB := v(embed{"b"}) - embedC := v(embed{"c"}) - tests := []sortTestCase{ - // No values. - { - []reflect.Value{}, - []reflect.Value{}, - }, - // Bools. - { - []reflect.Value{v(false), v(true), v(false)}, - []reflect.Value{v(false), v(false), v(true)}, - }, - // Ints. - { - []reflect.Value{v(2), v(1), v(3)}, - []reflect.Value{v(1), v(2), v(3)}, - }, - // Uints. - { - []reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))}, - []reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))}, - }, - // Floats. - { - []reflect.Value{v(2.0), v(1.0), v(3.0)}, - []reflect.Value{v(1.0), v(2.0), v(3.0)}, - }, - // Strings. - { - []reflect.Value{b, a, c}, - []reflect.Value{a, b, c}, - }, - // Array - { - []reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})}, - []reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})}, - }, - // Uintptrs. - { - []reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))}, - []reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))}, - }, - // SortableStructs. - { - // Note: not sorted - DisableMethods is set. - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - }, - // UnsortableStructs. - { - // Note: not sorted - SpewKeys is false. - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - }, - // Invalid. - { - []reflect.Value{embedB, embedA, embedC}, - []reflect.Value{embedB, embedA, embedC}, - }, - } - cs := spew.ConfigState{DisableMethods: true, SpewKeys: false} - helpTestSortValues(tests, &cs, t) -} - -// TestSortValuesWithMethods ensures the sort functionality for relect.Value -// based sorting works as intended when using string methods. -func TestSortValuesWithMethods(t *testing.T) { - v := reflect.ValueOf - - a := v("a") - b := v("b") - c := v("c") - tests := []sortTestCase{ - // Ints. - { - []reflect.Value{v(2), v(1), v(3)}, - []reflect.Value{v(1), v(2), v(3)}, - }, - // Strings. - { - []reflect.Value{b, a, c}, - []reflect.Value{a, b, c}, - }, - // SortableStructs. - { - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, - }, - // UnsortableStructs. - { - // Note: not sorted - SpewKeys is false. - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - }, - } - cs := spew.ConfigState{DisableMethods: false, SpewKeys: false} - helpTestSortValues(tests, &cs, t) -} - -// TestSortValuesWithSpew ensures the sort functionality for relect.Value -// based sorting works as intended when using spew to stringify keys. -func TestSortValuesWithSpew(t *testing.T) { - v := reflect.ValueOf - - a := v("a") - b := v("b") - c := v("c") - tests := []sortTestCase{ - // Ints. - { - []reflect.Value{v(2), v(1), v(3)}, - []reflect.Value{v(1), v(2), v(3)}, - }, - // Strings. - { - []reflect.Value{b, a, c}, - []reflect.Value{a, b, c}, - }, - // SortableStructs. - { - []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, - []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, - }, - // UnsortableStructs. - { - []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, - []reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})}, - }, - } - cs := spew.ConfigState{DisableMethods: true, SpewKeys: true} - helpTestSortValues(tests, &cs, t) -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go deleted file mode 100644 index 2b320401d..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * Copyright (c) 2013 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -Test Summary: -NOTE: For each test, a nil pointer, a single pointer and double pointer to the -base test element are also tested to ensure proper indirection across all types. - -- Max int8, int16, int32, int64, int -- Max uint8, uint16, uint32, uint64, uint -- Boolean true and false -- Standard complex64 and complex128 -- Array containing standard ints -- Array containing type with custom formatter on pointer receiver only -- Array containing interfaces -- Array containing bytes -- Slice containing standard float32 values -- Slice containing type with custom formatter on pointer receiver only -- Slice containing interfaces -- Slice containing bytes -- Nil slice -- Standard string -- Nil interface -- Sub-interface -- Map with string keys and int vals -- Map with custom formatter type on pointer receiver only keys and vals -- Map with interface keys and values -- Map with nil interface value -- Struct with primitives -- Struct that contains another struct -- Struct that contains custom type with Stringer pointer interface via both - exported and unexported fields -- Struct that contains embedded struct and field to same struct -- Uintptr to 0 (null pointer) -- Uintptr address of real variable -- Unsafe.Pointer to 0 (null pointer) -- Unsafe.Pointer to address of real variable -- Nil channel -- Standard int channel -- Function with no params and no returns -- Function with param and no returns -- Function with multiple params and multiple returns -- Struct that is circular through self referencing -- Structs that are circular through cross referencing -- Structs that are indirectly circular -- Type that panics in its Stringer interface -*/ - -package spew_test - -import ( - "bytes" - "fmt" - "testing" - "unsafe" - - "github.com/davecgh/go-spew/spew" -) - -// dumpTest is used to describe a test to be perfomed against the Dump method. -type dumpTest struct { - in interface{} - wants []string -} - -// dumpTests houses all of the tests to be performed against the Dump method. -var dumpTests = make([]dumpTest, 0) - -// addDumpTest is a helper method to append the passed input and desired result -// to dumpTests -func addDumpTest(in interface{}, wants ...string) { - test := dumpTest{in, wants} - dumpTests = append(dumpTests, test) -} - -func addIntDumpTests() { - // Max int8. - v := int8(127) - nv := (*int8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "int8" - vs := "127" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Max int16. - v2 := int16(32767) - nv2 := (*int16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "int16" - v2s := "32767" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")()\n") - - // Max int32. - v3 := int32(2147483647) - nv3 := (*int32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "int32" - v3s := "2147483647" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")()\n") - - // Max int64. - v4 := int64(9223372036854775807) - nv4 := (*int64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "int64" - v4s := "9223372036854775807" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")()\n") - - // Max int. - v5 := int(2147483647) - nv5 := (*int)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "int" - v5s := "2147483647" - addDumpTest(v5, "("+v5t+") "+v5s+"\n") - addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") - addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") - addDumpTest(nv5, "(*"+v5t+")()\n") -} - -func addUintDumpTests() { - // Max uint8. - v := uint8(255) - nv := (*uint8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uint8" - vs := "255" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Max uint16. - v2 := uint16(65535) - nv2 := (*uint16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")()\n") - - // Max uint32. - v3 := uint32(4294967295) - nv3 := (*uint32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "uint32" - v3s := "4294967295" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")()\n") - - // Max uint64. - v4 := uint64(18446744073709551615) - nv4 := (*uint64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "uint64" - v4s := "18446744073709551615" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")()\n") - - // Max uint. - v5 := uint(4294967295) - nv5 := (*uint)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "uint" - v5s := "4294967295" - addDumpTest(v5, "("+v5t+") "+v5s+"\n") - addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") - addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") - addDumpTest(nv5, "(*"+v5t+")()\n") -} - -func addBoolDumpTests() { - // Boolean true. - v := bool(true) - nv := (*bool)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "bool" - vs := "true" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Boolean false. - v2 := bool(false) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "bool" - v2s := "false" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") -} - -func addFloatDumpTests() { - // Standard float32. - v := float32(3.1415) - nv := (*float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "float32" - vs := "3.1415" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Standard float64. - v2 := float64(3.1415926) - nv2 := (*float64)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "float64" - v2s := "3.1415926" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")()\n") -} - -func addComplexDumpTests() { - // Standard complex64. - v := complex(float32(6), -2) - nv := (*complex64)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "complex64" - vs := "(6-2i)" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Standard complex128. - v2 := complex(float64(-6), 2) - nv2 := (*complex128)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "complex128" - v2s := "(-6+2i)" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")()\n") -} - -func addArrayDumpTests() { - // Array containing standard ints. - v := [3]int{1, 2, 3} - vLen := fmt.Sprintf("%d", len(v)) - vCap := fmt.Sprintf("%d", cap(v)) - nv := (*[3]int)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "int" - vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 1,\n (" + - vt + ") 2,\n (" + vt + ") 3\n}" - addDumpTest(v, "([3]"+vt+") "+vs+"\n") - addDumpTest(pv, "(*[3]"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**[3]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*[3]"+vt+")()\n") - - // Array containing type with custom formatter on pointer receiver only. - v2i0 := pstringer("1") - v2i1 := pstringer("2") - v2i2 := pstringer("3") - v2 := [3]pstringer{v2i0, v2i1, v2i2} - v2i0Len := fmt.Sprintf("%d", len(v2i0)) - v2i1Len := fmt.Sprintf("%d", len(v2i1)) - v2i2Len := fmt.Sprintf("%d", len(v2i2)) - v2Len := fmt.Sprintf("%d", len(v2)) - v2Cap := fmt.Sprintf("%d", cap(v2)) - nv2 := (*[3]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.pstringer" - v2sp := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + - ") (len=" + v2i0Len + ") stringer 1,\n (" + v2t + - ") (len=" + v2i1Len + ") stringer 2,\n (" + v2t + - ") (len=" + v2i2Len + ") " + "stringer 3\n}" - v2s := v2sp - if spew.UnsafeDisabled { - v2s = "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + - ") (len=" + v2i0Len + ") \"1\",\n (" + v2t + ") (len=" + - v2i1Len + ") \"2\",\n (" + v2t + ") (len=" + v2i2Len + - ") " + "\"3\"\n}" - } - addDumpTest(v2, "([3]"+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*[3]"+v2t+")("+v2Addr+")("+v2sp+")\n") - addDumpTest(&pv2, "(**[3]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2sp+")\n") - addDumpTest(nv2, "(*[3]"+v2t+")()\n") - - // Array containing interfaces. - v3i0 := "one" - v3 := [3]interface{}{v3i0, int(2), uint(3)} - v3i0Len := fmt.Sprintf("%d", len(v3i0)) - v3Len := fmt.Sprintf("%d", len(v3)) - v3Cap := fmt.Sprintf("%d", cap(v3)) - nv3 := (*[3]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[3]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + - "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + - v3t4 + ") 3\n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")()\n") - - // Array containing bytes. - v4 := [34]byte{ - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, - } - v4Len := fmt.Sprintf("%d", len(v4)) - v4Cap := fmt.Sprintf("%d", cap(v4)) - nv4 := (*[34]byte)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "[34]uint8" - v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + - "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + - " |............... |\n" + - " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + - " |!\"#$%&'()*+,-./0|\n" + - " 00000020 31 32 " + - " |12|\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")()\n") -} - -func addSliceDumpTests() { - // Slice containing standard float32 values. - v := []float32{3.14, 6.28, 12.56} - vLen := fmt.Sprintf("%d", len(v)) - vCap := fmt.Sprintf("%d", cap(v)) - nv := (*[]float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "float32" - vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 3.14,\n (" + - vt + ") 6.28,\n (" + vt + ") 12.56\n}" - addDumpTest(v, "([]"+vt+") "+vs+"\n") - addDumpTest(pv, "(*[]"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**[]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*[]"+vt+")()\n") - - // Slice containing type with custom formatter on pointer receiver only. - v2i0 := pstringer("1") - v2i1 := pstringer("2") - v2i2 := pstringer("3") - v2 := []pstringer{v2i0, v2i1, v2i2} - v2i0Len := fmt.Sprintf("%d", len(v2i0)) - v2i1Len := fmt.Sprintf("%d", len(v2i1)) - v2i2Len := fmt.Sprintf("%d", len(v2i2)) - v2Len := fmt.Sprintf("%d", len(v2)) - v2Cap := fmt.Sprintf("%d", cap(v2)) - nv2 := (*[]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.pstringer" - v2s := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" + - v2i0Len + ") stringer 1,\n (" + v2t + ") (len=" + v2i1Len + - ") stringer 2,\n (" + v2t + ") (len=" + v2i2Len + ") " + - "stringer 3\n}" - addDumpTest(v2, "([]"+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*[]"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**[]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*[]"+v2t+")()\n") - - // Slice containing interfaces. - v3i0 := "one" - v3 := []interface{}{v3i0, int(2), uint(3), nil} - v3i0Len := fmt.Sprintf("%d", len(v3i0)) - v3Len := fmt.Sprintf("%d", len(v3)) - v3Cap := fmt.Sprintf("%d", cap(v3)) - nv3 := (*[]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3t5 := "interface {}" - v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + - "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + - v3t4 + ") 3,\n (" + v3t5 + ") \n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")()\n") - - // Slice containing bytes. - v4 := []byte{ - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, - } - v4Len := fmt.Sprintf("%d", len(v4)) - v4Cap := fmt.Sprintf("%d", cap(v4)) - nv4 := (*[]byte)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "[]uint8" - v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + - "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + - " |............... |\n" + - " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + - " |!\"#$%&'()*+,-./0|\n" + - " 00000020 31 32 " + - " |12|\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")()\n") - - // Nil slice. - v5 := []int(nil) - nv5 := (*[]int)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "[]int" - v5s := "" - addDumpTest(v5, "("+v5t+") "+v5s+"\n") - addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") - addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") - addDumpTest(nv5, "(*"+v5t+")()\n") -} - -func addStringDumpTests() { - // Standard string. - v := "test" - vLen := fmt.Sprintf("%d", len(v)) - nv := (*string)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "string" - vs := "(len=" + vLen + ") \"test\"" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") -} - -func addInterfaceDumpTests() { - // Nil interface. - var v interface{} - nv := (*interface{})(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "interface {}" - vs := "" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Sub-interface. - v2 := interface{}(uint16(65535)) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") -} - -func addMapDumpTests() { - // Map with string keys and int vals. - k := "one" - kk := "two" - m := map[string]int{k: 1, kk: 2} - klen := fmt.Sprintf("%d", len(k)) // not kLen to shut golint up - kkLen := fmt.Sprintf("%d", len(kk)) - mLen := fmt.Sprintf("%d", len(m)) - nilMap := map[string]int(nil) - nm := (*map[string]int)(nil) - pm := &m - mAddr := fmt.Sprintf("%p", pm) - pmAddr := fmt.Sprintf("%p", &pm) - mt := "map[string]int" - mt1 := "string" - mt2 := "int" - ms := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + klen + ") " + - "\"one\": (" + mt2 + ") 1,\n (" + mt1 + ") (len=" + kkLen + - ") \"two\": (" + mt2 + ") 2\n}" - ms2 := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + kkLen + ") " + - "\"two\": (" + mt2 + ") 2,\n (" + mt1 + ") (len=" + klen + - ") \"one\": (" + mt2 + ") 1\n}" - addDumpTest(m, "("+mt+") "+ms+"\n", "("+mt+") "+ms2+"\n") - addDumpTest(pm, "(*"+mt+")("+mAddr+")("+ms+")\n", - "(*"+mt+")("+mAddr+")("+ms2+")\n") - addDumpTest(&pm, "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms+")\n", - "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms2+")\n") - addDumpTest(nm, "(*"+mt+")()\n") - addDumpTest(nilMap, "("+mt+") \n") - - // Map with custom formatter type on pointer receiver only keys and vals. - k2 := pstringer("one") - v2 := pstringer("1") - m2 := map[pstringer]pstringer{k2: v2} - k2Len := fmt.Sprintf("%d", len(k2)) - v2Len := fmt.Sprintf("%d", len(v2)) - m2Len := fmt.Sprintf("%d", len(m2)) - nilMap2 := map[pstringer]pstringer(nil) - nm2 := (*map[pstringer]pstringer)(nil) - pm2 := &m2 - m2Addr := fmt.Sprintf("%p", pm2) - pm2Addr := fmt.Sprintf("%p", &pm2) - m2t := "map[spew_test.pstringer]spew_test.pstringer" - m2t1 := "spew_test.pstringer" - m2t2 := "spew_test.pstringer" - m2s := "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + ") " + - "stringer one: (" + m2t2 + ") (len=" + v2Len + ") stringer 1\n}" - if spew.UnsafeDisabled { - m2s = "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + - ") " + "\"one\": (" + m2t2 + ") (len=" + v2Len + - ") \"1\"\n}" - } - addDumpTest(m2, "("+m2t+") "+m2s+"\n") - addDumpTest(pm2, "(*"+m2t+")("+m2Addr+")("+m2s+")\n") - addDumpTest(&pm2, "(**"+m2t+")("+pm2Addr+"->"+m2Addr+")("+m2s+")\n") - addDumpTest(nm2, "(*"+m2t+")()\n") - addDumpTest(nilMap2, "("+m2t+") \n") - - // Map with interface keys and values. - k3 := "one" - k3Len := fmt.Sprintf("%d", len(k3)) - m3 := map[interface{}]interface{}{k3: 1} - m3Len := fmt.Sprintf("%d", len(m3)) - nilMap3 := map[interface{}]interface{}(nil) - nm3 := (*map[interface{}]interface{})(nil) - pm3 := &m3 - m3Addr := fmt.Sprintf("%p", pm3) - pm3Addr := fmt.Sprintf("%p", &pm3) - m3t := "map[interface {}]interface {}" - m3t1 := "string" - m3t2 := "int" - m3s := "(len=" + m3Len + ") {\n (" + m3t1 + ") (len=" + k3Len + ") " + - "\"one\": (" + m3t2 + ") 1\n}" - addDumpTest(m3, "("+m3t+") "+m3s+"\n") - addDumpTest(pm3, "(*"+m3t+")("+m3Addr+")("+m3s+")\n") - addDumpTest(&pm3, "(**"+m3t+")("+pm3Addr+"->"+m3Addr+")("+m3s+")\n") - addDumpTest(nm3, "(*"+m3t+")()\n") - addDumpTest(nilMap3, "("+m3t+") \n") - - // Map with nil interface value. - k4 := "nil" - k4Len := fmt.Sprintf("%d", len(k4)) - m4 := map[string]interface{}{k4: nil} - m4Len := fmt.Sprintf("%d", len(m4)) - nilMap4 := map[string]interface{}(nil) - nm4 := (*map[string]interface{})(nil) - pm4 := &m4 - m4Addr := fmt.Sprintf("%p", pm4) - pm4Addr := fmt.Sprintf("%p", &pm4) - m4t := "map[string]interface {}" - m4t1 := "string" - m4t2 := "interface {}" - m4s := "(len=" + m4Len + ") {\n (" + m4t1 + ") (len=" + k4Len + ")" + - " \"nil\": (" + m4t2 + ") \n}" - addDumpTest(m4, "("+m4t+") "+m4s+"\n") - addDumpTest(pm4, "(*"+m4t+")("+m4Addr+")("+m4s+")\n") - addDumpTest(&pm4, "(**"+m4t+")("+pm4Addr+"->"+m4Addr+")("+m4s+")\n") - addDumpTest(nm4, "(*"+m4t+")()\n") - addDumpTest(nilMap4, "("+m4t+") \n") -} - -func addStructDumpTests() { - // Struct with primitives. - type s1 struct { - a int8 - b uint8 - } - v := s1{127, 255} - nv := (*s1)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.s1" - vt2 := "int8" - vt3 := "uint8" - vs := "{\n a: (" + vt2 + ") 127,\n b: (" + vt3 + ") 255\n}" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Struct that contains another struct. - type s2 struct { - s1 s1 - b bool - } - v2 := s2{s1{127, 255}, true} - nv2 := (*s2)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.s2" - v2t2 := "spew_test.s1" - v2t3 := "int8" - v2t4 := "uint8" - v2t5 := "bool" - v2s := "{\n s1: (" + v2t2 + ") {\n a: (" + v2t3 + ") 127,\n b: (" + - v2t4 + ") 255\n },\n b: (" + v2t5 + ") true\n}" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")()\n") - - // Struct that contains custom type with Stringer pointer interface via both - // exported and unexported fields. - type s3 struct { - s pstringer - S pstringer - } - v3 := s3{"test", "test2"} - nv3 := (*s3)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.s3" - v3t2 := "spew_test.pstringer" - v3s := "{\n s: (" + v3t2 + ") (len=4) stringer test,\n S: (" + v3t2 + - ") (len=5) stringer test2\n}" - v3sp := v3s - if spew.UnsafeDisabled { - v3s = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + - v3t2 + ") (len=5) \"test2\"\n}" - v3sp = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + - v3t2 + ") (len=5) stringer test2\n}" - } - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3sp+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3sp+")\n") - addDumpTest(nv3, "(*"+v3t+")()\n") - - // Struct that contains embedded struct and field to same struct. - e := embed{"embedstr"} - eLen := fmt.Sprintf("%d", len("embedstr")) - v4 := embedwrap{embed: &e, e: &e} - nv4 := (*embedwrap)(nil) - pv4 := &v4 - eAddr := fmt.Sprintf("%p", &e) - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "spew_test.embedwrap" - v4t2 := "spew_test.embed" - v4t3 := "string" - v4s := "{\n embed: (*" + v4t2 + ")(" + eAddr + ")({\n a: (" + v4t3 + - ") (len=" + eLen + ") \"embedstr\"\n }),\n e: (*" + v4t2 + - ")(" + eAddr + ")({\n a: (" + v4t3 + ") (len=" + eLen + ")" + - " \"embedstr\"\n })\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") - addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") - addDumpTest(nv4, "(*"+v4t+")()\n") -} - -func addUintptrDumpTests() { - // Null pointer. - v := uintptr(0) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uintptr" - vs := "" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - - // Address of real variable. - i := 1 - v2 := uintptr(unsafe.Pointer(&i)) - nv2 := (*uintptr)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uintptr" - v2s := fmt.Sprintf("%p", &i) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")()\n") -} - -func addUnsafePointerDumpTests() { - // Null pointer. - v := unsafe.Pointer(uintptr(0)) - nv := (*unsafe.Pointer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "unsafe.Pointer" - vs := "" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Address of real variable. - i := 1 - v2 := unsafe.Pointer(&i) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "unsafe.Pointer" - v2s := fmt.Sprintf("%p", &i) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv, "(*"+vt+")()\n") -} - -func addChanDumpTests() { - // Nil channel. - var v chan int - pv := &v - nv := (*chan int)(nil) - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "chan int" - vs := "" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Real channel. - v2 := make(chan int) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "chan int" - v2s := fmt.Sprintf("%p", v2) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") -} - -func addFuncDumpTests() { - // Function with no params and no returns. - v := addIntDumpTests - nv := (*func())(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "func()" - vs := fmt.Sprintf("%p", v) - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") - - // Function with param and no returns. - v2 := TestDump - nv2 := (*func(*testing.T))(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "func(*testing.T)" - v2s := fmt.Sprintf("%p", v2) - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") - addDumpTest(nv2, "(*"+v2t+")()\n") - - // Function with multiple params and multiple returns. - var v3 = func(i int, s string) (b bool, err error) { - return true, nil - } - nv3 := (*func(int, string) (bool, error))(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "func(int, string) (bool, error)" - v3s := fmt.Sprintf("%p", v3) - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") - addDumpTest(nv3, "(*"+v3t+")()\n") -} - -func addCircularDumpTests() { - // Struct that is circular through self referencing. - type circular struct { - c *circular - } - v := circular{nil} - v.c = &v - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.circular" - vs := "{\n c: (*" + vt + ")(" + vAddr + ")({\n c: (*" + vt + ")(" + - vAddr + ")()\n })\n}" - vs2 := "{\n c: (*" + vt + ")(" + vAddr + ")()\n}" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs2+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs2+")\n") - - // Structs that are circular through cross referencing. - v2 := xref1{nil} - ts2 := xref2{&v2} - v2.ps2 = &ts2 - pv2 := &v2 - ts2Addr := fmt.Sprintf("%p", &ts2) - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.xref1" - v2t2 := "spew_test.xref2" - v2s := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + - ")(" + v2Addr + ")({\n ps2: (*" + v2t2 + ")(" + ts2Addr + - ")()\n })\n })\n}" - v2s2 := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + - ")(" + v2Addr + ")()\n })\n}" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s2+")\n") - addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s2+")\n") - - // Structs that are indirectly circular. - v3 := indirCir1{nil} - tic2 := indirCir2{nil} - tic3 := indirCir3{&v3} - tic2.ps3 = &tic3 - v3.ps2 = &tic2 - pv3 := &v3 - tic2Addr := fmt.Sprintf("%p", &tic2) - tic3Addr := fmt.Sprintf("%p", &tic3) - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.indirCir1" - v3t2 := "spew_test.indirCir2" - v3t3 := "spew_test.indirCir3" - v3s := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + - ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + - ")({\n ps2: (*" + v3t2 + ")(" + tic2Addr + - ")()\n })\n })\n })\n}" - v3s2 := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + - ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + - ")()\n })\n })\n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s2+")\n") - addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s2+")\n") -} - -func addPanicDumpTests() { - // Type that panics in its Stringer interface. - v := panicer(127) - nv := (*panicer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.panicer" - vs := "(PANIC=test panic)127" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") -} - -func addErrorDumpTests() { - // Type that has a custom Error interface. - v := customError(127) - nv := (*customError)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.customError" - vs := "error: 127" - addDumpTest(v, "("+vt+") "+vs+"\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") - addDumpTest(nv, "(*"+vt+")()\n") -} - -// TestDump executes all of the tests described by dumpTests. -func TestDump(t *testing.T) { - // Setup tests. - addIntDumpTests() - addUintDumpTests() - addBoolDumpTests() - addFloatDumpTests() - addComplexDumpTests() - addArrayDumpTests() - addSliceDumpTests() - addStringDumpTests() - addInterfaceDumpTests() - addMapDumpTests() - addStructDumpTests() - addUintptrDumpTests() - addUnsafePointerDumpTests() - addChanDumpTests() - addFuncDumpTests() - addCircularDumpTests() - addPanicDumpTests() - addErrorDumpTests() - addCgoDumpTests() - - t.Logf("Running %d tests", len(dumpTests)) - for i, test := range dumpTests { - buf := new(bytes.Buffer) - spew.Fdump(buf, test.in) - s := buf.String() - if testFailed(s, test.wants) { - t.Errorf("Dump #%d\n got: %s %s", i, s, stringizeWants(test.wants)) - continue - } - } -} - -func TestDumpSortedKeys(t *testing.T) { - cfg := spew.ConfigState{SortKeys: true} - s := cfg.Sdump(map[int]string{1: "1", 3: "3", 2: "2"}) - expected := "(map[int]string) (len=3) {\n(int) 1: (string) (len=1) " + - "\"1\",\n(int) 2: (string) (len=1) \"2\",\n(int) 3: (string) " + - "(len=1) \"3\"\n" + - "}\n" - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - - s = cfg.Sdump(map[stringer]int{"1": 1, "3": 3, "2": 2}) - expected = "(map[spew_test.stringer]int) (len=3) {\n" + - "(spew_test.stringer) (len=1) stringer 1: (int) 1,\n" + - "(spew_test.stringer) (len=1) stringer 2: (int) 2,\n" + - "(spew_test.stringer) (len=1) stringer 3: (int) 3\n" + - "}\n" - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - - s = cfg.Sdump(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) - expected = "(map[spew_test.pstringer]int) (len=3) {\n" + - "(spew_test.pstringer) (len=1) stringer 1: (int) 1,\n" + - "(spew_test.pstringer) (len=1) stringer 2: (int) 2,\n" + - "(spew_test.pstringer) (len=1) stringer 3: (int) 3\n" + - "}\n" - if spew.UnsafeDisabled { - expected = "(map[spew_test.pstringer]int) (len=3) {\n" + - "(spew_test.pstringer) (len=1) \"1\": (int) 1,\n" + - "(spew_test.pstringer) (len=1) \"2\": (int) 2,\n" + - "(spew_test.pstringer) (len=1) \"3\": (int) 3\n" + - "}\n" - } - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - - s = cfg.Sdump(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) - expected = "(map[spew_test.customError]int) (len=3) {\n" + - "(spew_test.customError) error: 1: (int) 1,\n" + - "(spew_test.customError) error: 2: (int) 2,\n" + - "(spew_test.customError) error: 3: (int) 3\n" + - "}\n" - if s != expected { - t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) - } - -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go deleted file mode 100644 index 18a38358e..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2013 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when both cgo is supported and "-tags testcgo" is added to the go test -// command line. This means the cgo tests are only added (and hence run) when -// specifially requested. This configuration is used because spew itself -// does not require cgo to run even though it does handle certain cgo types -// specially. Rather than forcing all clients to require cgo and an external -// C compiler just to run the tests, this scheme makes them optional. -// +build cgo,testcgo - -package spew_test - -import ( - "fmt" - - "github.com/davecgh/go-spew/spew/testdata" -) - -func addCgoDumpTests() { - // C char pointer. - v := testdata.GetCgoCharPointer() - nv := testdata.GetCgoNullCharPointer() - pv := &v - vcAddr := fmt.Sprintf("%p", v) - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "*testdata._Ctype_char" - vs := "116" - addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n") - addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n") - addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n") - addDumpTest(nv, "("+vt+")()\n") - - // C char array. - v2, v2l, v2c := testdata.GetCgoCharArray() - v2Len := fmt.Sprintf("%d", v2l) - v2Cap := fmt.Sprintf("%d", v2c) - v2t := "[6]testdata._Ctype_char" - v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " + - "{\n 00000000 74 65 73 74 32 00 " + - " |test2.|\n}" - addDumpTest(v2, "("+v2t+") "+v2s+"\n") - - // C unsigned char array. - v3, v3l, v3c := testdata.GetCgoUnsignedCharArray() - v3Len := fmt.Sprintf("%d", v3l) - v3Cap := fmt.Sprintf("%d", v3c) - v3t := "[6]testdata._Ctype_unsignedchar" - v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " + - "{\n 00000000 74 65 73 74 33 00 " + - " |test3.|\n}" - addDumpTest(v3, "("+v3t+") "+v3s+"\n") - - // C signed char array. - v4, v4l, v4c := testdata.GetCgoSignedCharArray() - v4Len := fmt.Sprintf("%d", v4l) - v4Cap := fmt.Sprintf("%d", v4c) - v4t := "[6]testdata._Ctype_schar" - v4t2 := "testdata._Ctype_schar" - v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + - "{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 + - ") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 + - ") 0\n}" - addDumpTest(v4, "("+v4t+") "+v4s+"\n") - - // C uint8_t array. - v5, v5l, v5c := testdata.GetCgoUint8tArray() - v5Len := fmt.Sprintf("%d", v5l) - v5Cap := fmt.Sprintf("%d", v5c) - v5t := "[6]testdata._Ctype_uint8_t" - v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " + - "{\n 00000000 74 65 73 74 35 00 " + - " |test5.|\n}" - addDumpTest(v5, "("+v5t+") "+v5s+"\n") - - // C typedefed unsigned char array. - v6, v6l, v6c := testdata.GetCgoTypdefedUnsignedCharArray() - v6Len := fmt.Sprintf("%d", v6l) - v6Cap := fmt.Sprintf("%d", v6c) - v6t := "[6]testdata._Ctype_custom_uchar_t" - v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " + - "{\n 00000000 74 65 73 74 36 00 " + - " |test6.|\n}" - addDumpTest(v6, "("+v6t+") "+v6s+"\n") -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go deleted file mode 100644 index 52a0971fb..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2013 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when either cgo is not supported or "-tags testcgo" is not added to the go -// test command line. This file intentionally does not setup any cgo tests in -// this scenario. -// +build !cgo !testcgo - -package spew_test - -func addCgoDumpTests() { - // Don't add any tests for cgo since this file is only compiled when - // there should not be any cgo tests. -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go deleted file mode 100644 index de6c4e309..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2013 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew_test - -import ( - "fmt" - - "github.com/davecgh/go-spew/spew" -) - -type Flag int - -const ( - flagOne Flag = iota - flagTwo -) - -var flagStrings = map[Flag]string{ - flagOne: "flagOne", - flagTwo: "flagTwo", -} - -func (f Flag) String() string { - if s, ok := flagStrings[f]; ok { - return s - } - return fmt.Sprintf("Unknown flag (%d)", int(f)) -} - -type Bar struct { - data uintptr -} - -type Foo struct { - unexportedField Bar - ExportedField map[interface{}]interface{} -} - -// This example demonstrates how to use Dump to dump variables to stdout. -func ExampleDump() { - // The following package level declarations are assumed for this example: - /* - type Flag int - - const ( - flagOne Flag = iota - flagTwo - ) - - var flagStrings = map[Flag]string{ - flagOne: "flagOne", - flagTwo: "flagTwo", - } - - func (f Flag) String() string { - if s, ok := flagStrings[f]; ok { - return s - } - return fmt.Sprintf("Unknown flag (%d)", int(f)) - } - - type Bar struct { - data uintptr - } - - type Foo struct { - unexportedField Bar - ExportedField map[interface{}]interface{} - } - */ - - // Setup some sample data structures for the example. - bar := Bar{uintptr(0)} - s1 := Foo{bar, map[interface{}]interface{}{"one": true}} - f := Flag(5) - b := []byte{ - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, - } - - // Dump! - spew.Dump(s1, f, b) - - // Output: - // (spew_test.Foo) { - // unexportedField: (spew_test.Bar) { - // data: (uintptr) - // }, - // ExportedField: (map[interface {}]interface {}) (len=1) { - // (string) (len=3) "one": (bool) true - // } - // } - // (spew_test.Flag) Unknown flag (5) - // ([]uint8) (len=34 cap=34) { - // 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | - // 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| - // 00000020 31 32 |12| - // } - // -} - -// This example demonstrates how to use Printf to display a variable with a -// format string and inline formatting. -func ExamplePrintf() { - // Create a double pointer to a uint 8. - ui8 := uint8(5) - pui8 := &ui8 - ppui8 := &pui8 - - // Create a circular data type. - type circular struct { - ui8 uint8 - c *circular - } - c := circular{ui8: 1} - c.c = &c - - // Print! - spew.Printf("ppui8: %v\n", ppui8) - spew.Printf("circular: %v\n", c) - - // Output: - // ppui8: <**>5 - // circular: {1 <*>{1 <*>}} -} - -// This example demonstrates how to use a ConfigState. -func ExampleConfigState() { - // Modify the indent level of the ConfigState only. The global - // configuration is not modified. - scs := spew.ConfigState{Indent: "\t"} - - // Output using the ConfigState instance. - v := map[string]int{"one": 1} - scs.Printf("v: %v\n", v) - scs.Dump(v) - - // Output: - // v: map[one:1] - // (map[string]int) (len=1) { - // (string) (len=3) "one": (int) 1 - // } -} - -// This example demonstrates how to use ConfigState.Dump to dump variables to -// stdout -func ExampleConfigState_Dump() { - // See the top-level Dump example for details on the types used in this - // example. - - // Create two ConfigState instances with different indentation. - scs := spew.ConfigState{Indent: "\t"} - scs2 := spew.ConfigState{Indent: " "} - - // Setup some sample data structures for the example. - bar := Bar{uintptr(0)} - s1 := Foo{bar, map[interface{}]interface{}{"one": true}} - - // Dump using the ConfigState instances. - scs.Dump(s1) - scs2.Dump(s1) - - // Output: - // (spew_test.Foo) { - // unexportedField: (spew_test.Bar) { - // data: (uintptr) - // }, - // ExportedField: (map[interface {}]interface {}) (len=1) { - // (string) (len=3) "one": (bool) true - // } - // } - // (spew_test.Foo) { - // unexportedField: (spew_test.Bar) { - // data: (uintptr) - // }, - // ExportedField: (map[interface {}]interface {}) (len=1) { - // (string) (len=3) "one": (bool) true - // } - // } - // -} - -// This example demonstrates how to use ConfigState.Printf to display a variable -// with a format string and inline formatting. -func ExampleConfigState_Printf() { - // See the top-level Dump example for details on the types used in this - // example. - - // Create two ConfigState instances and modify the method handling of the - // first ConfigState only. - scs := spew.NewDefaultConfig() - scs2 := spew.NewDefaultConfig() - scs.DisableMethods = true - - // Alternatively - // scs := spew.ConfigState{Indent: " ", DisableMethods: true} - // scs2 := spew.ConfigState{Indent: " "} - - // This is of type Flag which implements a Stringer and has raw value 1. - f := flagTwo - - // Dump using the ConfigState instances. - scs.Printf("f: %v\n", f) - scs2.Printf("f: %v\n", f) - - // Output: - // f: 1 - // f: flagTwo -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go deleted file mode 100644 index b664b3f13..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go +++ /dev/null @@ -1,1558 +0,0 @@ -/* - * Copyright (c) 2013 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -Test Summary: -NOTE: For each test, a nil pointer, a single pointer and double pointer to the -base test element are also tested to ensure proper indirection across all types. - -- Max int8, int16, int32, int64, int -- Max uint8, uint16, uint32, uint64, uint -- Boolean true and false -- Standard complex64 and complex128 -- Array containing standard ints -- Array containing type with custom formatter on pointer receiver only -- Array containing interfaces -- Slice containing standard float32 values -- Slice containing type with custom formatter on pointer receiver only -- Slice containing interfaces -- Nil slice -- Standard string -- Nil interface -- Sub-interface -- Map with string keys and int vals -- Map with custom formatter type on pointer receiver only keys and vals -- Map with interface keys and values -- Map with nil interface value -- Struct with primitives -- Struct that contains another struct -- Struct that contains custom type with Stringer pointer interface via both - exported and unexported fields -- Struct that contains embedded struct and field to same struct -- Uintptr to 0 (null pointer) -- Uintptr address of real variable -- Unsafe.Pointer to 0 (null pointer) -- Unsafe.Pointer to address of real variable -- Nil channel -- Standard int channel -- Function with no params and no returns -- Function with param and no returns -- Function with multiple params and multiple returns -- Struct that is circular through self referencing -- Structs that are circular through cross referencing -- Structs that are indirectly circular -- Type that panics in its Stringer interface -- Type that has a custom Error interface -- %x passthrough with uint -- %#x passthrough with uint -- %f passthrough with precision -- %f passthrough with width and precision -- %d passthrough with width -- %q passthrough with string -*/ - -package spew_test - -import ( - "bytes" - "fmt" - "testing" - "unsafe" - - "github.com/davecgh/go-spew/spew" -) - -// formatterTest is used to describe a test to be perfomed against NewFormatter. -type formatterTest struct { - format string - in interface{} - wants []string -} - -// formatterTests houses all of the tests to be performed against NewFormatter. -var formatterTests = make([]formatterTest, 0) - -// addFormatterTest is a helper method to append the passed input and desired -// result to formatterTests. -func addFormatterTest(format string, in interface{}, wants ...string) { - test := formatterTest{format, in, wants} - formatterTests = append(formatterTests, test) -} - -func addIntFormatterTests() { - // Max int8. - v := int8(127) - nv := (*int8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "int8" - vs := "127" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Max int16. - v2 := int16(32767) - nv2 := (*int16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "int16" - v2s := "32767" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") - - // Max int32. - v3 := int32(2147483647) - nv3 := (*int32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "int32" - v3s := "2147483647" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%v", nv3, "") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - - // Max int64. - v4 := int64(9223372036854775807) - nv4 := (*int64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "int64" - v4s := "9223372036854775807" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%v", nv4, "") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") - - // Max int. - v5 := int(2147483647) - nv5 := (*int)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "int" - v5s := "2147483647" - addFormatterTest("%v", v5, v5s) - addFormatterTest("%v", pv5, "<*>"+v5s) - addFormatterTest("%v", &pv5, "<**>"+v5s) - addFormatterTest("%v", nv5, "") - addFormatterTest("%+v", v5, v5s) - addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) - addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%+v", nv5, "") - addFormatterTest("%#v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) - addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) - addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") - addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) - addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%#+v", nv5, "(*"+v5t+")"+"") -} - -func addUintFormatterTests() { - // Max uint8. - v := uint8(255) - nv := (*uint8)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uint8" - vs := "255" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Max uint16. - v2 := uint16(65535) - nv2 := (*uint16)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") - - // Max uint32. - v3 := uint32(4294967295) - nv3 := (*uint32)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "uint32" - v3s := "4294967295" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%v", nv3, "") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - - // Max uint64. - v4 := uint64(18446744073709551615) - nv4 := (*uint64)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "uint64" - v4s := "18446744073709551615" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%v", nv4, "") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") - - // Max uint. - v5 := uint(4294967295) - nv5 := (*uint)(nil) - pv5 := &v5 - v5Addr := fmt.Sprintf("%p", pv5) - pv5Addr := fmt.Sprintf("%p", &pv5) - v5t := "uint" - v5s := "4294967295" - addFormatterTest("%v", v5, v5s) - addFormatterTest("%v", pv5, "<*>"+v5s) - addFormatterTest("%v", &pv5, "<**>"+v5s) - addFormatterTest("%v", nv5, "") - addFormatterTest("%+v", v5, v5s) - addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) - addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%+v", nv5, "") - addFormatterTest("%#v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) - addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) - addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") - addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) - addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) - addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) - addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") -} - -func addBoolFormatterTests() { - // Boolean true. - v := bool(true) - nv := (*bool)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "bool" - vs := "true" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Boolean false. - v2 := bool(false) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "bool" - v2s := "false" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addFloatFormatterTests() { - // Standard float32. - v := float32(3.1415) - nv := (*float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "float32" - vs := "3.1415" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Standard float64. - v2 := float64(3.1415926) - nv2 := (*float64)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "float64" - v2s := "3.1415926" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") -} - -func addComplexFormatterTests() { - // Standard complex64. - v := complex(float32(6), -2) - nv := (*complex64)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "complex64" - vs := "(6-2i)" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Standard complex128. - v2 := complex(float64(-6), 2) - nv2 := (*complex128)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "complex128" - v2s := "(-6+2i)" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") -} - -func addArrayFormatterTests() { - // Array containing standard ints. - v := [3]int{1, 2, 3} - nv := (*[3]int)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "[3]int" - vs := "[1 2 3]" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Array containing type with custom formatter on pointer receiver only. - v2 := [3]pstringer{"1", "2", "3"} - nv2 := (*[3]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "[3]spew_test.pstringer" - v2sp := "[stringer 1 stringer 2 stringer 3]" - v2s := v2sp - if spew.UnsafeDisabled { - v2s = "[1 2 3]" - } - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2sp) - addFormatterTest("%v", &pv2, "<**>"+v2sp) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2sp) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2sp) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2sp) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2sp) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2sp) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2sp) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") - - // Array containing interfaces. - v3 := [3]interface{}{"one", int(2), uint(3)} - nv3 := (*[3]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[3]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3s := "[one 2 3]" - v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3]" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") -} - -func addSliceFormatterTests() { - // Slice containing standard float32 values. - v := []float32{3.14, 6.28, 12.56} - nv := (*[]float32)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "[]float32" - vs := "[3.14 6.28 12.56]" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Slice containing type with custom formatter on pointer receiver only. - v2 := []pstringer{"1", "2", "3"} - nv2 := (*[]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "[]spew_test.pstringer" - v2s := "[stringer 1 stringer 2 stringer 3]" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") - - // Slice containing interfaces. - v3 := []interface{}{"one", int(2), uint(3), nil} - nv3 := (*[]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "[]interface {}" - v3t2 := "string" - v3t3 := "int" - v3t4 := "uint" - v3t5 := "interface {}" - v3s := "[one 2 3 ]" - v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3 (" + v3t5 + - ")]" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") - - // Nil slice. - var v4 []int - nv4 := (*[]int)(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "[]int" - v4s := "" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") -} - -func addStringFormatterTests() { - // Standard string. - v := "test" - nv := (*string)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "string" - vs := "test" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") -} - -func addInterfaceFormatterTests() { - // Nil interface. - var v interface{} - nv := (*interface{})(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "interface {}" - vs := "" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Sub-interface. - v2 := interface{}(uint16(65535)) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uint16" - v2s := "65535" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addMapFormatterTests() { - // Map with string keys and int vals. - v := map[string]int{"one": 1, "two": 2} - nilMap := map[string]int(nil) - nv := (*map[string]int)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "map[string]int" - vs := "map[one:1 two:2]" - vs2 := "map[two:2 one:1]" - addFormatterTest("%v", v, vs, vs2) - addFormatterTest("%v", pv, "<*>"+vs, "<*>"+vs2) - addFormatterTest("%v", &pv, "<**>"+vs, "<**>"+vs2) - addFormatterTest("%+v", nilMap, "") - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs, vs2) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs, "<*>("+vAddr+")"+vs2) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs, - "<**>("+pvAddr+"->"+vAddr+")"+vs2) - addFormatterTest("%+v", nilMap, "") - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs, "("+vt+")"+vs2) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs, "(*"+vt+")"+vs2) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs, "(**"+vt+")"+vs2) - addFormatterTest("%#v", nilMap, "("+vt+")"+"") - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs, "("+vt+")"+vs2) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs, - "(*"+vt+")("+vAddr+")"+vs2) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs, - "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs2) - addFormatterTest("%#+v", nilMap, "("+vt+")"+"") - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Map with custom formatter type on pointer receiver only keys and vals. - v2 := map[pstringer]pstringer{"one": "1"} - nv2 := (*map[pstringer]pstringer)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "map[spew_test.pstringer]spew_test.pstringer" - v2s := "map[stringer one:stringer 1]" - if spew.UnsafeDisabled { - v2s = "map[one:1]" - } - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") - - // Map with interface keys and values. - v3 := map[interface{}]interface{}{"one": 1} - nv3 := (*map[interface{}]interface{})(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "map[interface {}]interface {}" - v3t1 := "string" - v3t2 := "int" - v3s := "map[one:1]" - v3s2 := "map[(" + v3t1 + ")one:(" + v3t2 + ")1]" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") - - // Map with nil interface value - v4 := map[string]interface{}{"nil": nil} - nv4 := (*map[string]interface{})(nil) - pv4 := &v4 - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "map[string]interface {}" - v4t1 := "interface {}" - v4s := "map[nil:]" - v4s2 := "map[nil:(" + v4t1 + ")]" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%+v", v4, v4s) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s2) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s2) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s2) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s2) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s2) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s2) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") -} - -func addStructFormatterTests() { - // Struct with primitives. - type s1 struct { - a int8 - b uint8 - } - v := s1{127, 255} - nv := (*s1)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.s1" - vt2 := "int8" - vt3 := "uint8" - vs := "{127 255}" - vs2 := "{a:127 b:255}" - vs3 := "{a:(" + vt2 + ")127 b:(" + vt3 + ")255}" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs2) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs2) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs2) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs3) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs3) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs3) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs3) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs3) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs3) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Struct that contains another struct. - type s2 struct { - s1 s1 - b bool - } - v2 := s2{s1{127, 255}, true} - nv2 := (*s2)(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.s2" - v2t2 := "spew_test.s1" - v2t3 := "int8" - v2t4 := "uint8" - v2t5 := "bool" - v2s := "{{127 255} true}" - v2s2 := "{s1:{a:127 b:255} b:true}" - v2s3 := "{s1:(" + v2t2 + "){a:(" + v2t3 + ")127 b:(" + v2t4 + ")255} b:(" + - v2t5 + ")true}" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%+v", v2, v2s2) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s2) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s2) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s3) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s3) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s3) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s3) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s3) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s3) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") - - // Struct that contains custom type with Stringer pointer interface via both - // exported and unexported fields. - type s3 struct { - s pstringer - S pstringer - } - v3 := s3{"test", "test2"} - nv3 := (*s3)(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.s3" - v3t2 := "spew_test.pstringer" - v3s := "{stringer test stringer test2}" - v3sp := v3s - v3s2 := "{s:stringer test S:stringer test2}" - v3s2p := v3s2 - v3s3 := "{s:(" + v3t2 + ")stringer test S:(" + v3t2 + ")stringer test2}" - v3s3p := v3s3 - if spew.UnsafeDisabled { - v3s = "{test test2}" - v3sp = "{test stringer test2}" - v3s2 = "{s:test S:test2}" - v3s2p = "{s:test S:stringer test2}" - v3s3 = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")test2}" - v3s3p = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")stringer test2}" - } - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3sp) - addFormatterTest("%v", &pv3, "<**>"+v3sp) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%+v", v3, v3s2) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s2p) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s2p) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s3) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s3p) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s3p) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s3) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s3p) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s3p) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") - - // Struct that contains embedded struct and field to same struct. - e := embed{"embedstr"} - v4 := embedwrap{embed: &e, e: &e} - nv4 := (*embedwrap)(nil) - pv4 := &v4 - eAddr := fmt.Sprintf("%p", &e) - v4Addr := fmt.Sprintf("%p", pv4) - pv4Addr := fmt.Sprintf("%p", &pv4) - v4t := "spew_test.embedwrap" - v4t2 := "spew_test.embed" - v4t3 := "string" - v4s := "{<*>{embedstr} <*>{embedstr}}" - v4s2 := "{embed:<*>(" + eAddr + "){a:embedstr} e:<*>(" + eAddr + - "){a:embedstr}}" - v4s3 := "{embed:(*" + v4t2 + "){a:(" + v4t3 + ")embedstr} e:(*" + v4t2 + - "){a:(" + v4t3 + ")embedstr}}" - v4s4 := "{embed:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + - ")embedstr} e:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + ")embedstr}}" - addFormatterTest("%v", v4, v4s) - addFormatterTest("%v", pv4, "<*>"+v4s) - addFormatterTest("%v", &pv4, "<**>"+v4s) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%+v", v4, v4s2) - addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s2) - addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s2) - addFormatterTest("%+v", nv4, "") - addFormatterTest("%#v", v4, "("+v4t+")"+v4s3) - addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s3) - addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s3) - addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") - addFormatterTest("%#+v", v4, "("+v4t+")"+v4s4) - addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s4) - addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s4) - addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") -} - -func addUintptrFormatterTests() { - // Null pointer. - v := uintptr(0) - nv := (*uintptr)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "uintptr" - vs := "" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Address of real variable. - i := 1 - v2 := uintptr(unsafe.Pointer(&i)) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "uintptr" - v2s := fmt.Sprintf("%p", &i) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addUnsafePointerFormatterTests() { - // Null pointer. - v := unsafe.Pointer(uintptr(0)) - nv := (*unsafe.Pointer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "unsafe.Pointer" - vs := "" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Address of real variable. - i := 1 - v2 := unsafe.Pointer(&i) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "unsafe.Pointer" - v2s := fmt.Sprintf("%p", &i) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addChanFormatterTests() { - // Nil channel. - var v chan int - pv := &v - nv := (*chan int)(nil) - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "chan int" - vs := "" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Real channel. - v2 := make(chan int) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "chan int" - v2s := fmt.Sprintf("%p", v2) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) -} - -func addFuncFormatterTests() { - // Function with no params and no returns. - v := addIntFormatterTests - nv := (*func())(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "func()" - vs := fmt.Sprintf("%p", v) - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") - - // Function with param and no returns. - v2 := TestFormatter - nv2 := (*func(*testing.T))(nil) - pv2 := &v2 - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "func(*testing.T)" - v2s := fmt.Sprintf("%p", v2) - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s) - addFormatterTest("%v", &pv2, "<**>"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%+v", v2, v2s) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%+v", nv2, "") - addFormatterTest("%#v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) - addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) - addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") - - // Function with multiple params and multiple returns. - var v3 = func(i int, s string) (b bool, err error) { - return true, nil - } - nv3 := (*func(int, string) (bool, error))(nil) - pv3 := &v3 - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "func(int, string) (bool, error)" - v3s := fmt.Sprintf("%p", v3) - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s) - addFormatterTest("%v", &pv3, "<**>"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%+v", v3, v3s) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%+v", nv3, "") - addFormatterTest("%#v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) - addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) - addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") -} - -func addCircularFormatterTests() { - // Struct that is circular through self referencing. - type circular struct { - c *circular - } - v := circular{nil} - v.c = &v - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.circular" - vs := "{<*>{<*>}}" - vs2 := "{<*>}" - vs3 := "{c:<*>(" + vAddr + "){c:<*>(" + vAddr + ")}}" - vs4 := "{c:<*>(" + vAddr + ")}" - vs5 := "{c:(*" + vt + "){c:(*" + vt + ")}}" - vs6 := "{c:(*" + vt + ")}" - vs7 := "{c:(*" + vt + ")(" + vAddr + "){c:(*" + vt + ")(" + vAddr + - ")}}" - vs8 := "{c:(*" + vt + ")(" + vAddr + ")}" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs2) - addFormatterTest("%v", &pv, "<**>"+vs2) - addFormatterTest("%+v", v, vs3) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs4) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs4) - addFormatterTest("%#v", v, "("+vt+")"+vs5) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs6) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs6) - addFormatterTest("%#+v", v, "("+vt+")"+vs7) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs8) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs8) - - // Structs that are circular through cross referencing. - v2 := xref1{nil} - ts2 := xref2{&v2} - v2.ps2 = &ts2 - pv2 := &v2 - ts2Addr := fmt.Sprintf("%p", &ts2) - v2Addr := fmt.Sprintf("%p", pv2) - pv2Addr := fmt.Sprintf("%p", &pv2) - v2t := "spew_test.xref1" - v2t2 := "spew_test.xref2" - v2s := "{<*>{<*>{<*>}}}" - v2s2 := "{<*>{<*>}}" - v2s3 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + "){ps2:<*>(" + - ts2Addr + ")}}}" - v2s4 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + ")}}" - v2s5 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + "){ps2:(*" + v2t2 + - ")}}}" - v2s6 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + ")}}" - v2s7 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + - ")(" + v2Addr + "){ps2:(*" + v2t2 + ")(" + ts2Addr + - ")}}}" - v2s8 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + - ")(" + v2Addr + ")}}" - addFormatterTest("%v", v2, v2s) - addFormatterTest("%v", pv2, "<*>"+v2s2) - addFormatterTest("%v", &pv2, "<**>"+v2s2) - addFormatterTest("%+v", v2, v2s3) - addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s4) - addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s4) - addFormatterTest("%#v", v2, "("+v2t+")"+v2s5) - addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s6) - addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s6) - addFormatterTest("%#+v", v2, "("+v2t+")"+v2s7) - addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s8) - addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s8) - - // Structs that are indirectly circular. - v3 := indirCir1{nil} - tic2 := indirCir2{nil} - tic3 := indirCir3{&v3} - tic2.ps3 = &tic3 - v3.ps2 = &tic2 - pv3 := &v3 - tic2Addr := fmt.Sprintf("%p", &tic2) - tic3Addr := fmt.Sprintf("%p", &tic3) - v3Addr := fmt.Sprintf("%p", pv3) - pv3Addr := fmt.Sprintf("%p", &pv3) - v3t := "spew_test.indirCir1" - v3t2 := "spew_test.indirCir2" - v3t3 := "spew_test.indirCir3" - v3s := "{<*>{<*>{<*>{<*>}}}}" - v3s2 := "{<*>{<*>{<*>}}}" - v3s3 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + - v3Addr + "){ps2:<*>(" + tic2Addr + ")}}}}" - v3s4 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + - v3Addr + ")}}}" - v3s5 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + - "){ps2:(*" + v3t2 + ")}}}}" - v3s6 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + - ")}}}" - v3s7 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + - tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + "){ps2:(*" + v3t2 + - ")(" + tic2Addr + ")}}}}" - v3s8 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + - tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + ")}}}" - addFormatterTest("%v", v3, v3s) - addFormatterTest("%v", pv3, "<*>"+v3s2) - addFormatterTest("%v", &pv3, "<**>"+v3s2) - addFormatterTest("%+v", v3, v3s3) - addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s4) - addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s4) - addFormatterTest("%#v", v3, "("+v3t+")"+v3s5) - addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s6) - addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s6) - addFormatterTest("%#+v", v3, "("+v3t+")"+v3s7) - addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s8) - addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s8) -} - -func addPanicFormatterTests() { - // Type that panics in its Stringer interface. - v := panicer(127) - nv := (*panicer)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.panicer" - vs := "(PANIC=test panic)127" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") -} - -func addErrorFormatterTests() { - // Type that has a custom Error interface. - v := customError(127) - nv := (*customError)(nil) - pv := &v - vAddr := fmt.Sprintf("%p", pv) - pvAddr := fmt.Sprintf("%p", &pv) - vt := "spew_test.customError" - vs := "error: 127" - addFormatterTest("%v", v, vs) - addFormatterTest("%v", pv, "<*>"+vs) - addFormatterTest("%v", &pv, "<**>"+vs) - addFormatterTest("%v", nv, "") - addFormatterTest("%+v", v, vs) - addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) - addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%+v", nv, "") - addFormatterTest("%#v", v, "("+vt+")"+vs) - addFormatterTest("%#v", pv, "(*"+vt+")"+vs) - addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) - addFormatterTest("%#v", nv, "(*"+vt+")"+"") - addFormatterTest("%#+v", v, "("+vt+")"+vs) - addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) - addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) - addFormatterTest("%#+v", nv, "(*"+vt+")"+"") -} - -func addPassthroughFormatterTests() { - // %x passthrough with uint. - v := uint(4294967295) - pv := &v - vAddr := fmt.Sprintf("%x", pv) - pvAddr := fmt.Sprintf("%x", &pv) - vs := "ffffffff" - addFormatterTest("%x", v, vs) - addFormatterTest("%x", pv, vAddr) - addFormatterTest("%x", &pv, pvAddr) - - // %#x passthrough with uint. - v2 := int(2147483647) - pv2 := &v2 - v2Addr := fmt.Sprintf("%#x", pv2) - pv2Addr := fmt.Sprintf("%#x", &pv2) - v2s := "0x7fffffff" - addFormatterTest("%#x", v2, v2s) - addFormatterTest("%#x", pv2, v2Addr) - addFormatterTest("%#x", &pv2, pv2Addr) - - // %f passthrough with precision. - addFormatterTest("%.2f", 3.1415, "3.14") - addFormatterTest("%.3f", 3.1415, "3.142") - addFormatterTest("%.4f", 3.1415, "3.1415") - - // %f passthrough with width and precision. - addFormatterTest("%5.2f", 3.1415, " 3.14") - addFormatterTest("%6.3f", 3.1415, " 3.142") - addFormatterTest("%7.4f", 3.1415, " 3.1415") - - // %d passthrough with width. - addFormatterTest("%3d", 127, "127") - addFormatterTest("%4d", 127, " 127") - addFormatterTest("%5d", 127, " 127") - - // %q passthrough with string. - addFormatterTest("%q", "test", "\"test\"") -} - -// TestFormatter executes all of the tests described by formatterTests. -func TestFormatter(t *testing.T) { - // Setup tests. - addIntFormatterTests() - addUintFormatterTests() - addBoolFormatterTests() - addFloatFormatterTests() - addComplexFormatterTests() - addArrayFormatterTests() - addSliceFormatterTests() - addStringFormatterTests() - addInterfaceFormatterTests() - addMapFormatterTests() - addStructFormatterTests() - addUintptrFormatterTests() - addUnsafePointerFormatterTests() - addChanFormatterTests() - addFuncFormatterTests() - addCircularFormatterTests() - addPanicFormatterTests() - addErrorFormatterTests() - addPassthroughFormatterTests() - - t.Logf("Running %d tests", len(formatterTests)) - for i, test := range formatterTests { - buf := new(bytes.Buffer) - spew.Fprintf(buf, test.format, test.in) - s := buf.String() - if testFailed(s, test.wants) { - t.Errorf("Formatter #%d format: %s got: %s %s", i, test.format, s, - stringizeWants(test.wants)) - continue - } - } -} - -type testStruct struct { - x int -} - -func (ts testStruct) String() string { - return fmt.Sprintf("ts.%d", ts.x) -} - -type testStructP struct { - x int -} - -func (ts *testStructP) String() string { - return fmt.Sprintf("ts.%d", ts.x) -} - -func TestPrintSortedKeys(t *testing.T) { - cfg := spew.ConfigState{SortKeys: true} - s := cfg.Sprint(map[int]string{1: "1", 3: "3", 2: "2"}) - expected := "map[1:1 2:2 3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 1:\n %v %v", s, expected) - } - - s = cfg.Sprint(map[stringer]int{"1": 1, "3": 3, "2": 2}) - expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 2:\n %v %v", s, expected) - } - - s = cfg.Sprint(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) - expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" - if spew.UnsafeDisabled { - expected = "map[1:1 2:2 3:3]" - } - if s != expected { - t.Errorf("Sorted keys mismatch 3:\n %v %v", s, expected) - } - - s = cfg.Sprint(map[testStruct]int{testStruct{1}: 1, testStruct{3}: 3, testStruct{2}: 2}) - expected = "map[ts.1:1 ts.2:2 ts.3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 4:\n %v %v", s, expected) - } - - if !spew.UnsafeDisabled { - s = cfg.Sprint(map[testStructP]int{testStructP{1}: 1, testStructP{3}: 3, testStructP{2}: 2}) - expected = "map[ts.1:1 ts.2:2 ts.3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 5:\n %v %v", s, expected) - } - } - - s = cfg.Sprint(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) - expected = "map[error: 1:1 error: 2:2 error: 3:3]" - if s != expected { - t.Errorf("Sorted keys mismatch 6:\n %v %v", s, expected) - } -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go deleted file mode 100644 index 1069ee21c..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2013 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -This test file is part of the spew package rather than than the spew_test -package because it needs access to internals to properly test certain cases -which are not possible via the public interface since they should never happen. -*/ - -package spew - -import ( - "bytes" - "reflect" - "testing" -) - -// dummyFmtState implements a fake fmt.State to use for testing invalid -// reflect.Value handling. This is necessary because the fmt package catches -// invalid values before invoking the formatter on them. -type dummyFmtState struct { - bytes.Buffer -} - -func (dfs *dummyFmtState) Flag(f int) bool { - if f == int('+') { - return true - } - return false -} - -func (dfs *dummyFmtState) Precision() (int, bool) { - return 0, false -} - -func (dfs *dummyFmtState) Width() (int, bool) { - return 0, false -} - -// TestInvalidReflectValue ensures the dump and formatter code handles an -// invalid reflect value properly. This needs access to internal state since it -// should never happen in real code and therefore can't be tested via the public -// API. -func TestInvalidReflectValue(t *testing.T) { - i := 1 - - // Dump invalid reflect value. - v := new(reflect.Value) - buf := new(bytes.Buffer) - d := dumpState{w: buf, cs: &Config} - d.dump(*v) - s := buf.String() - want := "" - if s != want { - t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want) - } - i++ - - // Formatter invalid reflect value. - buf2 := new(dummyFmtState) - f := formatState{value: *v, cs: &Config, fs: buf2} - f.format(*v) - s = buf2.String() - want = "" - if s != want { - t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want) - } -} - -// SortValues makes the internal sortValues function available to the test -// package. -func SortValues(values []reflect.Value, cs *ConfigState) { - sortValues(values, cs) -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go deleted file mode 100644 index 83e070e9a..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2013-2015 Dave Collins - -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. - -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is not running on Google App Engine and "-tags disableunsafe" -// is not added to the go build command line. -// +build !appengine,!disableunsafe - -/* -This test file is part of the spew package rather than than the spew_test -package because it needs access to internals to properly test certain cases -which are not possible via the public interface since they should never happen. -*/ - -package spew - -import ( - "bytes" - "reflect" - "testing" - "unsafe" -) - -// changeKind uses unsafe to intentionally change the kind of a reflect.Value to -// the maximum kind value which does not exist. This is needed to test the -// fallback code which punts to the standard fmt library for new types that -// might get added to the language. -func changeKind(v *reflect.Value, readOnly bool) { - rvf := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + offsetFlag)) - *rvf = *rvf | ((1< - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew_test - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "testing" - - "github.com/davecgh/go-spew/spew" -) - -// spewFunc is used to identify which public function of the spew package or -// ConfigState a test applies to. -type spewFunc int - -const ( - fCSFdump spewFunc = iota - fCSFprint - fCSFprintf - fCSFprintln - fCSPrint - fCSPrintln - fCSSdump - fCSSprint - fCSSprintf - fCSSprintln - fCSErrorf - fCSNewFormatter - fErrorf - fFprint - fFprintln - fPrint - fPrintln - fSdump - fSprint - fSprintf - fSprintln -) - -// Map of spewFunc values to names for pretty printing. -var spewFuncStrings = map[spewFunc]string{ - fCSFdump: "ConfigState.Fdump", - fCSFprint: "ConfigState.Fprint", - fCSFprintf: "ConfigState.Fprintf", - fCSFprintln: "ConfigState.Fprintln", - fCSSdump: "ConfigState.Sdump", - fCSPrint: "ConfigState.Print", - fCSPrintln: "ConfigState.Println", - fCSSprint: "ConfigState.Sprint", - fCSSprintf: "ConfigState.Sprintf", - fCSSprintln: "ConfigState.Sprintln", - fCSErrorf: "ConfigState.Errorf", - fCSNewFormatter: "ConfigState.NewFormatter", - fErrorf: "spew.Errorf", - fFprint: "spew.Fprint", - fFprintln: "spew.Fprintln", - fPrint: "spew.Print", - fPrintln: "spew.Println", - fSdump: "spew.Sdump", - fSprint: "spew.Sprint", - fSprintf: "spew.Sprintf", - fSprintln: "spew.Sprintln", -} - -func (f spewFunc) String() string { - if s, ok := spewFuncStrings[f]; ok { - return s - } - return fmt.Sprintf("Unknown spewFunc (%d)", int(f)) -} - -// spewTest is used to describe a test to be performed against the public -// functions of the spew package or ConfigState. -type spewTest struct { - cs *spew.ConfigState - f spewFunc - format string - in interface{} - want string -} - -// spewTests houses the tests to be performed against the public functions of -// the spew package and ConfigState. -// -// These tests are only intended to ensure the public functions are exercised -// and are intentionally not exhaustive of types. The exhaustive type -// tests are handled in the dump and format tests. -var spewTests []spewTest - -// redirStdout is a helper function to return the standard output from f as a -// byte slice. -func redirStdout(f func()) ([]byte, error) { - tempFile, err := ioutil.TempFile("", "ss-test") - if err != nil { - return nil, err - } - fileName := tempFile.Name() - defer os.Remove(fileName) // Ignore error - - origStdout := os.Stdout - os.Stdout = tempFile - f() - os.Stdout = origStdout - tempFile.Close() - - return ioutil.ReadFile(fileName) -} - -func initSpewTests() { - // Config states with various settings. - scsDefault := spew.NewDefaultConfig() - scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true} - scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true} - scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1} - scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true} - - // Variables for tests on types which implement Stringer interface with and - // without a pointer receiver. - ts := stringer("test") - tps := pstringer("test") - - // depthTester is used to test max depth handling for structs, array, slices - // and maps. - type depthTester struct { - ic indirCir1 - arr [1]string - slice []string - m map[string]int - } - dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"}, - map[string]int{"one": 1}} - - // Variable for tests on types which implement error interface. - te := customError(10) - - spewTests = []spewTest{ - {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"}, - {scsDefault, fCSFprint, "", int16(32767), "32767"}, - {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"}, - {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"}, - {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, - {scsDefault, fCSPrintln, "", uint8(255), "255\n"}, - {scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"}, - {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"}, - {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"}, - {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"}, - {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, - {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, - {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, - {scsDefault, fFprint, "", float32(3.14), "3.14"}, - {scsDefault, fFprintln, "", float64(6.28), "6.28\n"}, - {scsDefault, fPrint, "", true, "true"}, - {scsDefault, fPrintln, "", false, "false\n"}, - {scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"}, - {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"}, - {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"}, - {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"}, - {scsNoMethods, fCSFprint, "", ts, "test"}, - {scsNoMethods, fCSFprint, "", &ts, "<*>test"}, - {scsNoMethods, fCSFprint, "", tps, "test"}, - {scsNoMethods, fCSFprint, "", &tps, "<*>test"}, - {scsNoPmethods, fCSFprint, "", ts, "stringer test"}, - {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"}, - {scsNoPmethods, fCSFprint, "", tps, "test"}, - {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"}, - {scsMaxDepth, fCSFprint, "", dt, "{{} [] [] map[]}"}, - {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" + - " ic: (spew_test.indirCir1) {\n \n },\n" + - " arr: ([1]string) (len=1 cap=1) {\n \n },\n" + - " slice: ([]string) (len=1 cap=1) {\n \n },\n" + - " m: (map[string]int) (len=1) {\n \n }\n}\n"}, - {scsContinue, fCSFprint, "", ts, "(stringer test) test"}, - {scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " + - "(len=4) (stringer test) \"test\"\n"}, - {scsContinue, fCSFprint, "", te, "(error: 10) 10"}, - {scsContinue, fCSFdump, "", te, "(spew_test.customError) " + - "(error: 10) 10\n"}, - } -} - -// TestSpew executes all of the tests described by spewTests. -func TestSpew(t *testing.T) { - initSpewTests() - - t.Logf("Running %d tests", len(spewTests)) - for i, test := range spewTests { - buf := new(bytes.Buffer) - switch test.f { - case fCSFdump: - test.cs.Fdump(buf, test.in) - - case fCSFprint: - test.cs.Fprint(buf, test.in) - - case fCSFprintf: - test.cs.Fprintf(buf, test.format, test.in) - - case fCSFprintln: - test.cs.Fprintln(buf, test.in) - - case fCSPrint: - b, err := redirStdout(func() { test.cs.Print(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fCSPrintln: - b, err := redirStdout(func() { test.cs.Println(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fCSSdump: - str := test.cs.Sdump(test.in) - buf.WriteString(str) - - case fCSSprint: - str := test.cs.Sprint(test.in) - buf.WriteString(str) - - case fCSSprintf: - str := test.cs.Sprintf(test.format, test.in) - buf.WriteString(str) - - case fCSSprintln: - str := test.cs.Sprintln(test.in) - buf.WriteString(str) - - case fCSErrorf: - err := test.cs.Errorf(test.format, test.in) - buf.WriteString(err.Error()) - - case fCSNewFormatter: - fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in)) - - case fErrorf: - err := spew.Errorf(test.format, test.in) - buf.WriteString(err.Error()) - - case fFprint: - spew.Fprint(buf, test.in) - - case fFprintln: - spew.Fprintln(buf, test.in) - - case fPrint: - b, err := redirStdout(func() { spew.Print(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fPrintln: - b, err := redirStdout(func() { spew.Println(test.in) }) - if err != nil { - t.Errorf("%v #%d %v", test.f, i, err) - continue - } - buf.Write(b) - - case fSdump: - str := spew.Sdump(test.in) - buf.WriteString(str) - - case fSprint: - str := spew.Sprint(test.in) - buf.WriteString(str) - - case fSprintf: - str := spew.Sprintf(test.format, test.in) - buf.WriteString(str) - - case fSprintln: - str := spew.Sprintln(test.in) - buf.WriteString(str) - - default: - t.Errorf("%v #%d unrecognized function", test.f, i) - continue - } - s := buf.String() - if test.want != s { - t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want) - continue - } - } -} diff --git a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go b/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go deleted file mode 100644 index 5c87dd456..000000000 --- a/Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2013 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when both cgo is supported and "-tags testcgo" is added to the go test -// command line. This code should really only be in the dumpcgo_test.go file, -// but unfortunately Go will not allow cgo in test files, so this is a -// workaround to allow cgo types to be tested. This configuration is used -// because spew itself does not require cgo to run even though it does handle -// certain cgo types specially. Rather than forcing all clients to require cgo -// and an external C compiler just to run the tests, this scheme makes them -// optional. -// +build cgo,testcgo - -package testdata - -/* -#include -typedef unsigned char custom_uchar_t; - -char *ncp = 0; -char *cp = "test"; -char ca[6] = {'t', 'e', 's', 't', '2', '\0'}; -unsigned char uca[6] = {'t', 'e', 's', 't', '3', '\0'}; -signed char sca[6] = {'t', 'e', 's', 't', '4', '\0'}; -uint8_t ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'}; -custom_uchar_t tuca[6] = {'t', 'e', 's', 't', '6', '\0'}; -*/ -import "C" - -// GetCgoNullCharPointer returns a null char pointer via cgo. This is only -// used for tests. -func GetCgoNullCharPointer() interface{} { - return C.ncp -} - -// GetCgoCharPointer returns a char pointer via cgo. This is only used for -// tests. -func GetCgoCharPointer() interface{} { - return C.cp -} - -// GetCgoCharArray returns a char array via cgo and the array's len and cap. -// This is only used for tests. -func GetCgoCharArray() (interface{}, int, int) { - return C.ca, len(C.ca), cap(C.ca) -} - -// GetCgoUnsignedCharArray returns an unsigned char array via cgo and the -// array's len and cap. This is only used for tests. -func GetCgoUnsignedCharArray() (interface{}, int, int) { - return C.uca, len(C.uca), cap(C.uca) -} - -// GetCgoSignedCharArray returns a signed char array via cgo and the array's len -// and cap. This is only used for tests. -func GetCgoSignedCharArray() (interface{}, int, int) { - return C.sca, len(C.sca), cap(C.sca) -} - -// GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and -// cap. This is only used for tests. -func GetCgoUint8tArray() (interface{}, int, int) { - return C.ui8ta, len(C.ui8ta), cap(C.ui8ta) -} - -// GetCgoTypdefedUnsignedCharArray returns a typedefed unsigned char array via -// cgo and the array's len and cap. This is only used for tests. -func GetCgoTypdefedUnsignedCharArray() (interface{}, int, int) { - return C.tuca, len(C.tuca), cap(C.tuca) -} diff --git a/Godeps/_workspace/src/github.com/docker/distribution/digest/digest_test.go b/Godeps/_workspace/src/github.com/docker/distribution/digest/digest_test.go deleted file mode 100644 index afb4ebf63..000000000 --- a/Godeps/_workspace/src/github.com/docker/distribution/digest/digest_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package digest - -import ( - "testing" -) - -func TestParseDigest(t *testing.T) { - for _, testcase := range []struct { - input string - err error - algorithm Algorithm - hex string - }{ - { - input: "sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b", - algorithm: "sha256", - hex: "e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b", - }, - { - input: "sha384:d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", - algorithm: "sha384", - hex: "d3fc7881460b7e22e3d172954463dddd7866d17597e7248453c48b3e9d26d9596bf9c4a9cf8072c9d5bad76e19af801d", - }, - { - // empty hex - input: "sha256:", - err: ErrDigestInvalidFormat, - }, - { - // just hex - input: "d41d8cd98f00b204e9800998ecf8427e", - err: ErrDigestInvalidFormat, - }, - { - // not hex - input: "sha256:d41d8cd98f00b204e9800m98ecf8427e", - err: ErrDigestInvalidFormat, - }, - { - // too short - input: "sha256:abcdef0123456789", - err: ErrDigestInvalidLength, - }, - { - // too short (from different algorithm) - input: "sha512:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789", - err: ErrDigestInvalidLength, - }, - { - input: "foo:d41d8cd98f00b204e9800998ecf8427e", - err: ErrDigestUnsupported, - }, - } { - digest, err := ParseDigest(testcase.input) - if err != testcase.err { - t.Fatalf("error differed from expected while parsing %q: %v != %v", testcase.input, err, testcase.err) - } - - if testcase.err != nil { - continue - } - - if digest.Algorithm() != testcase.algorithm { - t.Fatalf("incorrect algorithm for parsed digest: %q != %q", digest.Algorithm(), testcase.algorithm) - } - - if digest.Hex() != testcase.hex { - t.Fatalf("incorrect hex for parsed digest: %q != %q", digest.Hex(), testcase.hex) - } - - // Parse string return value and check equality - newParsed, err := ParseDigest(digest.String()) - - if err != nil { - t.Fatalf("unexpected error parsing input %q: %v", testcase.input, err) - } - - if newParsed != digest { - t.Fatalf("expected equal: %q != %q", newParsed, digest) - } - } -} diff --git a/Godeps/_workspace/src/github.com/docker/distribution/digest/digester_resumable_test.go b/Godeps/_workspace/src/github.com/docker/distribution/digest/digester_resumable_test.go deleted file mode 100644 index 6ba21c801..000000000 --- a/Godeps/_workspace/src/github.com/docker/distribution/digest/digester_resumable_test.go +++ /dev/null @@ -1,21 +0,0 @@ -// +build !noresumabledigest - -package digest - -import ( - "testing" - - "github.com/stevvooe/resumable" - _ "github.com/stevvooe/resumable/sha256" -) - -// TestResumableDetection just ensures that the resumable capability of a hash -// is exposed through the digester type, which is just a hash plus a Digest -// method. -func TestResumableDetection(t *testing.T) { - d := Canonical.New() - - if _, ok := d.Hash().(resumable.Hash); !ok { - t.Fatalf("expected digester to implement resumable.Hash: %#v, %v", d, d.Hash()) - } -} diff --git a/Godeps/_workspace/src/github.com/docker/distribution/digest/set_test.go b/Godeps/_workspace/src/github.com/docker/distribution/digest/set_test.go deleted file mode 100644 index e9dab8795..000000000 --- a/Godeps/_workspace/src/github.com/docker/distribution/digest/set_test.go +++ /dev/null @@ -1,368 +0,0 @@ -package digest - -import ( - "crypto/sha256" - "encoding/binary" - "math/rand" - "testing" -) - -func assertEqualDigests(t *testing.T, d1, d2 Digest) { - if d1 != d2 { - t.Fatalf("Digests do not match:\n\tActual: %s\n\tExpected: %s", d1, d2) - } -} - -func TestLookup(t *testing.T) { - digests := []Digest{ - "sha256:1234511111111111111111111111111111111111111111111111111111111111", - "sha256:1234111111111111111111111111111111111111111111111111111111111111", - "sha256:1234611111111111111111111111111111111111111111111111111111111111", - "sha256:5432111111111111111111111111111111111111111111111111111111111111", - "sha256:6543111111111111111111111111111111111111111111111111111111111111", - "sha256:6432111111111111111111111111111111111111111111111111111111111111", - "sha256:6542111111111111111111111111111111111111111111111111111111111111", - "sha256:6532111111111111111111111111111111111111111111111111111111111111", - } - - dset := NewSet() - for i := range digests { - if err := dset.Add(digests[i]); err != nil { - t.Fatal(err) - } - } - - dgst, err := dset.Lookup("54") - if err != nil { - t.Fatal(err) - } - assertEqualDigests(t, dgst, digests[3]) - - dgst, err = dset.Lookup("1234") - if err == nil { - t.Fatal("Expected ambiguous error looking up: 1234") - } - if err != ErrDigestAmbiguous { - t.Fatal(err) - } - - dgst, err = dset.Lookup("9876") - if err == nil { - t.Fatal("Expected ambiguous error looking up: 9876") - } - if err != ErrDigestNotFound { - t.Fatal(err) - } - - dgst, err = dset.Lookup("sha256:1234") - if err == nil { - t.Fatal("Expected ambiguous error looking up: sha256:1234") - } - if err != ErrDigestAmbiguous { - t.Fatal(err) - } - - dgst, err = dset.Lookup("sha256:12345") - if err != nil { - t.Fatal(err) - } - assertEqualDigests(t, dgst, digests[0]) - - dgst, err = dset.Lookup("sha256:12346") - if err != nil { - t.Fatal(err) - } - assertEqualDigests(t, dgst, digests[2]) - - dgst, err = dset.Lookup("12346") - if err != nil { - t.Fatal(err) - } - assertEqualDigests(t, dgst, digests[2]) - - dgst, err = dset.Lookup("12345") - if err != nil { - t.Fatal(err) - } - assertEqualDigests(t, dgst, digests[0]) -} - -func TestAddDuplication(t *testing.T) { - digests := []Digest{ - "sha256:1234111111111111111111111111111111111111111111111111111111111111", - "sha256:1234511111111111111111111111111111111111111111111111111111111111", - "sha256:1234611111111111111111111111111111111111111111111111111111111111", - "sha256:5432111111111111111111111111111111111111111111111111111111111111", - "sha256:6543111111111111111111111111111111111111111111111111111111111111", - "sha512:65431111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", - "sha512:65421111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", - "sha512:65321111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", - } - - dset := NewSet() - for i := range digests { - if err := dset.Add(digests[i]); err != nil { - t.Fatal(err) - } - } - - if len(dset.entries) != 8 { - t.Fatal("Invalid dset size") - } - - if err := dset.Add(Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil { - t.Fatal(err) - } - - if len(dset.entries) != 8 { - t.Fatal("Duplicate digest insert allowed") - } - - if err := dset.Add(Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil { - t.Fatal(err) - } - - if len(dset.entries) != 9 { - t.Fatal("Insert with different algorithm not allowed") - } -} - -func TestRemove(t *testing.T) { - digests, err := createDigests(10) - if err != nil { - t.Fatal(err) - } - - dset := NewSet() - for i := range digests { - if err := dset.Add(digests[i]); err != nil { - t.Fatal(err) - } - } - - dgst, err := dset.Lookup(digests[0].String()) - if err != nil { - t.Fatal(err) - } - if dgst != digests[0] { - t.Fatalf("Unexpected digest value:\n\tExpected: %s\n\tActual: %s", digests[0], dgst) - } - - if err := dset.Remove(digests[0]); err != nil { - t.Fatal(err) - } - - if _, err := dset.Lookup(digests[0].String()); err != ErrDigestNotFound { - t.Fatalf("Expected error %v when looking up removed digest, got %v", ErrDigestNotFound, err) - } -} - -func TestAll(t *testing.T) { - digests, err := createDigests(100) - if err != nil { - t.Fatal(err) - } - - dset := NewSet() - for i := range digests { - if err := dset.Add(digests[i]); err != nil { - t.Fatal(err) - } - } - - all := map[Digest]struct{}{} - for _, dgst := range dset.All() { - all[dgst] = struct{}{} - } - - if len(all) != len(digests) { - t.Fatalf("Unexpected number of unique digests found:\n\tExpected: %d\n\tActual: %d", len(digests), len(all)) - } - - for i, dgst := range digests { - if _, ok := all[dgst]; !ok { - t.Fatalf("Missing element at position %d: %s", i, dgst) - } - } - -} - -func assertEqualShort(t *testing.T, actual, expected string) { - if actual != expected { - t.Fatalf("Unexpected short value:\n\tExpected: %s\n\tActual: %s", expected, actual) - } -} - -func TestShortCodeTable(t *testing.T) { - digests := []Digest{ - "sha256:1234111111111111111111111111111111111111111111111111111111111111", - "sha256:1234511111111111111111111111111111111111111111111111111111111111", - "sha256:1234611111111111111111111111111111111111111111111111111111111111", - "sha256:5432111111111111111111111111111111111111111111111111111111111111", - "sha256:6543111111111111111111111111111111111111111111111111111111111111", - "sha256:6432111111111111111111111111111111111111111111111111111111111111", - "sha256:6542111111111111111111111111111111111111111111111111111111111111", - "sha256:6532111111111111111111111111111111111111111111111111111111111111", - } - - dset := NewSet() - for i := range digests { - if err := dset.Add(digests[i]); err != nil { - t.Fatal(err) - } - } - - dump := ShortCodeTable(dset, 2) - - if len(dump) < len(digests) { - t.Fatalf("Error unexpected size: %d, expecting %d", len(dump), len(digests)) - } - assertEqualShort(t, dump[digests[0]], "12341") - assertEqualShort(t, dump[digests[1]], "12345") - assertEqualShort(t, dump[digests[2]], "12346") - assertEqualShort(t, dump[digests[3]], "54") - assertEqualShort(t, dump[digests[4]], "6543") - assertEqualShort(t, dump[digests[5]], "64") - assertEqualShort(t, dump[digests[6]], "6542") - assertEqualShort(t, dump[digests[7]], "653") -} - -func createDigests(count int) ([]Digest, error) { - r := rand.New(rand.NewSource(25823)) - digests := make([]Digest, count) - for i := range digests { - h := sha256.New() - if err := binary.Write(h, binary.BigEndian, r.Int63()); err != nil { - return nil, err - } - digests[i] = NewDigest("sha256", h) - } - return digests, nil -} - -func benchAddNTable(b *testing.B, n int) { - digests, err := createDigests(n) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} - for j := range digests { - if err = dset.Add(digests[j]); err != nil { - b.Fatal(err) - } - } - } -} - -func benchLookupNTable(b *testing.B, n int, shortLen int) { - digests, err := createDigests(n) - if err != nil { - b.Fatal(err) - } - dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} - for i := range digests { - if err := dset.Add(digests[i]); err != nil { - b.Fatal(err) - } - } - shorts := make([]string, 0, n) - for _, short := range ShortCodeTable(dset, shortLen) { - shorts = append(shorts, short) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err = dset.Lookup(shorts[i%n]); err != nil { - b.Fatal(err) - } - } -} - -func benchRemoveNTable(b *testing.B, n int) { - digests, err := createDigests(n) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} - b.StopTimer() - for j := range digests { - if err = dset.Add(digests[j]); err != nil { - b.Fatal(err) - } - } - b.StartTimer() - for j := range digests { - if err = dset.Remove(digests[j]); err != nil { - b.Fatal(err) - } - } - } -} - -func benchShortCodeNTable(b *testing.B, n int, shortLen int) { - digests, err := createDigests(n) - if err != nil { - b.Fatal(err) - } - dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))} - for i := range digests { - if err := dset.Add(digests[i]); err != nil { - b.Fatal(err) - } - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - ShortCodeTable(dset, shortLen) - } -} - -func BenchmarkAdd10(b *testing.B) { - benchAddNTable(b, 10) -} - -func BenchmarkAdd100(b *testing.B) { - benchAddNTable(b, 100) -} - -func BenchmarkAdd1000(b *testing.B) { - benchAddNTable(b, 1000) -} - -func BenchmarkRemove10(b *testing.B) { - benchRemoveNTable(b, 10) -} - -func BenchmarkRemove100(b *testing.B) { - benchRemoveNTable(b, 100) -} - -func BenchmarkRemove1000(b *testing.B) { - benchRemoveNTable(b, 1000) -} - -func BenchmarkLookup10(b *testing.B) { - benchLookupNTable(b, 10, 12) -} - -func BenchmarkLookup100(b *testing.B) { - benchLookupNTable(b, 100, 12) -} - -func BenchmarkLookup1000(b *testing.B) { - benchLookupNTable(b, 1000, 12) -} - -func BenchmarkShortCode10(b *testing.B) { - benchShortCodeNTable(b, 10, 12) -} -func BenchmarkShortCode100(b *testing.B) { - benchShortCodeNTable(b, 100, 12) -} -func BenchmarkShortCode1000(b *testing.B) { - benchShortCodeNTable(b, 1000, 12) -} diff --git a/Godeps/_workspace/src/github.com/docker/distribution/digest/verifiers_test.go b/Godeps/_workspace/src/github.com/docker/distribution/digest/verifiers_test.go deleted file mode 100644 index c342d6e7c..000000000 --- a/Godeps/_workspace/src/github.com/docker/distribution/digest/verifiers_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package digest - -import ( - "bytes" - "crypto/rand" - "io" - "testing" -) - -func TestDigestVerifier(t *testing.T) { - p := make([]byte, 1<<20) - rand.Read(p) - digest := FromBytes(p) - - verifier, err := NewDigestVerifier(digest) - if err != nil { - t.Fatalf("unexpected error getting digest verifier: %s", err) - } - - io.Copy(verifier, bytes.NewReader(p)) - - if !verifier.Verified() { - t.Fatalf("bytes not verified") - } -} - -// TestVerifierUnsupportedDigest ensures that unsupported digest validation is -// flowing through verifier creation. -func TestVerifierUnsupportedDigest(t *testing.T) { - unsupported := Digest("bean:0123456789abcdef") - - _, err := NewDigestVerifier(unsupported) - if err == nil { - t.Fatalf("expected error when creating verifier") - } - - if err != ErrDigestUnsupported { - t.Fatalf("incorrect error for unsupported digest: %v", err) - } -} - -// TODO(stevvooe): Add benchmarks to measure bytes/second throughput for -// DigestVerifier. -// -// The relevant benchmark for comparison can be run with the following -// commands: -// -// go test -bench . crypto/sha1 -// diff --git a/Godeps/_workspace/src/github.com/docker/distribution/reference/reference_test.go b/Godeps/_workspace/src/github.com/docker/distribution/reference/reference_test.go deleted file mode 100644 index cde1a7a2e..000000000 --- a/Godeps/_workspace/src/github.com/docker/distribution/reference/reference_test.go +++ /dev/null @@ -1,535 +0,0 @@ -package reference - -import ( - "encoding/json" - "strconv" - "strings" - "testing" - - "github.com/docker/distribution/digest" -) - -func TestReferenceParse(t *testing.T) { - // referenceTestcases is a unified set of testcases for - // testing the parsing of references - referenceTestcases := []struct { - // input is the repository name or name component testcase - input string - // err is the error expected from Parse, or nil - err error - // repository is the string representation for the reference - repository string - // hostname is the hostname expected in the reference - hostname string - // tag is the tag for the reference - tag string - // digest is the digest for the reference (enforces digest reference) - digest string - }{ - { - input: "test_com", - repository: "test_com", - }, - { - input: "test.com:tag", - repository: "test.com", - tag: "tag", - }, - { - input: "test.com:5000", - repository: "test.com", - tag: "5000", - }, - { - input: "test.com/repo:tag", - hostname: "test.com", - repository: "test.com/repo", - tag: "tag", - }, - { - input: "test:5000/repo", - hostname: "test:5000", - repository: "test:5000/repo", - }, - { - input: "test:5000/repo:tag", - hostname: "test:5000", - repository: "test:5000/repo", - tag: "tag", - }, - { - input: "test:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - hostname: "test:5000", - repository: "test:5000/repo", - digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - }, - { - input: "test:5000/repo:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - hostname: "test:5000", - repository: "test:5000/repo", - tag: "tag", - digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - }, - { - input: "test:5000/repo", - hostname: "test:5000", - repository: "test:5000/repo", - }, - { - input: "", - err: ErrNameEmpty, - }, - { - input: ":justtag", - err: ErrReferenceInvalidFormat, - }, - { - input: "@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - err: ErrReferenceInvalidFormat, - }, - { - input: "repo@sha256:ffffffffffffffffffffffffffffffffff", - err: digest.ErrDigestInvalidLength, - }, - { - input: "validname@invaliddigest:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - err: digest.ErrDigestUnsupported, - }, - { - input: strings.Repeat("a/", 128) + "a:tag", - err: ErrNameTooLong, - }, - { - input: strings.Repeat("a/", 127) + "a:tag-puts-this-over-max", - hostname: "a", - repository: strings.Repeat("a/", 127) + "a", - tag: "tag-puts-this-over-max", - }, - { - input: "aa/asdf$$^/aa", - err: ErrReferenceInvalidFormat, - }, - { - input: "sub-dom1.foo.com/bar/baz/quux", - hostname: "sub-dom1.foo.com", - repository: "sub-dom1.foo.com/bar/baz/quux", - }, - { - input: "sub-dom1.foo.com/bar/baz/quux:some-long-tag", - hostname: "sub-dom1.foo.com", - repository: "sub-dom1.foo.com/bar/baz/quux", - tag: "some-long-tag", - }, - { - input: "b.gcr.io/test.example.com/my-app:test.example.com", - hostname: "b.gcr.io", - repository: "b.gcr.io/test.example.com/my-app", - tag: "test.example.com", - }, - { - input: "xn--n3h.com/myimage:xn--n3h.com", // ☃.com in punycode - hostname: "xn--n3h.com", - repository: "xn--n3h.com/myimage", - tag: "xn--n3h.com", - }, - { - input: "xn--7o8h.com/myimage:xn--7o8h.com@sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // 🐳.com in punycode - hostname: "xn--7o8h.com", - repository: "xn--7o8h.com/myimage", - tag: "xn--7o8h.com", - digest: "sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - }, - { - input: "foo_bar.com:8080", - repository: "foo_bar.com", - tag: "8080", - }, - { - input: "foo/foo_bar.com:8080", - hostname: "foo", - repository: "foo/foo_bar.com", - tag: "8080", - }, - } - for _, testcase := range referenceTestcases { - failf := func(format string, v ...interface{}) { - t.Logf(strconv.Quote(testcase.input)+": "+format, v...) - t.Fail() - } - - repo, err := Parse(testcase.input) - if testcase.err != nil { - if err == nil { - failf("missing expected error: %v", testcase.err) - } else if testcase.err != err { - failf("mismatched error: got %v, expected %v", err, testcase.err) - } - continue - } else if err != nil { - failf("unexpected parse error: %v", err) - continue - } - if repo.String() != testcase.input { - failf("mismatched repo: got %q, expected %q", repo.String(), testcase.input) - } - - if named, ok := repo.(Named); ok { - if named.Name() != testcase.repository { - failf("unexpected repository: got %q, expected %q", named.Name(), testcase.repository) - } - hostname, _ := SplitHostname(named) - if hostname != testcase.hostname { - failf("unexpected hostname: got %q, expected %q", hostname, testcase.hostname) - } - } else if testcase.repository != "" || testcase.hostname != "" { - failf("expected named type, got %T", repo) - } - - tagged, ok := repo.(Tagged) - if testcase.tag != "" { - if ok { - if tagged.Tag() != testcase.tag { - failf("unexpected tag: got %q, expected %q", tagged.Tag(), testcase.tag) - } - } else { - failf("expected tagged type, got %T", repo) - } - } else if ok { - failf("unexpected tagged type") - } - - digested, ok := repo.(Digested) - if testcase.digest != "" { - if ok { - if digested.Digest().String() != testcase.digest { - failf("unexpected digest: got %q, expected %q", digested.Digest().String(), testcase.digest) - } - } else { - failf("expected digested type, got %T", repo) - } - } else if ok { - failf("unexpected digested type") - } - - } -} - -// TestWithNameFailure tests cases where WithName should fail. Cases where it -// should succeed are covered by TestSplitHostname, below. -func TestWithNameFailure(t *testing.T) { - testcases := []struct { - input string - err error - }{ - { - input: "", - err: ErrNameEmpty, - }, - { - input: ":justtag", - err: ErrReferenceInvalidFormat, - }, - { - input: "@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - err: ErrReferenceInvalidFormat, - }, - { - input: "validname@invaliddigest:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - err: ErrReferenceInvalidFormat, - }, - { - input: strings.Repeat("a/", 128) + "a:tag", - err: ErrNameTooLong, - }, - { - input: "aa/asdf$$^/aa", - err: ErrReferenceInvalidFormat, - }, - } - for _, testcase := range testcases { - failf := func(format string, v ...interface{}) { - t.Logf(strconv.Quote(testcase.input)+": "+format, v...) - t.Fail() - } - - _, err := WithName(testcase.input) - if err == nil { - failf("no error parsing name. expected: %s", testcase.err) - } - } -} - -func TestSplitHostname(t *testing.T) { - testcases := []struct { - input string - hostname string - name string - }{ - { - input: "test.com/foo", - hostname: "test.com", - name: "foo", - }, - { - input: "test_com/foo", - hostname: "", - name: "test_com/foo", - }, - { - input: "test:8080/foo", - hostname: "test:8080", - name: "foo", - }, - { - input: "test.com:8080/foo", - hostname: "test.com:8080", - name: "foo", - }, - { - input: "test-com:8080/foo", - hostname: "test-com:8080", - name: "foo", - }, - { - input: "xn--n3h.com:18080/foo", - hostname: "xn--n3h.com:18080", - name: "foo", - }, - } - for _, testcase := range testcases { - failf := func(format string, v ...interface{}) { - t.Logf(strconv.Quote(testcase.input)+": "+format, v...) - t.Fail() - } - - named, err := WithName(testcase.input) - if err != nil { - failf("error parsing name: %s", err) - } - hostname, name := SplitHostname(named) - if hostname != testcase.hostname { - failf("unexpected hostname: got %q, expected %q", hostname, testcase.hostname) - } - if name != testcase.name { - failf("unexpected name: got %q, expected %q", name, testcase.name) - } - } -} - -type serializationType struct { - Description string - Field Field -} - -func TestSerialization(t *testing.T) { - testcases := []struct { - description string - input string - name string - tag string - digest string - err error - }{ - { - description: "empty value", - err: ErrNameEmpty, - }, - { - description: "just a name", - input: "example.com:8000/named", - name: "example.com:8000/named", - }, - { - description: "name with a tag", - input: "example.com:8000/named:tagged", - name: "example.com:8000/named", - tag: "tagged", - }, - { - description: "name with digest", - input: "other.com/named@sha256:1234567890098765432112345667890098765432112345667890098765432112", - name: "other.com/named", - digest: "sha256:1234567890098765432112345667890098765432112345667890098765432112", - }, - } - for _, testcase := range testcases { - failf := func(format string, v ...interface{}) { - t.Logf(strconv.Quote(testcase.input)+": "+format, v...) - t.Fail() - } - - m := map[string]string{ - "Description": testcase.description, - "Field": testcase.input, - } - b, err := json.Marshal(m) - if err != nil { - failf("error marshalling: %v", err) - } - t := serializationType{} - - if err := json.Unmarshal(b, &t); err != nil { - if testcase.err == nil { - failf("error unmarshalling: %v", err) - } - if err != testcase.err { - failf("wrong error, expected %v, got %v", testcase.err, err) - } - - continue - } else if testcase.err != nil { - failf("expected error unmarshalling: %v", testcase.err) - } - - if t.Description != testcase.description { - failf("wrong description, expected %q, got %q", testcase.description, t.Description) - } - - ref := t.Field.Reference() - - if named, ok := ref.(Named); ok { - if named.Name() != testcase.name { - failf("unexpected repository: got %q, expected %q", named.Name(), testcase.name) - } - } else if testcase.name != "" { - failf("expected named type, got %T", ref) - } - - tagged, ok := ref.(Tagged) - if testcase.tag != "" { - if ok { - if tagged.Tag() != testcase.tag { - failf("unexpected tag: got %q, expected %q", tagged.Tag(), testcase.tag) - } - } else { - failf("expected tagged type, got %T", ref) - } - } else if ok { - failf("unexpected tagged type") - } - - digested, ok := ref.(Digested) - if testcase.digest != "" { - if ok { - if digested.Digest().String() != testcase.digest { - failf("unexpected digest: got %q, expected %q", digested.Digest().String(), testcase.digest) - } - } else { - failf("expected digested type, got %T", ref) - } - } else if ok { - failf("unexpected digested type") - } - - t = serializationType{ - Description: testcase.description, - Field: AsField(ref), - } - - b2, err := json.Marshal(t) - if err != nil { - failf("error marshing serialization type: %v", err) - } - - if string(b) != string(b2) { - failf("unexpected serialized value: expected %q, got %q", string(b), string(b2)) - } - - // Ensure t.Field is not implementing "Reference" directly, getting - // around the Reference type system - var fieldInterface interface{} = t.Field - if _, ok := fieldInterface.(Reference); ok { - failf("field should not implement Reference interface") - } - - } -} - -func TestWithTag(t *testing.T) { - testcases := []struct { - name string - tag string - combined string - }{ - { - name: "test.com/foo", - tag: "tag", - combined: "test.com/foo:tag", - }, - { - name: "foo", - tag: "tag2", - combined: "foo:tag2", - }, - { - name: "test.com:8000/foo", - tag: "tag4", - combined: "test.com:8000/foo:tag4", - }, - { - name: "test.com:8000/foo", - tag: "TAG5", - combined: "test.com:8000/foo:TAG5", - }, - } - for _, testcase := range testcases { - failf := func(format string, v ...interface{}) { - t.Logf(strconv.Quote(testcase.name)+": "+format, v...) - t.Fail() - } - - named, err := WithName(testcase.name) - if err != nil { - failf("error parsing name: %s", err) - } - tagged, err := WithTag(named, testcase.tag) - if err != nil { - failf("WithTag failed: %s", err) - } - if tagged.String() != testcase.combined { - failf("unexpected: got %q, expected %q", tagged.String(), testcase.combined) - } - } -} - -func TestWithDigest(t *testing.T) { - testcases := []struct { - name string - digest digest.Digest - combined string - }{ - { - name: "test.com/foo", - digest: "sha256:1234567890098765432112345667890098765", - combined: "test.com/foo@sha256:1234567890098765432112345667890098765", - }, - { - name: "foo", - digest: "sha256:1234567890098765432112345667890098765", - combined: "foo@sha256:1234567890098765432112345667890098765", - }, - { - name: "test.com:8000/foo", - digest: "sha256:1234567890098765432112345667890098765", - combined: "test.com:8000/foo@sha256:1234567890098765432112345667890098765", - }, - } - for _, testcase := range testcases { - failf := func(format string, v ...interface{}) { - t.Logf(strconv.Quote(testcase.name)+": "+format, v...) - t.Fail() - } - - named, err := WithName(testcase.name) - if err != nil { - failf("error parsing name: %s", err) - } - digested, err := WithDigest(named, testcase.digest) - if err != nil { - failf("WithDigest failed: %s", err) - } - if digested.String() != testcase.combined { - failf("unexpected: got %q, expected %q", digested.String(), testcase.combined) - } - } -} diff --git a/Godeps/_workspace/src/github.com/docker/distribution/reference/regexp_test.go b/Godeps/_workspace/src/github.com/docker/distribution/reference/regexp_test.go deleted file mode 100644 index 2ec39377a..000000000 --- a/Godeps/_workspace/src/github.com/docker/distribution/reference/regexp_test.go +++ /dev/null @@ -1,489 +0,0 @@ -package reference - -import ( - "regexp" - "strings" - "testing" -) - -type regexpMatch struct { - input string - match bool - subs []string -} - -func checkRegexp(t *testing.T, r *regexp.Regexp, m regexpMatch) { - matches := r.FindStringSubmatch(m.input) - if m.match && matches != nil { - if len(matches) != (r.NumSubexp()+1) || matches[0] != m.input { - t.Fatalf("Bad match result %#v for %q", matches, m.input) - } - if len(matches) < (len(m.subs) + 1) { - t.Errorf("Expected %d sub matches, only have %d for %q", len(m.subs), len(matches)-1, m.input) - } - for i := range m.subs { - if m.subs[i] != matches[i+1] { - t.Errorf("Unexpected submatch %d: %q, expected %q for %q", i+1, matches[i+1], m.subs[i], m.input) - } - } - } else if m.match { - t.Errorf("Expected match for %q", m.input) - } else if matches != nil { - t.Errorf("Unexpected match for %q", m.input) - } -} - -func TestHostRegexp(t *testing.T) { - hostcases := []regexpMatch{ - { - input: "test.com", - match: true, - }, - { - input: "test.com:10304", - match: true, - }, - { - input: "test.com:http", - match: false, - }, - { - input: "localhost", - match: true, - }, - { - input: "localhost:8080", - match: true, - }, - { - input: "a", - match: true, - }, - { - input: "a.b", - match: true, - }, - { - input: "ab.cd.com", - match: true, - }, - { - input: "a-b.com", - match: true, - }, - { - input: "-ab.com", - match: false, - }, - { - input: "ab-.com", - match: false, - }, - { - input: "ab.c-om", - match: true, - }, - { - input: "ab.-com", - match: false, - }, - { - input: "ab.com-", - match: false, - }, - { - input: "0101.com", - match: true, // TODO(dmcgowan): valid if this should be allowed - }, - { - input: "001a.com", - match: true, - }, - { - input: "b.gbc.io:443", - match: true, - }, - { - input: "b.gbc.io", - match: true, - }, - { - input: "xn--n3h.com", // ☃.com in punycode - match: true, - }, - { - input: "Asdf.com", // uppercase character - match: true, - }, - } - r := regexp.MustCompile(`^` + hostnameRegexp.String() + `$`) - for i := range hostcases { - checkRegexp(t, r, hostcases[i]) - } -} - -func TestFullNameRegexp(t *testing.T) { - if anchoredNameRegexp.NumSubexp() != 2 { - t.Fatalf("anchored name regexp should have two submatches: %v, %v != 2", - anchoredNameRegexp, anchoredNameRegexp.NumSubexp()) - } - - testcases := []regexpMatch{ - { - input: "", - match: false, - }, - { - input: "short", - match: true, - subs: []string{"", "short"}, - }, - { - input: "simple/name", - match: true, - subs: []string{"simple", "name"}, - }, - { - input: "library/ubuntu", - match: true, - subs: []string{"library", "ubuntu"}, - }, - { - input: "docker/stevvooe/app", - match: true, - subs: []string{"docker", "stevvooe/app"}, - }, - { - input: "aa/aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb", - match: true, - subs: []string{"aa", "aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb"}, - }, - { - input: "aa/aa/bb/bb/bb", - match: true, - subs: []string{"aa", "aa/bb/bb/bb"}, - }, - { - input: "a/a/a/a", - match: true, - subs: []string{"a", "a/a/a"}, - }, - { - input: "a/a/a/a/", - match: false, - }, - { - input: "a//a/a", - match: false, - }, - { - input: "a", - match: true, - subs: []string{"", "a"}, - }, - { - input: "a/aa", - match: true, - subs: []string{"a", "aa"}, - }, - { - input: "a/aa/a", - match: true, - subs: []string{"a", "aa/a"}, - }, - { - input: "foo.com", - match: true, - subs: []string{"", "foo.com"}, - }, - { - input: "foo.com/", - match: false, - }, - { - input: "foo.com:8080/bar", - match: true, - subs: []string{"foo.com:8080", "bar"}, - }, - { - input: "foo.com:http/bar", - match: false, - }, - { - input: "foo.com/bar", - match: true, - subs: []string{"foo.com", "bar"}, - }, - { - input: "foo.com/bar/baz", - match: true, - subs: []string{"foo.com", "bar/baz"}, - }, - { - input: "localhost:8080/bar", - match: true, - subs: []string{"localhost:8080", "bar"}, - }, - { - input: "sub-dom1.foo.com/bar/baz/quux", - match: true, - subs: []string{"sub-dom1.foo.com", "bar/baz/quux"}, - }, - { - input: "blog.foo.com/bar/baz", - match: true, - subs: []string{"blog.foo.com", "bar/baz"}, - }, - { - input: "a^a", - match: false, - }, - { - input: "aa/asdf$$^/aa", - match: false, - }, - { - input: "asdf$$^/aa", - match: false, - }, - { - input: "aa-a/a", - match: true, - subs: []string{"aa-a", "a"}, - }, - { - input: strings.Repeat("a/", 128) + "a", - match: true, - subs: []string{"a", strings.Repeat("a/", 127) + "a"}, - }, - { - input: "a-/a/a/a", - match: false, - }, - { - input: "foo.com/a-/a/a", - match: false, - }, - { - input: "-foo/bar", - match: false, - }, - { - input: "foo/bar-", - match: false, - }, - { - input: "foo-/bar", - match: false, - }, - { - input: "foo/-bar", - match: false, - }, - { - input: "_foo/bar", - match: false, - }, - { - input: "foo_bar", - match: true, - subs: []string{"", "foo_bar"}, - }, - { - input: "foo_bar.com", - match: true, - subs: []string{"", "foo_bar.com"}, - }, - { - input: "foo_bar.com:8080", - match: false, - }, - { - input: "foo_bar.com:8080/app", - match: false, - }, - { - input: "foo.com/foo_bar", - match: true, - subs: []string{"foo.com", "foo_bar"}, - }, - { - input: "____/____", - match: false, - }, - { - input: "_docker/_docker", - match: false, - }, - { - input: "docker_/docker_", - match: false, - }, - { - input: "b.gcr.io/test.example.com/my-app", - match: true, - subs: []string{"b.gcr.io", "test.example.com/my-app"}, - }, - { - input: "xn--n3h.com/myimage", // ☃.com in punycode - match: true, - subs: []string{"xn--n3h.com", "myimage"}, - }, - { - input: "xn--7o8h.com/myimage", // 🐳.com in punycode - match: true, - subs: []string{"xn--7o8h.com", "myimage"}, - }, - { - input: "example.com/xn--7o8h.com/myimage", // 🐳.com in punycode - match: true, - subs: []string{"example.com", "xn--7o8h.com/myimage"}, - }, - { - input: "example.com/some_separator__underscore/myimage", - match: true, - subs: []string{"example.com", "some_separator__underscore/myimage"}, - }, - { - input: "example.com/__underscore/myimage", - match: false, - }, - { - input: "example.com/..dots/myimage", - match: false, - }, - { - input: "example.com/.dots/myimage", - match: false, - }, - { - input: "example.com/nodouble..dots/myimage", - match: false, - }, - { - input: "example.com/nodouble..dots/myimage", - match: false, - }, - { - input: "docker./docker", - match: false, - }, - { - input: ".docker/docker", - match: false, - }, - { - input: "docker-/docker", - match: false, - }, - { - input: "-docker/docker", - match: false, - }, - { - input: "do..cker/docker", - match: false, - }, - { - input: "do__cker:8080/docker", - match: false, - }, - { - input: "do__cker/docker", - match: true, - subs: []string{"", "do__cker/docker"}, - }, - { - input: "b.gcr.io/test.example.com/my-app", - match: true, - subs: []string{"b.gcr.io", "test.example.com/my-app"}, - }, - { - input: "registry.io/foo/project--id.module--name.ver---sion--name", - match: true, - subs: []string{"registry.io", "foo/project--id.module--name.ver---sion--name"}, - }, - { - input: "Asdf.com/foo/bar", // uppercase character in hostname - match: true, - }, - { - input: "Foo/FarB", // uppercase characters in remote name - match: false, - }, - } - for i := range testcases { - checkRegexp(t, anchoredNameRegexp, testcases[i]) - } -} - -func TestReferenceRegexp(t *testing.T) { - if ReferenceRegexp.NumSubexp() != 3 { - t.Fatalf("anchored name regexp should have three submatches: %v, %v != 3", - ReferenceRegexp, ReferenceRegexp.NumSubexp()) - } - - testcases := []regexpMatch{ - { - input: "registry.com:8080/myapp:tag", - match: true, - subs: []string{"registry.com:8080/myapp", "tag", ""}, - }, - { - input: "registry.com:8080/myapp@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912", - match: true, - subs: []string{"registry.com:8080/myapp", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"}, - }, - { - input: "registry.com:8080/myapp:tag2@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912", - match: true, - subs: []string{"registry.com:8080/myapp", "tag2", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"}, - }, - { - input: "registry.com:8080/myapp@sha256:badbadbadbad", - match: false, - }, - { - input: "registry.com:8080/myapp:invalid~tag", - match: false, - }, - { - input: "bad_hostname.com:8080/myapp:tag", - match: false, - }, - { - input:// localhost treated as name, missing tag with 8080 as tag - "localhost:8080@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912", - match: true, - subs: []string{"localhost", "8080", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"}, - }, - { - input: "localhost:8080/name@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912", - match: true, - subs: []string{"localhost:8080/name", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"}, - }, - { - input: "localhost:http/name@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912", - match: false, - }, - { - // localhost will be treated as an image name without a host - input: "localhost@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912", - match: true, - subs: []string{"localhost", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"}, - }, - { - input: "registry.com:8080/myapp@bad", - match: false, - }, - { - input: "registry.com:8080/myapp@2bad", - match: false, // TODO(dmcgowan): Support this as valid - }, - } - - for i := range testcases { - checkRegexp(t, ReferenceRegexp, testcases[i]) - } - -} diff --git a/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/mount_test.go b/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/mount_test.go deleted file mode 100644 index 5c7f1b86a..000000000 --- a/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/mount_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package mount - -import ( - "os" - "path" - "testing" -) - -func TestMountOptionsParsing(t *testing.T) { - options := "noatime,ro,size=10k" - - flag, data := parseOptions(options) - - if data != "size=10k" { - t.Fatalf("Expected size=10 got %s", data) - } - - expectedFlag := NOATIME | RDONLY - - if flag != expectedFlag { - t.Fatalf("Expected %d got %d", expectedFlag, flag) - } -} - -func TestMounted(t *testing.T) { - tmp := path.Join(os.TempDir(), "mount-tests") - if err := os.MkdirAll(tmp, 0777); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - var ( - sourceDir = path.Join(tmp, "source") - targetDir = path.Join(tmp, "target") - sourcePath = path.Join(sourceDir, "file.txt") - targetPath = path.Join(targetDir, "file.txt") - ) - - os.Mkdir(sourceDir, 0777) - os.Mkdir(targetDir, 0777) - - f, err := os.Create(sourcePath) - if err != nil { - t.Fatal(err) - } - f.WriteString("hello") - f.Close() - - f, err = os.Create(targetPath) - if err != nil { - t.Fatal(err) - } - f.Close() - - if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() - - mounted, err := Mounted(targetDir) - if err != nil { - t.Fatal(err) - } - if !mounted { - t.Fatalf("Expected %s to be mounted", targetDir) - } - if _, err := os.Stat(targetDir); err != nil { - t.Fatal(err) - } -} - -func TestMountReadonly(t *testing.T) { - tmp := path.Join(os.TempDir(), "mount-tests") - if err := os.MkdirAll(tmp, 0777); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - var ( - sourceDir = path.Join(tmp, "source") - targetDir = path.Join(tmp, "target") - sourcePath = path.Join(sourceDir, "file.txt") - targetPath = path.Join(targetDir, "file.txt") - ) - - os.Mkdir(sourceDir, 0777) - os.Mkdir(targetDir, 0777) - - f, err := os.Create(sourcePath) - if err != nil { - t.Fatal(err) - } - f.WriteString("hello") - f.Close() - - f, err = os.Create(targetPath) - if err != nil { - t.Fatal(err) - } - f.Close() - - if err := Mount(sourceDir, targetDir, "none", "bind,ro"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() - - f, err = os.OpenFile(targetPath, os.O_RDWR, 0777) - if err == nil { - t.Fatal("Should not be able to open a ro file as rw") - } -} - -func TestGetMounts(t *testing.T) { - mounts, err := GetMounts() - if err != nil { - t.Fatal(err) - } - - root := false - for _, entry := range mounts { - if entry.Mountpoint == "/" { - root = true - } - } - - if !root { - t.Fatal("/ should be mounted at least") - } -} diff --git a/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/mountinfo_linux_test.go b/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/mountinfo_linux_test.go deleted file mode 100644 index 812d12e82..000000000 --- a/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/mountinfo_linux_test.go +++ /dev/null @@ -1,477 +0,0 @@ -// +build linux - -package mount - -import ( - "bytes" - "testing" -) - -const ( - fedoraMountinfo = `15 35 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw - 16 35 0:14 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw,seclabel - 17 35 0:5 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=8056484k,nr_inodes=2014121,mode=755 - 18 16 0:15 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:7 - securityfs securityfs rw - 19 16 0:13 / /sys/fs/selinux rw,relatime shared:8 - selinuxfs selinuxfs rw - 20 17 0:16 / /dev/shm rw,nosuid,nodev shared:3 - tmpfs tmpfs rw,seclabel - 21 17 0:10 / /dev/pts rw,nosuid,noexec,relatime shared:4 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=000 - 22 35 0:17 / /run rw,nosuid,nodev shared:21 - tmpfs tmpfs rw,seclabel,mode=755 - 23 16 0:18 / /sys/fs/cgroup rw,nosuid,nodev,noexec shared:9 - tmpfs tmpfs rw,seclabel,mode=755 - 24 23 0:19 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd - 25 16 0:20 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:20 - pstore pstore rw - 26 23 0:21 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,cpuset,clone_children - 27 23 0:22 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,cpuacct,cpu,clone_children - 28 23 0:23 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,memory,clone_children - 29 23 0:24 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,devices,clone_children - 30 23 0:25 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,freezer,clone_children - 31 23 0:26 / /sys/fs/cgroup/net_cls rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,net_cls,clone_children - 32 23 0:27 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,blkio,clone_children - 33 23 0:28 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,perf_event,clone_children - 34 23 0:29 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb,clone_children - 35 1 253:2 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root--f20 rw,seclabel,data=ordered - 36 15 0:30 / /proc/sys/fs/binfmt_misc rw,relatime shared:22 - autofs systemd-1 rw,fd=38,pgrp=1,timeout=300,minproto=5,maxproto=5,direct - 37 17 0:12 / /dev/mqueue rw,relatime shared:23 - mqueue mqueue rw,seclabel - 38 35 0:31 / /tmp rw shared:24 - tmpfs tmpfs rw,seclabel - 39 17 0:32 / /dev/hugepages rw,relatime shared:25 - hugetlbfs hugetlbfs rw,seclabel - 40 16 0:7 / /sys/kernel/debug rw,relatime shared:26 - debugfs debugfs rw - 41 16 0:33 / /sys/kernel/config rw,relatime shared:27 - configfs configfs rw - 42 35 0:34 / /var/lib/nfs/rpc_pipefs rw,relatime shared:28 - rpc_pipefs sunrpc rw - 43 15 0:35 / /proc/fs/nfsd rw,relatime shared:29 - nfsd sunrpc rw - 45 35 8:17 / /boot rw,relatime shared:30 - ext4 /dev/sdb1 rw,seclabel,data=ordered - 46 35 253:4 / /home rw,relatime shared:31 - ext4 /dev/mapper/ssd-home rw,seclabel,data=ordered - 47 35 253:5 / /var/lib/libvirt/images rw,noatime,nodiratime shared:32 - ext4 /dev/mapper/ssd-virt rw,seclabel,discard,data=ordered - 48 35 253:12 / /mnt/old rw,relatime shared:33 - ext4 /dev/mapper/HelpDeskRHEL6-FedoraRoot rw,seclabel,data=ordered - 121 22 0:36 / /run/user/1000/gvfs rw,nosuid,nodev,relatime shared:104 - fuse.gvfsd-fuse gvfsd-fuse rw,user_id=1000,group_id=1000 - 124 16 0:37 / /sys/fs/fuse/connections rw,relatime shared:107 - fusectl fusectl rw - 165 38 253:3 / /tmp/mnt rw,relatime shared:147 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered - 167 35 253:15 / /var/lib/docker/devicemapper/mnt/aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,relatime shared:149 - ext4 /dev/mapper/docker-253:2-425882-aae4076022f0e2b80a2afbf8fc6df450c52080191fcef7fb679a73e6f073e5c2 rw,seclabel,discard,stripe=16,data=ordered - 171 35 253:16 / /var/lib/docker/devicemapper/mnt/c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,relatime shared:153 - ext4 /dev/mapper/docker-253:2-425882-c71be651f114db95180e472f7871b74fa597ee70a58ccc35cb87139ddea15373 rw,seclabel,discard,stripe=16,data=ordered - 175 35 253:17 / /var/lib/docker/devicemapper/mnt/1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,relatime shared:157 - ext4 /dev/mapper/docker-253:2-425882-1bac6ab72862d2d5626560df6197cf12036b82e258c53d981fa29adce6f06c3c rw,seclabel,discard,stripe=16,data=ordered - 179 35 253:18 / /var/lib/docker/devicemapper/mnt/d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,relatime shared:161 - ext4 /dev/mapper/docker-253:2-425882-d710a357d77158e80d5b2c55710ae07c94e76d34d21ee7bae65ce5418f739b09 rw,seclabel,discard,stripe=16,data=ordered - 183 35 253:19 / /var/lib/docker/devicemapper/mnt/6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,relatime shared:165 - ext4 /dev/mapper/docker-253:2-425882-6479f52366114d5f518db6837254baab48fab39f2ac38d5099250e9a6ceae6c7 rw,seclabel,discard,stripe=16,data=ordered - 187 35 253:20 / /var/lib/docker/devicemapper/mnt/8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,relatime shared:169 - ext4 /dev/mapper/docker-253:2-425882-8d9df91c4cca5aef49eeb2725292aab324646f723a7feab56be34c2ad08268e1 rw,seclabel,discard,stripe=16,data=ordered - 191 35 253:21 / /var/lib/docker/devicemapper/mnt/c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,relatime shared:173 - ext4 /dev/mapper/docker-253:2-425882-c8240b768603d32e920d365dc9d1dc2a6af46cd23e7ae819947f969e1b4ec661 rw,seclabel,discard,stripe=16,data=ordered - 195 35 253:22 / /var/lib/docker/devicemapper/mnt/2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,relatime shared:177 - ext4 /dev/mapper/docker-253:2-425882-2eb3a01278380bbf3ed12d86ac629eaa70a4351301ee307a5cabe7b5f3b1615f rw,seclabel,discard,stripe=16,data=ordered - 199 35 253:23 / /var/lib/docker/devicemapper/mnt/37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,relatime shared:181 - ext4 /dev/mapper/docker-253:2-425882-37a17fb7c9d9b80821235d5f2662879bd3483915f245f9b49cdaa0e38779b70b rw,seclabel,discard,stripe=16,data=ordered - 203 35 253:24 / /var/lib/docker/devicemapper/mnt/aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,relatime shared:185 - ext4 /dev/mapper/docker-253:2-425882-aea459ae930bf1de913e2f29428fd80ee678a1e962d4080019d9f9774331ee2b rw,seclabel,discard,stripe=16,data=ordered - 207 35 253:25 / /var/lib/docker/devicemapper/mnt/928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,relatime shared:189 - ext4 /dev/mapper/docker-253:2-425882-928ead0bc06c454bd9f269e8585aeae0a6bd697f46dc8754c2a91309bc810882 rw,seclabel,discard,stripe=16,data=ordered - 211 35 253:26 / /var/lib/docker/devicemapper/mnt/0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,relatime shared:193 - ext4 /dev/mapper/docker-253:2-425882-0f284d18481d671644706e7a7244cbcf63d590d634cc882cb8721821929d0420 rw,seclabel,discard,stripe=16,data=ordered - 215 35 253:27 / /var/lib/docker/devicemapper/mnt/d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,relatime shared:197 - ext4 /dev/mapper/docker-253:2-425882-d9dd16722ab34c38db2733e23f69e8f4803ce59658250dd63e98adff95d04919 rw,seclabel,discard,stripe=16,data=ordered - 219 35 253:28 / /var/lib/docker/devicemapper/mnt/bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,relatime shared:201 - ext4 /dev/mapper/docker-253:2-425882-bc4500479f18c2c08c21ad5282e5f826a016a386177d9874c2764751c031d634 rw,seclabel,discard,stripe=16,data=ordered - 223 35 253:29 / /var/lib/docker/devicemapper/mnt/7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,relatime shared:205 - ext4 /dev/mapper/docker-253:2-425882-7770c8b24eb3d5cc159a065910076938910d307ab2f5d94e1dc3b24c06ee2c8a rw,seclabel,discard,stripe=16,data=ordered - 227 35 253:30 / /var/lib/docker/devicemapper/mnt/c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,relatime shared:209 - ext4 /dev/mapper/docker-253:2-425882-c280cd3d0bf0aa36b478b292279671624cceafc1a67eaa920fa1082601297adf rw,seclabel,discard,stripe=16,data=ordered - 231 35 253:31 / /var/lib/docker/devicemapper/mnt/8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,relatime shared:213 - ext4 /dev/mapper/docker-253:2-425882-8b59a7d9340279f09fea67fd6ad89ddef711e9e7050eb647984f8b5ef006335f rw,seclabel,discard,stripe=16,data=ordered - 235 35 253:32 / /var/lib/docker/devicemapper/mnt/1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,relatime shared:217 - ext4 /dev/mapper/docker-253:2-425882-1a28059f29eda821578b1bb27a60cc71f76f846a551abefabce6efd0146dce9f rw,seclabel,discard,stripe=16,data=ordered - 239 35 253:33 / /var/lib/docker/devicemapper/mnt/e9aa60c60128cad1 rw,relatime shared:221 - ext4 /dev/mapper/docker-253:2-425882-e9aa60c60128cad1 rw,seclabel,discard,stripe=16,data=ordered - 243 35 253:34 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,relatime shared:225 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d-init rw,seclabel,discard,stripe=16,data=ordered - 247 35 253:35 / /var/lib/docker/devicemapper/mnt/5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,relatime shared:229 - ext4 /dev/mapper/docker-253:2-425882-5fec11304b6f4713fea7b6ccdcc1adc0a1966187f590fe25a8227428a8df275d rw,seclabel,discard,stripe=16,data=ordered - 31 21 0:23 / /DATA/foo_bla_bla rw,relatime - cifs //foo/BLA\040BLA\040BLA/ rw,sec=ntlm,cache=loose,unc=\\foo\BLA BLA BLA,username=my_login,domain=mydomain.com,uid=12345678,forceuid,gid=12345678,forcegid,addr=10.1.30.10,file_mode=0755,dir_mode=0755,nounix,rsize=61440,wsize=65536,actimeo=1` - - ubuntuMountInfo = `15 20 0:14 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw -16 20 0:3 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw -17 20 0:5 / /dev rw,relatime - devtmpfs udev rw,size=1015140k,nr_inodes=253785,mode=755 -18 17 0:11 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000 -19 20 0:15 / /run rw,nosuid,noexec,relatime - tmpfs tmpfs rw,size=205044k,mode=755 -20 1 253:0 / / rw,relatime - ext4 /dev/disk/by-label/DOROOT rw,errors=remount-ro,data=ordered -21 15 0:16 / /sys/fs/cgroup rw,relatime - tmpfs none rw,size=4k,mode=755 -22 15 0:17 / /sys/fs/fuse/connections rw,relatime - fusectl none rw -23 15 0:6 / /sys/kernel/debug rw,relatime - debugfs none rw -24 15 0:10 / /sys/kernel/security rw,relatime - securityfs none rw -25 19 0:18 / /run/lock rw,nosuid,nodev,noexec,relatime - tmpfs none rw,size=5120k -26 21 0:19 / /sys/fs/cgroup/cpuset rw,relatime - cgroup cgroup rw,cpuset,clone_children -27 19 0:20 / /run/shm rw,nosuid,nodev,relatime - tmpfs none rw -28 21 0:21 / /sys/fs/cgroup/cpu rw,relatime - cgroup cgroup rw,cpu -29 19 0:22 / /run/user rw,nosuid,nodev,noexec,relatime - tmpfs none rw,size=102400k,mode=755 -30 15 0:23 / /sys/fs/pstore rw,relatime - pstore none rw -31 21 0:24 / /sys/fs/cgroup/cpuacct rw,relatime - cgroup cgroup rw,cpuacct -32 21 0:25 / /sys/fs/cgroup/memory rw,relatime - cgroup cgroup rw,memory -33 21 0:26 / /sys/fs/cgroup/devices rw,relatime - cgroup cgroup rw,devices -34 21 0:27 / /sys/fs/cgroup/freezer rw,relatime - cgroup cgroup rw,freezer -35 21 0:28 / /sys/fs/cgroup/blkio rw,relatime - cgroup cgroup rw,blkio -36 21 0:29 / /sys/fs/cgroup/perf_event rw,relatime - cgroup cgroup rw,perf_event -37 21 0:30 / /sys/fs/cgroup/hugetlb rw,relatime - cgroup cgroup rw,hugetlb -38 21 0:31 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup systemd rw,name=systemd -39 20 0:32 / /var/lib/docker/aufs/mnt/b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc rw,relatime - aufs none rw,si=caafa54fdc06525 -40 20 0:33 / /var/lib/docker/aufs/mnt/2eed44ac7ce7c75af04f088ed6cb4ce9d164801e91d78c6db65d7ef6d572bba8-init rw,relatime - aufs none rw,si=caafa54f882b525 -41 20 0:34 / /var/lib/docker/aufs/mnt/2eed44ac7ce7c75af04f088ed6cb4ce9d164801e91d78c6db65d7ef6d572bba8 rw,relatime - aufs none rw,si=caafa54f8829525 -42 20 0:35 / /var/lib/docker/aufs/mnt/16f4d7e96dd612903f425bfe856762f291ff2e36a8ecd55a2209b7d7cd81c30b rw,relatime - aufs none rw,si=caafa54f882d525 -43 20 0:36 / /var/lib/docker/aufs/mnt/63ca08b75d7438a9469a5954e003f48ffede73541f6286ce1cb4d7dd4811da7e-init rw,relatime - aufs none rw,si=caafa54f882f525 -44 20 0:37 / /var/lib/docker/aufs/mnt/63ca08b75d7438a9469a5954e003f48ffede73541f6286ce1cb4d7dd4811da7e rw,relatime - aufs none rw,si=caafa54f88ba525 -45 20 0:38 / /var/lib/docker/aufs/mnt/283f35a910233c756409313be71ecd8fcfef0df57108b8d740b61b3e88860452 rw,relatime - aufs none rw,si=caafa54f88b8525 -46 20 0:39 / /var/lib/docker/aufs/mnt/2c6c7253d4090faa3886871fb21bd660609daeb0206588c0602007f7d0f254b1-init rw,relatime - aufs none rw,si=caafa54f88be525 -47 20 0:40 / /var/lib/docker/aufs/mnt/2c6c7253d4090faa3886871fb21bd660609daeb0206588c0602007f7d0f254b1 rw,relatime - aufs none rw,si=caafa54f882c525 -48 20 0:41 / /var/lib/docker/aufs/mnt/de2b538c97d6366cc80e8658547c923ea1d042f85580df379846f36a4df7049d rw,relatime - aufs none rw,si=caafa54f85bb525 -49 20 0:42 / /var/lib/docker/aufs/mnt/94a3d8ed7c27e5b0aa71eba46c736bfb2742afda038e74f2dd6035fb28415b49-init rw,relatime - aufs none rw,si=caafa54fdc00525 -50 20 0:43 / /var/lib/docker/aufs/mnt/94a3d8ed7c27e5b0aa71eba46c736bfb2742afda038e74f2dd6035fb28415b49 rw,relatime - aufs none rw,si=caafa54fbaec525 -51 20 0:44 / /var/lib/docker/aufs/mnt/6ac1cace985c9fc9bea32234de8b36dba49bdd5e29a2972b327ff939d78a6274 rw,relatime - aufs none rw,si=caafa54f8e1a525 -52 20 0:45 / /var/lib/docker/aufs/mnt/dff147033e3a0ef061e1de1ad34256b523d4a8c1fa6bba71a0ab538e8628ff0b-init rw,relatime - aufs none rw,si=caafa54f8e1d525 -53 20 0:46 / /var/lib/docker/aufs/mnt/dff147033e3a0ef061e1de1ad34256b523d4a8c1fa6bba71a0ab538e8628ff0b rw,relatime - aufs none rw,si=caafa54f8e1b525 -54 20 0:47 / /var/lib/docker/aufs/mnt/cabb117d997f0f93519185aea58389a9762770b7496ed0b74a3e4a083fa45902 rw,relatime - aufs none rw,si=caafa54f810a525 -55 20 0:48 / /var/lib/docker/aufs/mnt/e1c8a94ffaa9d532bbbdc6ef771ce8a6c2c06757806ecaf8b68e9108fec65f33-init rw,relatime - aufs none rw,si=caafa54f8529525 -56 20 0:49 / /var/lib/docker/aufs/mnt/e1c8a94ffaa9d532bbbdc6ef771ce8a6c2c06757806ecaf8b68e9108fec65f33 rw,relatime - aufs none rw,si=caafa54f852f525 -57 20 0:50 / /var/lib/docker/aufs/mnt/16a1526fa445b84ce84f89506d219e87fa488a814063baf045d88b02f21166b3 rw,relatime - aufs none rw,si=caafa54f9e1d525 -58 20 0:51 / /var/lib/docker/aufs/mnt/57b9c92e1e368fa7dbe5079f7462e917777829caae732828b003c355fe49da9f-init rw,relatime - aufs none rw,si=caafa54f854d525 -59 20 0:52 / /var/lib/docker/aufs/mnt/57b9c92e1e368fa7dbe5079f7462e917777829caae732828b003c355fe49da9f rw,relatime - aufs none rw,si=caafa54f854e525 -60 20 0:53 / /var/lib/docker/aufs/mnt/e370c3e286bea027917baa0e4d251262681a472a87056e880dfd0513516dffd9 rw,relatime - aufs none rw,si=caafa54f840a525 -61 20 0:54 / /var/lib/docker/aufs/mnt/6b00d3b4f32b41997ec07412b5e18204f82fbe643e7122251cdeb3582abd424e-init rw,relatime - aufs none rw,si=caafa54f8408525 -62 20 0:55 / /var/lib/docker/aufs/mnt/6b00d3b4f32b41997ec07412b5e18204f82fbe643e7122251cdeb3582abd424e rw,relatime - aufs none rw,si=caafa54f8409525 -63 20 0:56 / /var/lib/docker/aufs/mnt/abd0b5ea5d355a67f911475e271924a5388ee60c27185fcd60d095afc4a09dc7 rw,relatime - aufs none rw,si=caafa54f9eb1525 -64 20 0:57 / /var/lib/docker/aufs/mnt/336222effc3f7b89867bb39ff7792ae5412c35c749f127c29159d046b6feedd2-init rw,relatime - aufs none rw,si=caafa54f85bf525 -65 20 0:58 / /var/lib/docker/aufs/mnt/336222effc3f7b89867bb39ff7792ae5412c35c749f127c29159d046b6feedd2 rw,relatime - aufs none rw,si=caafa54f85b8525 -66 20 0:59 / /var/lib/docker/aufs/mnt/912e1bf28b80a09644503924a8a1a4fb8ed10b808ca847bda27a369919aa52fa rw,relatime - aufs none rw,si=caafa54fbaea525 -67 20 0:60 / /var/lib/docker/aufs/mnt/386f722875013b4a875118367abc783fc6617a3cb7cf08b2b4dcf550b4b9c576-init rw,relatime - aufs none rw,si=caafa54f8472525 -68 20 0:61 / /var/lib/docker/aufs/mnt/386f722875013b4a875118367abc783fc6617a3cb7cf08b2b4dcf550b4b9c576 rw,relatime - aufs none rw,si=caafa54f8474525 -69 20 0:62 / /var/lib/docker/aufs/mnt/5aaebb79ef3097dfca377889aeb61a0c9d5e3795117d2b08d0751473c671dfb2 rw,relatime - aufs none rw,si=caafa54f8c5e525 -70 20 0:63 / /var/lib/docker/aufs/mnt/5ba3e493279d01277d583600b81c7c079e691b73c3a2bdea8e4b12a35a418be2-init rw,relatime - aufs none rw,si=caafa54f8c3b525 -71 20 0:64 / /var/lib/docker/aufs/mnt/5ba3e493279d01277d583600b81c7c079e691b73c3a2bdea8e4b12a35a418be2 rw,relatime - aufs none rw,si=caafa54f8c3d525 -72 20 0:65 / /var/lib/docker/aufs/mnt/2777f0763da4de93f8bebbe1595cc77f739806a158657b033eca06f827b6028a rw,relatime - aufs none rw,si=caafa54f8c3e525 -73 20 0:66 / /var/lib/docker/aufs/mnt/5d7445562acf73c6f0ae34c3dd0921d7457de1ba92a587d9e06a44fa209eeb3e-init rw,relatime - aufs none rw,si=caafa54f8c39525 -74 20 0:67 / /var/lib/docker/aufs/mnt/5d7445562acf73c6f0ae34c3dd0921d7457de1ba92a587d9e06a44fa209eeb3e rw,relatime - aufs none rw,si=caafa54f854f525 -75 20 0:68 / /var/lib/docker/aufs/mnt/06400b526ec18b66639c96efc41a84f4ae0b117cb28dafd56be420651b4084a0 rw,relatime - aufs none rw,si=caafa54f840b525 -76 20 0:69 / /var/lib/docker/aufs/mnt/e051d45ec42d8e3e1cc57bb39871a40de486dc123522e9c067fbf2ca6a357785-init rw,relatime - aufs none rw,si=caafa54fdddf525 -77 20 0:70 / /var/lib/docker/aufs/mnt/e051d45ec42d8e3e1cc57bb39871a40de486dc123522e9c067fbf2ca6a357785 rw,relatime - aufs none rw,si=caafa54f854b525 -78 20 0:71 / /var/lib/docker/aufs/mnt/1ff414fa93fd61ec81b0ab7b365a841ff6545accae03cceac702833aaeaf718f rw,relatime - aufs none rw,si=caafa54f8d85525 -79 20 0:72 / /var/lib/docker/aufs/mnt/c661b2f871dd5360e46a2aebf8f970f6d39a2ff64e06979aa0361227c88128b8-init rw,relatime - aufs none rw,si=caafa54f8da3525 -80 20 0:73 / /var/lib/docker/aufs/mnt/c661b2f871dd5360e46a2aebf8f970f6d39a2ff64e06979aa0361227c88128b8 rw,relatime - aufs none rw,si=caafa54f8da2525 -81 20 0:74 / /var/lib/docker/aufs/mnt/b68b1d4fe4d30016c552398e78b379a39f651661d8e1fa5f2460c24a5e723420 rw,relatime - aufs none rw,si=caafa54f8d81525 -82 20 0:75 / /var/lib/docker/aufs/mnt/c5c5979c936cd0153a4c626fa9d69ce4fce7d924cc74fa68b025d2f585031739-init rw,relatime - aufs none rw,si=caafa54f8da1525 -83 20 0:76 / /var/lib/docker/aufs/mnt/c5c5979c936cd0153a4c626fa9d69ce4fce7d924cc74fa68b025d2f585031739 rw,relatime - aufs none rw,si=caafa54f8da0525 -84 20 0:77 / /var/lib/docker/aufs/mnt/53e10b0329afc0e0d3322d31efaed4064139dc7027fe6ae445cffd7104bcc94f rw,relatime - aufs none rw,si=caafa54f8c35525 -85 20 0:78 / /var/lib/docker/aufs/mnt/3bfafd09ff2603e2165efacc2215c1f51afabba6c42d04a68cc2df0e8cc31494-init rw,relatime - aufs none rw,si=caafa54f8db8525 -86 20 0:79 / /var/lib/docker/aufs/mnt/3bfafd09ff2603e2165efacc2215c1f51afabba6c42d04a68cc2df0e8cc31494 rw,relatime - aufs none rw,si=caafa54f8dba525 -87 20 0:80 / /var/lib/docker/aufs/mnt/90fdd2c03eeaf65311f88f4200e18aef6d2772482712d9aea01cd793c64781b5 rw,relatime - aufs none rw,si=caafa54f8315525 -88 20 0:81 / /var/lib/docker/aufs/mnt/7bdf2591c06c154ceb23f5e74b1d03b18fbf6fe96e35fbf539b82d446922442f-init rw,relatime - aufs none rw,si=caafa54f8fc6525 -89 20 0:82 / /var/lib/docker/aufs/mnt/7bdf2591c06c154ceb23f5e74b1d03b18fbf6fe96e35fbf539b82d446922442f rw,relatime - aufs none rw,si=caafa54f8468525 -90 20 0:83 / /var/lib/docker/aufs/mnt/8cf9a993f50f3305abad3da268c0fc44ff78a1e7bba595ef9de963497496c3f9 rw,relatime - aufs none rw,si=caafa54f8c59525 -91 20 0:84 / /var/lib/docker/aufs/mnt/ecc896fd74b21840a8d35e8316b92a08b1b9c83d722a12acff847e9f0ff17173-init rw,relatime - aufs none rw,si=caafa54f846a525 -92 20 0:85 / /var/lib/docker/aufs/mnt/ecc896fd74b21840a8d35e8316b92a08b1b9c83d722a12acff847e9f0ff17173 rw,relatime - aufs none rw,si=caafa54f846b525 -93 20 0:86 / /var/lib/docker/aufs/mnt/d8c8288ec920439a48b5796bab5883ee47a019240da65e8d8f33400c31bac5df rw,relatime - aufs none rw,si=caafa54f8dbf525 -94 20 0:87 / /var/lib/docker/aufs/mnt/ecba66710bcd03199b9398e46c005cd6b68d0266ec81dc8b722a29cc417997c6-init rw,relatime - aufs none rw,si=caafa54f810f525 -95 20 0:88 / /var/lib/docker/aufs/mnt/ecba66710bcd03199b9398e46c005cd6b68d0266ec81dc8b722a29cc417997c6 rw,relatime - aufs none rw,si=caafa54fbae9525 -96 20 0:89 / /var/lib/docker/aufs/mnt/befc1c67600df449dddbe796c0d06da7caff1d2bbff64cde1f0ba82d224996b5 rw,relatime - aufs none rw,si=caafa54f8dab525 -97 20 0:90 / /var/lib/docker/aufs/mnt/c9f470e73d2742629cdc4084a1b2c1a8302914f2aa0d0ec4542371df9a050562-init rw,relatime - aufs none rw,si=caafa54fdc02525 -98 20 0:91 / /var/lib/docker/aufs/mnt/c9f470e73d2742629cdc4084a1b2c1a8302914f2aa0d0ec4542371df9a050562 rw,relatime - aufs none rw,si=caafa54f9eb0525 -99 20 0:92 / /var/lib/docker/aufs/mnt/2a31f10029f04ff9d4381167a9b739609853d7220d55a56cb654779a700ee246 rw,relatime - aufs none rw,si=caafa54f8c37525 -100 20 0:93 / /var/lib/docker/aufs/mnt/8c4261b8e3e4b21ebba60389bd64b6261217e7e6b9fd09e201d5a7f6760f6927-init rw,relatime - aufs none rw,si=caafa54fd173525 -101 20 0:94 / /var/lib/docker/aufs/mnt/8c4261b8e3e4b21ebba60389bd64b6261217e7e6b9fd09e201d5a7f6760f6927 rw,relatime - aufs none rw,si=caafa54f8108525 -102 20 0:95 / /var/lib/docker/aufs/mnt/eaa0f57403a3dc685268f91df3fbcd7a8423cee50e1a9ee5c3e1688d9d676bb4 rw,relatime - aufs none rw,si=caafa54f852d525 -103 20 0:96 / /var/lib/docker/aufs/mnt/9cfe69a2cbffd9bfc7f396d4754f6fe5cc457ef417b277797be3762dfe955a6b-init rw,relatime - aufs none rw,si=caafa54f8d80525 -104 20 0:97 / /var/lib/docker/aufs/mnt/9cfe69a2cbffd9bfc7f396d4754f6fe5cc457ef417b277797be3762dfe955a6b rw,relatime - aufs none rw,si=caafa54f8fc3525 -105 20 0:98 / /var/lib/docker/aufs/mnt/d1b322ae17613c6adee84e709641a9244ac56675244a89a64dc0075075fcbb83 rw,relatime - aufs none rw,si=caafa54f8c58525 -106 20 0:99 / /var/lib/docker/aufs/mnt/d46c2a8e9da7e91ab34fd9c192851c246a4e770a46720bda09e55c7554b9dbbd-init rw,relatime - aufs none rw,si=caafa54f8c63525 -107 20 0:100 / /var/lib/docker/aufs/mnt/d46c2a8e9da7e91ab34fd9c192851c246a4e770a46720bda09e55c7554b9dbbd rw,relatime - aufs none rw,si=caafa54f8c67525 -108 20 0:101 / /var/lib/docker/aufs/mnt/bc9d2a264158f83a617a069bf17cbbf2a2ba453db7d3951d9dc63cc1558b1c2b rw,relatime - aufs none rw,si=caafa54f8dbe525 -109 20 0:102 / /var/lib/docker/aufs/mnt/9e6abb8d72bbeb4d5cf24b96018528015ba830ce42b4859965bd482cbd034e99-init rw,relatime - aufs none rw,si=caafa54f9e0d525 -110 20 0:103 / /var/lib/docker/aufs/mnt/9e6abb8d72bbeb4d5cf24b96018528015ba830ce42b4859965bd482cbd034e99 rw,relatime - aufs none rw,si=caafa54f9e1b525 -111 20 0:104 / /var/lib/docker/aufs/mnt/d4dca7b02569c732e740071e1c654d4ad282de5c41edb619af1f0aafa618be26 rw,relatime - aufs none rw,si=caafa54f8dae525 -112 20 0:105 / /var/lib/docker/aufs/mnt/fea63da40fa1c5ffbad430dde0bc64a8fc2edab09a051fff55b673c40a08f6b7-init rw,relatime - aufs none rw,si=caafa54f8c5c525 -113 20 0:106 / /var/lib/docker/aufs/mnt/fea63da40fa1c5ffbad430dde0bc64a8fc2edab09a051fff55b673c40a08f6b7 rw,relatime - aufs none rw,si=caafa54fd172525 -114 20 0:107 / /var/lib/docker/aufs/mnt/e60c57499c0b198a6734f77f660cdbbd950a5b78aa23f470ca4f0cfcc376abef rw,relatime - aufs none rw,si=caafa54909c4525 -115 20 0:108 / /var/lib/docker/aufs/mnt/099c78e7ccd9c8717471bb1bbfff838c0a9913321ba2f214fbeaf92c678e5b35-init rw,relatime - aufs none rw,si=caafa54909c3525 -116 20 0:109 / /var/lib/docker/aufs/mnt/099c78e7ccd9c8717471bb1bbfff838c0a9913321ba2f214fbeaf92c678e5b35 rw,relatime - aufs none rw,si=caafa54909c7525 -117 20 0:110 / /var/lib/docker/aufs/mnt/2997be666d58b9e71469759bcb8bd9608dad0e533a1a7570a896919ba3388825 rw,relatime - aufs none rw,si=caafa54f8557525 -118 20 0:111 / /var/lib/docker/aufs/mnt/730694eff438ef20569df38dfb38a920969d7ff2170cc9aa7cb32a7ed8147a93-init rw,relatime - aufs none rw,si=caafa54c6e88525 -119 20 0:112 / /var/lib/docker/aufs/mnt/730694eff438ef20569df38dfb38a920969d7ff2170cc9aa7cb32a7ed8147a93 rw,relatime - aufs none rw,si=caafa54c6e8e525 -120 20 0:113 / /var/lib/docker/aufs/mnt/a672a1e2f2f051f6e19ed1dfbe80860a2d774174c49f7c476695f5dd1d5b2f67 rw,relatime - aufs none rw,si=caafa54c6e15525 -121 20 0:114 / /var/lib/docker/aufs/mnt/aba3570e17859f76cf29d282d0d150659c6bd80780fdc52a465ba05245c2a420-init rw,relatime - aufs none rw,si=caafa54f8dad525 -122 20 0:115 / /var/lib/docker/aufs/mnt/aba3570e17859f76cf29d282d0d150659c6bd80780fdc52a465ba05245c2a420 rw,relatime - aufs none rw,si=caafa54f8d84525 -123 20 0:116 / /var/lib/docker/aufs/mnt/2abc86007aca46fb4a817a033e2a05ccacae40b78ea4b03f8ea616b9ada40e2e rw,relatime - aufs none rw,si=caafa54c6e8b525 -124 20 0:117 / /var/lib/docker/aufs/mnt/36352f27f7878e648367a135bd1ec3ed497adcb8ac13577ee892a0bd921d2374-init rw,relatime - aufs none rw,si=caafa54c6e8d525 -125 20 0:118 / /var/lib/docker/aufs/mnt/36352f27f7878e648367a135bd1ec3ed497adcb8ac13577ee892a0bd921d2374 rw,relatime - aufs none rw,si=caafa54f8c34525 -126 20 0:119 / /var/lib/docker/aufs/mnt/2f95ca1a629cea8363b829faa727dd52896d5561f2c96ddee4f697ea2fc872c2 rw,relatime - aufs none rw,si=caafa54c6e8a525 -127 20 0:120 / /var/lib/docker/aufs/mnt/f108c8291654f179ef143a3e07de2b5a34adbc0b28194a0ab17742b6db9a7fb2-init rw,relatime - aufs none rw,si=caafa54f8e19525 -128 20 0:121 / /var/lib/docker/aufs/mnt/f108c8291654f179ef143a3e07de2b5a34adbc0b28194a0ab17742b6db9a7fb2 rw,relatime - aufs none rw,si=caafa54fa8c6525 -129 20 0:122 / /var/lib/docker/aufs/mnt/c1d04dfdf8cccb3676d5a91e84e9b0781ce40623d127d038bcfbe4c761b27401 rw,relatime - aufs none rw,si=caafa54f8c30525 -130 20 0:123 / /var/lib/docker/aufs/mnt/3f4898ffd0e1239aeebf1d1412590cdb7254207fa3883663e2c40cf772e5f05a-init rw,relatime - aufs none rw,si=caafa54c6e1a525 -131 20 0:124 / /var/lib/docker/aufs/mnt/3f4898ffd0e1239aeebf1d1412590cdb7254207fa3883663e2c40cf772e5f05a rw,relatime - aufs none rw,si=caafa54c6e1c525 -132 20 0:125 / /var/lib/docker/aufs/mnt/5ae3b6fccb1539fc02d420e86f3e9637bef5b711fed2ca31a2f426c8f5deddbf rw,relatime - aufs none rw,si=caafa54c4fea525 -133 20 0:126 / /var/lib/docker/aufs/mnt/310bfaf80d57020f2e73b06aeffb0b9b0ca2f54895f88bf5e4d1529ccac58fe0-init rw,relatime - aufs none rw,si=caafa54c6e1e525 -134 20 0:127 / /var/lib/docker/aufs/mnt/310bfaf80d57020f2e73b06aeffb0b9b0ca2f54895f88bf5e4d1529ccac58fe0 rw,relatime - aufs none rw,si=caafa54fa8c0525 -135 20 0:128 / /var/lib/docker/aufs/mnt/f382bd5aaccaf2d04a59089ac7cb12ec87efd769fd0c14d623358fbfd2a3f896 rw,relatime - aufs none rw,si=caafa54c4fec525 -136 20 0:129 / /var/lib/docker/aufs/mnt/50d45e9bb2d779bc6362824085564c7578c231af5ae3b3da116acf7e17d00735-init rw,relatime - aufs none rw,si=caafa54c4fef525 -137 20 0:130 / /var/lib/docker/aufs/mnt/50d45e9bb2d779bc6362824085564c7578c231af5ae3b3da116acf7e17d00735 rw,relatime - aufs none rw,si=caafa54c4feb525 -138 20 0:131 / /var/lib/docker/aufs/mnt/a9c5ee0854dc083b6bf62b7eb1e5291aefbb10702289a446471ce73aba0d5d7d rw,relatime - aufs none rw,si=caafa54909c6525 -139 20 0:134 / /var/lib/docker/aufs/mnt/03a613e7bd5078819d1fd92df4e671c0127559a5e0b5a885cc8d5616875162f0-init rw,relatime - aufs none rw,si=caafa54804fe525 -140 20 0:135 / /var/lib/docker/aufs/mnt/03a613e7bd5078819d1fd92df4e671c0127559a5e0b5a885cc8d5616875162f0 rw,relatime - aufs none rw,si=caafa54804fa525 -141 20 0:136 / /var/lib/docker/aufs/mnt/7ec3277e5c04c907051caf9c9c35889f5fcd6463e5485971b25404566830bb70 rw,relatime - aufs none rw,si=caafa54804f9525 -142 20 0:139 / /var/lib/docker/aufs/mnt/26b5b5d71d79a5b2bfcf8bc4b2280ee829f261eb886745dd90997ed410f7e8b8-init rw,relatime - aufs none rw,si=caafa54c6ef6525 -143 20 0:140 / /var/lib/docker/aufs/mnt/26b5b5d71d79a5b2bfcf8bc4b2280ee829f261eb886745dd90997ed410f7e8b8 rw,relatime - aufs none rw,si=caafa54c6ef5525 -144 20 0:356 / /var/lib/docker/aufs/mnt/e6ecde9e2c18cd3c75f424c67b6d89685cfee0fc67abf2cb6bdc0867eb998026 rw,relatime - aufs none rw,si=caafa548068e525` - - gentooMountinfo = `15 1 8:6 / / rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered -16 15 0:3 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw -17 15 0:14 / /run rw,nosuid,nodev,relatime - tmpfs tmpfs rw,size=3292172k,mode=755 -18 15 0:5 / /dev rw,nosuid,relatime - devtmpfs udev rw,size=10240k,nr_inodes=4106451,mode=755 -19 18 0:12 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw -20 18 0:10 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000 -21 18 0:15 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw -22 15 0:16 / /sys rw,nosuid,nodev,noexec,relatime - sysfs sysfs rw -23 22 0:7 / /sys/kernel/debug rw,nosuid,nodev,noexec,relatime - debugfs debugfs rw -24 22 0:17 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs cgroup_root rw,size=10240k,mode=755 -25 24 0:18 / /sys/fs/cgroup/openrc rw,nosuid,nodev,noexec,relatime - cgroup openrc rw,release_agent=/lib64/rc/sh/cgroup-release-agent.sh,name=openrc -26 24 0:19 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime - cgroup cpuset rw,cpuset,clone_children -27 24 0:20 / /sys/fs/cgroup/cpu rw,nosuid,nodev,noexec,relatime - cgroup cpu rw,cpu,clone_children -28 24 0:21 / /sys/fs/cgroup/cpuacct rw,nosuid,nodev,noexec,relatime - cgroup cpuacct rw,cpuacct,clone_children -29 24 0:22 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup memory rw,memory,clone_children -30 24 0:23 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime - cgroup devices rw,devices,clone_children -31 24 0:24 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime - cgroup freezer rw,freezer,clone_children -32 24 0:25 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime - cgroup blkio rw,blkio,clone_children -33 15 8:1 / /boot rw,noatime,nodiratime - vfat /dev/sda1 rw,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro -34 15 8:18 / /mnt/xfs rw,noatime,nodiratime - xfs /dev/sdb2 rw,attr2,inode64,noquota -35 15 0:26 / /tmp rw,relatime - tmpfs tmpfs rw -36 16 0:27 / /proc/sys/fs/binfmt_misc rw,nosuid,nodev,noexec,relatime - binfmt_misc binfmt_misc rw -42 15 0:33 / /var/lib/nfs/rpc_pipefs rw,relatime - rpc_pipefs rpc_pipefs rw -43 16 0:34 / /proc/fs/nfsd rw,nosuid,nodev,noexec,relatime - nfsd nfsd rw -44 15 0:35 / /home/tianon/.gvfs rw,nosuid,nodev,relatime - fuse.gvfs-fuse-daemon gvfs-fuse-daemon rw,user_id=1000,group_id=1000 -68 15 0:3336 / /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd rw,relatime - aufs none rw,si=9b4a7640128db39c -85 68 8:6 /var/lib/docker/init/dockerinit-0.7.2-dev//deleted /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/.dockerinit rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered -86 68 8:6 /var/lib/docker/containers/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/config.env /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/.dockerenv rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered -87 68 8:6 /etc/resolv.conf /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/etc/resolv.conf rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered -88 68 8:6 /var/lib/docker/containers/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/hostname /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/etc/hostname rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered -89 68 8:6 /var/lib/docker/containers/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/hosts /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/etc/hosts rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered -38 15 0:3384 / /var/lib/docker/aufs/mnt/0292005a9292401bb5197657f2b682d97d8edcb3b72b5e390d2a680139985b55 rw,relatime - aufs none rw,si=9b4a7642b584939c -39 15 0:3385 / /var/lib/docker/aufs/mnt/59db98c889de5f71b70cfb82c40cbe47b64332f0f56042a2987a9e5df6e5e3aa rw,relatime - aufs none rw,si=9b4a7642b584e39c -40 15 0:3386 / /var/lib/docker/aufs/mnt/0545f0f2b6548eb9601d08f35a08f5a0a385407d36027a28f58e06e9f61e0278 rw,relatime - aufs none rw,si=9b4a7642b584b39c -41 15 0:3387 / /var/lib/docker/aufs/mnt/d882cfa16d1aa8fe0331a36e79be3d80b151e49f24fc39a39c3fed1735d5feb5 rw,relatime - aufs none rw,si=9b4a76453040039c -45 15 0:3388 / /var/lib/docker/aufs/mnt/055ca3befcb1626e74f5344b3398724ff05c0de0e20021683d04305c9e70a3f6 rw,relatime - aufs none rw,si=9b4a76453040739c -46 15 0:3389 / /var/lib/docker/aufs/mnt/b899e4567a351745d4285e7f1c18fdece75d877deb3041981cd290be348b7aa6 rw,relatime - aufs none rw,si=9b4a7647def4039c -47 15 0:3390 / /var/lib/docker/aufs/mnt/067ca040292c58954c5129f953219accfae0d40faca26b4d05e76ca76a998f16 rw,relatime - aufs none rw,si=9b4a7647def4239c -48 15 0:3391 / /var/lib/docker/aufs/mnt/8c995e7cb6e5082742daeea720e340b021d288d25d92e0412c03d200df308a11 rw,relatime - aufs none rw,si=9b4a764479c1639c -49 15 0:3392 / /var/lib/docker/aufs/mnt/07cc54dfae5b45300efdacdd53cc72c01b9044956a86ce7bff42d087e426096d rw,relatime - aufs none rw,si=9b4a764479c1739c -50 15 0:3393 / /var/lib/docker/aufs/mnt/0a9c95cf4c589c05b06baa79150b0cc1d8e7102759fe3ce4afaabb8247ca4f85 rw,relatime - aufs none rw,si=9b4a7644059c839c -51 15 0:3394 / /var/lib/docker/aufs/mnt/468fa98cececcf4e226e8370f18f4f848d63faf287fb8321a07f73086441a3a0 rw,relatime - aufs none rw,si=9b4a7644059ca39c -52 15 0:3395 / /var/lib/docker/aufs/mnt/0b826192231c5ce066fffb5beff4397337b5fc19a377aa7c6282c7c0ce7f111f rw,relatime - aufs none rw,si=9b4a764479c1339c -53 15 0:3396 / /var/lib/docker/aufs/mnt/93b8ba1b772fbe79709b909c43ea4b2c30d712e53548f467db1ffdc7a384f196 rw,relatime - aufs none rw,si=9b4a7640798a739c -54 15 0:3397 / /var/lib/docker/aufs/mnt/0c0d0acfb506859b12ef18cdfef9ebed0b43a611482403564224bde9149d373c rw,relatime - aufs none rw,si=9b4a7640798a039c -55 15 0:3398 / /var/lib/docker/aufs/mnt/33648c39ab6c7c74af0243d6d6a81b052e9e25ad1e04b19892eb2dde013e358b rw,relatime - aufs none rw,si=9b4a7644b439b39c -56 15 0:3399 / /var/lib/docker/aufs/mnt/0c12bea97a1c958a3c739fb148536c1c89351d48e885ecda8f0499b5cc44407e rw,relatime - aufs none rw,si=9b4a7640798a239c -57 15 0:3400 / /var/lib/docker/aufs/mnt/ed443988ce125f172d7512e84a4de2627405990fd767a16adefa8ce700c19ce8 rw,relatime - aufs none rw,si=9b4a7644c8ed339c -59 15 0:3402 / /var/lib/docker/aufs/mnt/f61612c324ff3c924d3f7a82fb00a0f8d8f73c248c41897061949e9f5ab7e3b1 rw,relatime - aufs none rw,si=9b4a76442810c39c -60 15 0:3403 / /var/lib/docker/aufs/mnt/0f1ee55c6c4e25027b80de8e64b8b6fb542b3b41aa0caab9261da75752e22bfd rw,relatime - aufs none rw,si=9b4a76442810e39c -61 15 0:3404 / /var/lib/docker/aufs/mnt/956f6cc4af5785cb3ee6963dcbca668219437d9b28f513290b1453ac64a34f97 rw,relatime - aufs none rw,si=9b4a7644303ec39c -62 15 0:3405 / /var/lib/docker/aufs/mnt/1099769158c4b4773e2569e38024e8717e400f87a002c41d8cf47cb81b051ba6 rw,relatime - aufs none rw,si=9b4a7644303ee39c -63 15 0:3406 / /var/lib/docker/aufs/mnt/11890ceb98d4442595b676085cd7b21550ab85c5df841e0fba997ff54e3d522d rw,relatime - aufs none rw,si=9b4a7644303ed39c -64 15 0:3407 / /var/lib/docker/aufs/mnt/acdb90dc378e8ed2420b43a6d291f1c789a081cd1904018780cc038fcd7aae53 rw,relatime - aufs none rw,si=9b4a76434be2139c -65 15 0:3408 / /var/lib/docker/aufs/mnt/120e716f19d4714fbe63cc1ed246204f2c1106eefebc6537ba2587d7e7711959 rw,relatime - aufs none rw,si=9b4a76434be2339c -66 15 0:3409 / /var/lib/docker/aufs/mnt/b197b7fffb61d89e0ba1c40de9a9fc0d912e778b3c1bd828cf981ff37c1963bc rw,relatime - aufs none rw,si=9b4a76434be2039c -70 15 0:3412 / /var/lib/docker/aufs/mnt/1434b69d2e1bb18a9f0b96b9cdac30132b2688f5d1379f68a39a5e120c2f93eb rw,relatime - aufs none rw,si=9b4a76434be2639c -71 15 0:3413 / /var/lib/docker/aufs/mnt/16006e83caf33ab5eb0cd6afc92ea2ee8edeff897496b0bb3ec3a75b767374b3 rw,relatime - aufs none rw,si=9b4a7644d790439c -72 15 0:3414 / /var/lib/docker/aufs/mnt/55bfa5f44e94d27f91f79ba901b118b15098449165c87abf1b53ffff147ff164 rw,relatime - aufs none rw,si=9b4a7644d790239c -73 15 0:3415 / /var/lib/docker/aufs/mnt/1912b97a07ab21ccd98a2a27bc779bf3cf364a3138afa3c3e6f7f169a3c3eab5 rw,relatime - aufs none rw,si=9b4a76441822739c -76 15 0:3418 / /var/lib/docker/aufs/mnt/1a7c3292e8879bd91ffd9282e954f643b1db5683093574c248ff14a9609f2f56 rw,relatime - aufs none rw,si=9b4a76438cb7239c -77 15 0:3419 / /var/lib/docker/aufs/mnt/bb1faaf0d076ddba82c2318305a85f490dafa4e8a8640a8db8ed657c439120cc rw,relatime - aufs none rw,si=9b4a76438cb7339c -78 15 0:3420 / /var/lib/docker/aufs/mnt/1ab869f21d2241a73ac840c7f988490313f909ac642eba71d092204fec66dd7c rw,relatime - aufs none rw,si=9b4a76438cb7639c -79 15 0:3421 / /var/lib/docker/aufs/mnt/fd7245b2cfe3890fa5f5b452260e4edf9e7fb7746532ed9d83f7a0d7dbaa610e rw,relatime - aufs none rw,si=9b4a7644bdc0139c -80 15 0:3422 / /var/lib/docker/aufs/mnt/1e5686c5301f26b9b3cd24e322c608913465cc6c5d0dcd7c5e498d1314747d61 rw,relatime - aufs none rw,si=9b4a7644bdc0639c -81 15 0:3423 / /var/lib/docker/aufs/mnt/52edf6ee6e40bfec1e9301a4d4a92ab83d144e2ae4ce5099e99df6138cb844bf rw,relatime - aufs none rw,si=9b4a7644bdc0239c -82 15 0:3424 / /var/lib/docker/aufs/mnt/1ea10fb7085d28cda4904657dff0454e52598d28e1d77e4f2965bbc3666e808f rw,relatime - aufs none rw,si=9b4a76438cb7139c -83 15 0:3425 / /var/lib/docker/aufs/mnt/9c03e98c3593946dbd4087f8d83f9ca262f4a2efdc952ce60690838b9ba6c526 rw,relatime - aufs none rw,si=9b4a76443020639c -84 15 0:3426 / /var/lib/docker/aufs/mnt/220a2344d67437602c6d2cee9a98c46be13f82c2a8063919dd2fad52bf2fb7dd rw,relatime - aufs none rw,si=9b4a76434bff339c -94 15 0:3427 / /var/lib/docker/aufs/mnt/3b32876c5b200312c50baa476ff342248e88c8ea96e6a1032cd53a88738a1cf2 rw,relatime - aufs none rw,si=9b4a76434bff139c -95 15 0:3428 / /var/lib/docker/aufs/mnt/23ee2b8b0d4ae8db6f6d1e168e2c6f79f8a18f953b09f65e0d22cc1e67a3a6fa rw,relatime - aufs none rw,si=9b4a7646c305c39c -96 15 0:3429 / /var/lib/docker/aufs/mnt/e86e6daa70b61b57945fa178222615f3c3d6bcef12c9f28e9f8623d44dc2d429 rw,relatime - aufs none rw,si=9b4a7646c305f39c -97 15 0:3430 / /var/lib/docker/aufs/mnt/2413d07623e80860bb2e9e306fbdee699afd07525785c025c591231e864aa162 rw,relatime - aufs none rw,si=9b4a76434bff039c -98 15 0:3431 / /var/lib/docker/aufs/mnt/adfd622eb22340fc80b429e5564b125668e260bf9068096c46dd59f1386a4b7d rw,relatime - aufs none rw,si=9b4a7646a7a1039c -102 15 0:3435 / /var/lib/docker/aufs/mnt/27cd92e7a91d02e2d6b44d16679a00fb6d169b19b88822891084e7fd1a84882d rw,relatime - aufs none rw,si=9b4a7646f25ec39c -103 15 0:3436 / /var/lib/docker/aufs/mnt/27dfdaf94cfbf45055c748293c37dd68d9140240bff4c646cb09216015914a88 rw,relatime - aufs none rw,si=9b4a7646732f939c -104 15 0:3437 / /var/lib/docker/aufs/mnt/5ed7524aff68dfbf0fc601cbaeac01bab14391850a973dabf3653282a627920f rw,relatime - aufs none rw,si=9b4a7646732f839c -105 15 0:3438 / /var/lib/docker/aufs/mnt/2a0d4767e536beb5785b60e071e3ac8e5e812613ab143a9627bee77d0c9ab062 rw,relatime - aufs none rw,si=9b4a7646732fe39c -106 15 0:3439 / /var/lib/docker/aufs/mnt/dea3fc045d9f4ae51ba952450b948a822cf85c39411489ca5224f6d9a8d02bad rw,relatime - aufs none rw,si=9b4a764012ad839c -107 15 0:3440 / /var/lib/docker/aufs/mnt/2d140a787160798da60cb67c21b1210054ad4dafecdcf832f015995b9aa99cfd rw,relatime - aufs none rw,si=9b4a764012add39c -108 15 0:3441 / /var/lib/docker/aufs/mnt/cb190b2a8e984475914430fbad2382e0d20b9b659f8ef83ae8d170cc672e519c rw,relatime - aufs none rw,si=9b4a76454d9c239c -109 15 0:3442 / /var/lib/docker/aufs/mnt/2f4a012d5a7ffd90256a6e9aa479054b3dddbc3c6a343f26dafbf3196890223b rw,relatime - aufs none rw,si=9b4a76454d9c439c -110 15 0:3443 / /var/lib/docker/aufs/mnt/63cc77904b80c4ffbf49cb974c5d8733dc52ad7640d3ae87554b325d7312d87f rw,relatime - aufs none rw,si=9b4a76454d9c339c -111 15 0:3444 / /var/lib/docker/aufs/mnt/30333e872c451482ea2d235ff2192e875bd234006b238ae2bdde3b91a86d7522 rw,relatime - aufs none rw,si=9b4a76422cebf39c -112 15 0:3445 / /var/lib/docker/aufs/mnt/6c54fc1125da3925cae65b5c9a98f3be55b0a2c2666082e5094a4ba71beb5bff rw,relatime - aufs none rw,si=9b4a7646dd5a439c -113 15 0:3446 / /var/lib/docker/aufs/mnt/3087d48cb01cda9d0a83a9ca301e6ea40e8593d18c4921be4794c91a420ab9a3 rw,relatime - aufs none rw,si=9b4a7646dd5a739c -114 15 0:3447 / /var/lib/docker/aufs/mnt/cc2607462a8f55b179a749b144c3fdbb50678e1a4f3065ea04e283e9b1f1d8e2 rw,relatime - aufs none rw,si=9b4a7646dd5a239c -117 15 0:3450 / /var/lib/docker/aufs/mnt/310c5e8392b29e8658a22e08d96d63936633b7e2c38e8d220047928b00a03d24 rw,relatime - aufs none rw,si=9b4a7647932d739c -118 15 0:3451 / /var/lib/docker/aufs/mnt/38a1f0029406ba9c3b6058f2f406d8a1d23c855046cf355c91d87d446fcc1460 rw,relatime - aufs none rw,si=9b4a76445abc939c -119 15 0:3452 / /var/lib/docker/aufs/mnt/42e109ab7914ae997a11ccd860fd18e4d488c50c044c3240423ce15774b8b62e rw,relatime - aufs none rw,si=9b4a76445abca39c -120 15 0:3453 / /var/lib/docker/aufs/mnt/365d832af0402d052b389c1e9c0d353b48487533d20cd4351df8e24ec4e4f9d8 rw,relatime - aufs none rw,si=9b4a7644066aa39c -121 15 0:3454 / /var/lib/docker/aufs/mnt/d3fa8a24d695b6cda9b64f96188f701963d28bef0473343f8b212df1a2cf1d2b rw,relatime - aufs none rw,si=9b4a7644066af39c -122 15 0:3455 / /var/lib/docker/aufs/mnt/37d4f491919abc49a15d0c7a7cc8383f087573525d7d288accd14f0b4af9eae0 rw,relatime - aufs none rw,si=9b4a7644066ad39c -123 15 0:3456 / /var/lib/docker/aufs/mnt/93902707fe12cbdd0068ce73f2baad4b3a299189b1b19cb5f8a2025e106ae3f5 rw,relatime - aufs none rw,si=9b4a76444445f39c -126 15 0:3459 / /var/lib/docker/aufs/mnt/3b49291670a625b9bbb329ffba99bf7fa7abff80cefef040f8b89e2b3aad4f9f rw,relatime - aufs none rw,si=9b4a7640798a339c -127 15 0:3460 / /var/lib/docker/aufs/mnt/8d9c7b943cc8f854f4d0d4ec19f7c16c13b0cc4f67a41472a072648610cecb59 rw,relatime - aufs none rw,si=9b4a76427383039c -128 15 0:3461 / /var/lib/docker/aufs/mnt/3b6c90036526c376307df71d49c9f5fce334c01b926faa6a78186842de74beac rw,relatime - aufs none rw,si=9b4a7644badd439c -130 15 0:3463 / /var/lib/docker/aufs/mnt/7b24158eeddfb5d31b7e932e406ea4899fd728344335ff8e0765e89ddeb351dd rw,relatime - aufs none rw,si=9b4a7644badd539c -131 15 0:3464 / /var/lib/docker/aufs/mnt/3ead6dd5773765c74850cf6c769f21fe65c29d622ffa712664f9f5b80364ce27 rw,relatime - aufs none rw,si=9b4a7642f469939c -132 15 0:3465 / /var/lib/docker/aufs/mnt/3f825573b29547744a37b65597a9d6d15a8350be4429b7038d126a4c9a8e178f rw,relatime - aufs none rw,si=9b4a7642f469c39c -133 15 0:3466 / /var/lib/docker/aufs/mnt/f67aaaeb3681e5dcb99a41f847087370bd1c206680cb8c7b6a9819fd6c97a331 rw,relatime - aufs none rw,si=9b4a7647cc25939c -134 15 0:3467 / /var/lib/docker/aufs/mnt/41afe6cfb3c1fc2280b869db07699da88552786e28793f0bc048a265c01bd942 rw,relatime - aufs none rw,si=9b4a7647cc25c39c -135 15 0:3468 / /var/lib/docker/aufs/mnt/b8092ea59da34a40b120e8718c3ae9fa8436996edc4fc50e4b99c72dfd81e1af rw,relatime - aufs none rw,si=9b4a76445abc439c -136 15 0:3469 / /var/lib/docker/aufs/mnt/42c69d2cc179e2684458bb8596a9da6dad182c08eae9b74d5f0e615b399f75a5 rw,relatime - aufs none rw,si=9b4a76455ddbe39c -137 15 0:3470 / /var/lib/docker/aufs/mnt/ea0871954acd2d62a211ac60e05969622044d4c74597870c4f818fbb0c56b09b rw,relatime - aufs none rw,si=9b4a76455ddbf39c -138 15 0:3471 / /var/lib/docker/aufs/mnt/4307906b275ab3fc971786b3841ae3217ac85b6756ddeb7ad4ba09cd044c2597 rw,relatime - aufs none rw,si=9b4a76455ddb839c -139 15 0:3472 / /var/lib/docker/aufs/mnt/4390b872928c53500a5035634f3421622ed6299dc1472b631fc45de9f56dc180 rw,relatime - aufs none rw,si=9b4a76402f2fd39c -140 15 0:3473 / /var/lib/docker/aufs/mnt/6bb41e78863b85e4aa7da89455314855c8c3bda64e52a583bab15dc1fa2e80c2 rw,relatime - aufs none rw,si=9b4a76402f2fa39c -141 15 0:3474 / /var/lib/docker/aufs/mnt/4444f583c2a79c66608f4673a32c9c812154f027045fbd558c2d69920c53f835 rw,relatime - aufs none rw,si=9b4a764479dbd39c -142 15 0:3475 / /var/lib/docker/aufs/mnt/6f11883af4a05ea362e0c54df89058da4859f977efd07b6f539e1f55c1d2a668 rw,relatime - aufs none rw,si=9b4a76402f30b39c -143 15 0:3476 / /var/lib/docker/aufs/mnt/453490dd32e7c2e9ef906f995d8fb3c2753923d1a5e0ba3fd3296e2e4dc238e7 rw,relatime - aufs none rw,si=9b4a76402f30c39c -144 15 0:3477 / /var/lib/docker/aufs/mnt/45e5945735ee102b5e891c91650c57ec4b52bb53017d68f02d50ea8a6e230610 rw,relatime - aufs none rw,si=9b4a76423260739c -147 15 0:3480 / /var/lib/docker/aufs/mnt/4727a64a5553a1125f315b96bed10d3073d6988225a292cce732617c925b56ab rw,relatime - aufs none rw,si=9b4a76443030339c -150 15 0:3483 / /var/lib/docker/aufs/mnt/4e348b5187b9a567059306afc72d42e0ec5c893b0d4abd547526d5f9b6fb4590 rw,relatime - aufs none rw,si=9b4a7644f5d8c39c -151 15 0:3484 / /var/lib/docker/aufs/mnt/4efc616bfbc3f906718b052da22e4335f8e9f91ee9b15866ed3a8029645189ef rw,relatime - aufs none rw,si=9b4a7644f5d8939c -152 15 0:3485 / /var/lib/docker/aufs/mnt/83e730ae9754d5adb853b64735472d98dfa17136b8812ac9cfcd1eba7f4e7d2d rw,relatime - aufs none rw,si=9b4a76469aa7139c -153 15 0:3486 / /var/lib/docker/aufs/mnt/4fc5ba8a5b333be2b7eefacccb626772eeec0ae8a6975112b56c9fb36c0d342f rw,relatime - aufs none rw,si=9b4a7640128dc39c -154 15 0:3487 / /var/lib/docker/aufs/mnt/50200d5edff5dfe8d1ef3c78b0bbd709793ac6e936aa16d74ff66f7ea577b6f9 rw,relatime - aufs none rw,si=9b4a7640128da39c -155 15 0:3488 / /var/lib/docker/aufs/mnt/51e5e51604361448f0b9777f38329f414bc5ba9cf238f26d465ff479bd574b61 rw,relatime - aufs none rw,si=9b4a76444f68939c -156 15 0:3489 / /var/lib/docker/aufs/mnt/52a142149aa98bba83df8766bbb1c629a97b9799944ead90dd206c4bdf0b8385 rw,relatime - aufs none rw,si=9b4a76444f68b39c -157 15 0:3490 / /var/lib/docker/aufs/mnt/52dd21a94a00f58a1ed489312fcfffb91578089c76c5650364476f1d5de031bc rw,relatime - aufs none rw,si=9b4a76444f68f39c -158 15 0:3491 / /var/lib/docker/aufs/mnt/ee562415ddaad353ed22c88d0ca768a0c74bfba6333b6e25c46849ee22d990da rw,relatime - aufs none rw,si=9b4a7640128d839c -159 15 0:3492 / /var/lib/docker/aufs/mnt/db47a9e87173f7554f550c8a01891de79cf12acdd32e01f95c1a527a08bdfb2c rw,relatime - aufs none rw,si=9b4a764405a1d39c -160 15 0:3493 / /var/lib/docker/aufs/mnt/55e827bf6d44d930ec0b827c98356eb8b68c3301e2d60d1429aa72e05b4c17df rw,relatime - aufs none rw,si=9b4a764405a1a39c -162 15 0:3495 / /var/lib/docker/aufs/mnt/578dc4e0a87fc37ec081ca098430499a59639c09f6f12a8f48de29828a091aa6 rw,relatime - aufs none rw,si=9b4a76406d7d439c -163 15 0:3496 / /var/lib/docker/aufs/mnt/728cc1cb04fa4bc6f7bf7a90980beda6d8fc0beb71630874c0747b994efb0798 rw,relatime - aufs none rw,si=9b4a76444f20e39c -164 15 0:3497 / /var/lib/docker/aufs/mnt/5850cc4bd9b55aea46c7ad598f1785117607974084ea643580f58ce3222e683a rw,relatime - aufs none rw,si=9b4a7644a824239c -165 15 0:3498 / /var/lib/docker/aufs/mnt/89443b3f766d5a37bc8b84e29da8b84e6a3ea8486d3cf154e2aae1816516e4a8 rw,relatime - aufs none rw,si=9b4a7644a824139c -166 15 0:3499 / /var/lib/docker/aufs/mnt/f5ae8fd5a41a337907d16515bc3162525154b59c32314c695ecd092c3b47943d rw,relatime - aufs none rw,si=9b4a7644a824439c -167 15 0:3500 / /var/lib/docker/aufs/mnt/5a430854f2a03a9e5f7cbc9f3fb46a8ebca526a5b3f435236d8295e5998798f5 rw,relatime - aufs none rw,si=9b4a7647fc82439c -168 15 0:3501 / /var/lib/docker/aufs/mnt/eda16901ae4cead35070c39845cbf1e10bd6b8cb0ffa7879ae2d8a186e460f91 rw,relatime - aufs none rw,si=9b4a76441e0df39c -169 15 0:3502 / /var/lib/docker/aufs/mnt/5a593721430c2a51b119ff86a7e06ea2b37e3b4131f8f1344d402b61b0c8d868 rw,relatime - aufs none rw,si=9b4a764248bad39c -170 15 0:3503 / /var/lib/docker/aufs/mnt/d662ad0a30fbfa902e0962108685b9330597e1ee2abb16dc9462eb5a67fdd23f rw,relatime - aufs none rw,si=9b4a764248bae39c -171 15 0:3504 / /var/lib/docker/aufs/mnt/5bc9de5c79812843fb36eee96bef1ddba812407861f572e33242f4ee10da2c15 rw,relatime - aufs none rw,si=9b4a764248ba839c -172 15 0:3505 / /var/lib/docker/aufs/mnt/5e763de8e9b0f7d58d2e12a341e029ab4efb3b99788b175090d8209e971156c1 rw,relatime - aufs none rw,si=9b4a764248baa39c -173 15 0:3506 / /var/lib/docker/aufs/mnt/b4431dc2739936f1df6387e337f5a0c99cf051900c896bd7fd46a870ce61c873 rw,relatime - aufs none rw,si=9b4a76401263539c -174 15 0:3507 / /var/lib/docker/aufs/mnt/5f37830e5a02561ab8c67ea3113137ba69f67a60e41c05cb0e7a0edaa1925b24 rw,relatime - aufs none rw,si=9b4a76401263639c -184 15 0:3508 / /var/lib/docker/aufs/mnt/62ea10b957e6533538a4633a1e1d678502f50ddcdd354b2ca275c54dd7a7793a rw,relatime - aufs none rw,si=9b4a76401263039c -187 15 0:3509 / /var/lib/docker/aufs/mnt/d56ee9d44195fe390e042fda75ec15af5132adb6d5c69468fa8792f4e54a6953 rw,relatime - aufs none rw,si=9b4a76401263239c -188 15 0:3510 / /var/lib/docker/aufs/mnt/6a300930673174549c2b62f36c933f0332a20735978c007c805a301f897146c5 rw,relatime - aufs none rw,si=9b4a76455d4c539c -189 15 0:3511 / /var/lib/docker/aufs/mnt/64496c45c84d348c24d410015456d101601c30cab4d1998c395591caf7e57a70 rw,relatime - aufs none rw,si=9b4a76455d4c639c -190 15 0:3512 / /var/lib/docker/aufs/mnt/65a6a645883fe97a7422cd5e71ebe0bc17c8e6302a5361edf52e89747387e908 rw,relatime - aufs none rw,si=9b4a76455d4c039c -191 15 0:3513 / /var/lib/docker/aufs/mnt/672be40695f7b6e13b0a3ed9fc996c73727dede3481f58155950fcfad57ed616 rw,relatime - aufs none rw,si=9b4a76455d4c239c -192 15 0:3514 / /var/lib/docker/aufs/mnt/d42438acb2bfb2169e1c0d8e917fc824f7c85d336dadb0b0af36dfe0f001b3ba rw,relatime - aufs none rw,si=9b4a7642bfded39c -193 15 0:3515 / /var/lib/docker/aufs/mnt/b48a54abf26d01cb2ddd908b1ed6034d17397c1341bf0eb2b251a3e5b79be854 rw,relatime - aufs none rw,si=9b4a7642bfdee39c -194 15 0:3516 / /var/lib/docker/aufs/mnt/76f27134491f052bfb87f59092126e53ef875d6851990e59195a9da16a9412f8 rw,relatime - aufs none rw,si=9b4a7642bfde839c -195 15 0:3517 / /var/lib/docker/aufs/mnt/6bd626a5462b4f8a8e1cc7d10351326dca97a59b2758e5ea549a4f6350ce8a90 rw,relatime - aufs none rw,si=9b4a7642bfdea39c -196 15 0:3518 / /var/lib/docker/aufs/mnt/f1fe3549dbd6f5ca615e9139d9b53f0c83a3b825565df37628eacc13e70cbd6d rw,relatime - aufs none rw,si=9b4a7642bfdf539c -197 15 0:3519 / /var/lib/docker/aufs/mnt/6d0458c8426a9e93d58d0625737e6122e725c9408488ed9e3e649a9984e15c34 rw,relatime - aufs none rw,si=9b4a7642bfdf639c -198 15 0:3520 / /var/lib/docker/aufs/mnt/6e4c97db83aa82145c9cf2bafc20d500c0b5389643b689e3ae84188c270a48c5 rw,relatime - aufs none rw,si=9b4a7642bfdf039c -199 15 0:3521 / /var/lib/docker/aufs/mnt/eb94d6498f2c5969eaa9fa11ac2934f1ab90ef88e2d002258dca08e5ba74ea27 rw,relatime - aufs none rw,si=9b4a7642bfdf239c -200 15 0:3522 / /var/lib/docker/aufs/mnt/fe3f88f0c511608a2eec5f13a98703aa16e55dbf930309723d8a37101f539fe1 rw,relatime - aufs none rw,si=9b4a7642bfc3539c -201 15 0:3523 / /var/lib/docker/aufs/mnt/6f40c229fb9cad85fabf4b64a2640a5403ec03fe5ac1a57d0609fb8b606b9c83 rw,relatime - aufs none rw,si=9b4a7642bfc3639c -202 15 0:3524 / /var/lib/docker/aufs/mnt/7513e9131f7a8acf58ff15248237feb767c78732ca46e159f4d791e6ef031dbc rw,relatime - aufs none rw,si=9b4a7642bfc3039c -203 15 0:3525 / /var/lib/docker/aufs/mnt/79f48b00aa713cdf809c6bb7c7cb911b66e9a8076c81d6c9d2504139984ea2da rw,relatime - aufs none rw,si=9b4a7642bfc3239c -204 15 0:3526 / /var/lib/docker/aufs/mnt/c3680418350d11358f0a96c676bc5aa74fa00a7c89e629ef5909d3557b060300 rw,relatime - aufs none rw,si=9b4a7642f47cd39c -205 15 0:3527 / /var/lib/docker/aufs/mnt/7a1744dd350d7fcc0cccb6f1757ca4cbe5453f203a5888b0f1014d96ad5a5ef9 rw,relatime - aufs none rw,si=9b4a7642f47ce39c -206 15 0:3528 / /var/lib/docker/aufs/mnt/7fa99662db046be9f03c33c35251afda9ccdc0085636bbba1d90592cec3ff68d rw,relatime - aufs none rw,si=9b4a7642f47c839c -207 15 0:3529 / /var/lib/docker/aufs/mnt/f815021ef20da9c9b056bd1d52d8aaf6e2c0c19f11122fc793eb2b04eb995e35 rw,relatime - aufs none rw,si=9b4a7642f47ca39c -208 15 0:3530 / /var/lib/docker/aufs/mnt/801086ae3110192d601dfcebdba2db92e86ce6b6a9dba6678ea04488e4513669 rw,relatime - aufs none rw,si=9b4a7642dc6dd39c -209 15 0:3531 / /var/lib/docker/aufs/mnt/822ba7db69f21daddda87c01cfbfbf73013fc03a879daf96d16cdde6f9b1fbd6 rw,relatime - aufs none rw,si=9b4a7642dc6de39c -210 15 0:3532 / /var/lib/docker/aufs/mnt/834227c1a950fef8cae3827489129d0dd220541e60c6b731caaa765bf2e6a199 rw,relatime - aufs none rw,si=9b4a7642dc6d839c -211 15 0:3533 / /var/lib/docker/aufs/mnt/83dccbc385299bd1c7cf19326e791b33a544eea7b4cdfb6db70ea94eed4389fb rw,relatime - aufs none rw,si=9b4a7642dc6da39c -212 15 0:3534 / /var/lib/docker/aufs/mnt/f1b8e6f0e7c8928b5dcdab944db89306ebcae3e0b32f9ff40d2daa8329f21600 rw,relatime - aufs none rw,si=9b4a7645a126039c -213 15 0:3535 / /var/lib/docker/aufs/mnt/970efb262c7a020c2404cbcc5b3259efba0d110a786079faeef05bc2952abf3a rw,relatime - aufs none rw,si=9b4a7644c8ed139c -214 15 0:3536 / /var/lib/docker/aufs/mnt/84b6d73af7450f3117a77e15a5ca1255871fea6182cd8e8a7be6bc744be18c2c rw,relatime - aufs none rw,si=9b4a76406559139c -215 15 0:3537 / /var/lib/docker/aufs/mnt/88be2716e026bc681b5e63fe7942068773efbd0b6e901ca7ba441412006a96b6 rw,relatime - aufs none rw,si=9b4a76406559339c -216 15 0:3538 / /var/lib/docker/aufs/mnt/c81939aa166ce50cd8bca5cfbbcc420a78e0318dd5cd7c755209b9166a00a752 rw,relatime - aufs none rw,si=9b4a76406559239c -217 15 0:3539 / /var/lib/docker/aufs/mnt/e0f241645d64b7dc5ff6a8414087cca226be08fb54ce987d1d1f6350c57083aa rw,relatime - aufs none rw,si=9b4a7647cfc0f39c -218 15 0:3540 / /var/lib/docker/aufs/mnt/e10e2bf75234ed51d8a6a4bb39e465404fecbe318e54400d3879cdb2b0679c78 rw,relatime - aufs none rw,si=9b4a7647cfc0939c -219 15 0:3541 / /var/lib/docker/aufs/mnt/8f71d74c8cfc3228b82564aa9f09b2e576cff0083ddfb6aa5cb350346063f080 rw,relatime - aufs none rw,si=9b4a7647cfc0a39c -220 15 0:3542 / /var/lib/docker/aufs/mnt/9159f1eba2aef7f5205cc18d015cda7f5933cd29bba3b1b8aed5ccb5824c69ee rw,relatime - aufs none rw,si=9b4a76468cedd39c -221 15 0:3543 / /var/lib/docker/aufs/mnt/932cad71e652e048e500d9fbb5b8ea4fc9a269d42a3134ce527ceef42a2be56b rw,relatime - aufs none rw,si=9b4a76468cede39c -222 15 0:3544 / /var/lib/docker/aufs/mnt/bf1e1b5f529e8943cc0144ee86dbaaa37885c1ddffcef29537e0078ee7dd316a rw,relatime - aufs none rw,si=9b4a76468ced839c -223 15 0:3545 / /var/lib/docker/aufs/mnt/949d93ecf3322e09f858ce81d5f4b434068ec44ff84c375de03104f7b45ee955 rw,relatime - aufs none rw,si=9b4a76468ceda39c -224 15 0:3546 / /var/lib/docker/aufs/mnt/d65c6087f92dc2a3841b5251d2fe9ca07d4c6e5b021597692479740816e4e2a1 rw,relatime - aufs none rw,si=9b4a7645a126239c -225 15 0:3547 / /var/lib/docker/aufs/mnt/98a0153119d0651c193d053d254f6e16a68345a141baa80c87ae487e9d33f290 rw,relatime - aufs none rw,si=9b4a7640787cf39c -226 15 0:3548 / /var/lib/docker/aufs/mnt/99daf7fe5847c017392f6e59aa9706b3dfdd9e6d1ba11dae0f7fffde0a60b5e5 rw,relatime - aufs none rw,si=9b4a7640787c839c -227 15 0:3549 / /var/lib/docker/aufs/mnt/9ad1f2fe8a5599d4e10c5a6effa7f03d932d4e92ee13149031a372087a359079 rw,relatime - aufs none rw,si=9b4a7640787ca39c -228 15 0:3550 / /var/lib/docker/aufs/mnt/c26d64494da782ddac26f8370d86ac93e7c1666d88a7b99110fc86b35ea6a85d rw,relatime - aufs none rw,si=9b4a7642fc6b539c -229 15 0:3551 / /var/lib/docker/aufs/mnt/a49e4a8275133c230ec640997f35f172312eb0ea5bd2bbe10abf34aae98f30eb rw,relatime - aufs none rw,si=9b4a7642fc6b639c -230 15 0:3552 / /var/lib/docker/aufs/mnt/b5e2740c867ed843025f49d84e8d769de9e8e6039b3c8cb0735b5bf358994bc7 rw,relatime - aufs none rw,si=9b4a7642fc6b039c -231 15 0:3553 / /var/lib/docker/aufs/mnt/a826fdcf3a7039b30570054579b65763db605a314275d7aef31b872c13311b4b rw,relatime - aufs none rw,si=9b4a7642fc6b239c -232 15 0:3554 / /var/lib/docker/aufs/mnt/addf3025babf5e43b5a3f4a0da7ad863dda3c01fb8365c58fd8d28bb61dc11bc rw,relatime - aufs none rw,si=9b4a76407871d39c -233 15 0:3555 / /var/lib/docker/aufs/mnt/c5b6c6813ab3e5ebdc6d22cb2a3d3106a62095f2c298be52b07a3b0fa20ff690 rw,relatime - aufs none rw,si=9b4a76407871e39c -234 15 0:3556 / /var/lib/docker/aufs/mnt/af0609eaaf64e2392060cb46f5a9f3d681a219bb4c651d4f015bf573fbe6c4cf rw,relatime - aufs none rw,si=9b4a76407871839c -235 15 0:3557 / /var/lib/docker/aufs/mnt/e7f20e3c37ecad39cd90a97cd3549466d0d106ce4f0a930b8495442634fa4a1f rw,relatime - aufs none rw,si=9b4a76407871a39c -237 15 0:3559 / /var/lib/docker/aufs/mnt/b57a53d440ffd0c1295804fa68cdde35d2fed5409484627e71b9c37e4249fd5c rw,relatime - aufs none rw,si=9b4a76444445a39c -238 15 0:3560 / /var/lib/docker/aufs/mnt/b5e7d7b8f35e47efbba3d80c5d722f5e7bd43e54c824e54b4a4b351714d36d42 rw,relatime - aufs none rw,si=9b4a7647932d439c -239 15 0:3561 / /var/lib/docker/aufs/mnt/f1b136def157e9465640658f277f3347de593c6ae76412a2e79f7002f091cae2 rw,relatime - aufs none rw,si=9b4a76445abcd39c -240 15 0:3562 / /var/lib/docker/aufs/mnt/b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc rw,relatime - aufs none rw,si=9b4a7644403b339c -241 15 0:3563 / /var/lib/docker/aufs/mnt/b89b140cdbc95063761864e0a23346207fa27ee4c5c63a1ae85c9069a9d9cf1d rw,relatime - aufs none rw,si=9b4a7644aa19739c -242 15 0:3564 / /var/lib/docker/aufs/mnt/bc6a69ed51c07f5228f6b4f161c892e6a949c0e7e86a9c3432049d4c0e5cd298 rw,relatime - aufs none rw,si=9b4a7644aa19139c -243 15 0:3565 / /var/lib/docker/aufs/mnt/be4e2ba3f136933e239f7cf3d136f484fb9004f1fbdfee24a62a2c7b0ab30670 rw,relatime - aufs none rw,si=9b4a7644aa19339c -244 15 0:3566 / /var/lib/docker/aufs/mnt/e04ca1a4a5171e30d20f0c92f90a50b8b6f8600af5459c4b4fb25e42e864dfe1 rw,relatime - aufs none rw,si=9b4a7647932d139c -245 15 0:3567 / /var/lib/docker/aufs/mnt/be61576b31db893129aaffcd3dcb5ce35e49c4b71b30c392a78609a45c7323d8 rw,relatime - aufs none rw,si=9b4a7642d85f739c -246 15 0:3568 / /var/lib/docker/aufs/mnt/dda42c191e56becf672327658ab84fcb563322db3764b91c2fefe4aaef04c624 rw,relatime - aufs none rw,si=9b4a7642d85f139c -247 15 0:3569 / /var/lib/docker/aufs/mnt/c0a7995053330f3d88969247a2e72b07e2dd692133f5668a4a35ea3905561072 rw,relatime - aufs none rw,si=9b4a7642d85f339c -249 15 0:3571 / /var/lib/docker/aufs/mnt/c3594b2e5f08c59ff5ed338a1ba1eceeeb1f7fc5d180068338110c00b1eb8502 rw,relatime - aufs none rw,si=9b4a7642738c739c -250 15 0:3572 / /var/lib/docker/aufs/mnt/c58dce03a0ab0a7588393880379dc3bce9f96ec08ed3f99cf1555260ff0031e8 rw,relatime - aufs none rw,si=9b4a7642738c139c -251 15 0:3573 / /var/lib/docker/aufs/mnt/c73e9f1d109c9d14cb36e1c7489df85649be3911116d76c2fd3648ec8fd94e23 rw,relatime - aufs none rw,si=9b4a7642738c339c -252 15 0:3574 / /var/lib/docker/aufs/mnt/c9eef28c344877cd68aa09e543c0710ab2b305a0ff96dbb859bfa7808c3e8d01 rw,relatime - aufs none rw,si=9b4a7642d85f439c -253 15 0:3575 / /var/lib/docker/aufs/mnt/feb67148f548d70cb7484f2aaad2a86051cd6867a561741a2f13b552457d666e rw,relatime - aufs none rw,si=9b4a76468c55739c -254 15 0:3576 / /var/lib/docker/aufs/mnt/cdf1f96c36d35a96041a896bf398ec0f7dc3b0fb0643612a0f4b6ff96e04e1bb rw,relatime - aufs none rw,si=9b4a76468c55139c -255 15 0:3577 / /var/lib/docker/aufs/mnt/ec6e505872353268451ac4bc034c1df00f3bae4a3ea2261c6e48f7bd5417c1b3 rw,relatime - aufs none rw,si=9b4a76468c55339c -256 15 0:3578 / /var/lib/docker/aufs/mnt/d6dc8aca64efd90e0bc10274001882d0efb310d42ccbf5712b99b169053b8b1a rw,relatime - aufs none rw,si=9b4a7642738c439c -257 15 0:3579 / /var/lib/docker/aufs/mnt/d712594e2ff6eaeb895bfd150d694bd1305fb927e7a186b2dab7df2ea95f8f81 rw,relatime - aufs none rw,si=9b4a76401268f39c -259 15 0:3581 / /var/lib/docker/aufs/mnt/dbfa1174cd78cde2d7410eae442af0b416c4a0e6f87ed4ff1e9f169a0029abc0 rw,relatime - aufs none rw,si=9b4a76401268b39c -260 15 0:3582 / /var/lib/docker/aufs/mnt/e883f5a82316d7856fbe93ee8c0af5a920b7079619dd95c4ffd88bbd309d28dd rw,relatime - aufs none rw,si=9b4a76468c55439c -261 15 0:3583 / /var/lib/docker/aufs/mnt/fdec3eff581c4fc2b09f87befa2fa021f3f2d373bea636a87f1fb5b367d6347a rw,relatime - aufs none rw,si=9b4a7644aa1af39c -262 15 0:3584 / /var/lib/docker/aufs/mnt/ef764e26712184653067ecf7afea18a80854c41331ca0f0ef03e1bacf90a6ffc rw,relatime - aufs none rw,si=9b4a7644aa1a939c -263 15 0:3585 / /var/lib/docker/aufs/mnt/f3176b40c41fce8ce6942936359a2001a6f1b5c1bb40ee224186db0789ec2f76 rw,relatime - aufs none rw,si=9b4a7644aa1ab39c -264 15 0:3586 / /var/lib/docker/aufs/mnt/f5daf06785d3565c6dd18ea7d953d9a8b9606107781e63270fe0514508736e6a rw,relatime - aufs none rw,si=9b4a76401268c39c -58 15 0:3587 / /var/lib/docker/aufs/mnt/cde8c40f6524b7361af4f5ad05bb857dc9ee247c20852ba666195c0739e3a2b8-init rw,relatime - aufs none rw,si=9b4a76444445839c -67 15 0:3588 / /var/lib/docker/aufs/mnt/cde8c40f6524b7361af4f5ad05bb857dc9ee247c20852ba666195c0739e3a2b8 rw,relatime - aufs none rw,si=9b4a7644badd339c -265 15 0:3610 / /var/lib/docker/aufs/mnt/e812472cd2c8c4748d1ef71fac4e77e50d661b9349abe66ce3e23511ed44f414 rw,relatime - aufs none rw,si=9b4a76427937d39c -270 15 0:3615 / /var/lib/docker/aufs/mnt/997636e7c5c9d0d1376a217e295c14c205350b62bc12052804fb5f90abe6f183 rw,relatime - aufs none rw,si=9b4a76406540739c -273 15 0:3618 / /var/lib/docker/aufs/mnt/d5794d080417b6e52e69227c3873e0e4c1ff0d5a845ebe3860ec2f89a47a2a1e rw,relatime - aufs none rw,si=9b4a76454814039c -278 15 0:3623 / /var/lib/docker/aufs/mnt/586bdd48baced671bb19bc4d294ec325f26c55545ae267db426424f157d59c48 rw,relatime - aufs none rw,si=9b4a7644b439f39c -281 15 0:3626 / /var/lib/docker/aufs/mnt/69739d022f89f8586908bbd5edbbdd95ea5256356f177f9ffcc6ef9c0ea752d2 rw,relatime - aufs none rw,si=9b4a7644a0f1b39c -286 15 0:3631 / /var/lib/docker/aufs/mnt/ff28c27d5f894363993622de26d5dd352dba072f219e4691d6498c19bbbc15a9 rw,relatime - aufs none rw,si=9b4a7642265b339c -289 15 0:3634 / /var/lib/docker/aufs/mnt/aa128fe0e64fdede333aa48fd9de39530c91a9244a0f0649a3c411c61e372daa rw,relatime - aufs none rw,si=9b4a764012ada39c -99 15 8:33 / /media/REMOVE\040ME rw,nosuid,nodev,relatime - fuseblk /dev/sdc1 rw,user_id=0,group_id=0,allow_other,blksize=4096` -) - -func TestParseFedoraMountinfo(t *testing.T) { - r := bytes.NewBuffer([]byte(fedoraMountinfo)) - _, err := parseInfoFile(r) - if err != nil { - t.Fatal(err) - } -} - -func TestParseUbuntuMountinfo(t *testing.T) { - r := bytes.NewBuffer([]byte(ubuntuMountInfo)) - _, err := parseInfoFile(r) - if err != nil { - t.Fatal(err) - } -} - -func TestParseGentooMountinfo(t *testing.T) { - r := bytes.NewBuffer([]byte(gentooMountinfo)) - _, err := parseInfoFile(r) - if err != nil { - t.Fatal(err) - } -} - -func TestParseFedoraMountinfoFields(t *testing.T) { - r := bytes.NewBuffer([]byte(fedoraMountinfo)) - infos, err := parseInfoFile(r) - if err != nil { - t.Fatal(err) - } - expectedLength := 58 - if len(infos) != expectedLength { - t.Fatalf("Expected %d entries, got %d", expectedLength, len(infos)) - } - mi := Info{ - ID: 15, - Parent: 35, - Major: 0, - Minor: 3, - Root: "/", - Mountpoint: "/proc", - Opts: "rw,nosuid,nodev,noexec,relatime", - Optional: "shared:5", - Fstype: "proc", - Source: "proc", - VfsOpts: "rw", - } - - if *infos[0] != mi { - t.Fatalf("expected %#v, got %#v", mi, infos[0]) - } -} diff --git a/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/sharedsubtree_linux_test.go b/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/sharedsubtree_linux_test.go deleted file mode 100644 index 4a8d22f02..000000000 --- a/Godeps/_workspace/src/github.com/docker/docker/pkg/mount/sharedsubtree_linux_test.go +++ /dev/null @@ -1,331 +0,0 @@ -// +build linux - -package mount - -import ( - "os" - "path" - "syscall" - "testing" -) - -// nothing is propagated in or out -func TestSubtreePrivate(t *testing.T) { - tmp := path.Join(os.TempDir(), "mount-tests") - if err := os.MkdirAll(tmp, 0777); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - var ( - sourceDir = path.Join(tmp, "source") - targetDir = path.Join(tmp, "target") - outside1Dir = path.Join(tmp, "outside1") - outside2Dir = path.Join(tmp, "outside2") - - outside1Path = path.Join(outside1Dir, "file.txt") - outside2Path = path.Join(outside2Dir, "file.txt") - outside1CheckPath = path.Join(targetDir, "a", "file.txt") - outside2CheckPath = path.Join(sourceDir, "b", "file.txt") - ) - if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil { - t.Fatal(err) - } - if err := os.MkdirAll(path.Join(sourceDir, "b"), 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(targetDir, 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(outside1Dir, 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(outside2Dir, 0777); err != nil { - t.Fatal(err) - } - - if err := createFile(outside1Path); err != nil { - t.Fatal(err) - } - if err := createFile(outside2Path); err != nil { - t.Fatal(err) - } - - // mount the shared directory to a target - if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() - - // next, make the target private - if err := MakePrivate(targetDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() - - // mount in an outside path to a mounted path inside the _source_ - if err := Mount(outside1Dir, path.Join(sourceDir, "a"), "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(path.Join(sourceDir, "a")); err != nil { - t.Fatal(err) - } - }() - - // check that this file _does_not_ show in the _target_ - if _, err := os.Stat(outside1CheckPath); err != nil && !os.IsNotExist(err) { - t.Fatal(err) - } else if err == nil { - t.Fatalf("%q should not be visible, but is", outside1CheckPath) - } - - // next mount outside2Dir into the _target_ - if err := Mount(outside2Dir, path.Join(targetDir, "b"), "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(path.Join(targetDir, "b")); err != nil { - t.Fatal(err) - } - }() - - // check that this file _does_not_ show in the _source_ - if _, err := os.Stat(outside2CheckPath); err != nil && !os.IsNotExist(err) { - t.Fatal(err) - } else if err == nil { - t.Fatalf("%q should not be visible, but is", outside2CheckPath) - } -} - -// Testing that when a target is a shared mount, -// then child mounts propagate to the source -func TestSubtreeShared(t *testing.T) { - tmp := path.Join(os.TempDir(), "mount-tests") - if err := os.MkdirAll(tmp, 0777); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - var ( - sourceDir = path.Join(tmp, "source") - targetDir = path.Join(tmp, "target") - outsideDir = path.Join(tmp, "outside") - - outsidePath = path.Join(outsideDir, "file.txt") - sourceCheckPath = path.Join(sourceDir, "a", "file.txt") - ) - - if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(targetDir, 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(outsideDir, 0777); err != nil { - t.Fatal(err) - } - - if err := createFile(outsidePath); err != nil { - t.Fatal(err) - } - - // mount the source as shared - if err := MakeShared(sourceDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(sourceDir); err != nil { - t.Fatal(err) - } - }() - - // mount the shared directory to a target - if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() - - // mount in an outside path to a mounted path inside the target - if err := Mount(outsideDir, path.Join(targetDir, "a"), "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(path.Join(targetDir, "a")); err != nil { - t.Fatal(err) - } - }() - - // NOW, check that the file from the outside directory is avaible in the source directory - if _, err := os.Stat(sourceCheckPath); err != nil { - t.Fatal(err) - } -} - -// testing that mounts to a shared source show up in the slave target, -// and that mounts into a slave target do _not_ show up in the shared source -func TestSubtreeSharedSlave(t *testing.T) { - tmp := path.Join(os.TempDir(), "mount-tests") - if err := os.MkdirAll(tmp, 0777); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - var ( - sourceDir = path.Join(tmp, "source") - targetDir = path.Join(tmp, "target") - outside1Dir = path.Join(tmp, "outside1") - outside2Dir = path.Join(tmp, "outside2") - - outside1Path = path.Join(outside1Dir, "file.txt") - outside2Path = path.Join(outside2Dir, "file.txt") - outside1CheckPath = path.Join(targetDir, "a", "file.txt") - outside2CheckPath = path.Join(sourceDir, "b", "file.txt") - ) - if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil { - t.Fatal(err) - } - if err := os.MkdirAll(path.Join(sourceDir, "b"), 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(targetDir, 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(outside1Dir, 0777); err != nil { - t.Fatal(err) - } - if err := os.Mkdir(outside2Dir, 0777); err != nil { - t.Fatal(err) - } - - if err := createFile(outside1Path); err != nil { - t.Fatal(err) - } - if err := createFile(outside2Path); err != nil { - t.Fatal(err) - } - - // mount the source as shared - if err := MakeShared(sourceDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(sourceDir); err != nil { - t.Fatal(err) - } - }() - - // mount the shared directory to a target - if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() - - // next, make the target slave - if err := MakeSlave(targetDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() - - // mount in an outside path to a mounted path inside the _source_ - if err := Mount(outside1Dir, path.Join(sourceDir, "a"), "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(path.Join(sourceDir, "a")); err != nil { - t.Fatal(err) - } - }() - - // check that this file _does_ show in the _target_ - if _, err := os.Stat(outside1CheckPath); err != nil { - t.Fatal(err) - } - - // next mount outside2Dir into the _target_ - if err := Mount(outside2Dir, path.Join(targetDir, "b"), "none", "bind,rw"); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(path.Join(targetDir, "b")); err != nil { - t.Fatal(err) - } - }() - - // check that this file _does_not_ show in the _source_ - if _, err := os.Stat(outside2CheckPath); err != nil && !os.IsNotExist(err) { - t.Fatal(err) - } else if err == nil { - t.Fatalf("%q should not be visible, but is", outside2CheckPath) - } -} - -func TestSubtreeUnbindable(t *testing.T) { - tmp := path.Join(os.TempDir(), "mount-tests") - if err := os.MkdirAll(tmp, 0777); err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - var ( - sourceDir = path.Join(tmp, "source") - targetDir = path.Join(tmp, "target") - ) - if err := os.MkdirAll(sourceDir, 0777); err != nil { - t.Fatal(err) - } - if err := os.MkdirAll(targetDir, 0777); err != nil { - t.Fatal(err) - } - - // next, make the source unbindable - if err := MakeUnbindable(sourceDir); err != nil { - t.Fatal(err) - } - defer func() { - if err := Unmount(sourceDir); err != nil { - t.Fatal(err) - } - }() - - // then attempt to mount it to target. It should fail - if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil && err != syscall.EINVAL { - t.Fatal(err) - } else if err == nil { - t.Fatalf("%q should not have been bindable", sourceDir) - } - defer func() { - if err := Unmount(targetDir); err != nil { - t.Fatal(err) - } - }() -} - -func createFile(path string) error { - f, err := os.Create(path) - if err != nil { - return err - } - f.WriteString("hello world!") - return f.Close() -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/events/events.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/events/events.go deleted file mode 100644 index c5987aaf1..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/events/events.go +++ /dev/null @@ -1,38 +0,0 @@ -package events - -const ( - // ContainerEventType is the event type that containers generate - ContainerEventType = "container" - // ImageEventType is the event type that images generate - ImageEventType = "image" - // VolumeEventType is the event type that volumes generate - VolumeEventType = "volume" - // NetworkEventType is the event type that networks generate - NetworkEventType = "network" -) - -// Actor describes something that generates events, -// like a container, or a network, or a volume. -// It has a defined name and a set or attributes. -// The container attributes are its labels, other actors -// can generate these attributes from other properties. -type Actor struct { - ID string - Attributes map[string]string -} - -// Message represents the information an event contains -type Message struct { - // Deprecated information from JSONMessage. - // With data only in container events. - Status string `json:"status,omitempty"` - ID string `json:"id,omitempty"` - From string `json:"from,omitempty"` - - Type string - Action string - Actor Actor - - Time int64 `json:"time,omitempty"` - TimeNano int64 `json:"timeNano,omitempty"` -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/filters/parse_test.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/filters/parse_test.go deleted file mode 100644 index 037783b91..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/filters/parse_test.go +++ /dev/null @@ -1,394 +0,0 @@ -package filters - -import ( - "fmt" - "testing" -) - -func TestParseArgs(t *testing.T) { - // equivalent of `docker ps -f 'created=today' -f 'image.name=ubuntu*' -f 'image.name=*untu'` - flagArgs := []string{ - "created=today", - "image.name=ubuntu*", - "image.name=*untu", - } - var ( - args = NewArgs() - err error - ) - for i := range flagArgs { - args, err = ParseFlag(flagArgs[i], args) - if err != nil { - t.Errorf("failed to parse %s: %s", flagArgs[i], err) - } - } - if len(args.Get("created")) != 1 { - t.Errorf("failed to set this arg") - } - if len(args.Get("image.name")) != 2 { - t.Errorf("the args should have collapsed") - } -} - -func TestParseArgsEdgeCase(t *testing.T) { - var filters Args - args, err := ParseFlag("", filters) - if err != nil { - t.Fatal(err) - } - if args.Len() != 0 { - t.Fatalf("Expected an empty Args (map), got %v", args) - } - if args, err = ParseFlag("anything", args); err == nil || err != ErrBadFormat { - t.Fatalf("Expected ErrBadFormat, got %v", err) - } -} - -func TestToParam(t *testing.T) { - fields := map[string]map[string]bool{ - "created": {"today": true}, - "image.name": {"ubuntu*": true, "*untu": true}, - } - a := Args{fields: fields} - - _, err := ToParam(a) - if err != nil { - t.Errorf("failed to marshal the filters: %s", err) - } -} - -func TestToParamWithVersion(t *testing.T) { - fields := map[string]map[string]bool{ - "created": {"today": true}, - "image.name": {"ubuntu*": true, "*untu": true}, - } - a := Args{fields: fields} - - str1, err := ToParamWithVersion("1.21", a) - if err != nil { - t.Errorf("failed to marshal the filters with version < 1.22: %s", err) - } - str2, err := ToParamWithVersion("1.22", a) - if err != nil { - t.Errorf("failed to marshal the filters with version >= 1.22: %s", err) - } - if str1 != `{"created":["today"],"image.name":["*untu","ubuntu*"]}` && - str1 != `{"created":["today"],"image.name":["ubuntu*","*untu"]}` { - t.Errorf("incorrectly marshaled the filters: %s", str1) - } - if str2 != `{"created":{"today":true},"image.name":{"*untu":true,"ubuntu*":true}}` && - str2 != `{"created":{"today":true},"image.name":{"ubuntu*":true,"*untu":true}}` { - t.Errorf("incorrectly marshaled the filters: %s", str2) - } -} - -func TestFromParam(t *testing.T) { - invalids := []string{ - "anything", - "['a','list']", - "{'key': 'value'}", - `{"key": "value"}`, - } - valid := map[*Args][]string{ - &Args{fields: map[string]map[string]bool{"key": {"value": true}}}: { - `{"key": ["value"]}`, - `{"key": {"value": true}}`, - }, - &Args{fields: map[string]map[string]bool{"key": {"value1": true, "value2": true}}}: { - `{"key": ["value1", "value2"]}`, - `{"key": {"value1": true, "value2": true}}`, - }, - &Args{fields: map[string]map[string]bool{"key1": {"value1": true}, "key2": {"value2": true}}}: { - `{"key1": ["value1"], "key2": ["value2"]}`, - `{"key1": {"value1": true}, "key2": {"value2": true}}`, - }, - } - - for _, invalid := range invalids { - if _, err := FromParam(invalid); err == nil { - t.Fatalf("Expected an error with %v, got nothing", invalid) - } - } - - for expectedArgs, matchers := range valid { - for _, json := range matchers { - args, err := FromParam(json) - if err != nil { - t.Fatal(err) - } - if args.Len() != expectedArgs.Len() { - t.Fatalf("Expected %v, go %v", expectedArgs, args) - } - for key, expectedValues := range expectedArgs.fields { - values := args.Get(key) - - if len(values) != len(expectedValues) { - t.Fatalf("Expected %v, go %v", expectedArgs, args) - } - - for _, v := range values { - if !expectedValues[v] { - t.Fatalf("Expected %v, go %v", expectedArgs, args) - } - } - } - } - } -} - -func TestEmpty(t *testing.T) { - a := Args{} - v, err := ToParam(a) - if err != nil { - t.Errorf("failed to marshal the filters: %s", err) - } - v1, err := FromParam(v) - if err != nil { - t.Errorf("%s", err) - } - if a.Len() != v1.Len() { - t.Errorf("these should both be empty sets") - } -} - -func TestArgsMatchKVListEmptySources(t *testing.T) { - args := NewArgs() - if !args.MatchKVList("created", map[string]string{}) { - t.Fatalf("Expected true for (%v,created), got true", args) - } - - args = Args{map[string]map[string]bool{"created": {"today": true}}} - if args.MatchKVList("created", map[string]string{}) { - t.Fatalf("Expected false for (%v,created), got true", args) - } -} - -func TestArgsMatchKVList(t *testing.T) { - // Not empty sources - sources := map[string]string{ - "key1": "value1", - "key2": "value2", - "key3": "value3", - } - - matches := map[*Args]string{ - &Args{}: "field", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"today": true}, - "labels": map[string]bool{"key1": true}}, - }: "labels", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"today": true}, - "labels": map[string]bool{"key1=value1": true}}, - }: "labels", - } - - for args, field := range matches { - if args.MatchKVList(field, sources) != true { - t.Fatalf("Expected true for %v on %v, got false", sources, args) - } - } - - differs := map[*Args]string{ - &Args{map[string]map[string]bool{ - "created": map[string]bool{"today": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"today": true}, - "labels": map[string]bool{"key4": true}}, - }: "labels", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"today": true}, - "labels": map[string]bool{"key1=value3": true}}, - }: "labels", - } - - for args, field := range differs { - if args.MatchKVList(field, sources) != false { - t.Fatalf("Expected false for %v on %v, got true", sources, args) - } - } -} - -func TestArgsMatch(t *testing.T) { - source := "today" - - matches := map[*Args]string{ - &Args{}: "field", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"today": true}}, - }: "today", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"to*": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"to(.*)": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"tod": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"anyting": true, "to*": true}}, - }: "created", - } - - for args, field := range matches { - if args.Match(field, source) != true { - t.Fatalf("Expected true for %v on %v, got false", source, args) - } - } - - differs := map[*Args]string{ - &Args{map[string]map[string]bool{ - "created": map[string]bool{"tomorrow": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"to(day": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"tom(.*)": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"tom": true}}, - }: "created", - &Args{map[string]map[string]bool{ - "created": map[string]bool{"today1": true}, - "labels": map[string]bool{"today": true}}, - }: "created", - } - - for args, field := range differs { - if args.Match(field, source) != false { - t.Fatalf("Expected false for %v on %v, got true", source, args) - } - } -} - -func TestAdd(t *testing.T) { - f := NewArgs() - f.Add("status", "running") - v := f.fields["status"] - if len(v) != 1 || !v["running"] { - t.Fatalf("Expected to include a running status, got %v", v) - } - - f.Add("status", "paused") - if len(v) != 2 || !v["paused"] { - t.Fatalf("Expected to include a paused status, got %v", v) - } -} - -func TestDel(t *testing.T) { - f := NewArgs() - f.Add("status", "running") - f.Del("status", "running") - v := f.fields["status"] - if v["running"] { - t.Fatalf("Expected to not include a running status filter, got true") - } -} - -func TestLen(t *testing.T) { - f := NewArgs() - if f.Len() != 0 { - t.Fatalf("Expected to not include any field") - } - f.Add("status", "running") - if f.Len() != 1 { - t.Fatalf("Expected to include one field") - } -} - -func TestExactMatch(t *testing.T) { - f := NewArgs() - - if !f.ExactMatch("status", "running") { - t.Fatalf("Expected to match `running` when there are no filters, got false") - } - - f.Add("status", "running") - f.Add("status", "pause*") - - if !f.ExactMatch("status", "running") { - t.Fatalf("Expected to match `running` with one of the filters, got false") - } - - if f.ExactMatch("status", "paused") { - t.Fatalf("Expected to not match `paused` with one of the filters, got true") - } -} - -func TestInclude(t *testing.T) { - f := NewArgs() - if f.Include("status") { - t.Fatalf("Expected to not include a status key, got true") - } - f.Add("status", "running") - if !f.Include("status") { - t.Fatalf("Expected to include a status key, got false") - } -} - -func TestValidate(t *testing.T) { - f := NewArgs() - f.Add("status", "running") - - valid := map[string]bool{ - "status": true, - "dangling": true, - } - - if err := f.Validate(valid); err != nil { - t.Fatal(err) - } - - f.Add("bogus", "running") - if err := f.Validate(valid); err == nil { - t.Fatalf("Expected to return an error, got nil") - } -} - -func TestWalkValues(t *testing.T) { - f := NewArgs() - f.Add("status", "running") - f.Add("status", "paused") - - f.WalkValues("status", func(value string) error { - if value != "running" && value != "paused" { - t.Fatalf("Unexpected value %s", value) - } - return nil - }) - - err := f.WalkValues("status", func(value string) error { - return fmt.Errorf("return") - }) - if err == nil { - t.Fatalf("Expected to get an error, got nil") - } - - err = f.WalkValues("foo", func(value string) error { - return fmt.Errorf("return") - }) - if err != nil { - t.Fatalf("Expected to not iterate when the field doesn't exist, got %v", err) - } -} - -func TestFuzzyMatch(t *testing.T) { - f := NewArgs() - f.Add("container", "foo") - - cases := map[string]bool{ - "foo": true, - "foobar": true, - "barfoo": false, - "bar": false, - } - for source, match := range cases { - got := f.FuzzyMatch("container", source) - if got != match { - t.Fatalf("Expected %v, got %v: %s", match, got, source) - } - } -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/reference/image_reference.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/reference/image_reference.go deleted file mode 100644 index 742015820..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/reference/image_reference.go +++ /dev/null @@ -1,32 +0,0 @@ -package reference - -import ( - distreference "github.com/docker/distribution/reference" -) - -// Parse parses the given references and returns the repository and -// tag (if present) from it. If there is an error during parsing, it will -// return an error. -func Parse(ref string) (string, string, error) { - distributionRef, err := distreference.ParseNamed(ref) - if err != nil { - return "", "", err - } - - tag := GetTagFromNamedRef(distributionRef) - return distributionRef.Name(), tag, nil -} - -// GetTagFromNamedRef returns a tag from the specified reference. -// This function is necessary as long as the docker "server" api makes the distinction between repository -// and tags. -func GetTagFromNamedRef(ref distreference.Named) string { - var tag string - switch x := ref.(type) { - case distreference.Digested: - tag = x.Digest().String() - case distreference.NamedTagged: - tag = x.Tag() - } - return tag -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/strslice/strslice_test.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/strslice/strslice_test.go deleted file mode 100644 index 1163b3652..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/strslice/strslice_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package strslice - -import ( - "encoding/json" - "reflect" - "testing" -) - -func TestStrSliceMarshalJSON(t *testing.T) { - for _, testcase := range []struct { - input StrSlice - expected string - }{ - // MADNESS(stevvooe): No clue why nil would be "" but empty would be - // "null". Had to make a change here that may affect compatibility. - {input: nil, expected: "null"}, - {StrSlice{}, "[]"}, - {StrSlice{"/bin/sh", "-c", "echo"}, `["/bin/sh","-c","echo"]`}, - } { - data, err := json.Marshal(testcase.input) - if err != nil { - t.Fatal(err) - } - if string(data) != testcase.expected { - t.Fatalf("%#v: expected %v, got %v", testcase.input, testcase.expected, string(data)) - } - } -} - -func TestStrSliceUnmarshalJSON(t *testing.T) { - parts := map[string][]string{ - "": {"default", "values"}, - "[]": {}, - `["/bin/sh","-c","echo"]`: {"/bin/sh", "-c", "echo"}, - } - for json, expectedParts := range parts { - strs := StrSlice{"default", "values"} - if err := strs.UnmarshalJSON([]byte(json)); err != nil { - t.Fatal(err) - } - - actualParts := []string(strs) - if !reflect.DeepEqual(actualParts, expectedParts) { - t.Fatalf("%#v: expected %v, got %v", json, expectedParts, actualParts) - } - - } -} - -func TestStrSliceUnmarshalString(t *testing.T) { - var e StrSlice - echo, err := json.Marshal("echo") - if err != nil { - t.Fatal(err) - } - if err := json.Unmarshal(echo, &e); err != nil { - t.Fatal(err) - } - - if len(e) != 1 { - t.Fatalf("expected 1 element after unmarshal: %q", e) - } - - if e[0] != "echo" { - t.Fatalf("expected `echo`, got: %q", e[0]) - } -} - -func TestStrSliceUnmarshalSlice(t *testing.T) { - var e StrSlice - echo, err := json.Marshal([]string{"echo"}) - if err != nil { - t.Fatal(err) - } - if err := json.Unmarshal(echo, &e); err != nil { - t.Fatal(err) - } - - if len(e) != 1 { - t.Fatalf("expected 1 element after unmarshal: %q", e) - } - - if e[0] != "echo" { - t.Fatalf("expected `echo`, got: %q", e[0]) - } -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/time/timestamp.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/time/timestamp.go deleted file mode 100644 index d3695ba72..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/time/timestamp.go +++ /dev/null @@ -1,124 +0,0 @@ -package time - -import ( - "fmt" - "math" - "strconv" - "strings" - "time" -) - -// These are additional predefined layouts for use in Time.Format and Time.Parse -// with --since and --until parameters for `docker logs` and `docker events` -const ( - rFC3339Local = "2006-01-02T15:04:05" // RFC3339 with local timezone - rFC3339NanoLocal = "2006-01-02T15:04:05.999999999" // RFC3339Nano with local timezone - dateWithZone = "2006-01-02Z07:00" // RFC3339 with time at 00:00:00 - dateLocal = "2006-01-02" // RFC3339 with local timezone and time at 00:00:00 -) - -// GetTimestamp tries to parse given string as golang duration, -// then RFC3339 time and finally as a Unix timestamp. If -// any of these were successful, it returns a Unix timestamp -// as string otherwise returns the given value back. -// In case of duration input, the returned timestamp is computed -// as the given reference time minus the amount of the duration. -func GetTimestamp(value string, reference time.Time) (string, error) { - if d, err := time.ParseDuration(value); value != "0" && err == nil { - return strconv.FormatInt(reference.Add(-d).Unix(), 10), nil - } - - var format string - var parseInLocation bool - - // if the string has a Z or a + or three dashes use parse otherwise use parseinlocation - parseInLocation = !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3) - - if strings.Contains(value, ".") { - if parseInLocation { - format = rFC3339NanoLocal - } else { - format = time.RFC3339Nano - } - } else if strings.Contains(value, "T") { - // we want the number of colons in the T portion of the timestamp - tcolons := strings.Count(value, ":") - // if parseInLocation is off and we have a +/- zone offset (not Z) then - // there will be an extra colon in the input for the tz offset subtract that - // colon from the tcolons count - if !parseInLocation && !strings.ContainsAny(value, "zZ") && tcolons > 0 { - tcolons-- - } - if parseInLocation { - switch tcolons { - case 0: - format = "2006-01-02T15" - case 1: - format = "2006-01-02T15:04" - default: - format = rFC3339Local - } - } else { - switch tcolons { - case 0: - format = "2006-01-02T15Z07:00" - case 1: - format = "2006-01-02T15:04Z07:00" - default: - format = time.RFC3339 - } - } - } else if parseInLocation { - format = dateLocal - } else { - format = dateWithZone - } - - var t time.Time - var err error - - if parseInLocation { - t, err = time.ParseInLocation(format, value, time.FixedZone(reference.Zone())) - } else { - t, err = time.Parse(format, value) - } - - if err != nil { - // if there is a `-` then its an RFC3339 like timestamp otherwise assume unixtimestamp - if strings.Contains(value, "-") { - return "", err // was probably an RFC3339 like timestamp but the parser failed with an error - } - return value, nil // unixtimestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server) - } - - return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil -} - -// ParseTimestamps returns seconds and nanoseconds from a timestamp that has the -// format "%d.%09d", time.Unix(), int64(time.Nanosecond())) -// if the incoming nanosecond portion is longer or shorter than 9 digits it is -// converted to nanoseconds. The expectation is that the seconds and -// seconds will be used to create a time variable. For example: -// seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0) -// if err == nil since := time.Unix(seconds, nanoseconds) -// returns seconds as def(aultSeconds) if value == "" -func ParseTimestamps(value string, def int64) (int64, int64, error) { - if value == "" { - return def, 0, nil - } - sa := strings.SplitN(value, ".", 2) - s, err := strconv.ParseInt(sa[0], 10, 64) - if err != nil { - return s, 0, err - } - if len(sa) != 2 { - return s, 0, nil - } - n, err := strconv.ParseInt(sa[1], 10, 64) - if err != nil { - return s, n, err - } - // should already be in nanoseconds but just in case convert n to nanoseonds - n = int64(float64(n) * math.Pow(float64(10), float64(9-len(sa[1])))) - return s, n, nil -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/time/timestamp_test.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/time/timestamp_test.go deleted file mode 100644 index a1651309d..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/time/timestamp_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package time - -import ( - "fmt" - "testing" - "time" -) - -func TestGetTimestamp(t *testing.T) { - now := time.Now().In(time.UTC) - cases := []struct { - in, expected string - expectedErr bool - }{ - // Partial RFC3339 strings get parsed with second precision - {"2006-01-02T15:04:05.999999999+07:00", "1136189045.999999999", false}, - {"2006-01-02T15:04:05.999999999Z", "1136214245.999999999", false}, - {"2006-01-02T15:04:05.999999999", "1136214245.999999999", false}, - {"2006-01-02T15:04:05Z", "1136214245.000000000", false}, - {"2006-01-02T15:04:05", "1136214245.000000000", false}, - {"2006-01-02T15:04:0Z", "", true}, - {"2006-01-02T15:04:0", "", true}, - {"2006-01-02T15:04Z", "1136214240.000000000", false}, - {"2006-01-02T15:04+00:00", "1136214240.000000000", false}, - {"2006-01-02T15:04-00:00", "1136214240.000000000", false}, - {"2006-01-02T15:04", "1136214240.000000000", false}, - {"2006-01-02T15:0Z", "", true}, - {"2006-01-02T15:0", "", true}, - {"2006-01-02T15Z", "1136214000.000000000", false}, - {"2006-01-02T15+00:00", "1136214000.000000000", false}, - {"2006-01-02T15-00:00", "1136214000.000000000", false}, - {"2006-01-02T15", "1136214000.000000000", false}, - {"2006-01-02T1Z", "1136163600.000000000", false}, - {"2006-01-02T1", "1136163600.000000000", false}, - {"2006-01-02TZ", "", true}, - {"2006-01-02T", "", true}, - {"2006-01-02+00:00", "1136160000.000000000", false}, - {"2006-01-02-00:00", "1136160000.000000000", false}, - {"2006-01-02-00:01", "1136160060.000000000", false}, - {"2006-01-02Z", "1136160000.000000000", false}, - {"2006-01-02", "1136160000.000000000", false}, - {"2015-05-13T20:39:09Z", "1431549549.000000000", false}, - - // unix timestamps returned as is - {"1136073600", "1136073600", false}, - {"1136073600.000000001", "1136073600.000000001", false}, - // Durations - {"1m", fmt.Sprintf("%d", now.Add(-1*time.Minute).Unix()), false}, - {"1.5h", fmt.Sprintf("%d", now.Add(-90*time.Minute).Unix()), false}, - {"1h30m", fmt.Sprintf("%d", now.Add(-90*time.Minute).Unix()), false}, - - // String fallback - {"invalid", "invalid", false}, - } - - for _, c := range cases { - o, err := GetTimestamp(c.in, now) - if o != c.expected || - (err == nil && c.expectedErr) || - (err != nil && !c.expectedErr) { - t.Errorf("wrong value for '%s'. expected:'%s' got:'%s' with error: `%s`", c.in, c.expected, o, err) - t.Fail() - } - } -} - -func TestParseTimestamps(t *testing.T) { - cases := []struct { - in string - def, expectedS, expectedN int64 - expectedErr bool - }{ - // unix timestamps - {"1136073600", 0, 1136073600, 0, false}, - {"1136073600.000000001", 0, 1136073600, 1, false}, - {"1136073600.0000000010", 0, 1136073600, 1, false}, - {"1136073600.00000001", 0, 1136073600, 10, false}, - {"foo.bar", 0, 0, 0, true}, - {"1136073600.bar", 0, 1136073600, 0, true}, - {"", -1, -1, 0, false}, - } - - for _, c := range cases { - s, n, err := ParseTimestamps(c.in, c.def) - if s != c.expectedS || - n != c.expectedN || - (err == nil && c.expectedErr) || - (err != nil && !c.expectedErr) { - t.Errorf("wrong values for input `%s` with default `%d` expected:'%d'seconds and `%d`nanosecond got:'%d'seconds and `%d`nanoseconds with error: `%s`", c.in, c.def, c.expectedS, c.expectedN, s, n, err) - t.Fail() - } - } -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/compare_test.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/compare_test.go deleted file mode 100644 index c2b96869f..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/compare_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package versions - -import ( - "testing" -) - -func assertVersion(t *testing.T, a, b string, result int) { - if r := compare(a, b); r != result { - t.Fatalf("Unexpected version comparison result. Found %d, expected %d", r, result) - } -} - -func TestCompareVersion(t *testing.T) { - assertVersion(t, "1.12", "1.12", 0) - assertVersion(t, "1.0.0", "1", 0) - assertVersion(t, "1", "1.0.0", 0) - assertVersion(t, "1.05.00.0156", "1.0.221.9289", 1) - assertVersion(t, "1", "1.0.1", -1) - assertVersion(t, "1.0.1", "1", 1) - assertVersion(t, "1.0.1", "1.0.2", -1) - assertVersion(t, "1.0.2", "1.0.3", -1) - assertVersion(t, "1.0.3", "1.1", -1) - assertVersion(t, "1.1", "1.1.1", -1) - assertVersion(t, "1.1.1", "1.1.2", -1) - assertVersion(t, "1.1.2", "1.2", -1) -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/v1p19/types.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/v1p19/types.go deleted file mode 100644 index 4ed433588..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/v1p19/types.go +++ /dev/null @@ -1,35 +0,0 @@ -// Package v1p19 provides specific API types for the API version 1, patch 19. -package v1p19 - -import ( - "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/container" - "github.com/docker/engine-api/types/versions/v1p20" - "github.com/docker/go-connections/nat" -) - -// ContainerJSON is a backcompatibility struct for APIs prior to 1.20. -// Note this is not used by the Windows daemon. -type ContainerJSON struct { - *types.ContainerJSONBase - Volumes map[string]string - VolumesRW map[string]bool - Config *ContainerConfig - NetworkSettings *v1p20.NetworkSettings -} - -// ContainerConfig is a backcompatibility struct for APIs prior to 1.20. -type ContainerConfig struct { - *container.Config - - MacAddress string - NetworkDisabled bool - ExposedPorts map[nat.Port]struct{} - - // backward compatibility, they now live in HostConfig - VolumeDriver string - Memory int64 - MemorySwap int64 - CPUShares int64 `json:"CpuShares"` - CPUSet string `json:"Cpuset"` -} diff --git a/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/v1p20/types.go b/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/v1p20/types.go deleted file mode 100644 index 5736efad0..000000000 --- a/Godeps/_workspace/src/github.com/docker/engine-api/types/versions/v1p20/types.go +++ /dev/null @@ -1,40 +0,0 @@ -// Package v1p20 provides specific API types for the API version 1, patch 20. -package v1p20 - -import ( - "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/container" - "github.com/docker/go-connections/nat" -) - -// ContainerJSON is a backcompatibility struct for the API 1.20 -type ContainerJSON struct { - *types.ContainerJSONBase - Mounts []types.MountPoint - Config *ContainerConfig - NetworkSettings *NetworkSettings -} - -// ContainerConfig is a backcompatibility struct used in ContainerJSON for the API 1.20 -type ContainerConfig struct { - *container.Config - - MacAddress string - NetworkDisabled bool - ExposedPorts map[nat.Port]struct{} - - // backward compatibility, they now live in HostConfig - VolumeDriver string -} - -// StatsJSON is a backcompatibility struct used in Stats for APIs prior to 1.21 -type StatsJSON struct { - types.Stats - Network types.NetworkStats `json:"network,omitempty"` -} - -// NetworkSettings is a backward compatible struct for APIs prior to 1.21 -type NetworkSettings struct { - types.NetworkSettingsBase - types.DefaultNetworkSettings -} diff --git a/Godeps/_workspace/src/github.com/docker/go-connections/nat/nat_test.go b/Godeps/_workspace/src/github.com/docker/go-connections/nat/nat_test.go deleted file mode 100644 index 651dcd307..000000000 --- a/Godeps/_workspace/src/github.com/docker/go-connections/nat/nat_test.go +++ /dev/null @@ -1,525 +0,0 @@ -package nat - -import ( - "testing" -) - -func TestParsePort(t *testing.T) { - var ( - p int - err error - ) - - p, err = ParsePort("1234") - - if err != nil || p != 1234 { - t.Fatal("Parsing '1234' did not succeed") - } - - // FIXME currently this is a valid port. I don't think it should be. - // I'm leaving this test commented out until we make a decision. - // - erikh - - /* - p, err = ParsePort("0123") - - if err != nil { - t.Fatal("Successfully parsed port '0123' to '123'") - } - */ - - p, err = ParsePort("asdf") - - if err == nil || p != 0 { - t.Fatal("Parsing port 'asdf' succeeded") - } - - p, err = ParsePort("1asdf") - - if err == nil || p != 0 { - t.Fatal("Parsing port '1asdf' succeeded") - } -} - -func TestParsePortRangeToInt(t *testing.T) { - var ( - begin int - end int - err error - ) - - type TestRange struct { - Range string - Begin int - End int - } - validRanges := []TestRange{ - {"1234", 1234, 1234}, - {"1234-1234", 1234, 1234}, - {"1234-1235", 1234, 1235}, - {"8000-9000", 8000, 9000}, - {"0", 0, 0}, - {"0-0", 0, 0}, - } - - for _, r := range validRanges { - begin, end, err = ParsePortRangeToInt(r.Range) - - if err != nil || begin != r.Begin { - t.Fatalf("Parsing port range '%s' did not succeed. Expected begin %d, got %d", r.Range, r.Begin, begin) - } - if err != nil || end != r.End { - t.Fatalf("Parsing port range '%s' did not succeed. Expected end %d, got %d", r.Range, r.End, end) - } - } - - invalidRanges := []string{ - "asdf", - "1asdf", - "9000-8000", - "9000-", - "-8000", - "-8000-", - } - - for _, r := range invalidRanges { - begin, end, err = ParsePortRangeToInt(r) - - if err == nil || begin != 0 || end != 0 { - t.Fatalf("Parsing port range '%s' succeeded", r) - } - } -} - -func TestPort(t *testing.T) { - p, err := NewPort("tcp", "1234") - - if err != nil { - t.Fatalf("tcp, 1234 had a parsing issue: %v", err) - } - - if string(p) != "1234/tcp" { - t.Fatal("tcp, 1234 did not result in the string 1234/tcp") - } - - if p.Proto() != "tcp" { - t.Fatal("protocol was not tcp") - } - - if p.Port() != "1234" { - t.Fatal("port string value was not 1234") - } - - if p.Int() != 1234 { - t.Fatal("port int value was not 1234") - } - - p, err = NewPort("tcp", "asd1234") - if err == nil { - t.Fatal("tcp, asd1234 was supposed to fail") - } - - p, err = NewPort("tcp", "1234-1230") - if err == nil { - t.Fatal("tcp, 1234-1230 was supposed to fail") - } - - p, err = NewPort("tcp", "1234-1242") - if err != nil { - t.Fatalf("tcp, 1234-1242 had a parsing issue: %v", err) - } - - if string(p) != "1234-1242/tcp" { - t.Fatal("tcp, 1234-1242 did not result in the string 1234-1242/tcp") - } -} - -func TestSplitProtoPort(t *testing.T) { - var ( - proto string - port string - ) - - proto, port = SplitProtoPort("1234/tcp") - - if proto != "tcp" || port != "1234" { - t.Fatal("Could not split 1234/tcp properly") - } - - proto, port = SplitProtoPort("") - - if proto != "" || port != "" { - t.Fatal("parsing an empty string yielded surprising results", proto, port) - } - - proto, port = SplitProtoPort("1234") - - if proto != "tcp" || port != "1234" { - t.Fatal("tcp is not the default protocol for portspec '1234'", proto, port) - } - - proto, port = SplitProtoPort("1234/") - - if proto != "tcp" || port != "1234" { - t.Fatal("parsing '1234/' yielded:" + port + "/" + proto) - } - - proto, port = SplitProtoPort("/tcp") - - if proto != "" || port != "" { - t.Fatal("parsing '/tcp' yielded:" + port + "/" + proto) - } -} - -func TestParsePortSpecs(t *testing.T) { - var ( - portMap map[Port]struct{} - bindingMap map[Port][]PortBinding - err error - ) - - portMap, bindingMap, err = ParsePortSpecs([]string{"1234/tcp", "2345/udp"}) - - if err != nil { - t.Fatalf("Error while processing ParsePortSpecs: %s", err) - } - - if _, ok := portMap[Port("1234/tcp")]; !ok { - t.Fatal("1234/tcp was not parsed properly") - } - - if _, ok := portMap[Port("2345/udp")]; !ok { - t.Fatal("2345/udp was not parsed properly") - } - - for portspec, bindings := range bindingMap { - if len(bindings) != 1 { - t.Fatalf("%s should have exactly one binding", portspec) - } - - if bindings[0].HostIP != "" { - t.Fatalf("HostIP should not be set for %s", portspec) - } - - if bindings[0].HostPort != "" { - t.Fatalf("HostPort should not be set for %s", portspec) - } - } - - portMap, bindingMap, err = ParsePortSpecs([]string{"1234:1234/tcp", "2345:2345/udp"}) - - if err != nil { - t.Fatalf("Error while processing ParsePortSpecs: %s", err) - } - - if _, ok := portMap[Port("1234/tcp")]; !ok { - t.Fatal("1234/tcp was not parsed properly") - } - - if _, ok := portMap[Port("2345/udp")]; !ok { - t.Fatal("2345/udp was not parsed properly") - } - - for portspec, bindings := range bindingMap { - _, port := SplitProtoPort(string(portspec)) - - if len(bindings) != 1 { - t.Fatalf("%s should have exactly one binding", portspec) - } - - if bindings[0].HostIP != "" { - t.Fatalf("HostIP should not be set for %s", portspec) - } - - if bindings[0].HostPort != port { - t.Fatalf("HostPort should be %s for %s", port, portspec) - } - } - - portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234:1234/tcp", "0.0.0.0:2345:2345/udp"}) - - if err != nil { - t.Fatalf("Error while processing ParsePortSpecs: %s", err) - } - - if _, ok := portMap[Port("1234/tcp")]; !ok { - t.Fatal("1234/tcp was not parsed properly") - } - - if _, ok := portMap[Port("2345/udp")]; !ok { - t.Fatal("2345/udp was not parsed properly") - } - - for portspec, bindings := range bindingMap { - _, port := SplitProtoPort(string(portspec)) - - if len(bindings) != 1 { - t.Fatalf("%s should have exactly one binding", portspec) - } - - if bindings[0].HostIP != "0.0.0.0" { - t.Fatalf("HostIP is not 0.0.0.0 for %s", portspec) - } - - if bindings[0].HostPort != port { - t.Fatalf("HostPort should be %s for %s", port, portspec) - } - } - - _, _, err = ParsePortSpecs([]string{"localhost:1234:1234/tcp"}) - - if err == nil { - t.Fatal("Received no error while trying to parse a hostname instead of ip") - } -} - -func TestParsePortSpecsWithRange(t *testing.T) { - var ( - portMap map[Port]struct{} - bindingMap map[Port][]PortBinding - err error - ) - - portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236/tcp", "2345-2347/udp"}) - - if err != nil { - t.Fatalf("Error while processing ParsePortSpecs: %s", err) - } - - if _, ok := portMap[Port("1235/tcp")]; !ok { - t.Fatal("1234/tcp was not parsed properly") - } - - if _, ok := portMap[Port("2346/udp")]; !ok { - t.Fatal("2345/udp was not parsed properly") - } - - for portspec, bindings := range bindingMap { - if len(bindings) != 1 { - t.Fatalf("%s should have exactly one binding", portspec) - } - - if bindings[0].HostIP != "" { - t.Fatalf("HostIP should not be set for %s", portspec) - } - - if bindings[0].HostPort != "" { - t.Fatalf("HostPort should not be set for %s", portspec) - } - } - - portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236:1234-1236/tcp", "2345-2347:2345-2347/udp"}) - - if err != nil { - t.Fatalf("Error while processing ParsePortSpecs: %s", err) - } - - if _, ok := portMap[Port("1235/tcp")]; !ok { - t.Fatal("1234/tcp was not parsed properly") - } - - if _, ok := portMap[Port("2346/udp")]; !ok { - t.Fatal("2345/udp was not parsed properly") - } - - for portspec, bindings := range bindingMap { - _, port := SplitProtoPort(string(portspec)) - if len(bindings) != 1 { - t.Fatalf("%s should have exactly one binding", portspec) - } - - if bindings[0].HostIP != "" { - t.Fatalf("HostIP should not be set for %s", portspec) - } - - if bindings[0].HostPort != port { - t.Fatalf("HostPort should be %s for %s", port, portspec) - } - } - - portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234-1236:1234-1236/tcp", "0.0.0.0:2345-2347:2345-2347/udp"}) - - if err != nil { - t.Fatalf("Error while processing ParsePortSpecs: %s", err) - } - - if _, ok := portMap[Port("1235/tcp")]; !ok { - t.Fatal("1234/tcp was not parsed properly") - } - - if _, ok := portMap[Port("2346/udp")]; !ok { - t.Fatal("2345/udp was not parsed properly") - } - - for portspec, bindings := range bindingMap { - _, port := SplitProtoPort(string(portspec)) - if len(bindings) != 1 || bindings[0].HostIP != "0.0.0.0" || bindings[0].HostPort != port { - t.Fatalf("Expect single binding to port %s but found %s", port, bindings) - } - } - - _, _, err = ParsePortSpecs([]string{"localhost:1234-1236:1234-1236/tcp"}) - - if err == nil { - t.Fatal("Received no error while trying to parse a hostname instead of ip") - } -} - -func TestParseNetworkOptsPrivateOnly(t *testing.T) { - ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::80"}) - if err != nil { - t.Fatal(err) - } - if len(ports) != 1 { - t.Logf("Expected 1 got %d", len(ports)) - t.FailNow() - } - if len(bindings) != 1 { - t.Logf("Expected 1 got %d", len(bindings)) - t.FailNow() - } - for k := range ports { - if k.Proto() != "tcp" { - t.Logf("Expected tcp got %s", k.Proto()) - t.Fail() - } - if k.Port() != "80" { - t.Logf("Expected 80 got %s", k.Port()) - t.Fail() - } - b, exists := bindings[k] - if !exists { - t.Log("Binding does not exist") - t.FailNow() - } - if len(b) != 1 { - t.Logf("Expected 1 got %d", len(b)) - t.FailNow() - } - s := b[0] - if s.HostPort != "" { - t.Logf("Expected \"\" got %s", s.HostPort) - t.Fail() - } - if s.HostIP != "192.168.1.100" { - t.Fail() - } - } -} - -func TestParseNetworkOptsPublic(t *testing.T) { - ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:8080:80"}) - if err != nil { - t.Fatal(err) - } - if len(ports) != 1 { - t.Logf("Expected 1 got %d", len(ports)) - t.FailNow() - } - if len(bindings) != 1 { - t.Logf("Expected 1 got %d", len(bindings)) - t.FailNow() - } - for k := range ports { - if k.Proto() != "tcp" { - t.Logf("Expected tcp got %s", k.Proto()) - t.Fail() - } - if k.Port() != "80" { - t.Logf("Expected 80 got %s", k.Port()) - t.Fail() - } - b, exists := bindings[k] - if !exists { - t.Log("Binding does not exist") - t.FailNow() - } - if len(b) != 1 { - t.Logf("Expected 1 got %d", len(b)) - t.FailNow() - } - s := b[0] - if s.HostPort != "8080" { - t.Logf("Expected 8080 got %s", s.HostPort) - t.Fail() - } - if s.HostIP != "192.168.1.100" { - t.Fail() - } - } -} - -func TestParseNetworkOptsPublicNoPort(t *testing.T) { - ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100"}) - - if err == nil { - t.Logf("Expected error Invalid containerPort") - t.Fail() - } - if ports != nil { - t.Logf("Expected nil got %s", ports) - t.Fail() - } - if bindings != nil { - t.Logf("Expected nil got %s", bindings) - t.Fail() - } -} - -func TestParseNetworkOptsNegativePorts(t *testing.T) { - ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:-1:-1"}) - - if err == nil { - t.Fail() - } - if len(ports) != 0 { - t.Logf("Expected nil got %d", len(ports)) - t.Fail() - } - if len(bindings) != 0 { - t.Logf("Expected 0 got %d", len(bindings)) - t.Fail() - } -} - -func TestParseNetworkOptsUdp(t *testing.T) { - ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::6000/udp"}) - if err != nil { - t.Fatal(err) - } - if len(ports) != 1 { - t.Logf("Expected 1 got %d", len(ports)) - t.FailNow() - } - if len(bindings) != 1 { - t.Logf("Expected 1 got %d", len(bindings)) - t.FailNow() - } - for k := range ports { - if k.Proto() != "udp" { - t.Logf("Expected udp got %s", k.Proto()) - t.Fail() - } - if k.Port() != "6000" { - t.Logf("Expected 6000 got %s", k.Port()) - t.Fail() - } - b, exists := bindings[k] - if !exists { - t.Log("Binding does not exist") - t.FailNow() - } - if len(b) != 1 { - t.Logf("Expected 1 got %d", len(b)) - t.FailNow() - } - s := b[0] - if s.HostPort != "" { - t.Logf("Expected \"\" got %s", s.HostPort) - t.Fail() - } - if s.HostIP != "192.168.1.100" { - t.Fail() - } - } -} diff --git a/Godeps/_workspace/src/github.com/docker/go-connections/nat/parse_test.go b/Godeps/_workspace/src/github.com/docker/go-connections/nat/parse_test.go deleted file mode 100644 index 2ac204a05..000000000 --- a/Godeps/_workspace/src/github.com/docker/go-connections/nat/parse_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package nat - -import ( - "strings" - "testing" -) - -func TestParsePortRange(t *testing.T) { - if start, end, err := ParsePortRange("8000-8080"); err != nil || start != 8000 || end != 8080 { - t.Fatalf("Error: %s or Expecting {start,end} values {8000,8080} but found {%d,%d}.", err, start, end) - } -} - -func TestParsePortRangeEmpty(t *testing.T) { - if _, _, err := ParsePortRange(""); err == nil || err.Error() != "Empty string specified for ports." { - t.Fatalf("Expected error 'Empty string specified for ports.', got %v", err) - } -} - -func TestParsePortRangeWithNoRange(t *testing.T) { - start, end, err := ParsePortRange("8080") - if err != nil { - t.Fatal(err) - } - if start != 8080 || end != 8080 { - t.Fatalf("Expected start and end to be the same and equal to 8080, but were %v and %v", start, end) - } -} - -func TestParsePortRangeIncorrectRange(t *testing.T) { - if _, _, err := ParsePortRange("9000-8080"); err == nil || !strings.Contains(err.Error(), "Invalid range specified for the Port") { - t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err) - } -} - -func TestParsePortRangeIncorrectEndRange(t *testing.T) { - if _, _, err := ParsePortRange("8000-a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") { - t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err) - } - - if _, _, err := ParsePortRange("8000-30a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") { - t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err) - } -} - -func TestParsePortRangeIncorrectStartRange(t *testing.T) { - if _, _, err := ParsePortRange("a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") { - t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err) - } - - if _, _, err := ParsePortRange("30a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") { - t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err) - } -} diff --git a/Godeps/_workspace/src/github.com/docker/go-connections/nat/sort_test.go b/Godeps/_workspace/src/github.com/docker/go-connections/nat/sort_test.go deleted file mode 100644 index 88ed91115..000000000 --- a/Godeps/_workspace/src/github.com/docker/go-connections/nat/sort_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package nat - -import ( - "fmt" - "reflect" - "testing" -) - -func TestSortUniquePorts(t *testing.T) { - ports := []Port{ - Port("6379/tcp"), - Port("22/tcp"), - } - - Sort(ports, func(ip, jp Port) bool { - return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") - }) - - first := ports[0] - if fmt.Sprint(first) != "22/tcp" { - t.Log(fmt.Sprint(first)) - t.Fail() - } -} - -func TestSortSamePortWithDifferentProto(t *testing.T) { - ports := []Port{ - Port("8888/tcp"), - Port("8888/udp"), - Port("6379/tcp"), - Port("6379/udp"), - } - - Sort(ports, func(ip, jp Port) bool { - return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") - }) - - first := ports[0] - if fmt.Sprint(first) != "6379/tcp" { - t.Fail() - } -} - -func TestSortPortMap(t *testing.T) { - ports := []Port{ - Port("22/tcp"), - Port("22/udp"), - Port("8000/tcp"), - Port("6379/tcp"), - Port("9999/tcp"), - } - - portMap := PortMap{ - Port("22/tcp"): []PortBinding{ - {}, - }, - Port("8000/tcp"): []PortBinding{ - {}, - }, - Port("6379/tcp"): []PortBinding{ - {}, - {HostIP: "0.0.0.0", HostPort: "32749"}, - }, - Port("9999/tcp"): []PortBinding{ - {HostIP: "0.0.0.0", HostPort: "40000"}, - }, - } - - SortPortMap(ports, portMap) - if !reflect.DeepEqual(ports, []Port{ - Port("9999/tcp"), - Port("6379/tcp"), - Port("8000/tcp"), - Port("22/tcp"), - Port("22/udp"), - }) { - t.Errorf("failed to prioritize port with explicit mappings, got %v", ports) - } - if pm := portMap[Port("6379/tcp")]; !reflect.DeepEqual(pm, []PortBinding{ - {HostIP: "0.0.0.0", HostPort: "32749"}, - {}, - }) { - t.Errorf("failed to prioritize bindings with explicit mappings, got %v", pm) - } -} diff --git a/Godeps/_workspace/src/github.com/docker/go-units/duration_test.go b/Godeps/_workspace/src/github.com/docker/go-units/duration_test.go deleted file mode 100644 index 63baa515b..000000000 --- a/Godeps/_workspace/src/github.com/docker/go-units/duration_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package units - -import ( - "fmt" - "testing" - "time" -) - -func ExampleHumanDuration() { - fmt.Println(HumanDuration(450 * time.Millisecond)) - fmt.Println(HumanDuration(47 * time.Second)) - fmt.Println(HumanDuration(1 * time.Minute)) - fmt.Println(HumanDuration(3 * time.Minute)) - fmt.Println(HumanDuration(35 * time.Minute)) - fmt.Println(HumanDuration(35*time.Minute + 40*time.Second)) - fmt.Println(HumanDuration(1 * time.Hour)) - fmt.Println(HumanDuration(1*time.Hour + 45*time.Minute)) - fmt.Println(HumanDuration(3 * time.Hour)) - fmt.Println(HumanDuration(3*time.Hour + 59*time.Minute)) - fmt.Println(HumanDuration(3*time.Hour + 60*time.Minute)) - fmt.Println(HumanDuration(24 * time.Hour)) - fmt.Println(HumanDuration(24*time.Hour + 12*time.Hour)) - fmt.Println(HumanDuration(2 * 24 * time.Hour)) - fmt.Println(HumanDuration(7 * 24 * time.Hour)) - fmt.Println(HumanDuration(13*24*time.Hour + 5*time.Hour)) - fmt.Println(HumanDuration(2 * 7 * 24 * time.Hour)) - fmt.Println(HumanDuration(2*7*24*time.Hour + 4*24*time.Hour)) - fmt.Println(HumanDuration(3 * 7 * 24 * time.Hour)) - fmt.Println(HumanDuration(4 * 7 * 24 * time.Hour)) - fmt.Println(HumanDuration(4*7*24*time.Hour + 3*24*time.Hour)) - fmt.Println(HumanDuration(1 * 30 * 24 * time.Hour)) - fmt.Println(HumanDuration(1*30*24*time.Hour + 2*7*24*time.Hour)) - fmt.Println(HumanDuration(2 * 30 * 24 * time.Hour)) - fmt.Println(HumanDuration(3*30*24*time.Hour + 1*7*24*time.Hour)) - fmt.Println(HumanDuration(5*30*24*time.Hour + 2*7*24*time.Hour)) - fmt.Println(HumanDuration(13 * 30 * 24 * time.Hour)) - fmt.Println(HumanDuration(23 * 30 * 24 * time.Hour)) - fmt.Println(HumanDuration(24 * 30 * 24 * time.Hour)) - fmt.Println(HumanDuration(24*30*24*time.Hour + 2*7*24*time.Hour)) - fmt.Println(HumanDuration(3*365*24*time.Hour + 2*30*24*time.Hour)) -} - -func TestHumanDuration(t *testing.T) { - // Useful duration abstractions - day := 24 * time.Hour - week := 7 * day - month := 30 * day - year := 365 * day - - assertEquals(t, "Less than a second", HumanDuration(450*time.Millisecond)) - assertEquals(t, "47 seconds", HumanDuration(47*time.Second)) - assertEquals(t, "About a minute", HumanDuration(1*time.Minute)) - assertEquals(t, "3 minutes", HumanDuration(3*time.Minute)) - assertEquals(t, "35 minutes", HumanDuration(35*time.Minute)) - assertEquals(t, "35 minutes", HumanDuration(35*time.Minute+40*time.Second)) - assertEquals(t, "About an hour", HumanDuration(1*time.Hour)) - assertEquals(t, "About an hour", HumanDuration(1*time.Hour+45*time.Minute)) - assertEquals(t, "3 hours", HumanDuration(3*time.Hour)) - assertEquals(t, "3 hours", HumanDuration(3*time.Hour+59*time.Minute)) - assertEquals(t, "4 hours", HumanDuration(3*time.Hour+60*time.Minute)) - assertEquals(t, "24 hours", HumanDuration(24*time.Hour)) - assertEquals(t, "36 hours", HumanDuration(1*day+12*time.Hour)) - assertEquals(t, "2 days", HumanDuration(2*day)) - assertEquals(t, "7 days", HumanDuration(7*day)) - assertEquals(t, "13 days", HumanDuration(13*day+5*time.Hour)) - assertEquals(t, "2 weeks", HumanDuration(2*week)) - assertEquals(t, "2 weeks", HumanDuration(2*week+4*day)) - assertEquals(t, "3 weeks", HumanDuration(3*week)) - assertEquals(t, "4 weeks", HumanDuration(4*week)) - assertEquals(t, "4 weeks", HumanDuration(4*week+3*day)) - assertEquals(t, "4 weeks", HumanDuration(1*month)) - assertEquals(t, "6 weeks", HumanDuration(1*month+2*week)) - assertEquals(t, "8 weeks", HumanDuration(2*month)) - assertEquals(t, "3 months", HumanDuration(3*month+1*week)) - assertEquals(t, "5 months", HumanDuration(5*month+2*week)) - assertEquals(t, "13 months", HumanDuration(13*month)) - assertEquals(t, "23 months", HumanDuration(23*month)) - assertEquals(t, "24 months", HumanDuration(24*month)) - assertEquals(t, "2 years", HumanDuration(24*month+2*week)) - assertEquals(t, "3 years", HumanDuration(3*year+2*month)) -} diff --git a/Godeps/_workspace/src/github.com/docker/go-units/size_test.go b/Godeps/_workspace/src/github.com/docker/go-units/size_test.go deleted file mode 100644 index a968f5c0d..000000000 --- a/Godeps/_workspace/src/github.com/docker/go-units/size_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package units - -import ( - "fmt" - "reflect" - "runtime" - "strings" - "testing" -) - -func ExampleBytesSize() { - fmt.Println(BytesSize(1024)) - fmt.Println(BytesSize(1024 * 1024)) - fmt.Println(BytesSize(1048576)) - fmt.Println(BytesSize(2 * MiB)) - fmt.Println(BytesSize(3.42 * GiB)) - fmt.Println(BytesSize(5.372 * TiB)) - fmt.Println(BytesSize(2.22 * PiB)) -} - -func ExampleHumanSize() { - fmt.Println(HumanSize(1000)) - fmt.Println(HumanSize(1024)) - fmt.Println(HumanSize(1000000)) - fmt.Println(HumanSize(1048576)) - fmt.Println(HumanSize(2 * MB)) - fmt.Println(HumanSize(float64(3.42 * GB))) - fmt.Println(HumanSize(float64(5.372 * TB))) - fmt.Println(HumanSize(float64(2.22 * PB))) -} - -func ExampleFromHumanSize() { - fmt.Println(FromHumanSize("32")) - fmt.Println(FromHumanSize("32b")) - fmt.Println(FromHumanSize("32B")) - fmt.Println(FromHumanSize("32k")) - fmt.Println(FromHumanSize("32K")) - fmt.Println(FromHumanSize("32kb")) - fmt.Println(FromHumanSize("32Kb")) - fmt.Println(FromHumanSize("32Mb")) - fmt.Println(FromHumanSize("32Gb")) - fmt.Println(FromHumanSize("32Tb")) - fmt.Println(FromHumanSize("32Pb")) -} - -func ExampleRAMInBytes() { - fmt.Println(RAMInBytes("32")) - fmt.Println(RAMInBytes("32b")) - fmt.Println(RAMInBytes("32B")) - fmt.Println(RAMInBytes("32k")) - fmt.Println(RAMInBytes("32K")) - fmt.Println(RAMInBytes("32kb")) - fmt.Println(RAMInBytes("32Kb")) - fmt.Println(RAMInBytes("32Mb")) - fmt.Println(RAMInBytes("32Gb")) - fmt.Println(RAMInBytes("32Tb")) - fmt.Println(RAMInBytes("32Pb")) - fmt.Println(RAMInBytes("32PB")) - fmt.Println(RAMInBytes("32P")) -} - -func TestBytesSize(t *testing.T) { - assertEquals(t, "1 KiB", BytesSize(1024)) - assertEquals(t, "1 MiB", BytesSize(1024*1024)) - assertEquals(t, "1 MiB", BytesSize(1048576)) - assertEquals(t, "2 MiB", BytesSize(2*MiB)) - assertEquals(t, "3.42 GiB", BytesSize(3.42*GiB)) - assertEquals(t, "5.372 TiB", BytesSize(5.372*TiB)) - assertEquals(t, "2.22 PiB", BytesSize(2.22*PiB)) -} - -func TestHumanSize(t *testing.T) { - assertEquals(t, "1 kB", HumanSize(1000)) - assertEquals(t, "1.024 kB", HumanSize(1024)) - assertEquals(t, "1 MB", HumanSize(1000000)) - assertEquals(t, "1.049 MB", HumanSize(1048576)) - assertEquals(t, "2 MB", HumanSize(2*MB)) - assertEquals(t, "3.42 GB", HumanSize(float64(3.42*GB))) - assertEquals(t, "5.372 TB", HumanSize(float64(5.372*TB))) - assertEquals(t, "2.22 PB", HumanSize(float64(2.22*PB))) -} - -func TestFromHumanSize(t *testing.T) { - assertSuccessEquals(t, 32, FromHumanSize, "32") - assertSuccessEquals(t, 32, FromHumanSize, "32b") - assertSuccessEquals(t, 32, FromHumanSize, "32B") - assertSuccessEquals(t, 32*KB, FromHumanSize, "32k") - assertSuccessEquals(t, 32*KB, FromHumanSize, "32K") - assertSuccessEquals(t, 32*KB, FromHumanSize, "32kb") - assertSuccessEquals(t, 32*KB, FromHumanSize, "32Kb") - assertSuccessEquals(t, 32*MB, FromHumanSize, "32Mb") - assertSuccessEquals(t, 32*GB, FromHumanSize, "32Gb") - assertSuccessEquals(t, 32*TB, FromHumanSize, "32Tb") - assertSuccessEquals(t, 32*PB, FromHumanSize, "32Pb") - - assertError(t, FromHumanSize, "") - assertError(t, FromHumanSize, "hello") - assertError(t, FromHumanSize, "-32") - assertError(t, FromHumanSize, "32.3") - assertError(t, FromHumanSize, " 32 ") - assertError(t, FromHumanSize, "32.3Kb") - assertError(t, FromHumanSize, "32 mb") - assertError(t, FromHumanSize, "32m b") - assertError(t, FromHumanSize, "32bm") -} - -func TestRAMInBytes(t *testing.T) { - assertSuccessEquals(t, 32, RAMInBytes, "32") - assertSuccessEquals(t, 32, RAMInBytes, "32b") - assertSuccessEquals(t, 32, RAMInBytes, "32B") - assertSuccessEquals(t, 32*KiB, RAMInBytes, "32k") - assertSuccessEquals(t, 32*KiB, RAMInBytes, "32K") - assertSuccessEquals(t, 32*KiB, RAMInBytes, "32kb") - assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kb") - assertSuccessEquals(t, 32*MiB, RAMInBytes, "32Mb") - assertSuccessEquals(t, 32*GiB, RAMInBytes, "32Gb") - assertSuccessEquals(t, 32*TiB, RAMInBytes, "32Tb") - assertSuccessEquals(t, 32*PiB, RAMInBytes, "32Pb") - assertSuccessEquals(t, 32*PiB, RAMInBytes, "32PB") - assertSuccessEquals(t, 32*PiB, RAMInBytes, "32P") - - assertError(t, RAMInBytes, "") - assertError(t, RAMInBytes, "hello") - assertError(t, RAMInBytes, "-32") - assertError(t, RAMInBytes, "32.3") - assertError(t, RAMInBytes, " 32 ") - assertError(t, RAMInBytes, "32.3Kb") - assertError(t, RAMInBytes, "32 mb") - assertError(t, RAMInBytes, "32m b") - assertError(t, RAMInBytes, "32bm") -} - -func assertEquals(t *testing.T, expected, actual interface{}) { - if expected != actual { - t.Errorf("Expected '%v' but got '%v'", expected, actual) - } -} - -// func that maps to the parse function signatures as testing abstraction -type parseFn func(string) (int64, error) - -// Define 'String()' for pretty-print -func (fn parseFn) String() string { - fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() - return fnName[strings.LastIndex(fnName, ".")+1:] -} - -func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) { - res, err := fn(arg) - if err != nil || res != expected { - t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err) - } -} - -func assertError(t *testing.T, fn parseFn, arg string) { - res, err := fn(arg) - if err == nil && res != -1 { - t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res) - } -} diff --git a/Godeps/_workspace/src/github.com/docker/go-units/ulimit_test.go b/Godeps/_workspace/src/github.com/docker/go-units/ulimit_test.go deleted file mode 100644 index 3e7f10fc2..000000000 --- a/Godeps/_workspace/src/github.com/docker/go-units/ulimit_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package units - -import ( - "fmt" - "strconv" - "testing" -) - -func ExampleParseUlimit() { - fmt.Println(ParseUlimit("nofile=512:1024")) - fmt.Println(ParseUlimit("nofile=1024")) - fmt.Println(ParseUlimit("cpu=2:4")) - fmt.Println(ParseUlimit("cpu=6")) -} - -func TestParseUlimitValid(t *testing.T) { - u1 := &Ulimit{"nofile", 1024, 512} - if u2, _ := ParseUlimit("nofile=512:1024"); *u1 != *u2 { - t.Fatalf("expected %q, but got %q", u1, u2) - } -} - -func TestParseUlimitInvalidLimitType(t *testing.T) { - if _, err := ParseUlimit("notarealtype=1024:1024"); err == nil { - t.Fatalf("expected error on invalid ulimit type") - } -} - -func TestParseUlimitBadFormat(t *testing.T) { - if _, err := ParseUlimit("nofile:1024:1024"); err == nil { - t.Fatal("expected error on bad syntax") - } - - if _, err := ParseUlimit("nofile"); err == nil { - t.Fatal("expected error on bad syntax") - } - - if _, err := ParseUlimit("nofile="); err == nil { - t.Fatal("expected error on bad syntax") - } - if _, err := ParseUlimit("nofile=:"); err == nil { - t.Fatal("expected error on bad syntax") - } - if _, err := ParseUlimit("nofile=:1024"); err == nil { - t.Fatal("expected error on bad syntax") - } -} - -func TestParseUlimitHardLessThanSoft(t *testing.T) { - if _, err := ParseUlimit("nofile=1024:1"); err == nil { - t.Fatal("expected error on hard limit less than soft limit") - } -} - -func TestParseUlimitInvalidValueType(t *testing.T) { - if _, err := ParseUlimit("nofile=asdf"); err == nil { - t.Fatal("expected error on bad value type, but got no error") - } else if _, ok := err.(*strconv.NumError); !ok { - t.Fatalf("expected error on bad value type, but got `%s`", err) - } - - if _, err := ParseUlimit("nofile=1024:asdf"); err == nil { - t.Fatal("expected error on bad value type, but got no error") - } else if _, ok := err.(*strconv.NumError); !ok { - t.Fatalf("expected error on bad value type, but got `%s`", err) - } -} - -func TestUlimitStringOutput(t *testing.T) { - u := &Ulimit{"nofile", 1024, 512} - if s := u.String(); s != "nofile=512:1024" { - t.Fatal("expected String to return nofile=512:1024, but got", s) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/bench_curly_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/bench_curly_test.go deleted file mode 100644 index db6a1a752..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/bench_curly_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package restful - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" -) - -func setupCurly(container *Container) []string { - wsCount := 26 - rtCount := 26 - urisCurly := []string{} - - container.Router(CurlyRouter{}) - for i := 0; i < wsCount; i++ { - root := fmt.Sprintf("/%s/{%s}/", string(i+97), string(i+97)) - ws := new(WebService).Path(root) - for j := 0; j < rtCount; j++ { - sub := fmt.Sprintf("/%s2/{%s2}", string(j+97), string(j+97)) - ws.Route(ws.GET(sub).Consumes("application/xml").Produces("application/xml").To(echoCurly)) - } - container.Add(ws) - for _, each := range ws.Routes() { - urisCurly = append(urisCurly, "http://bench.com"+each.Path) - } - } - return urisCurly -} - -func echoCurly(req *Request, resp *Response) {} - -func BenchmarkManyCurly(b *testing.B) { - container := NewContainer() - urisCurly := setupCurly(container) - b.ResetTimer() - for t := 0; t < b.N; t++ { - for r := 0; r < 1000; r++ { - for _, each := range urisCurly { - sendNoReturnTo(each, container, t) - } - } - } -} - -func sendNoReturnTo(address string, container *Container, t int) { - httpRequest, _ := http.NewRequest("GET", address, nil) - httpRequest.Header.Set("Accept", "application/xml") - httpWriter := httptest.NewRecorder() - container.dispatch(httpWriter, httpRequest) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/bench_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/bench_test.go deleted file mode 100644 index 3e77c2d29..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/bench_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package restful - -import ( - "fmt" - "io" - "testing" -) - -var uris = []string{} - -func setup(container *Container) { - wsCount := 26 - rtCount := 26 - - for i := 0; i < wsCount; i++ { - root := fmt.Sprintf("/%s/{%s}/", string(i+97), string(i+97)) - ws := new(WebService).Path(root) - for j := 0; j < rtCount; j++ { - sub := fmt.Sprintf("/%s2/{%s2}", string(j+97), string(j+97)) - ws.Route(ws.GET(sub).To(echo)) - } - container.Add(ws) - for _, each := range ws.Routes() { - uris = append(uris, "http://bench.com"+each.Path) - } - } -} - -func echo(req *Request, resp *Response) { - io.WriteString(resp.ResponseWriter, "echo") -} - -func BenchmarkMany(b *testing.B) { - container := NewContainer() - setup(container) - b.ResetTimer() - for t := 0; t < b.N; t++ { - for _, each := range uris { - // println(each) - sendItTo(each, container) - } - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/compress_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/compress_test.go deleted file mode 100644 index 84a93c3fc..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/compress_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package restful - -import ( - "bytes" - "compress/gzip" - "compress/zlib" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" -) - -// go test -v -test.run TestGzip ...restful -func TestGzip(t *testing.T) { - EnableContentEncoding = true - httpRequest, _ := http.NewRequest("GET", "/test", nil) - httpRequest.Header.Set("Accept-Encoding", "gzip,deflate") - httpWriter := httptest.NewRecorder() - wanted, encoding := wantsCompressedResponse(httpRequest) - if !wanted { - t.Fatal("should accept gzip") - } - if encoding != "gzip" { - t.Fatal("expected gzip") - } - c, err := NewCompressingResponseWriter(httpWriter, encoding) - if err != nil { - t.Fatal(err.Error()) - } - c.Write([]byte("Hello World")) - c.Close() - if httpWriter.Header().Get("Content-Encoding") != "gzip" { - t.Fatal("Missing gzip header") - } - reader, err := gzip.NewReader(httpWriter.Body) - if err != nil { - t.Fatal(err.Error()) - } - data, err := ioutil.ReadAll(reader) - if err != nil { - t.Fatal(err.Error()) - } - if got, want := string(data), "Hello World"; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestDeflate(t *testing.T) { - EnableContentEncoding = true - httpRequest, _ := http.NewRequest("GET", "/test", nil) - httpRequest.Header.Set("Accept-Encoding", "deflate,gzip") - httpWriter := httptest.NewRecorder() - wanted, encoding := wantsCompressedResponse(httpRequest) - if !wanted { - t.Fatal("should accept deflate") - } - if encoding != "deflate" { - t.Fatal("expected deflate") - } - c, err := NewCompressingResponseWriter(httpWriter, encoding) - if err != nil { - t.Fatal(err.Error()) - } - c.Write([]byte("Hello World")) - c.Close() - if httpWriter.Header().Get("Content-Encoding") != "deflate" { - t.Fatal("Missing deflate header") - } - reader, err := zlib.NewReader(httpWriter.Body) - if err != nil { - t.Fatal(err.Error()) - } - data, err := ioutil.ReadAll(reader) - if err != nil { - t.Fatal(err.Error()) - } - if got, want := string(data), "Hello World"; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestGzipDecompressRequestBody(t *testing.T) { - b := new(bytes.Buffer) - w := newGzipWriter() - w.Reset(b) - io.WriteString(w, `{"msg":"hi"}`) - w.Flush() - w.Close() - - req := new(Request) - httpRequest, _ := http.NewRequest("GET", "/", bytes.NewReader(b.Bytes())) - httpRequest.Header.Set("Content-Type", "application/json") - httpRequest.Header.Set("Content-Encoding", "gzip") - req.Request = httpRequest - - doCacheReadEntityBytes = false - doc := make(map[string]interface{}) - req.ReadEntity(&doc) - - if got, want := doc["msg"], "hi"; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestZlibDecompressRequestBody(t *testing.T) { - b := new(bytes.Buffer) - w := newZlibWriter() - w.Reset(b) - io.WriteString(w, `{"msg":"hi"}`) - w.Flush() - w.Close() - - req := new(Request) - httpRequest, _ := http.NewRequest("GET", "/", bytes.NewReader(b.Bytes())) - httpRequest.Header.Set("Content-Type", "application/json") - httpRequest.Header.Set("Content-Encoding", "deflate") - req.Request = httpRequest - - doCacheReadEntityBytes = false - doc := make(map[string]interface{}) - req.ReadEntity(&doc) - - if got, want := doc["msg"], "hi"; got != want { - t.Errorf("got %v want %v", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/container_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/container_test.go deleted file mode 100644 index dd2552c37..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/container_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package restful - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -// go test -v -test.run TestContainer_computeAllowedMethods ...restful -func TestContainer_computeAllowedMethods(t *testing.T) { - wc := NewContainer() - ws1 := new(WebService).Path("/users") - ws1.Route(ws1.GET("{i}").To(dummy)) - ws1.Route(ws1.POST("{i}").To(dummy)) - wc.Add(ws1) - httpRequest, _ := http.NewRequest("GET", "http://api.his.com/users/1", nil) - rreq := Request{Request: httpRequest} - m := wc.computeAllowedMethods(&rreq) - if len(m) != 2 { - t.Errorf("got %d expected 2 methods, %v", len(m), m) - } -} - -func TestContainer_HandleWithFilter(t *testing.T) { - prefilterCalled := false - postfilterCalled := false - httpHandlerCalled := false - - wc := NewContainer() - wc.Filter(func(request *Request, response *Response, chain *FilterChain) { - prefilterCalled = true - chain.ProcessFilter(request, response) - }) - wc.HandleWithFilter("/", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - httpHandlerCalled = true - w.Write([]byte("ok")) - })) - wc.Filter(func(request *Request, response *Response, chain *FilterChain) { - postfilterCalled = true - chain.ProcessFilter(request, response) - }) - - recorder := httptest.NewRecorder() - request, _ := http.NewRequest("GET", "/", nil) - wc.ServeHTTP(recorder, request) - if recorder.Code != http.StatusOK { - t.Errorf("unexpected code %d", recorder.Code) - } - if recorder.Body.String() != "ok" { - t.Errorf("unexpected body %s", recorder.Body.String()) - } - if !prefilterCalled { - t.Errorf("filter added before calling HandleWithFilter wasn't called") - } - if !postfilterCalled { - t.Errorf("filter added after calling HandleWithFilter wasn't called") - } - if !httpHandlerCalled { - t.Errorf("handler added by calling HandleWithFilter wasn't called") - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/cors_filter_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/cors_filter_test.go deleted file mode 100644 index 9b4723089..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/cors_filter_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package restful - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -// go test -v -test.run TestCORSFilter_Preflight ...restful -// http://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request -func TestCORSFilter_Preflight(t *testing.T) { - tearDown() - ws := new(WebService) - ws.Route(ws.PUT("/cors").To(dummy)) - Add(ws) - - cors := CrossOriginResourceSharing{ - ExposeHeaders: []string{"X-Custom-Header"}, - AllowedHeaders: []string{"X-Custom-Header", "X-Additional-Header"}, - CookiesAllowed: true, - Container: DefaultContainer} - Filter(cors.Filter) - - // Preflight - httpRequest, _ := http.NewRequest("OPTIONS", "http://api.alice.com/cors", nil) - httpRequest.Method = "OPTIONS" - httpRequest.Header.Set(HEADER_Origin, "http://api.bob.com") - httpRequest.Header.Set(HEADER_AccessControlRequestMethod, "PUT") - httpRequest.Header.Set(HEADER_AccessControlRequestHeaders, "X-Custom-Header, X-Additional-Header") - - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - - actual := httpWriter.Header().Get(HEADER_AccessControlAllowOrigin) - if "http://api.bob.com" != actual { - t.Fatal("expected: http://api.bob.com but got:" + actual) - } - actual = httpWriter.Header().Get(HEADER_AccessControlAllowMethods) - if "PUT" != actual { - t.Fatal("expected: PUT but got:" + actual) - } - actual = httpWriter.Header().Get(HEADER_AccessControlAllowHeaders) - if "X-Custom-Header, X-Additional-Header" != actual { - t.Fatal("expected: X-Custom-Header, X-Additional-Header but got:" + actual) - } - - if !cors.isOriginAllowed("somewhere") { - t.Fatal("origin expected to be allowed") - } - cors.AllowedDomains = []string{"overthere.com"} - if cors.isOriginAllowed("somewhere") { - t.Fatal("origin [somewhere] expected NOT to be allowed") - } - if !cors.isOriginAllowed("overthere.com") { - t.Fatal("origin [overthere] expected to be allowed") - } - -} - -// go test -v -test.run TestCORSFilter_Actual ...restful -// http://www.html5rocks.com/en/tutorials/cors/#toc-handling-a-not-so-simple-request -func TestCORSFilter_Actual(t *testing.T) { - tearDown() - ws := new(WebService) - ws.Route(ws.PUT("/cors").To(dummy)) - Add(ws) - - cors := CrossOriginResourceSharing{ - ExposeHeaders: []string{"X-Custom-Header"}, - AllowedHeaders: []string{"X-Custom-Header", "X-Additional-Header"}, - CookiesAllowed: true, - Container: DefaultContainer} - Filter(cors.Filter) - - // Actual - httpRequest, _ := http.NewRequest("PUT", "http://api.alice.com/cors", nil) - httpRequest.Header.Set(HEADER_Origin, "http://api.bob.com") - httpRequest.Header.Set("X-Custom-Header", "value") - - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - actual := httpWriter.Header().Get(HEADER_AccessControlAllowOrigin) - if "http://api.bob.com" != actual { - t.Fatal("expected: http://api.bob.com but got:" + actual) - } - if httpWriter.Body.String() != "dummy" { - t.Fatal("expected: dummy but got:" + httpWriter.Body.String()) - } -} - -var allowedDomainInput = []struct { - domains []string - origin string - accepted bool -}{ - {[]string{}, "http://anything.com", true}, -} - -// go test -v -test.run TestCORSFilter_AllowedDomains ...restful -func TestCORSFilter_AllowedDomains(t *testing.T) { - for _, each := range allowedDomainInput { - tearDown() - ws := new(WebService) - ws.Route(ws.PUT("/cors").To(dummy)) - Add(ws) - - cors := CrossOriginResourceSharing{ - AllowedDomains: each.domains, - CookiesAllowed: true, - Container: DefaultContainer} - Filter(cors.Filter) - - httpRequest, _ := http.NewRequest("PUT", "http://api.his.com/cors", nil) - httpRequest.Header.Set(HEADER_Origin, each.origin) - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - actual := httpWriter.Header().Get(HEADER_AccessControlAllowOrigin) - if actual != each.origin && each.accepted { - t.Fatal("expected to be accepted") - } - if actual == each.origin && !each.accepted { - t.Fatal("did not expect to be accepted") - } - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/curly_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/curly_test.go deleted file mode 100644 index 31d66dcbd..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/curly_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package restful - -import ( - "io" - "net/http" - "testing" -) - -var requestPaths = []struct { - // url with path (1) is handled by service with root (2) and remainder has value final (3) - path, root string -}{ - {"/", "/"}, - {"/p", "/p"}, - {"/p/x", "/p/{q}"}, - {"/q/x", "/q"}, - {"/p/x/", "/p/{q}"}, - {"/p/x/y", "/p/{q}"}, - {"/q/x/y", "/q"}, - {"/z/q", "/{p}/q"}, - {"/a/b/c/q", "/"}, -} - -// go test -v -test.run TestCurlyDetectWebService ...restful -func TestCurlyDetectWebService(t *testing.T) { - ws1 := new(WebService).Path("/") - ws2 := new(WebService).Path("/p") - ws3 := new(WebService).Path("/q") - ws4 := new(WebService).Path("/p/q") - ws5 := new(WebService).Path("/p/{q}") - ws7 := new(WebService).Path("/{p}/q") - var wss = []*WebService{ws1, ws2, ws3, ws4, ws5, ws7} - - for _, each := range wss { - t.Logf("path=%s,toks=%v\n", each.pathExpr.Source, each.pathExpr.tokens) - } - - router := CurlyRouter{} - - ok := true - for i, fixture := range requestPaths { - requestTokens := tokenizePath(fixture.path) - who := router.detectWebService(requestTokens, wss) - if who != nil && who.RootPath() != fixture.root { - t.Logf("[line:%v] Unexpected dispatcher, expected:%v, actual:%v", i, fixture.root, who.RootPath()) - ok = false - } - } - if !ok { - t.Fail() - } -} - -var serviceDetects = []struct { - path string - found bool - root string -}{ - {"/a/b", true, "/{p}/{q}/{r}"}, - {"/p/q", true, "/p/q"}, - {"/q/p", true, "/q"}, - {"/", true, "/"}, - {"/p/q/r", true, "/p/q"}, -} - -// go test -v -test.run Test_detectWebService ...restful -func Test_detectWebService(t *testing.T) { - router := CurlyRouter{} - ws1 := new(WebService).Path("/") - ws2 := new(WebService).Path("/p") - ws3 := new(WebService).Path("/q") - ws4 := new(WebService).Path("/p/q") - ws5 := new(WebService).Path("/p/{q}") - ws6 := new(WebService).Path("/p/{q}/") - ws7 := new(WebService).Path("/{p}/q") - ws8 := new(WebService).Path("/{p}/{q}/{r}") - var wss = []*WebService{ws8, ws7, ws6, ws5, ws4, ws3, ws2, ws1} - for _, fix := range serviceDetects { - requestPath := fix.path - requestTokens := tokenizePath(requestPath) - for _, ws := range wss { - serviceTokens := ws.pathExpr.tokens - matches, score := router.computeWebserviceScore(requestTokens, serviceTokens) - t.Logf("req=%s,toks:%v,ws=%s,toks:%v,score=%d,matches=%v", requestPath, requestTokens, ws.RootPath(), serviceTokens, score, matches) - } - best := router.detectWebService(requestTokens, wss) - if best != nil { - if fix.found { - t.Logf("best=%s", best.RootPath()) - } else { - t.Fatalf("should have found:%s", fix.root) - } - } - } -} - -var routeMatchers = []struct { - route string - path string - matches bool - paramCount int - staticCount int -}{ - // route, request-path - {"/a", "/a", true, 0, 1}, - {"/a", "/b", false, 0, 0}, - {"/a", "/b", false, 0, 0}, - {"/a/{b}/c/", "/a/2/c", true, 1, 2}, - {"/{a}/{b}/{c}/", "/a/b", false, 0, 0}, - {"/{x:*}", "/", false, 0, 0}, - {"/{x:*}", "/a", true, 1, 0}, - {"/{x:*}", "/a/b", true, 1, 0}, - {"/a/{x:*}", "/a/b", true, 1, 1}, - {"/a/{x:[A-Z][A-Z]}", "/a/ZX", true, 1, 1}, - {"/basepath/{resource:*}", "/basepath/some/other/location/test.xml", true, 1, 1}, -} - -// clear && go test -v -test.run Test_matchesRouteByPathTokens ...restful -func Test_matchesRouteByPathTokens(t *testing.T) { - router := CurlyRouter{} - for i, each := range routeMatchers { - routeToks := tokenizePath(each.route) - reqToks := tokenizePath(each.path) - matches, pCount, sCount := router.matchesRouteByPathTokens(routeToks, reqToks) - if matches != each.matches { - t.Fatalf("[%d] unexpected matches outcome route:%s, path:%s, matches:%v", i, each.route, each.path, matches) - } - if pCount != each.paramCount { - t.Fatalf("[%d] unexpected paramCount got:%d want:%d ", i, pCount, each.paramCount) - } - if sCount != each.staticCount { - t.Fatalf("[%d] unexpected staticCount got:%d want:%d ", i, sCount, each.staticCount) - } - } -} - -// clear && go test -v -test.run TestExtractParameters_Wildcard1 ...restful -func TestExtractParameters_Wildcard1(t *testing.T) { - params := doExtractParams("/fixed/{var:*}", 2, "/fixed/remainder", t) - if params["var"] != "remainder" { - t.Errorf("parameter mismatch var: %s", params["var"]) - } -} - -// clear && go test -v -test.run TestExtractParameters_Wildcard2 ...restful -func TestExtractParameters_Wildcard2(t *testing.T) { - params := doExtractParams("/fixed/{var:*}", 2, "/fixed/remain/der", t) - if params["var"] != "remain/der" { - t.Errorf("parameter mismatch var: %s", params["var"]) - } -} - -// clear && go test -v -test.run TestExtractParameters_Wildcard3 ...restful -func TestExtractParameters_Wildcard3(t *testing.T) { - params := doExtractParams("/static/{var:*}", 2, "/static/test/sub/hi.html", t) - if params["var"] != "test/sub/hi.html" { - t.Errorf("parameter mismatch var: %s", params["var"]) - } -} - -// clear && go test -v -test.run TestCurly_ISSUE_34 ...restful -func TestCurly_ISSUE_34(t *testing.T) { - ws1 := new(WebService).Path("/") - ws1.Route(ws1.GET("/{type}/{id}").To(curlyDummy)) - ws1.Route(ws1.GET("/network/{id}").To(curlyDummy)) - routes := CurlyRouter{}.selectRoutes(ws1, tokenizePath("/network/12")) - if len(routes) != 2 { - t.Fatal("expected 2 routes") - } - if routes[0].Path != "/network/{id}" { - t.Error("first is", routes[0].Path) - } -} - -// clear && go test -v -test.run TestCurly_ISSUE_34_2 ...restful -func TestCurly_ISSUE_34_2(t *testing.T) { - ws1 := new(WebService) - ws1.Route(ws1.GET("/network/{id}").To(curlyDummy)) - ws1.Route(ws1.GET("/{type}/{id}").To(curlyDummy)) - routes := CurlyRouter{}.selectRoutes(ws1, tokenizePath("/network/12")) - if len(routes) != 2 { - t.Fatal("expected 2 routes") - } - if routes[0].Path != "/network/{id}" { - t.Error("first is", routes[0].Path) - } -} - -// clear && go test -v -test.run TestCurly_JsonHtml ...restful -func TestCurly_JsonHtml(t *testing.T) { - ws1 := new(WebService) - ws1.Path("/") - ws1.Route(ws1.GET("/some.html").To(curlyDummy).Consumes("*/*").Produces("text/html")) - req, _ := http.NewRequest("GET", "/some.html", nil) - req.Header.Set("Accept", "application/json") - _, route, err := CurlyRouter{}.SelectRoute([]*WebService{ws1}, req) - if err == nil { - t.Error("error expected") - } - if route != nil { - t.Error("no route expected") - } -} - -// go test -v -test.run TestCurly_ISSUE_137 ...restful -func TestCurly_ISSUE_137(t *testing.T) { - ws1 := new(WebService) - ws1.Route(ws1.GET("/hello").To(curlyDummy)) - ws1.Path("/") - req, _ := http.NewRequest("GET", "/", nil) - _, route, _ := CurlyRouter{}.SelectRoute([]*WebService{ws1}, req) - t.Log(route) - if route != nil { - t.Error("no route expected") - } -} - -// go test -v -test.run TestCurly_ISSUE_137_2 ...restful -func TestCurly_ISSUE_137_2(t *testing.T) { - ws1 := new(WebService) - ws1.Route(ws1.GET("/hello").To(curlyDummy)) - ws1.Path("/") - req, _ := http.NewRequest("GET", "/hello/bob", nil) - _, route, _ := CurlyRouter{}.SelectRoute([]*WebService{ws1}, req) - t.Log(route) - if route != nil { - t.Errorf("no route expected, got %v", route) - } -} - -func curlyDummy(req *Request, resp *Response) { io.WriteString(resp.ResponseWriter, "curlyDummy") } diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/doc_examples_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/doc_examples_test.go deleted file mode 100644 index 0af636e55..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/doc_examples_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package restful - -import "net/http" - -func ExampleOPTIONSFilter() { - // Install the OPTIONS filter on the default Container - Filter(OPTIONSFilter()) -} -func ExampleContainer_OPTIONSFilter() { - // Install the OPTIONS filter on a Container - myContainer := new(Container) - myContainer.Filter(myContainer.OPTIONSFilter) -} - -func ExampleContainer() { - // The Default container of go-restful uses the http.DefaultServeMux. - // You can create your own Container using restful.NewContainer() and create a new http.Server for that particular container - - ws := new(WebService) - wsContainer := NewContainer() - wsContainer.Add(ws) - server := &http.Server{Addr: ":8080", Handler: wsContainer} - server.ListenAndServe() -} - -func ExampleCrossOriginResourceSharing() { - // To install this filter on the Default Container use: - cors := CrossOriginResourceSharing{ExposeHeaders: []string{"X-My-Header"}, CookiesAllowed: false, Container: DefaultContainer} - Filter(cors.Filter) -} - -func ExampleServiceError() { - resp := new(Response) - resp.WriteEntity(NewError(http.StatusBadRequest, "Non-integer {id} path parameter")) -} - -func ExampleBoundedCachedCompressors() { - // Register a compressor provider (gzip/deflate read/write) that uses - // a bounded cache with a maximum of 20 writers and 20 readers. - SetCompressorProvider(NewBoundedCachedCompressors(20, 20)) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/entity_accessors_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/entity_accessors_test.go deleted file mode 100644 index 943093ae0..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/entity_accessors_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package restful - -import ( - "bytes" - "fmt" - "io" - "net/http" - "net/http/httptest" - "reflect" - "testing" -) - -type keyvalue struct { - readCalled bool - writeCalled bool -} - -func (kv *keyvalue) Read(req *Request, v interface{}) error { - //t := reflect.TypeOf(v) - //rv := reflect.ValueOf(v) - kv.readCalled = true - return nil -} - -func (kv *keyvalue) Write(resp *Response, status int, v interface{}) error { - t := reflect.TypeOf(v) - rv := reflect.ValueOf(v) - for ix := 0; ix < t.NumField(); ix++ { - sf := t.Field(ix) - io.WriteString(resp, sf.Name) - io.WriteString(resp, "=") - io.WriteString(resp, fmt.Sprintf("%v\n", rv.Field(ix).Interface())) - } - kv.writeCalled = true - return nil -} - -// go test -v -test.run TestKeyValueEncoding ...restful -func TestKeyValueEncoding(t *testing.T) { - type Book struct { - Title string - Author string - PublishedYear int - } - kv := new(keyvalue) - RegisterEntityAccessor("application/kv", kv) - b := Book{"Singing for Dummies", "john doe", 2015} - - // Write - httpWriter := httptest.NewRecorder() - // Accept Produces - resp := Response{httpWriter, "application/kv,*/*;q=0.8", []string{"application/kv"}, 0, 0, true, nil} - resp.WriteEntity(b) - t.Log(string(httpWriter.Body.Bytes())) - if !kv.writeCalled { - t.Error("Write never called") - } - - // Read - bodyReader := bytes.NewReader(httpWriter.Body.Bytes()) - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/kv; charset=UTF-8") - request := NewRequest(httpRequest) - var bb Book - request.ReadEntity(&bb) - if !kv.readCalled { - t.Error("Read never called") - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/.goconvey b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/.goconvey deleted file mode 100644 index 8485e986e..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/.goconvey +++ /dev/null @@ -1 +0,0 @@ -ignore \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/.goconvey b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/.goconvey deleted file mode 100644 index 8485e986e..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/.goconvey +++ /dev/null @@ -1 +0,0 @@ -ignore \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/app.yaml b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/app.yaml deleted file mode 100644 index 362db6b07..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/app.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# -# Include your application ID here -# -application: -version: 1 -runtime: go -api_version: go1 - -handlers: -# -# Regex for all swagger files to make as static content. -# You should create the folder static/swagger and copy -# swagger-ui into it. -# -- url: /apidocs/(.*?)/(.*\.(js|html|css)) - static_files: static/swagger/\1/\2 - upload: static/swagger/(.*?)/(.*\.(js|html|css)) - -- url: /.* - script: _go_app diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/.goconvey b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/.goconvey deleted file mode 100644 index 8485e986e..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/.goconvey +++ /dev/null @@ -1 +0,0 @@ -ignore \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/app.yaml b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/app.yaml deleted file mode 100644 index 1ac9dca28..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/app.yaml +++ /dev/null @@ -1,18 +0,0 @@ -application: -version: 1 -runtime: go -api_version: go1 - -handlers: -# Regex for all swagger files to make as static content. -# You should create the folder static/swagger and copy -# swagger-ui into it. -# -- url: /apidocs/(.*?)/(.*\.(js|html|css)) - static_files: static/swagger/\1/\2 - upload: static/swagger/(.*?)/(.*\.(js|html|css)) - -# Catch all. -- url: /.* - script: _go_app - login: required diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/main.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/main.go deleted file mode 100644 index ca2908180..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/datastore/main.go +++ /dev/null @@ -1,266 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "github.com/emicklei/go-restful/swagger" - "google.golang.org/appengine" - "google.golang.org/appengine/datastore" - "google.golang.org/appengine/user" - "net/http" - "time" -) - -// This example demonstrates a reasonably complete suite of RESTful operations backed -// by DataStore on Google App Engine. - -// Our simple example struct. -type Profile struct { - LastModified time.Time `json:"-" xml:"-"` - Email string `json:"-" xml:"-"` - FirstName string `json:"first_name" xml:"first-name"` - NickName string `json:"nick_name" xml:"nick-name"` - LastName string `json:"last_name" xml:"last-name"` -} - -type ProfileApi struct { - Path string -} - -func gaeUrl() string { - if appengine.IsDevAppServer() { - return "http://localhost:8080" - } else { - // Include your URL on App Engine here. - // I found no way to get AppID without appengine.Context and this always - // based on a http.Request. - return "http://federatedservices.appspot.com" - } -} - -func init() { - u := ProfileApi{Path: "/profiles"} - u.register() - - // Optionally, you can install the Swagger Service which provides a nice Web UI on your REST API - // You need to download the Swagger HTML5 assets and change the FilePath location in the config below. - // Open .appspot.com/apidocs and enter - // Place the Swagger UI files into a folder called static/swagger if you wish to use Swagger - // http://.appspot.com/apidocs.json in the api input field. - // For testing, you can use http://localhost:8080/apidocs.json - config := swagger.Config{ - // You control what services are visible - WebServices: restful.RegisteredWebServices(), - WebServicesUrl: gaeUrl(), - ApiPath: "/apidocs.json", - - // Optionally, specifiy where the UI is located - SwaggerPath: "/apidocs/", - - // GAE support static content which is configured in your app.yaml. - // This example expect the swagger-ui in static/swagger so you should place it there :) - SwaggerFilePath: "static/swagger"} - swagger.InstallSwaggerService(config) -} - -func (u ProfileApi) register() { - ws := new(restful.WebService) - - ws. - Path(u.Path). - // You can specify consumes and produces per route as well. - Consumes(restful.MIME_JSON, restful.MIME_XML). - Produces(restful.MIME_JSON, restful.MIME_XML) - - ws.Route(ws.POST("").To(u.insert). - // Swagger documentation. - Doc("insert a new profile"). - Param(ws.BodyParameter("Profile", "representation of a profile").DataType("main.Profile")). - Reads(Profile{})) - - ws.Route(ws.GET("/{profile-id}").To(u.read). - // Swagger documentation. - Doc("read a profile"). - Param(ws.PathParameter("profile-id", "identifier for a profile").DataType("string")). - Writes(Profile{})) - - ws.Route(ws.PUT("/{profile-id}").To(u.update). - // Swagger documentation. - Doc("update an existing profile"). - Param(ws.PathParameter("profile-id", "identifier for a profile").DataType("string")). - Param(ws.BodyParameter("Profile", "representation of a profile").DataType("main.Profile")). - Reads(Profile{})) - - ws.Route(ws.DELETE("/{profile-id}").To(u.remove). - // Swagger documentation. - Doc("remove a profile"). - Param(ws.PathParameter("profile-id", "identifier for a profile").DataType("string"))) - - restful.Add(ws) -} - -// POST http://localhost:8080/profiles -// {"first_name": "Ivan", "nick_name": "Socks", "last_name": "Hawkes"} -// -func (u *ProfileApi) insert(r *restful.Request, w *restful.Response) { - c := appengine.NewContext(r.Request) - - // Marshall the entity from the request into a struct. - p := new(Profile) - err := r.ReadEntity(&p) - if err != nil { - w.WriteError(http.StatusNotAcceptable, err) - return - } - - // Ensure we start with a sensible value for this field. - p.LastModified = time.Now() - - // The profile belongs to this user. - p.Email = user.Current(c).String() - - k, err := datastore.Put(c, datastore.NewIncompleteKey(c, "profiles", nil), p) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // Let them know the location of the newly created resource. - // TODO: Use a safe Url path append function. - w.AddHeader("Location", u.Path+"/"+k.Encode()) - - // Return the resultant entity. - w.WriteHeader(http.StatusCreated) - w.WriteEntity(p) -} - -// GET http://localhost:8080/profiles/ahdkZXZ-ZmVkZXJhdGlvbi1zZXJ2aWNlc3IVCxIIcHJvZmlsZXMYgICAgICAgAoM -// -func (u ProfileApi) read(r *restful.Request, w *restful.Response) { - c := appengine.NewContext(r.Request) - - // Decode the request parameter to determine the key for the entity. - k, err := datastore.DecodeKey(r.PathParameter("profile-id")) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // Retrieve the entity from the datastore. - p := Profile{} - if err := datastore.Get(c, k, &p); err != nil { - if err.Error() == "datastore: no such entity" { - http.Error(w, err.Error(), http.StatusNotFound) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - return - } - - // Check we own the profile before allowing them to view it. - // Optionally, return a 404 instead to help prevent guessing ids. - // TODO: Allow admins access. - if p.Email != user.Current(c).String() { - http.Error(w, "You do not have access to this resource", http.StatusForbidden) - return - } - - w.WriteEntity(p) -} - -// PUT http://localhost:8080/profiles/ahdkZXZ-ZmVkZXJhdGlvbi1zZXJ2aWNlc3IVCxIIcHJvZmlsZXMYgICAgICAgAoM -// {"first_name": "Ivan", "nick_name": "Socks", "last_name": "Hawkes"} -// -func (u *ProfileApi) update(r *restful.Request, w *restful.Response) { - c := appengine.NewContext(r.Request) - - // Decode the request parameter to determine the key for the entity. - k, err := datastore.DecodeKey(r.PathParameter("profile-id")) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // Marshall the entity from the request into a struct. - p := new(Profile) - err = r.ReadEntity(&p) - if err != nil { - w.WriteError(http.StatusNotAcceptable, err) - return - } - - // Retrieve the old entity from the datastore. - old := Profile{} - if err := datastore.Get(c, k, &old); err != nil { - if err.Error() == "datastore: no such entity" { - http.Error(w, err.Error(), http.StatusNotFound) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - return - } - - // Check we own the profile before allowing them to update it. - // Optionally, return a 404 instead to help prevent guessing ids. - // TODO: Allow admins access. - if old.Email != user.Current(c).String() { - http.Error(w, "You do not have access to this resource", http.StatusForbidden) - return - } - - // Since the whole entity is re-written, we need to assign any invariant fields again - // e.g. the owner of the entity. - p.Email = user.Current(c).String() - - // Keep track of the last modification date. - p.LastModified = time.Now() - - // Attempt to overwrite the old entity. - _, err = datastore.Put(c, k, p) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - // Let them know it succeeded. - w.WriteHeader(http.StatusNoContent) -} - -// DELETE http://localhost:8080/profiles/ahdkZXZ-ZmVkZXJhdGlvbi1zZXJ2aWNlc3IVCxIIcHJvZmlsZXMYgICAgICAgAoM -// -func (u *ProfileApi) remove(r *restful.Request, w *restful.Response) { - c := appengine.NewContext(r.Request) - - // Decode the request parameter to determine the key for the entity. - k, err := datastore.DecodeKey(r.PathParameter("profile-id")) - if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - // Retrieve the old entity from the datastore. - old := Profile{} - if err := datastore.Get(c, k, &old); err != nil { - if err.Error() == "datastore: no such entity" { - http.Error(w, err.Error(), http.StatusNotFound) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - return - } - - // Check we own the profile before allowing them to delete it. - // Optionally, return a 404 instead to help prevent guessing ids. - // TODO: Allow admins access. - if old.Email != user.Current(c).String() { - http.Error(w, "You do not have access to this resource", http.StatusForbidden) - return - } - - // Delete the entity. - if err := datastore.Delete(c, k); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - - // Success notification. - w.WriteHeader(http.StatusNoContent) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/restful-appstats-integration.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/restful-appstats-integration.go deleted file mode 100644 index b3261eeb9..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/restful-appstats-integration.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "github.com/mjibson/appstats" -) - - -func stats(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - c := appstats.NewContext(req.Request) - chain.ProcessFilter(req, resp) - c.Stats.Status = resp.StatusCode() - c.Save() -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/restful-user-service.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/restful-user-service.go deleted file mode 100644 index 3f38fd6b2..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/google_app_engine/restful-user-service.go +++ /dev/null @@ -1,161 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "github.com/emicklei/go-restful/swagger" - "google.golang.org/appengine" - "google.golang.org/appengine/memcache" - "net/http" -) - -// This example is functionally the same as ../restful-user-service.go -// but it`s supposed to run on Goole App Engine (GAE) -// -// contributed by ivanhawkes - -type User struct { - Id, Name string -} - -type UserService struct { - // normally one would use DAO (data access object) - // but in this example we simple use memcache. -} - -func (u UserService) Register() { - ws := new(restful.WebService) - - ws. - Path("/users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well - - ws.Route(ws.GET("/{user-id}").To(u.findUser). - // docs - Doc("get a user"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). - Writes(User{})) // on the response - - ws.Route(ws.PATCH("").To(u.updateUser). - // docs - Doc("update a user"). - Reads(User{})) // from the request - - ws.Route(ws.PUT("/{user-id}").To(u.createUser). - // docs - Doc("create a user"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). - Reads(User{})) // from the request - - ws.Route(ws.DELETE("/{user-id}").To(u.removeUser). - // docs - Doc("delete a user"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string"))) - - restful.Add(ws) -} - -// GET http://localhost:8080/users/1 -// -func (u UserService) findUser(request *restful.Request, response *restful.Response) { - c := appengine.NewContext(request.Request) - id := request.PathParameter("user-id") - usr := new(User) - _, err := memcache.Gob.Get(c, id, &usr) - if err != nil || len(usr.Id) == 0 { - response.WriteErrorString(http.StatusNotFound, "User could not be found.") - } else { - response.WriteEntity(usr) - } -} - -// PATCH http://localhost:8080/users -// 1Melissa Raspberry -// -func (u *UserService) updateUser(request *restful.Request, response *restful.Response) { - c := appengine.NewContext(request.Request) - usr := new(User) - err := request.ReadEntity(&usr) - if err == nil { - item := &memcache.Item{ - Key: usr.Id, - Object: &usr, - } - err = memcache.Gob.Set(c, item) - if err != nil { - response.WriteError(http.StatusInternalServerError, err) - return - } - response.WriteEntity(usr) - } else { - response.WriteError(http.StatusInternalServerError, err) - } -} - -// PUT http://localhost:8080/users/1 -// 1Melissa -// -func (u *UserService) createUser(request *restful.Request, response *restful.Response) { - c := appengine.NewContext(request.Request) - usr := User{Id: request.PathParameter("user-id")} - err := request.ReadEntity(&usr) - if err == nil { - item := &memcache.Item{ - Key: usr.Id, - Object: &usr, - } - err = memcache.Gob.Add(c, item) - if err != nil { - response.WriteError(http.StatusInternalServerError, err) - return - } - response.WriteHeader(http.StatusCreated) - response.WriteEntity(usr) - } else { - response.WriteError(http.StatusInternalServerError, err) - } -} - -// DELETE http://localhost:8080/users/1 -// -func (u *UserService) removeUser(request *restful.Request, response *restful.Response) { - c := appengine.NewContext(request.Request) - id := request.PathParameter("user-id") - err := memcache.Delete(c, id) - if err != nil { - response.WriteError(http.StatusInternalServerError, err) - } -} - -func getGaeURL() string { - if appengine.IsDevAppServer() { - return "http://localhost:8080" - } else { - /** - * Include your URL on App Engine here. - * I found no way to get AppID without appengine.Context and this always - * based on a http.Request. - */ - return "http://.appspot.com" - } -} - -func init() { - u := UserService{} - u.Register() - - // Optionally, you can install the Swagger Service which provides a nice Web UI on your REST API - // You need to download the Swagger HTML5 assets and change the FilePath location in the config below. - // Open .appspot.com/apidocs and enter http://.appspot.com/apidocs.json in the api input field. - config := swagger.Config{ - WebServices: restful.RegisteredWebServices(), // you control what services are visible - WebServicesUrl: getGaeURL(), - ApiPath: "/apidocs.json", - - // Optionally, specifiy where the UI is located - SwaggerPath: "/apidocs/", - // GAE support static content which is configured in your app.yaml. - // This example expect the swagger-ui in static/swagger so you should place it there :) - SwaggerFilePath: "static/swagger"} - swagger.InstallSwaggerService(config) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/home.html b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/home.html deleted file mode 100644 index e5d49b42c..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/home.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - -

{{.Text}}

- - \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-CORS-filter.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-CORS-filter.go deleted file mode 100644 index 6419d2538..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-CORS-filter.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import ( - "io" - "log" - "net/http" - - "github.com/emicklei/go-restful" -) - -// Cross-origin resource sharing (CORS) is a mechanism that allows JavaScript on a web page -// to make XMLHttpRequests to another domain, not the domain the JavaScript originated from. -// -// http://en.wikipedia.org/wiki/Cross-origin_resource_sharing -// http://enable-cors.org/server.html -// -// GET http://localhost:8080/users -// -// GET http://localhost:8080/users/1 -// -// PUT http://localhost:8080/users/1 -// -// DELETE http://localhost:8080/users/1 -// -// OPTIONS http://localhost:8080/users/1 with Header "Origin" set to some domain and - -type UserResource struct{} - -func (u UserResource) RegisterTo(container *restful.Container) { - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes("*/*"). - Produces("*/*") - - ws.Route(ws.GET("/{user-id}").To(u.nop)) - ws.Route(ws.POST("").To(u.nop)) - ws.Route(ws.PUT("/{user-id}").To(u.nop)) - ws.Route(ws.DELETE("/{user-id}").To(u.nop)) - - container.Add(ws) -} - -func (u UserResource) nop(request *restful.Request, response *restful.Response) { - io.WriteString(response.ResponseWriter, "this would be a normal response") -} - -func main() { - wsContainer := restful.NewContainer() - u := UserResource{} - u.RegisterTo(wsContainer) - - // Add container filter to enable CORS - cors := restful.CrossOriginResourceSharing{ - ExposeHeaders: []string{"X-My-Header"}, - AllowedHeaders: []string{"Content-Type", "Accept"}, - AllowedMethods: []string{"GET", "POST"}, - CookiesAllowed: false, - Container: wsContainer} - wsContainer.Filter(cors.Filter) - - // Add container filter to respond to OPTIONS - wsContainer.Filter(wsContainer.OPTIONSFilter) - - log.Printf("start listening on localhost:8080") - server := &http.Server{Addr: ":8080", Handler: wsContainer} - log.Fatal(server.ListenAndServe()) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-NCSA-logging.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-NCSA-logging.go deleted file mode 100644 index 0cda50d34..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-NCSA-logging.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "io" - "log" - "net/http" - "os" - "strings" - "time" -) - -// This example shows how to create a filter that produces log lines -// according to the Common Log Format, also known as the NCSA standard. -// -// kindly contributed by leehambley -// -// GET http://localhost:8080/ping - -var logger *log.Logger = log.New(os.Stdout, "", 0) - -func NCSACommonLogFormatLogger() restful.FilterFunction { - return func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - var username = "-" - if req.Request.URL.User != nil { - if name := req.Request.URL.User.Username(); name != "" { - username = name - } - } - chain.ProcessFilter(req, resp) - logger.Printf("%s - %s [%s] \"%s %s %s\" %d %d", - strings.Split(req.Request.RemoteAddr, ":")[0], - username, - time.Now().Format("02/Jan/2006:15:04:05 -0700"), - req.Request.Method, - req.Request.URL.RequestURI(), - req.Request.Proto, - resp.StatusCode(), - resp.ContentLength(), - ) - } -} - -func main() { - ws := new(restful.WebService) - ws.Filter(NCSACommonLogFormatLogger()) - ws.Route(ws.GET("/ping").To(hello)) - restful.Add(ws) - http.ListenAndServe(":8080", nil) -} - -func hello(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "pong") -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-basic-authentication.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-basic-authentication.go deleted file mode 100644 index 5dd3067e9..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-basic-authentication.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "io" - "net/http" -) - -// This example shows how to create a (Route) Filter that performs Basic Authentication on the Http request. -// -// GET http://localhost:8080/secret -// and use admin,admin for the credentials - -func main() { - ws := new(restful.WebService) - ws.Route(ws.GET("/secret").Filter(basicAuthenticate).To(secret)) - restful.Add(ws) - http.ListenAndServe(":8080", nil) -} - -func basicAuthenticate(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - encoded := req.Request.Header.Get("Authorization") - // usr/pwd = admin/admin - // real code does some decoding - if len(encoded) == 0 || "Basic YWRtaW46YWRtaW4=" != encoded { - resp.AddHeader("WWW-Authenticate", "Basic realm=Protected Area") - resp.WriteErrorString(401, "401: Not Authorized") - return - } - chain.ProcessFilter(req, resp) -} - -func secret(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "42") -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-cpuprofiler-service.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-cpuprofiler-service.go deleted file mode 100644 index 9148213cf..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-cpuprofiler-service.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "io" - "log" - "os" - "runtime/pprof" -) - -// ProfilingService is a WebService that can start/stop a CPU profile and write results to a file -// GET /{rootPath}/start will activate CPU profiling -// GET /{rootPath}/stop will stop profiling -// -// NewProfileService("/profiler", "ace.prof").AddWebServiceTo(restful.DefaultContainer) -// -type ProfilingService struct { - rootPath string // the base (root) of the service, e.g. /profiler - cpuprofile string // the output filename to write profile results, e.g. myservice.prof - cpufile *os.File // if not nil, then profiling is active -} - -func NewProfileService(rootPath string, outputFilename string) *ProfilingService { - ps := new(ProfilingService) - ps.rootPath = rootPath - ps.cpuprofile = outputFilename - return ps -} - -// Add this ProfileService to a restful Container -func (p ProfilingService) AddWebServiceTo(container *restful.Container) { - ws := new(restful.WebService) - ws.Path(p.rootPath).Consumes("*/*").Produces(restful.MIME_JSON) - ws.Route(ws.GET("/start").To(p.startProfiler)) - ws.Route(ws.GET("/stop").To(p.stopProfiler)) - container.Add(ws) -} - -func (p *ProfilingService) startProfiler(req *restful.Request, resp *restful.Response) { - if p.cpufile != nil { - io.WriteString(resp.ResponseWriter, "[restful] CPU profiling already running") - return // error? - } - cpufile, err := os.Create(p.cpuprofile) - if err != nil { - log.Fatal(err) - } - // remember for close - p.cpufile = cpufile - pprof.StartCPUProfile(cpufile) - io.WriteString(resp.ResponseWriter, "[restful] CPU profiling started, writing on:"+p.cpuprofile) -} - -func (p *ProfilingService) stopProfiler(req *restful.Request, resp *restful.Response) { - if p.cpufile == nil { - io.WriteString(resp.ResponseWriter, "[restful] CPU profiling not active") - return // error? - } - pprof.StopCPUProfile() - p.cpufile.Close() - p.cpufile = nil - io.WriteString(resp.ResponseWriter, "[restful] CPU profiling stopped, closing:"+p.cpuprofile) -} - -func main() {} // exists for example compilation only diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-curly-router.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-curly-router.go deleted file mode 100644 index 1b95dd02b..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-curly-router.go +++ /dev/null @@ -1,107 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "log" - "net/http" -) - -// This example has the same service definition as restful-user-resource -// but uses a different router (CurlyRouter) that does not use regular expressions -// -// POST http://localhost:8080/users -// 1Melissa Raspberry -// -// GET http://localhost:8080/users/1 -// -// PUT http://localhost:8080/users/1 -// 1Melissa -// -// DELETE http://localhost:8080/users/1 -// - -type User struct { - Id, Name string -} - -type UserResource struct { - // normally one would use DAO (data access object) - users map[string]User -} - -func (u UserResource) Register(container *restful.Container) { - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well - - ws.Route(ws.GET("/{user-id}").To(u.findUser)) - ws.Route(ws.POST("").To(u.updateUser)) - ws.Route(ws.PUT("/{user-id}").To(u.createUser)) - ws.Route(ws.DELETE("/{user-id}").To(u.removeUser)) - - container.Add(ws) -} - -// GET http://localhost:8080/users/1 -// -func (u UserResource) findUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - usr := u.users[id] - if len(usr.Id) == 0 { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusNotFound, "User could not be found.") - } else { - response.WriteEntity(usr) - } -} - -// POST http://localhost:8080/users -// 1Melissa Raspberry -// -func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) { - usr := new(User) - err := request.ReadEntity(&usr) - if err == nil { - u.users[usr.Id] = *usr - response.WriteEntity(usr) - } else { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusInternalServerError, err.Error()) - } -} - -// PUT http://localhost:8080/users/1 -// 1Melissa -// -func (u *UserResource) createUser(request *restful.Request, response *restful.Response) { - usr := User{Id: request.PathParameter("user-id")} - err := request.ReadEntity(&usr) - if err == nil { - u.users[usr.Id] = usr - response.WriteHeader(http.StatusCreated) - response.WriteEntity(usr) - } else { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusInternalServerError, err.Error()) - } -} - -// DELETE http://localhost:8080/users/1 -// -func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - delete(u.users, id) -} - -func main() { - wsContainer := restful.NewContainer() - wsContainer.Router(restful.CurlyRouter{}) - u := UserResource{map[string]User{}} - u.Register(wsContainer) - - log.Printf("start listening on localhost:8080") - server := &http.Server{Addr: ":8080", Handler: wsContainer} - log.Fatal(server.ListenAndServe()) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-curly-router_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-curly-router_test.go deleted file mode 100644 index 9609eb31d..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-curly-router_test.go +++ /dev/null @@ -1,149 +0,0 @@ -package examples - -import ( - "bytes" - "fmt" - "log" - "net/http" - "testing" - "time" - - "github.com/emicklei/go-restful" -) - -type User struct { - Id, Name string -} - -type UserResource struct { - users map[string]User -} - -func (u UserResource) Register(container *restful.Container) { - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) - - ws.Route(ws.GET("/{user-id}").To(u.findUser)) - ws.Route(ws.POST("").To(u.updateUser)) - ws.Route(ws.PUT("/{user-id}").To(u.createUser)) - ws.Route(ws.DELETE("/{user-id}").To(u.removeUser)) - - container.Add(ws) -} - -// GET http://localhost:8090/users/1 -// -func (u UserResource) findUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - usr := u.users[id] - if len(usr.Id) == 0 { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusNotFound, "User could not be found.") - } else { - response.WriteEntity(usr) - } -} - -// POST http://localhost:8090/users -// 1Melissa Raspberry -// -func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) { - usr := new(User) - err := request.ReadEntity(&usr) - if err == nil { - u.users[usr.Id] = *usr - response.WriteEntity(usr) - } else { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusInternalServerError, err.Error()) - } -} - -// PUT http://localhost:8090/users/1 -// 1Melissa -// -func (u *UserResource) createUser(request *restful.Request, response *restful.Response) { - usr := User{Id: request.PathParameter("user-id")} - err := request.ReadEntity(&usr) - if err == nil { - u.users[usr.Id] = usr - response.WriteHeader(http.StatusCreated) - response.WriteEntity(usr) - } else { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusInternalServerError, err.Error()) - } -} - -// DELETE http://localhost:8090/users/1 -// -func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - delete(u.users, id) -} - -func RunRestfulCurlyRouterServer() { - wsContainer := restful.NewContainer() - wsContainer.Router(restful.CurlyRouter{}) - u := UserResource{map[string]User{}} - u.Register(wsContainer) - - log.Printf("start listening on localhost:8090") - server := &http.Server{Addr: ":8090", Handler: wsContainer} - log.Fatal(server.ListenAndServe()) -} - -func waitForServerUp(serverURL string) error { - for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) { - _, err := http.Get(serverURL + "/") - if err == nil { - return nil - } - } - return fmt.Errorf("waiting for server timed out") -} - -func TestServer(t *testing.T) { - serverURL := "http://localhost:8090" - go func() { - RunRestfulCurlyRouterServer() - }() - if err := waitForServerUp(serverURL); err != nil { - t.Errorf("%v", err) - } - - // GET should give a 405 - resp, err := http.Get(serverURL + "/users/") - if err != nil { - t.Errorf("unexpected error in GET /users/: %v", err) - } - if resp.StatusCode != http.StatusMethodNotAllowed { - t.Errorf("unexpected response: %v, expected: %v", resp.StatusCode, http.StatusOK) - } - - // Send a POST request. - var jsonStr = []byte(`{"id":"1","name":"user1"}`) - req, err := http.NewRequest("POST", serverURL+"/users/", bytes.NewBuffer(jsonStr)) - req.Header.Set("Content-Type", restful.MIME_JSON) - - client := &http.Client{} - resp, err = client.Do(req) - if err != nil { - t.Errorf("unexpected error in sending req: %v", err) - } - if resp.StatusCode != http.StatusOK { - t.Errorf("unexpected response: %v, expected: %v", resp.StatusCode, http.StatusOK) - } - - // Test that GET works. - resp, err = http.Get(serverURL + "/users/1") - if err != nil { - t.Errorf("unexpected error in GET /users/1: %v", err) - } - if resp.StatusCode != http.StatusOK { - t.Errorf("unexpected response: %v, expected: %v", resp.StatusCode, http.StatusOK) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-encoding-filter.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-encoding-filter.go deleted file mode 100644 index 6094c4909..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-encoding-filter.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "log" - "net/http" -) - -type User struct { - Id, Name string -} - -type UserList struct { - Users []User -} - -// -// This example shows how to use the CompressingResponseWriter by a Filter -// such that encoding can be enabled per WebService or per Route (instead of per container) -// Using restful.DefaultContainer.EnableContentEncoding(true) will encode all responses served by WebServices in the DefaultContainer. -// -// Set Accept-Encoding to gzip or deflate -// GET http://localhost:8080/users/42 -// and look at the response headers - -func main() { - restful.Add(NewUserService()) - log.Printf("start listening on localhost:8080") - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func NewUserService() *restful.WebService { - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) - - // install a response encoding filter - ws.Route(ws.GET("/{user-id}").Filter(encodingFilter).To(findUser)) - return ws -} - -// Route Filter (defines FilterFunction) -func encodingFilter(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - log.Printf("[encoding-filter] %s,%s\n", req.Request.Method, req.Request.URL) - // wrap responseWriter into a compressing one - compress, _ := restful.NewCompressingResponseWriter(resp.ResponseWriter, restful.ENCODING_GZIP) - resp.ResponseWriter = compress - defer func() { - compress.Close() - }() - chain.ProcessFilter(req, resp) -} - -// GET http://localhost:8080/users/42 -// -func findUser(request *restful.Request, response *restful.Response) { - log.Printf("findUser") - response.WriteEntity(User{"42", "Gandalf"}) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-filters.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-filters.go deleted file mode 100644 index 47e1146a0..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-filters.go +++ /dev/null @@ -1,114 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "log" - "net/http" - "time" -) - -type User struct { - Id, Name string -} - -type UserList struct { - Users []User -} - -// This example show how to create and use the three different Filters (Container,WebService and Route) -// When applied to the restful.DefaultContainer, we refer to them as a global filter. -// -// GET http://locahost:8080/users/42 -// and see the logging per filter (try repeating this request) - -func main() { - // install a global (=DefaultContainer) filter (processed before any webservice in the DefaultContainer) - restful.Filter(globalLogging) - - restful.Add(NewUserService()) - log.Printf("start listening on localhost:8080") - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func NewUserService() *restful.WebService { - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) - - // install a webservice filter (processed before any route) - ws.Filter(webserviceLogging).Filter(measureTime) - - // install a counter filter - ws.Route(ws.GET("").Filter(NewCountFilter().routeCounter).To(getAllUsers)) - - // install 2 chained route filters (processed before calling findUser) - ws.Route(ws.GET("/{user-id}").Filter(routeLogging).Filter(NewCountFilter().routeCounter).To(findUser)) - return ws -} - -// Global Filter -func globalLogging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - log.Printf("[global-filter (logger)] %s,%s\n", req.Request.Method, req.Request.URL) - chain.ProcessFilter(req, resp) -} - -// WebService Filter -func webserviceLogging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - log.Printf("[webservice-filter (logger)] %s,%s\n", req.Request.Method, req.Request.URL) - chain.ProcessFilter(req, resp) -} - -// WebService (post-process) Filter (as a struct that defines a FilterFunction) -func measureTime(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - now := time.Now() - chain.ProcessFilter(req, resp) - log.Printf("[webservice-filter (timer)] %v\n", time.Now().Sub(now)) -} - -// Route Filter (defines FilterFunction) -func routeLogging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - log.Printf("[route-filter (logger)] %s,%s\n", req.Request.Method, req.Request.URL) - chain.ProcessFilter(req, resp) -} - -// Route Filter (as a struct that defines a FilterFunction) -// CountFilter implements a FilterFunction for counting requests. -type CountFilter struct { - count int - counter chan int // for go-routine safe count increments -} - -// NewCountFilter creates and initializes a new CountFilter. -func NewCountFilter() *CountFilter { - c := new(CountFilter) - c.counter = make(chan int) - go func() { - for { - c.count += <-c.counter - } - }() - return c -} - -// routeCounter increments the count of the filter (through a channel) -func (c *CountFilter) routeCounter(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - c.counter <- 1 - log.Printf("[route-filter (counter)] count:%d", c.count) - chain.ProcessFilter(req, resp) -} - -// GET http://localhost:8080/users -// -func getAllUsers(request *restful.Request, response *restful.Response) { - log.Printf("getAllUsers") - response.WriteEntity(UserList{[]User{User{"42", "Gandalf"}, User{"3.14", "Pi"}}}) -} - -// GET http://localhost:8080/users/42 -// -func findUser(request *restful.Request, response *restful.Response) { - log.Printf("findUser") - response.WriteEntity(User{"42", "Gandalf"}) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-form-handling.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-form-handling.go deleted file mode 100644 index a83db4492..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-form-handling.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "fmt" - "github.com/emicklei/go-restful" - "github.com/gorilla/schema" - "io" - "net/http" -) - -// This example shows how to handle a POST of a HTML form that uses the standard x-www-form-urlencoded content-type. -// It uses the gorilla web tool kit schema package to decode the form data into a struct. -// -// GET http://localhost:8080/profiles -// - -type Profile struct { - Name string - Age int -} - -var decoder *schema.Decoder - -func main() { - decoder = schema.NewDecoder() - ws := new(restful.WebService) - ws.Route(ws.POST("/profiles").Consumes("application/x-www-form-urlencoded").To(postAdddress)) - ws.Route(ws.GET("/profiles").To(addresssForm)) - restful.Add(ws) - http.ListenAndServe(":8080", nil) -} - -func postAdddress(req *restful.Request, resp *restful.Response) { - err := req.Request.ParseForm() - if err != nil { - resp.WriteErrorString(http.StatusBadRequest, err.Error()) - return - } - p := new(Profile) - err = decoder.Decode(p, req.Request.PostForm) - if err != nil { - resp.WriteErrorString(http.StatusBadRequest, err.Error()) - return - } - io.WriteString(resp.ResponseWriter, fmt.Sprintf("Name=%s, Age=%d", p.Name, p.Age)) -} - -func addresssForm(req *restful.Request, resp *restful.Response) { - io.WriteString(resp.ResponseWriter, - ` - -

Enter Profile

-
- - - - - -
- - `) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-hello-world.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-hello-world.go deleted file mode 100644 index a21c2a69c..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-hello-world.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "io" - "net/http" -) - -// This example shows the minimal code needed to get a restful.WebService working. -// -// GET http://localhost:8080/hello - -func main() { - ws := new(restful.WebService) - ws.Route(ws.GET("/hello").To(hello)) - restful.Add(ws) - http.ListenAndServe(":8080", nil) -} - -func hello(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "world") -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-html-template.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-html-template.go deleted file mode 100644 index de51c5919..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-html-template.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "log" - "net/http" - "text/template" - - "github.com/emicklei/go-restful" -) - -// This example shows how to serve a HTML page using the standard Go template engine. -// -// GET http://localhost:8080/ - -func main() { - ws := new(restful.WebService) - ws.Route(ws.GET("/").To(home)) - restful.Add(ws) - print("open browser on http://localhost:8080/\n") - http.ListenAndServe(":8080", nil) -} - -type Message struct { - Text string -} - -func home(req *restful.Request, resp *restful.Response) { - p := &Message{"restful-html-template demo"} - // you might want to cache compiled templates - t, err := template.ParseFiles("home.html") - if err != nil { - log.Fatalf("Template gave: %s", err) - } - t.Execute(resp.ResponseWriter, p) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-multi-containers.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-multi-containers.go deleted file mode 100644 index 3f1650b36..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-multi-containers.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "io" - "log" - "net/http" -) - -// This example shows how to have a program with 2 WebServices containers -// each having a http server listening on its own port. -// -// The first "hello" is added to the restful.DefaultContainer (and uses DefaultServeMux) -// For the second "hello", a new container and ServeMux is created -// and requires a new http.Server with the container being the Handler. -// This first server is spawn in its own go-routine such that the program proceeds to create the second. -// -// GET http://localhost:8080/hello -// GET http://localhost:8081/hello - -func main() { - ws := new(restful.WebService) - ws.Route(ws.GET("/hello").To(hello)) - restful.Add(ws) - go func() { - http.ListenAndServe(":8080", nil) - }() - - container2 := restful.NewContainer() - ws2 := new(restful.WebService) - ws2.Route(ws2.GET("/hello").To(hello2)) - container2.Add(ws2) - server := &http.Server{Addr: ":8081", Handler: container2} - log.Fatal(server.ListenAndServe()) -} - -func hello(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "default world") -} - -func hello2(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "second world") -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-no-cache-filter.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-no-cache-filter.go deleted file mode 100644 index 04fae8dce..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-no-cache-filter.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "io" - "net/http" - - "github.com/emicklei/go-restful" -) - -func NoBrowserCacheFilter(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - resp.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1. - resp.Header().Set("Pragma", "no-cache") // HTTP 1.0. - resp.Header().Set("Expires", "0") // Proxies. - chain.ProcessFilter(req, resp) -} - -// This example shows how to use a WebService filter that passed the Http headers to disable browser cacheing. -// -// GET http://localhost:8080/hello - -func main() { - ws := new(restful.WebService) - ws.Filter(NoBrowserCacheFilter) - ws.Route(ws.GET("/hello").To(hello)) - restful.Add(ws) - http.ListenAndServe(":8080", nil) -} - -func hello(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "world") -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-options-filter.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-options-filter.go deleted file mode 100644 index 73dc3cfe5..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-options-filter.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "io" - "log" - "net/http" -) - -// This example shows how to use the OPTIONSFilter on a Container -// -// OPTIONS http://localhost:8080/users -// -// OPTIONS http://localhost:8080/users/1 - -type UserResource struct{} - -func (u UserResource) RegisterTo(container *restful.Container) { - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes("*/*"). - Produces("*/*") - - ws.Route(ws.GET("/{user-id}").To(u.nop)) - ws.Route(ws.POST("").To(u.nop)) - ws.Route(ws.PUT("/{user-id}").To(u.nop)) - ws.Route(ws.DELETE("/{user-id}").To(u.nop)) - - container.Add(ws) -} - -func (u UserResource) nop(request *restful.Request, response *restful.Response) { - io.WriteString(response.ResponseWriter, "this would be a normal response") -} - -func main() { - wsContainer := restful.NewContainer() - u := UserResource{} - u.RegisterTo(wsContainer) - - // Add container filter to respond to OPTIONS - wsContainer.Filter(wsContainer.OPTIONSFilter) - - // For use on the default container, you can write - // restful.Filter(restful.OPTIONSFilter()) - - log.Printf("start listening on localhost:8080") - server := &http.Server{Addr: ":8080", Handler: wsContainer} - log.Fatal(server.ListenAndServe()) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-path-tail.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-path-tail.go deleted file mode 100644 index 8488a232c..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-path-tail.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "io" - "net/http" - . "github.com/emicklei/go-restful" -) - -// This example shows how to a Route that matches the "tail" of a path. -// Requires the use of a CurlyRouter and the star "*" path parameter pattern. -// -// GET http://localhost:8080/basepath/some/other/location/test.xml - -func main() { - DefaultContainer.Router(CurlyRouter{}) - ws := new(WebService) - ws.Route(ws.GET("/basepath/{resource:*}").To(staticFromPathParam)) - Add(ws) - - println("[go-restful] serve path tails from http://localhost:8080/basepath") - http.ListenAndServe(":8080", nil) -} - -func staticFromPathParam(req *Request, resp *Response) { - io.WriteString(resp, "Tail="+req.PathParameter("resource")) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-pre-post-filters.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-pre-post-filters.go deleted file mode 100644 index 0b55f1493..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-pre-post-filters.go +++ /dev/null @@ -1,98 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "io" - "log" - "net/http" -) - -// This example shows how the different types of filters are called in the request-response flow. -// The call chain is logged on the console when sending an http request. -// -// GET http://localhost:8080/1 -// GET http://localhost:8080/2 - -var indentLevel int - -func container_filter_A(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - log.Printf("url path:%v\n", req.Request.URL) - trace("container_filter_A: before", 1) - chain.ProcessFilter(req, resp) - trace("container_filter_A: after", -1) -} - -func container_filter_B(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - trace("container_filter_B: before", 1) - chain.ProcessFilter(req, resp) - trace("container_filter_B: after", -1) -} - -func service_filter_A(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - trace("service_filter_A: before", 1) - chain.ProcessFilter(req, resp) - trace("service_filter_A: after", -1) -} - -func service_filter_B(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - trace("service_filter_B: before", 1) - chain.ProcessFilter(req, resp) - trace("service_filter_B: after", -1) -} - -func route_filter_A(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - trace("route_filter_A: before", 1) - chain.ProcessFilter(req, resp) - trace("route_filter_A: after", -1) -} - -func route_filter_B(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) { - trace("route_filter_B: before", 1) - chain.ProcessFilter(req, resp) - trace("route_filter_B: after", -1) -} - -func trace(what string, delta int) { - indented := what - if delta < 0 { - indentLevel += delta - } - for t := 0; t < indentLevel; t++ { - indented = "." + indented - } - log.Printf("%s", indented) - if delta > 0 { - indentLevel += delta - } -} - -func main() { - restful.Filter(container_filter_A) - restful.Filter(container_filter_B) - - ws1 := new(restful.WebService) - ws1.Path("/1") - ws1.Filter(service_filter_A) - ws1.Filter(service_filter_B) - ws1.Route(ws1.GET("").To(doit1).Filter(route_filter_A).Filter(route_filter_B)) - - ws2 := new(restful.WebService) - ws2.Path("/2") - ws2.Filter(service_filter_A) - ws2.Filter(service_filter_B) - ws2.Route(ws2.GET("").To(doit2).Filter(route_filter_A).Filter(route_filter_B)) - - restful.Add(ws1) - restful.Add(ws2) - - log.Print("go-restful example listing on http://localhost:8080/1 and http://localhost:8080/2") - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func doit1(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "nothing to see in 1") -} - -func doit2(req *restful.Request, resp *restful.Response) { - io.WriteString(resp, "nothing to see in 2") -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-resource-functions.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-resource-functions.go deleted file mode 100644 index fb1012a02..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-resource-functions.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "github.com/emicklei/go-restful" - "log" - "net/http" -) - -// This example shows how to use methods as RouteFunctions for WebServices. -// The ProductResource has a Register() method that creates and initializes -// a WebService to expose its methods as REST operations. -// The WebService is added to the restful.DefaultContainer. -// A ProductResource is typically created using some data access object. -// -// GET http://localhost:8080/products/1 -// POST http://localhost:8080/products -// 1The First - -type Product struct { - Id, Title string -} - -type ProductResource struct { - // typically reference a DAO (data-access-object) -} - -func (p ProductResource) getOne(req *restful.Request, resp *restful.Response) { - id := req.PathParameter("id") - log.Println("getting product with id:" + id) - resp.WriteEntity(Product{Id: id, Title: "test"}) -} - -func (p ProductResource) postOne(req *restful.Request, resp *restful.Response) { - updatedProduct := new(Product) - err := req.ReadEntity(updatedProduct) - if err != nil { // bad request - resp.WriteErrorString(http.StatusBadRequest, err.Error()) - return - } - log.Println("updating product with id:" + updatedProduct.Id) -} - -func (p ProductResource) Register() { - ws := new(restful.WebService) - ws.Path("/products") - ws.Consumes(restful.MIME_XML) - ws.Produces(restful.MIME_XML) - - ws.Route(ws.GET("/{id}").To(p.getOne). - Doc("get the product by its id"). - Param(ws.PathParameter("id", "identifier of the product").DataType("string"))) - - ws.Route(ws.POST("").To(p.postOne). - Doc("update or create a product"). - Param(ws.BodyParameter("Product", "a Product (XML)").DataType("main.Product"))) - - restful.Add(ws) -} - -func main() { - ProductResource{}.Register() - http.ListenAndServe(":8080", nil) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-route_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-route_test.go deleted file mode 100644 index 20c366bf9..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-route_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/emicklei/go-restful" -) - -var ( - Result string -) - -func TestRouteExtractParameter(t *testing.T) { - // setup service - ws := new(restful.WebService) - ws.Consumes(restful.MIME_XML) - ws.Route(ws.GET("/test/{param}").To(DummyHandler)) - restful.Add(ws) - - // setup request + writer - bodyReader := strings.NewReader("42") - httpRequest, _ := http.NewRequest("GET", "/test/THIS", bodyReader) - httpRequest.Header.Set("Content-Type", restful.MIME_XML) - httpWriter := httptest.NewRecorder() - - // run - restful.DefaultContainer.ServeHTTP(httpWriter, httpRequest) - - if Result != "THIS" { - t.Fatalf("Result is actually: %s", Result) - } -} - -func DummyHandler(rq *restful.Request, rp *restful.Response) { - Result = rq.PathParameter("param") -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-routefunction_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-routefunction_test.go deleted file mode 100644 index 957c05550..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-routefunction_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/emicklei/go-restful" -) - -// This example show how to test one particular RouteFunction (getIt) -// It uses the httptest.ResponseRecorder to capture output - -func getIt(req *restful.Request, resp *restful.Response) { - resp.WriteHeader(204) -} - -func TestCallFunction(t *testing.T) { - httpReq, _ := http.NewRequest("GET", "/", nil) - req := restful.NewRequest(httpReq) - - recorder := new(httptest.ResponseRecorder) - resp := restful.NewResponse(recorder) - - getIt(req, resp) - if recorder.Code != 204 { - t.Fatalf("Missing or wrong status code:%d", recorder.Code) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-serve-static.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-serve-static.go deleted file mode 100644 index 8cb7848c1..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-serve-static.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "path" - - "github.com/emicklei/go-restful" -) - -// This example shows how to define methods that serve static files -// It uses the standard http.ServeFile method -// -// GET http://localhost:8080/static/test.xml -// GET http://localhost:8080/static/ -// -// GET http://localhost:8080/static?resource=subdir/test.xml - -var rootdir = "/tmp" - -func main() { - restful.DefaultContainer.Router(restful.CurlyRouter{}) - - ws := new(restful.WebService) - ws.Route(ws.GET("/static/{subpath:*}").To(staticFromPathParam)) - ws.Route(ws.GET("/static").To(staticFromQueryParam)) - restful.Add(ws) - - println("[go-restful] serving files on http://localhost:8080/static from local /tmp") - http.ListenAndServe(":8080", nil) -} - -func staticFromPathParam(req *restful.Request, resp *restful.Response) { - actual := path.Join(rootdir, req.PathParameter("subpath")) - fmt.Printf("serving %s ... (from %s)\n", actual, req.PathParameter("subpath")) - http.ServeFile( - resp.ResponseWriter, - req.Request, - actual) -} - -func staticFromQueryParam(req *restful.Request, resp *restful.Response) { - http.ServeFile( - resp.ResponseWriter, - req.Request, - path.Join(rootdir, req.QueryParameter("resource"))) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-swagger.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-swagger.go deleted file mode 100644 index 7746b5b07..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-swagger.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "log" - "net/http" - - "github.com/emicklei/go-restful" - "github.com/emicklei/go-restful/swagger" -) - -type Book struct { - Title string - Author string -} - -func main() { - ws := new(restful.WebService) - ws.Path("/books") - ws.Consumes(restful.MIME_JSON, restful.MIME_XML) - ws.Produces(restful.MIME_JSON, restful.MIME_XML) - restful.Add(ws) - - ws.Route(ws.GET("/{medium}").To(noop). - Doc("Search all books"). - Param(ws.PathParameter("medium", "digital or paperback").DataType("string")). - Param(ws.QueryParameter("language", "en,nl,de").DataType("string")). - Param(ws.HeaderParameter("If-Modified-Since", "last known timestamp").DataType("datetime")). - Do(returns200, returns500)) - - ws.Route(ws.PUT("/{medium}").To(noop). - Doc("Add a new book"). - Param(ws.PathParameter("medium", "digital or paperback").DataType("string")). - Reads(Book{})) - - // You can install the Swagger Service which provides a nice Web UI on your REST API - // You need to download the Swagger HTML5 assets and change the FilePath location in the config below. - // Open http://localhost:8080/apidocs and enter http://localhost:8080/apidocs.json in the api input field. - config := swagger.Config{ - WebServices: restful.DefaultContainer.RegisteredWebServices(), // you control what services are visible - WebServicesUrl: "http://localhost:8080", - ApiPath: "/apidocs.json", - - // Optionally, specifiy where the UI is located - SwaggerPath: "/apidocs/", - SwaggerFilePath: "/Users/emicklei/xProjects/swagger-ui/dist"} - swagger.RegisterSwaggerService(config, restful.DefaultContainer) - - log.Printf("start listening on localhost:8080") - server := &http.Server{Addr: ":8080", Handler: restful.DefaultContainer} - log.Fatal(server.ListenAndServe()) -} - -func noop(req *restful.Request, resp *restful.Response) {} - -func returns200(b *restful.RouteBuilder) { - b.Returns(http.StatusOK, "OK", Book{}) -} - -func returns500(b *restful.RouteBuilder) { - b.Returns(http.StatusInternalServerError, "Bummer, something went wrong", nil) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-user-resource.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-user-resource.go deleted file mode 100644 index 6b860dc20..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-user-resource.go +++ /dev/null @@ -1,152 +0,0 @@ -package main - -import ( - "log" - "net/http" - "strconv" - - "github.com/emicklei/go-restful" - "github.com/emicklei/go-restful/swagger" -) - -// This example show a complete (GET,PUT,POST,DELETE) conventional example of -// a REST Resource including documentation to be served by e.g. a Swagger UI -// It is recommended to create a Resource struct (UserResource) that can encapsulate -// an object that provide domain access (a DAO) -// It has a Register method including the complete Route mapping to methods together -// with all the appropriate documentation -// -// POST http://localhost:8080/users -// 1Melissa Raspberry -// -// GET http://localhost:8080/users/1 -// -// PUT http://localhost:8080/users/1 -// 1Melissa -// -// DELETE http://localhost:8080/users/1 -// - -type User struct { - Id, Name string -} - -type UserResource struct { - // normally one would use DAO (data access object) - users map[string]User -} - -func (u UserResource) Register(container *restful.Container) { - ws := new(restful.WebService) - ws. - Path("/users"). - Doc("Manage Users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well - - ws.Route(ws.GET("/{user-id}").To(u.findUser). - // docs - Doc("get a user"). - Operation("findUser"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). - Writes(User{})) // on the response - - ws.Route(ws.PUT("/{user-id}").To(u.updateUser). - // docs - Doc("update a user"). - Operation("updateUser"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). - ReturnsError(409, "duplicate user-id", nil). - Reads(User{})) // from the request - - ws.Route(ws.POST("").To(u.createUser). - // docs - Doc("create a user"). - Operation("createUser"). - Reads(User{})) // from the request - - ws.Route(ws.DELETE("/{user-id}").To(u.removeUser). - // docs - Doc("delete a user"). - Operation("removeUser"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string"))) - - container.Add(ws) -} - -// GET http://localhost:8080/users/1 -// -func (u UserResource) findUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - usr := u.users[id] - if len(usr.Id) == 0 { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusNotFound, "404: User could not be found.") - return - } - response.WriteEntity(usr) -} - -// POST http://localhost:8080/users -// Melissa -// -func (u *UserResource) createUser(request *restful.Request, response *restful.Response) { - usr := new(User) - err := request.ReadEntity(usr) - if err != nil { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusInternalServerError, err.Error()) - return - } - usr.Id = strconv.Itoa(len(u.users) + 1) // simple id generation - u.users[usr.Id] = *usr - response.WriteHeaderAndEntity(http.StatusCreated, usr) -} - -// PUT http://localhost:8080/users/1 -// 1Melissa Raspberry -// -func (u *UserResource) updateUser(request *restful.Request, response *restful.Response) { - usr := new(User) - err := request.ReadEntity(&usr) - if err != nil { - response.AddHeader("Content-Type", "text/plain") - response.WriteErrorString(http.StatusInternalServerError, err.Error()) - return - } - u.users[usr.Id] = *usr - response.WriteEntity(usr) -} - -// DELETE http://localhost:8080/users/1 -// -func (u *UserResource) removeUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - delete(u.users, id) -} - -func main() { - // to see what happens in the package, uncomment the following - //restful.TraceLogger(log.New(os.Stdout, "[restful] ", log.LstdFlags|log.Lshortfile)) - - wsContainer := restful.NewContainer() - u := UserResource{map[string]User{}} - u.Register(wsContainer) - - // Optionally, you can install the Swagger Service which provides a nice Web UI on your REST API - // You need to download the Swagger HTML5 assets and change the FilePath location in the config below. - // Open http://localhost:8080/apidocs and enter http://localhost:8080/apidocs.json in the api input field. - config := swagger.Config{ - WebServices: wsContainer.RegisteredWebServices(), // you control what services are visible - WebServicesUrl: "http://localhost:8080", - ApiPath: "/apidocs.json", - - // Optionally, specifiy where the UI is located - SwaggerPath: "/apidocs/", - SwaggerFilePath: "/Users/emicklei/xProjects/swagger-ui/dist"} - swagger.RegisterSwaggerService(config, wsContainer) - - log.Printf("start listening on localhost:8080") - server := &http.Server{Addr: ":8080", Handler: wsContainer} - log.Fatal(server.ListenAndServe()) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-user-service.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-user-service.go deleted file mode 100644 index 77c678ce4..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/examples/restful-user-service.go +++ /dev/null @@ -1,137 +0,0 @@ -package main - -import ( - "log" - "net/http" - - "github.com/emicklei/go-restful" - "github.com/emicklei/go-restful/swagger" -) - -// This example is functionally the same as the example in restful-user-resource.go -// with the only difference that is served using the restful.DefaultContainer - -type User struct { - Id, Name string -} - -type UserService struct { - // normally one would use DAO (data access object) - users map[string]User -} - -func (u UserService) Register() { - ws := new(restful.WebService) - ws. - Path("/users"). - Consumes(restful.MIME_XML, restful.MIME_JSON). - Produces(restful.MIME_JSON, restful.MIME_XML) // you can specify this per route as well - - ws.Route(ws.GET("/").To(u.findAllUsers). - // docs - Doc("get all users"). - Operation("findAllUsers"). - Returns(200, "OK", []User{})) - - ws.Route(ws.GET("/{user-id}").To(u.findUser). - // docs - Doc("get a user"). - Operation("findUser"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). - Writes(User{})) // on the response - - ws.Route(ws.PUT("/{user-id}").To(u.updateUser). - // docs - Doc("update a user"). - Operation("updateUser"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string")). - Reads(User{})) // from the request - - ws.Route(ws.PUT("").To(u.createUser). - // docs - Doc("create a user"). - Operation("createUser"). - Reads(User{})) // from the request - - ws.Route(ws.DELETE("/{user-id}").To(u.removeUser). - // docs - Doc("delete a user"). - Operation("removeUser"). - Param(ws.PathParameter("user-id", "identifier of the user").DataType("string"))) - - restful.Add(ws) -} - -// GET http://localhost:8080/users -// -func (u UserService) findAllUsers(request *restful.Request, response *restful.Response) { - response.WriteEntity(u.users) -} - -// GET http://localhost:8080/users/1 -// -func (u UserService) findUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - usr := u.users[id] - if len(usr.Id) == 0 { - response.WriteErrorString(http.StatusNotFound, "User could not be found.") - } else { - response.WriteEntity(usr) - } -} - -// PUT http://localhost:8080/users/1 -// 1Melissa Raspberry -// -func (u *UserService) updateUser(request *restful.Request, response *restful.Response) { - usr := new(User) - err := request.ReadEntity(&usr) - if err == nil { - u.users[usr.Id] = *usr - response.WriteEntity(usr) - } else { - response.WriteError(http.StatusInternalServerError, err) - } -} - -// PUT http://localhost:8080/users/1 -// 1Melissa -// -func (u *UserService) createUser(request *restful.Request, response *restful.Response) { - usr := User{Id: request.PathParameter("user-id")} - err := request.ReadEntity(&usr) - if err == nil { - u.users[usr.Id] = usr - response.WriteHeaderAndEntity(http.StatusCreated, usr) - } else { - response.WriteError(http.StatusInternalServerError, err) - } -} - -// DELETE http://localhost:8080/users/1 -// -func (u *UserService) removeUser(request *restful.Request, response *restful.Response) { - id := request.PathParameter("user-id") - delete(u.users, id) -} - -func main() { - u := UserService{map[string]User{}} - u.Register() - - // Optionally, you can install the Swagger Service which provides a nice Web UI on your REST API - // You need to download the Swagger HTML5 assets and change the FilePath location in the config below. - // Open http://localhost:8080/apidocs and enter http://localhost:8080/apidocs.json in the api input field. - config := swagger.Config{ - WebServices: restful.RegisteredWebServices(), // you control what services are visible - WebServicesUrl: "http://localhost:8080", - ApiPath: "/apidocs.json", - - // Optionally, specifiy where the UI is located - SwaggerPath: "/apidocs/", - SwaggerFilePath: "/Users/emicklei/Projects/swagger-ui/dist"} - swagger.InstallSwaggerService(config) - - log.Printf("start listening on localhost:8080") - log.Fatal(http.ListenAndServe(":8080", nil)) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/filter_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/filter_test.go deleted file mode 100644 index fadfb570f..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/filter_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package restful - -import ( - "io" - "net/http" - "net/http/httptest" - "testing" -) - -func setupServices(addGlobalFilter bool, addServiceFilter bool, addRouteFilter bool) { - if addGlobalFilter { - Filter(globalFilter) - } - Add(newTestService(addServiceFilter, addRouteFilter)) -} - -func tearDown() { - DefaultContainer.webServices = []*WebService{} - DefaultContainer.isRegisteredOnRoot = true // this allows for setupServices multiple times - DefaultContainer.containerFilters = []FilterFunction{} -} - -func newTestService(addServiceFilter bool, addRouteFilter bool) *WebService { - ws := new(WebService).Path("") - if addServiceFilter { - ws.Filter(serviceFilter) - } - rb := ws.GET("/foo").To(foo) - if addRouteFilter { - rb.Filter(routeFilter) - } - ws.Route(rb) - ws.Route(ws.GET("/bar").To(bar)) - return ws -} - -func foo(req *Request, resp *Response) { - io.WriteString(resp.ResponseWriter, "foo") -} - -func bar(req *Request, resp *Response) { - io.WriteString(resp.ResponseWriter, "bar") -} - -func fail(req *Request, resp *Response) { - http.Error(resp.ResponseWriter, "something failed", http.StatusInternalServerError) -} - -func globalFilter(req *Request, resp *Response, chain *FilterChain) { - io.WriteString(resp.ResponseWriter, "global-") - chain.ProcessFilter(req, resp) -} - -func serviceFilter(req *Request, resp *Response, chain *FilterChain) { - io.WriteString(resp.ResponseWriter, "service-") - chain.ProcessFilter(req, resp) -} - -func routeFilter(req *Request, resp *Response, chain *FilterChain) { - io.WriteString(resp.ResponseWriter, "route-") - chain.ProcessFilter(req, resp) -} - -func TestNoFilter(t *testing.T) { - tearDown() - setupServices(false, false, false) - actual := sendIt("http://example.com/foo") - if "foo" != actual { - t.Fatal("expected: foo but got:" + actual) - } -} - -func TestGlobalFilter(t *testing.T) { - tearDown() - setupServices(true, false, false) - actual := sendIt("http://example.com/foo") - if "global-foo" != actual { - t.Fatal("expected: global-foo but got:" + actual) - } -} - -func TestWebServiceFilter(t *testing.T) { - tearDown() - setupServices(true, true, false) - actual := sendIt("http://example.com/foo") - if "global-service-foo" != actual { - t.Fatal("expected: global-service-foo but got:" + actual) - } -} - -func TestRouteFilter(t *testing.T) { - tearDown() - setupServices(true, true, true) - actual := sendIt("http://example.com/foo") - if "global-service-route-foo" != actual { - t.Fatal("expected: global-service-route-foo but got:" + actual) - } -} - -func TestRouteFilterOnly(t *testing.T) { - tearDown() - setupServices(false, false, true) - actual := sendIt("http://example.com/foo") - if "route-foo" != actual { - t.Fatal("expected: route-foo but got:" + actual) - } -} - -func TestBar(t *testing.T) { - tearDown() - setupServices(false, true, false) - actual := sendIt("http://example.com/bar") - if "service-bar" != actual { - t.Fatal("expected: service-bar but got:" + actual) - } -} - -func TestAllFiltersBar(t *testing.T) { - tearDown() - setupServices(true, true, true) - actual := sendIt("http://example.com/bar") - if "global-service-bar" != actual { - t.Fatal("expected: global-service-bar but got:" + actual) - } -} - -func sendIt(address string) string { - httpRequest, _ := http.NewRequest("GET", address, nil) - httpRequest.Header.Set("Accept", "*/*") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - return httpWriter.Body.String() -} - -func sendItTo(address string, container *Container) string { - httpRequest, _ := http.NewRequest("GET", address, nil) - httpRequest.Header.Set("Accept", "*/*") - httpWriter := httptest.NewRecorder() - container.dispatch(httpWriter, httpRequest) - return httpWriter.Body.String() -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/jsr311_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/jsr311_test.go deleted file mode 100644 index 3e79a6def..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/jsr311_test.go +++ /dev/null @@ -1,212 +0,0 @@ -package restful - -import ( - "io" - "sort" - "testing" -) - -// -// Step 1 tests -// -var paths = []struct { - // url with path (1) is handled by service with root (2) and last capturing group has value final (3) - path, root, final string -}{ - {"/", "/", "/"}, - {"/p", "/p", ""}, - {"/p/x", "/p/{q}", ""}, - {"/q/x", "/q", "/x"}, - {"/p/x/", "/p/{q}", "/"}, - {"/p/x/y", "/p/{q}", "/y"}, - {"/q/x/y", "/q", "/x/y"}, - {"/z/q", "/{p}/q", ""}, - {"/a/b/c/q", "/", "/a/b/c/q"}, -} - -func TestDetectDispatcher(t *testing.T) { - ws1 := new(WebService).Path("/") - ws2 := new(WebService).Path("/p") - ws3 := new(WebService).Path("/q") - ws4 := new(WebService).Path("/p/q") - ws5 := new(WebService).Path("/p/{q}") - ws6 := new(WebService).Path("/p/{q}/") - ws7 := new(WebService).Path("/{p}/q") - var dispatchers = []*WebService{ws1, ws2, ws3, ws4, ws5, ws6, ws7} - - wc := NewContainer() - for _, each := range dispatchers { - wc.Add(each) - } - - router := RouterJSR311{} - - ok := true - for i, fixture := range paths { - who, final, err := router.detectDispatcher(fixture.path, dispatchers) - if err != nil { - t.Logf("error in detection:%v", err) - ok = false - } - if who.RootPath() != fixture.root { - t.Logf("[line:%v] Unexpected dispatcher, expected:%v, actual:%v", i, fixture.root, who.RootPath()) - ok = false - } - if final != fixture.final { - t.Logf("[line:%v] Unexpected final, expected:%v, actual:%v", i, fixture.final, final) - ok = false - } - } - if !ok { - t.Fail() - } -} - -// -// Step 2 tests -// - -// go test -v -test.run TestISSUE_179 ...restful -func TestISSUE_179(t *testing.T) { - ws1 := new(WebService) - ws1.Route(ws1.GET("/v1/category/{param:*}").To(dummy)) - routes := RouterJSR311{}.selectRoutes(ws1, "/v1/category/sub/sub") - t.Logf("%v", routes) -} - -// go test -v -test.run TestISSUE_30 ...restful -func TestISSUE_30(t *testing.T) { - ws1 := new(WebService).Path("/users") - ws1.Route(ws1.GET("/{id}").To(dummy)) - ws1.Route(ws1.POST("/login").To(dummy)) - routes := RouterJSR311{}.selectRoutes(ws1, "/login") - if len(routes) != 2 { - t.Fatal("expected 2 routes") - } - if routes[0].Path != "/users/login" { - t.Error("first is", routes[0].Path) - t.Logf("routes:%v", routes) - } -} - -// go test -v -test.run TestISSUE_34 ...restful -func TestISSUE_34(t *testing.T) { - ws1 := new(WebService).Path("/") - ws1.Route(ws1.GET("/{type}/{id}").To(dummy)) - ws1.Route(ws1.GET("/network/{id}").To(dummy)) - routes := RouterJSR311{}.selectRoutes(ws1, "/network/12") - if len(routes) != 2 { - t.Fatal("expected 2 routes") - } - if routes[0].Path != "/network/{id}" { - t.Error("first is", routes[0].Path) - t.Logf("routes:%v", routes) - } -} - -// go test -v -test.run TestISSUE_34_2 ...restful -func TestISSUE_34_2(t *testing.T) { - ws1 := new(WebService).Path("/") - // change the registration order - ws1.Route(ws1.GET("/network/{id}").To(dummy)) - ws1.Route(ws1.GET("/{type}/{id}").To(dummy)) - routes := RouterJSR311{}.selectRoutes(ws1, "/network/12") - if len(routes) != 2 { - t.Fatal("expected 2 routes") - } - if routes[0].Path != "/network/{id}" { - t.Error("first is", routes[0].Path) - } -} - -// go test -v -test.run TestISSUE_137 ...restful -func TestISSUE_137(t *testing.T) { - ws1 := new(WebService) - ws1.Route(ws1.GET("/hello").To(dummy)) - routes := RouterJSR311{}.selectRoutes(ws1, "/") - t.Log(routes) - if len(routes) > 0 { - t.Error("no route expected") - } -} - -func TestSelectRoutesSlash(t *testing.T) { - ws1 := new(WebService).Path("/") - ws1.Route(ws1.GET("").To(dummy)) - ws1.Route(ws1.GET("/").To(dummy)) - ws1.Route(ws1.GET("/u").To(dummy)) - ws1.Route(ws1.POST("/u").To(dummy)) - ws1.Route(ws1.POST("/u/v").To(dummy)) - ws1.Route(ws1.POST("/u/{w}").To(dummy)) - ws1.Route(ws1.POST("/u/{w}/z").To(dummy)) - routes := RouterJSR311{}.selectRoutes(ws1, "/u") - checkRoutesContains(routes, "/u", t) - checkRoutesContainsNo(routes, "/u/v", t) - checkRoutesContainsNo(routes, "/", t) - checkRoutesContainsNo(routes, "/u/{w}/z", t) -} -func TestSelectRoutesU(t *testing.T) { - ws1 := new(WebService).Path("/u") - ws1.Route(ws1.GET("").To(dummy)) - ws1.Route(ws1.GET("/").To(dummy)) - ws1.Route(ws1.GET("/v").To(dummy)) - ws1.Route(ws1.POST("/{w}").To(dummy)) - ws1.Route(ws1.POST("/{w}/z").To(dummy)) // so full path = /u/{w}/z - routes := RouterJSR311{}.selectRoutes(ws1, "/v") // test against /u/v - checkRoutesContains(routes, "/u/{w}", t) -} - -func TestSelectRoutesUsers1(t *testing.T) { - ws1 := new(WebService).Path("/users") - ws1.Route(ws1.POST("").To(dummy)) - ws1.Route(ws1.POST("/").To(dummy)) - ws1.Route(ws1.PUT("/{id}").To(dummy)) - routes := RouterJSR311{}.selectRoutes(ws1, "/1") - checkRoutesContains(routes, "/users/{id}", t) -} -func checkRoutesContains(routes []Route, path string, t *testing.T) { - if !containsRoutePath(routes, path, t) { - for _, r := range routes { - t.Logf("route %v %v", r.Method, r.Path) - } - t.Fatalf("routes should include [%v]:", path) - } -} -func checkRoutesContainsNo(routes []Route, path string, t *testing.T) { - if containsRoutePath(routes, path, t) { - for _, r := range routes { - t.Logf("route %v %v", r.Method, r.Path) - } - t.Fatalf("routes should not include [%v]:", path) - } -} -func containsRoutePath(routes []Route, path string, t *testing.T) bool { - for _, each := range routes { - if each.Path == path { - return true - } - } - return false -} - -// go test -v -test.run TestSortableRouteCandidates ...restful -func TestSortableRouteCandidates(t *testing.T) { - fixture := &sortableRouteCandidates{} - r1 := routeCandidate{matchesCount: 0, literalCount: 0, nonDefaultCount: 0} - r2 := routeCandidate{matchesCount: 0, literalCount: 0, nonDefaultCount: 1} - r3 := routeCandidate{matchesCount: 0, literalCount: 1, nonDefaultCount: 1} - r4 := routeCandidate{matchesCount: 1, literalCount: 1, nonDefaultCount: 0} - r5 := routeCandidate{matchesCount: 1, literalCount: 0, nonDefaultCount: 0} - fixture.candidates = append(fixture.candidates, r5, r4, r3, r2, r1) - sort.Sort(sort.Reverse(fixture)) - first := fixture.candidates[0] - if first.matchesCount != 1 && first.literalCount != 1 && first.nonDefaultCount != 0 { - t.Fatal("expected r4") - } - last := fixture.candidates[len(fixture.candidates)-1] - if last.matchesCount != 0 && last.literalCount != 0 && last.nonDefaultCount != 0 { - t.Fatal("expected r1") - } -} - -func dummy(req *Request, resp *Response) { io.WriteString(resp.ResponseWriter, "dummy") } diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/mime_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/mime_test.go deleted file mode 100644 index a910bb100..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/mime_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package restful - -import ( - "fmt" - "testing" -) - -// go test -v -test.run TestSortMimes ...restful -func TestSortMimes(t *testing.T) { - accept := "text/html; q=0.8, text/plain, image/gif, */*; q=0.01, image/jpeg" - result := sortedMimes(accept) - got := fmt.Sprintf("%v", result) - want := "[{text/plain 1} {image/gif 1} {image/jpeg 1} {text/html 0.8} {*/* 0.01}]" - if got != want { - t.Errorf("bad sort order of mime types:%s", got) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/options_filter_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/options_filter_test.go deleted file mode 100644 index f0fceb834..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/options_filter_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package restful - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -// go test -v -test.run TestOptionsFilter ...restful -func TestOptionsFilter(t *testing.T) { - tearDown() - ws := new(WebService) - ws.Route(ws.GET("/candy/{kind}").To(dummy)) - ws.Route(ws.DELETE("/candy/{kind}").To(dummy)) - ws.Route(ws.POST("/candies").To(dummy)) - Add(ws) - Filter(OPTIONSFilter()) - - httpRequest, _ := http.NewRequest("OPTIONS", "http://here.io/candy/gum", nil) - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - actual := httpWriter.Header().Get(HEADER_Allow) - if "GET,DELETE" != actual { - t.Fatal("expected: GET,DELETE but got:" + actual) - } - - httpRequest, _ = http.NewRequest("OPTIONS", "http://here.io/candies", nil) - httpWriter = httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - actual = httpWriter.Header().Get(HEADER_Allow) - if "POST" != actual { - t.Fatal("expected: POST but got:" + actual) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/path_expression_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/path_expression_test.go deleted file mode 100644 index 334fcef73..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/path_expression_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package restful - -import "testing" - -var tempregexs = []struct { - template, regex string - literalCount, varCount int -}{ - {"", "^(/.*)?$", 0, 0}, - {"/a/{b}/c/", "^/a/([^/]+?)/c(/.*)?$", 2, 1}, - {"/{a}/{b}/{c-d-e}/", "^/([^/]+?)/([^/]+?)/([^/]+?)(/.*)?$", 0, 3}, - {"/{p}/abcde", "^/([^/]+?)/abcde(/.*)?$", 5, 1}, - {"/a/{b:*}", "^/a/(.*)(/.*)?$", 1, 1}, - {"/a/{b:[a-z]+}", "^/a/([a-z]+)(/.*)?$", 1, 1}, -} - -func TestTemplateToRegularExpression(t *testing.T) { - ok := true - for i, fixture := range tempregexs { - actual, lCount, vCount, _ := templateToRegularExpression(fixture.template) - if actual != fixture.regex { - t.Logf("regex mismatch, expected:%v , actual:%v, line:%v\n", fixture.regex, actual, i) // 11 = where the data starts - ok = false - } - if lCount != fixture.literalCount { - t.Logf("literal count mismatch, expected:%v , actual:%v, line:%v\n", fixture.literalCount, lCount, i) - ok = false - } - if vCount != fixture.varCount { - t.Logf("variable count mismatch, expected:%v , actual:%v, line:%v\n", fixture.varCount, vCount, i) - ok = false - } - } - if !ok { - t.Fatal("one or more expression did not match") - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/request_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/request_test.go deleted file mode 100644 index 72f078f92..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/request_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package restful - -import ( - "encoding/json" - "net/http" - "net/url" - "strconv" - "strings" - "testing" -) - -func TestQueryParameter(t *testing.T) { - hreq := http.Request{Method: "GET"} - hreq.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar") - rreq := Request{Request: &hreq} - if rreq.QueryParameter("q") != "foo" { - t.Errorf("q!=foo %#v", rreq) - } -} - -type Anything map[string]interface{} - -type Number struct { - ValueFloat float64 - ValueInt int64 -} - -type Sample struct { - Value string -} - -func TestReadEntityXmlCached(t *testing.T) { - SetCacheReadEntity(true) - bodyReader := strings.NewReader("42") - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/xml") - request := &Request{Request: httpRequest} - sam := new(Sample) - request.ReadEntity(sam) - if sam.Value != "42" { - t.Fatal("read failed") - } - if request.bodyContent == nil { - t.Fatal("no expected cached bytes found") - } -} - -func TestReadEntityXmlNonCached(t *testing.T) { - SetCacheReadEntity(false) - bodyReader := strings.NewReader("42") - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/xml") - request := &Request{Request: httpRequest} - sam := new(Sample) - request.ReadEntity(sam) - if sam.Value != "42" { - t.Fatal("read failed") - } - if request.bodyContent != nil { - t.Fatal("unexpected cached bytes found") - } -} - -func TestReadEntityJson(t *testing.T) { - bodyReader := strings.NewReader(`{"Value" : "42"}`) - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/json") - request := &Request{Request: httpRequest} - sam := new(Sample) - request.ReadEntity(sam) - if sam.Value != "42" { - t.Fatal("read failed") - } -} - -func TestReadEntityJsonCharset(t *testing.T) { - bodyReader := strings.NewReader(`{"Value" : "42"}`) - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/json; charset=UTF-8") - request := NewRequest(httpRequest) - sam := new(Sample) - request.ReadEntity(sam) - if sam.Value != "42" { - t.Fatal("read failed") - } -} - -func TestReadEntityJsonNumber(t *testing.T) { - SetCacheReadEntity(true) - bodyReader := strings.NewReader(`{"Value" : 4899710515899924123}`) - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/json") - request := &Request{Request: httpRequest} - any := make(Anything) - request.ReadEntity(&any) - number, ok := any["Value"].(json.Number) - if !ok { - t.Fatal("read failed") - } - vint, err := number.Int64() - if err != nil { - t.Fatal("convert failed") - } - if vint != 4899710515899924123 { - t.Fatal("read failed") - } - vfloat, err := number.Float64() - if err != nil { - t.Fatal("convert failed") - } - // match the default behaviour - vstring := strconv.FormatFloat(vfloat, 'e', 15, 64) - if vstring != "4.899710515899924e+18" { - t.Fatal("convert float64 failed") - } -} - -func TestReadEntityJsonNumberNonCached(t *testing.T) { - SetCacheReadEntity(false) - bodyReader := strings.NewReader(`{"Value" : 4899710515899924123}`) - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/json") - request := &Request{Request: httpRequest} - any := make(Anything) - request.ReadEntity(&any) - number, ok := any["Value"].(json.Number) - if !ok { - t.Fatal("read failed") - } - vint, err := number.Int64() - if err != nil { - t.Fatal("convert failed") - } - if vint != 4899710515899924123 { - t.Fatal("read failed") - } - vfloat, err := number.Float64() - if err != nil { - t.Fatal("convert failed") - } - // match the default behaviour - vstring := strconv.FormatFloat(vfloat, 'e', 15, 64) - if vstring != "4.899710515899924e+18" { - t.Fatal("convert float64 failed") - } -} - -func TestReadEntityJsonLong(t *testing.T) { - bodyReader := strings.NewReader(`{"ValueFloat" : 4899710515899924123, "ValueInt": 4899710515899924123}`) - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/json") - request := &Request{Request: httpRequest} - number := new(Number) - request.ReadEntity(&number) - if number.ValueInt != 4899710515899924123 { - t.Fatal("read failed") - } - // match the default behaviour - vstring := strconv.FormatFloat(number.ValueFloat, 'e', 15, 64) - if vstring != "4.899710515899924e+18" { - t.Fatal("convert float64 failed") - } -} - -func TestBodyParameter(t *testing.T) { - bodyReader := strings.NewReader(`value1=42&value2=43`) - httpRequest, _ := http.NewRequest("POST", "/test?value1=44", bodyReader) // POST and PUT body parameters take precedence over URL query string - httpRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") - request := NewRequest(httpRequest) - v1, err := request.BodyParameter("value1") - if err != nil { - t.Error(err) - } - v2, err := request.BodyParameter("value2") - if err != nil { - t.Error(err) - } - if v1 != "42" || v2 != "43" { - t.Fatal("read failed") - } -} - -func TestReadEntityUnkown(t *testing.T) { - bodyReader := strings.NewReader("?") - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - httpRequest.Header.Set("Content-Type", "application/rubbish") - request := NewRequest(httpRequest) - sam := new(Sample) - err := request.ReadEntity(sam) - if err == nil { - t.Fatal("read should be in error") - } -} - -func TestSetAttribute(t *testing.T) { - bodyReader := strings.NewReader("?") - httpRequest, _ := http.NewRequest("GET", "/test", bodyReader) - request := NewRequest(httpRequest) - request.SetAttribute("go", "there") - there := request.Attribute("go") - if there != "there" { - t.Fatalf("missing request attribute:%v", there) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/response_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/response_test.go deleted file mode 100644 index d3db82c0d..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/response_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package restful - -import ( - "errors" - "net/http" - "net/http/httptest" - "strings" - "testing" -) - -func TestWriteHeader(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil} - resp.WriteHeader(123) - if resp.StatusCode() != 123 { - t.Errorf("Unexpected status code:%d", resp.StatusCode()) - } -} - -func TestNoWriteHeader(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil} - if resp.StatusCode() != http.StatusOK { - t.Errorf("Unexpected status code:%d", resp.StatusCode()) - } -} - -type food struct { - Kind string -} - -// go test -v -test.run TestMeasureContentLengthXml ...restful -func TestMeasureContentLengthXml(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil} - resp.WriteAsXml(food{"apple"}) - if resp.ContentLength() != 76 { - t.Errorf("Incorrect measured length:%d", resp.ContentLength()) - } -} - -// go test -v -test.run TestMeasureContentLengthJson ...restful -func TestMeasureContentLengthJson(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil} - resp.WriteAsJson(food{"apple"}) - if resp.ContentLength() != 22 { - t.Errorf("Incorrect measured length:%d", resp.ContentLength()) - } -} - -// go test -v -test.run TestMeasureContentLengthJsonNotPretty ...restful -func TestMeasureContentLengthJsonNotPretty(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, false, nil} - resp.WriteAsJson(food{"apple"}) - if resp.ContentLength() != 17 { // 16+1 using the Encoder directly yields another /n - t.Errorf("Incorrect measured length:%d", resp.ContentLength()) - } -} - -// go test -v -test.run TestMeasureContentLengthWriteErrorString ...restful -func TestMeasureContentLengthWriteErrorString(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil} - resp.WriteErrorString(404, "Invalid") - if resp.ContentLength() != len("Invalid") { - t.Errorf("Incorrect measured length:%d", resp.ContentLength()) - } -} - -// go test -v -test.run TestStatusIsPassedToResponse ...restful -func TestStatusIsPassedToResponse(t *testing.T) { - for _, each := range []struct { - write, read int - }{ - {write: 204, read: 204}, - {write: 304, read: 304}, - {write: 200, read: 200}, - {write: 400, read: 400}, - } { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "*/*", []string{"*/*"}, 0, 0, true, nil} - resp.WriteHeader(each.write) - if got, want := httpWriter.Code, each.read; got != want { - t.Errorf("got %v want %v", got, want) - } - } -} - -// go test -v -test.run TestStatusCreatedAndContentTypeJson_Issue54 ...restful -func TestStatusCreatedAndContentTypeJson_Issue54(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true, nil} - resp.WriteHeader(201) - resp.WriteAsJson(food{"Juicy"}) - if httpWriter.HeaderMap.Get("Content-Type") != "application/json" { - t.Errorf("Expected content type json but got:%d", httpWriter.HeaderMap.Get("Content-Type")) - } - if httpWriter.Code != 201 { - t.Errorf("Expected status 201 but got:%d", httpWriter.Code) - } -} - -type errorOnWriteRecorder struct { - *httptest.ResponseRecorder -} - -func (e errorOnWriteRecorder) Write(bytes []byte) (int, error) { - return 0, errors.New("fail") -} - -// go test -v -test.run TestLastWriteErrorCaught ...restful -func TestLastWriteErrorCaught(t *testing.T) { - httpWriter := errorOnWriteRecorder{httptest.NewRecorder()} - resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true, nil} - err := resp.WriteAsJson(food{"Juicy"}) - if err.Error() != "fail" { - t.Errorf("Unexpected error message:%v", err) - } -} - -// go test -v -test.run TestAcceptStarStar_Issue83 ...restful -func TestAcceptStarStar_Issue83(t *testing.T) { - httpWriter := httptest.NewRecorder() - // Accept Produces - resp := Response{httpWriter, "application/bogus,*/*;q=0.8", []string{"application/json"}, 0, 0, true, nil} - resp.WriteEntity(food{"Juicy"}) - ct := httpWriter.Header().Get("Content-Type") - if "application/json" != ct { - t.Errorf("Unexpected content type:%s", ct) - } -} - -// go test -v -test.run TestAcceptSkipStarStar_Issue83 ...restful -func TestAcceptSkipStarStar_Issue83(t *testing.T) { - httpWriter := httptest.NewRecorder() - // Accept Produces - resp := Response{httpWriter, " application/xml ,*/* ; q=0.8", []string{"application/json", "application/xml"}, 0, 0, true, nil} - resp.WriteEntity(food{"Juicy"}) - ct := httpWriter.Header().Get("Content-Type") - if "application/xml" != ct { - t.Errorf("Unexpected content type:%s", ct) - } -} - -// go test -v -test.run TestAcceptXmlBeforeStarStar_Issue83 ...restful -func TestAcceptXmlBeforeStarStar_Issue83(t *testing.T) { - httpWriter := httptest.NewRecorder() - // Accept Produces - resp := Response{httpWriter, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", []string{"application/json"}, 0, 0, true, nil} - resp.WriteEntity(food{"Juicy"}) - ct := httpWriter.Header().Get("Content-Type") - if "application/json" != ct { - t.Errorf("Unexpected content type:%s", ct) - } -} - -// go test -v -test.run TestWriteHeaderNoContent_Issue124 ...restful -func TestWriteHeaderNoContent_Issue124(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "text/plain", []string{"text/plain"}, 0, 0, true, nil} - resp.WriteHeader(http.StatusNoContent) - if httpWriter.Code != http.StatusNoContent { - t.Errorf("got %d want %d", httpWriter.Code, http.StatusNoContent) - } -} - -// go test -v -test.run TestStatusCreatedAndContentTypeJson_Issue163 ...restful -func TestStatusCreatedAndContentTypeJson_Issue163(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true, nil} - resp.WriteHeader(http.StatusNotModified) - if httpWriter.Code != http.StatusNotModified { - t.Errorf("Got %d want %d", httpWriter.Code, http.StatusNotModified) - } -} - -func TestWriteHeaderAndEntity_Issue235(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "application/json", []string{"application/json"}, 0, 0, true, nil} - var pong = struct { - Foo string `json:"foo"` - }{Foo: "123"} - resp.WriteHeaderAndEntity(404, pong) - if httpWriter.Code != http.StatusNotFound { - t.Errorf("got %d want %d", httpWriter.Code, http.StatusNoContent) - } - if got, want := httpWriter.Header().Get("Content-Type"), "application/json"; got != want { - t.Errorf("got %v want %v", got, want) - } - if !strings.HasPrefix(httpWriter.Body.String(), "{") { - t.Errorf("expected pong struct in json:%s", httpWriter.Body.String()) - } -} - -func TestWriteEntityNoAcceptMatchWithProduces(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "application/bogus", []string{"application/json"}, 0, 0, true, nil} - resp.WriteEntity("done") - if httpWriter.Code != http.StatusOK { - t.Errorf("got %d want %d", httpWriter.Code, http.StatusOK) - } -} - -func TestWriteEntityNoAcceptMatchNoProduces(t *testing.T) { - httpWriter := httptest.NewRecorder() - resp := Response{httpWriter, "application/bogus", []string{}, 0, 0, true, nil} - resp.WriteEntity("done") - if httpWriter.Code != http.StatusNotAcceptable { - t.Errorf("got %d want %d", httpWriter.Code, http.StatusNotAcceptable) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/route_builder_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/route_builder_test.go deleted file mode 100644 index 56dbe02e4..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/route_builder_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package restful - -import ( - "testing" -) - -func TestRouteBuilder_PathParameter(t *testing.T) { - p := &Parameter{&ParameterData{Name: "name", Description: "desc"}} - p.AllowMultiple(true) - p.DataType("int") - p.Required(true) - values := map[string]string{"a": "b"} - p.AllowableValues(values) - p.bePath() - - b := new(RouteBuilder) - b.function = dummy - b.Param(p) - r := b.Build() - if !r.ParameterDocs[0].Data().AllowMultiple { - t.Error("AllowMultiple invalid") - } - if r.ParameterDocs[0].Data().DataType != "int" { - t.Error("dataType invalid") - } - if !r.ParameterDocs[0].Data().Required { - t.Error("required invalid") - } - if r.ParameterDocs[0].Data().Kind != PathParameterKind { - t.Error("kind invalid") - } - if r.ParameterDocs[0].Data().AllowableValues["a"] != "b" { - t.Error("allowableValues invalid") - } - if b.ParameterNamed("name") == nil { - t.Error("access to parameter failed") - } -} - -func TestRouteBuilder(t *testing.T) { - json := "application/json" - b := new(RouteBuilder) - b.To(dummy) - b.Path("/routes").Method("HEAD").Consumes(json).Produces(json) - r := b.Build() - if r.Path != "/routes" { - t.Error("path invalid") - } - if r.Produces[0] != json { - t.Error("produces invalid") - } - if r.Consumes[0] != json { - t.Error("consumes invalid") - } - if r.Operation != "dummy" { - t.Error("Operation not set") - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/route_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/route_test.go deleted file mode 100644 index 6a104aff8..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/route_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package restful - -import ( - "testing" -) - -// accept should match produces -func TestMatchesAcceptPlainTextWhenProducePlainTextAsLast(t *testing.T) { - r := Route{Produces: []string{"application/json", "text/plain"}} - if !r.matchesAccept("text/plain") { - t.Errorf("accept should match text/plain") - } -} - -// accept should match produces -func TestMatchesAcceptStar(t *testing.T) { - r := Route{Produces: []string{"application/xml"}} - if !r.matchesAccept("*/*") { - t.Errorf("accept should match star") - } -} - -// accept should match produces -func TestMatchesAcceptIE(t *testing.T) { - r := Route{Produces: []string{"application/xml"}} - if !r.matchesAccept("text/html, application/xhtml+xml, */*") { - t.Errorf("accept should match star") - } -} - -// accept should match produces -func TestMatchesAcceptXml(t *testing.T) { - r := Route{Produces: []string{"application/xml"}} - if r.matchesAccept("application/json") { - t.Errorf("accept should not match json") - } - if !r.matchesAccept("application/xml") { - t.Errorf("accept should match xml") - } -} - -// accept should match produces -func TestMatchesAcceptAny(t *testing.T) { - r := Route{Produces: []string{"*/*"}} - if !r.matchesAccept("application/json") { - t.Errorf("accept should match json") - } - if !r.matchesAccept("application/xml") { - t.Errorf("accept should match xml") - } -} - -// content type should match consumes -func TestMatchesContentTypeXml(t *testing.T) { - r := Route{Consumes: []string{"application/xml"}} - if r.matchesContentType("application/json") { - t.Errorf("accept should not match json") - } - if !r.matchesContentType("application/xml") { - t.Errorf("accept should match xml") - } -} - -// content type should match consumes -func TestMatchesContentTypeCharsetInformation(t *testing.T) { - r := Route{Consumes: []string{"application/json"}} - if !r.matchesContentType("application/json; charset=UTF-8") { - t.Errorf("matchesContentType should ignore charset information") - } -} - -func TestMatchesPath_OneParam(t *testing.T) { - params := doExtractParams("/from/{source}", 2, "/from/here", t) - if params["source"] != "here" { - t.Errorf("parameter mismatch here") - } -} - -func TestMatchesPath_Slash(t *testing.T) { - params := doExtractParams("/", 0, "/", t) - if len(params) != 0 { - t.Errorf("expected empty parameters") - } -} - -func TestMatchesPath_SlashNonVar(t *testing.T) { - params := doExtractParams("/any", 1, "/any", t) - if len(params) != 0 { - t.Errorf("expected empty parameters") - } -} - -func TestMatchesPath_TwoVars(t *testing.T) { - params := doExtractParams("/from/{source}/to/{destination}", 4, "/from/AMS/to/NY", t) - if params["source"] != "AMS" { - t.Errorf("parameter mismatch AMS") - } -} - -func TestMatchesPath_VarOnFront(t *testing.T) { - params := doExtractParams("{what}/from/{source}/", 3, "who/from/SOS/", t) - if params["source"] != "SOS" { - t.Errorf("parameter mismatch SOS") - } -} - -func TestExtractParameters_EmptyValue(t *testing.T) { - params := doExtractParams("/fixed/{var}", 2, "/fixed/", t) - if params["var"] != "" { - t.Errorf("parameter mismatch var") - } -} - -func TestTokenizePath(t *testing.T) { - if len(tokenizePath("/")) != 0 { - t.Errorf("not empty path tokens") - } -} - -func doExtractParams(routePath string, size int, urlPath string, t *testing.T) map[string]string { - r := Route{Path: routePath} - r.postBuild() - if len(r.pathParts) != size { - t.Fatalf("len not %v %v, but %v", size, r.pathParts, len(r.pathParts)) - } - return r.extractParameters(urlPath) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_builder_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_builder_test.go deleted file mode 100644 index ba782a255..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_builder_test.go +++ /dev/null @@ -1,1138 +0,0 @@ -package swagger - -import ( - "net" - "testing" - "time" -) - -type YesNo bool - -func (y YesNo) MarshalJSON() ([]byte, error) { - if y { - return []byte("yes"), nil - } - return []byte("no"), nil -} - -// clear && go test -v -test.run TestRef_Issue190 ...swagger -func TestRef_Issue190(t *testing.T) { - type User struct { - items []string - } - testJsonFromStruct(t, User{}, `{ - "swagger.User": { - "id": "swagger.User", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }`) -} - -// clear && go test -v -test.run TestCustomMarshaller_Issue96 ...swagger -func TestCustomMarshaller_Issue96(t *testing.T) { - type Vote struct { - What YesNo - } - testJsonFromStruct(t, Vote{}, `{ - "swagger.Vote": { - "id": "swagger.Vote", - "required": [ - "What" - ], - "properties": { - "What": { - "type": "string" - } - } - } - }`) -} - -// clear && go test -v -test.run TestPrimitiveTypes ...swagger -func TestPrimitiveTypes(t *testing.T) { - type Prims struct { - f float64 - t time.Time - } - testJsonFromStruct(t, Prims{}, `{ - "swagger.Prims": { - "id": "swagger.Prims", - "required": [ - "f", - "t" - ], - "properties": { - "f": { - "type": "number", - "format": "double" - }, - "t": { - "type": "string", - "format": "date-time" - } - } - } - }`) -} - -// clear && go test -v -test.run TestPrimitivePtrTypes ...swagger -func TestPrimitivePtrTypes(t *testing.T) { - type Prims struct { - f *float64 - t *time.Time - b *bool - s *string - i *int - } - testJsonFromStruct(t, Prims{}, `{ - "swagger.Prims": { - "id": "swagger.Prims", - "required": [ - "f", - "t", - "b", - "s", - "i" - ], - "properties": { - "b": { - "type": "boolean" - }, - "f": { - "type": "number", - "format": "double" - }, - "i": { - "type": "integer", - "format": "int32" - }, - "s": { - "type": "string" - }, - "t": { - "type": "string", - "format": "date-time" - } - } - } - }`) -} - -// clear && go test -v -test.run TestS1 ...swagger -func TestS1(t *testing.T) { - type S1 struct { - Id string - } - testJsonFromStruct(t, S1{}, `{ - "swagger.S1": { - "id": "swagger.S1", - "required": [ - "Id" - ], - "properties": { - "Id": { - "type": "string" - } - } - } - }`) -} - -// clear && go test -v -test.run TestS2 ...swagger -func TestS2(t *testing.T) { - type S2 struct { - Ids []string - } - testJsonFromStruct(t, S2{}, `{ - "swagger.S2": { - "id": "swagger.S2", - "required": [ - "Ids" - ], - "properties": { - "Ids": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }`) -} - -// clear && go test -v -test.run TestS3 ...swagger -func TestS3(t *testing.T) { - type NestedS3 struct { - Id string - } - type S3 struct { - Nested NestedS3 - } - testJsonFromStruct(t, S3{}, `{ - "swagger.NestedS3": { - "id": "swagger.NestedS3", - "required": [ - "Id" - ], - "properties": { - "Id": { - "type": "string" - } - } - }, - "swagger.S3": { - "id": "swagger.S3", - "required": [ - "Nested" - ], - "properties": { - "Nested": { - "$ref": "swagger.NestedS3" - } - } - } - }`) -} - -type sample struct { - id string `swagger:"required"` // TODO - items []item - rootItem item `json:"root" description:"root desc"` -} - -type item struct { - itemName string `json:"name"` -} - -// clear && go test -v -test.run TestSampleToModelAsJson ...swagger -func TestSampleToModelAsJson(t *testing.T) { - testJsonFromStruct(t, sample{items: []item{}}, `{ - "swagger.item": { - "id": "swagger.item", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - } - } - }, - "swagger.sample": { - "id": "swagger.sample", - "required": [ - "id", - "items", - "root" - ], - "properties": { - "id": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "swagger.item" - } - }, - "root": { - "$ref": "swagger.item", - "description": "root desc" - } - } - } - }`) -} - -func TestJsonTags(t *testing.T) { - type X struct { - A string - B string `json:"-"` - C int `json:",string"` - D int `json:","` - } - - expected := `{ - "swagger.X": { - "id": "swagger.X", - "required": [ - "A", - "C", - "D" - ], - "properties": { - "A": { - "type": "string" - }, - "C": { - "type": "string" - }, - "D": { - "type": "integer", - "format": "int32" - } - } - } - }` - - testJsonFromStruct(t, X{}, expected) -} - -func TestJsonTagOmitempty(t *testing.T) { - type X struct { - A int `json:",omitempty"` - B int `json:"C,omitempty"` - } - - expected := `{ - "swagger.X": { - "id": "swagger.X", - "properties": { - "A": { - "type": "integer", - "format": "int32" - }, - "C": { - "type": "integer", - "format": "int32" - } - } - } - }` - - testJsonFromStruct(t, X{}, expected) -} - -func TestJsonTagName(t *testing.T) { - type X struct { - A string `json:"B"` - } - - expected := `{ - "swagger.X": { - "id": "swagger.X", - "required": [ - "B" - ], - "properties": { - "B": { - "type": "string" - } - } - } - }` - - testJsonFromStruct(t, X{}, expected) -} - -func TestAnonymousStruct(t *testing.T) { - type X struct { - A struct { - B int - } - } - - expected := `{ - "swagger.X": { - "id": "swagger.X", - "required": [ - "A" - ], - "properties": { - "A": { - "$ref": "swagger.X.A" - } - } - }, - "swagger.X.A": { - "id": "swagger.X.A", - "required": [ - "B" - ], - "properties": { - "B": { - "type": "integer", - "format": "int32" - } - } - } - }` - - testJsonFromStruct(t, X{}, expected) -} - -func TestAnonymousPtrStruct(t *testing.T) { - type X struct { - A *struct { - B int - } - } - - expected := `{ - "swagger.X": { - "id": "swagger.X", - "required": [ - "A" - ], - "properties": { - "A": { - "$ref": "swagger.X.A" - } - } - }, - "swagger.X.A": { - "id": "swagger.X.A", - "required": [ - "B" - ], - "properties": { - "B": { - "type": "integer", - "format": "int32" - } - } - } - }` - - testJsonFromStruct(t, X{}, expected) -} - -func TestAnonymousArrayStruct(t *testing.T) { - type X struct { - A []struct { - B int - } - } - - expected := `{ - "swagger.X": { - "id": "swagger.X", - "required": [ - "A" - ], - "properties": { - "A": { - "type": "array", - "items": { - "$ref": "swagger.X.A" - } - } - } - }, - "swagger.X.A": { - "id": "swagger.X.A", - "required": [ - "B" - ], - "properties": { - "B": { - "type": "integer", - "format": "int32" - } - } - } - }` - - testJsonFromStruct(t, X{}, expected) -} - -func TestAnonymousPtrArrayStruct(t *testing.T) { - type X struct { - A *[]struct { - B int - } - } - - expected := `{ - "swagger.X": { - "id": "swagger.X", - "required": [ - "A" - ], - "properties": { - "A": { - "type": "array", - "items": { - "$ref": "swagger.X.A" - } - } - } - }, - "swagger.X.A": { - "id": "swagger.X.A", - "required": [ - "B" - ], - "properties": { - "B": { - "type": "integer", - "format": "int32" - } - } - } - }` - - testJsonFromStruct(t, X{}, expected) -} - -// go test -v -test.run TestEmbeddedStruct_Issue98 ...swagger -func TestEmbeddedStruct_Issue98(t *testing.T) { - type Y struct { - A int - } - type X struct { - Y - } - testJsonFromStruct(t, X{}, `{ - "swagger.X": { - "id": "swagger.X", - "required": [ - "A" - ], - "properties": { - "A": { - "type": "integer", - "format": "int32" - } - } - } - }`) -} - -type Dataset struct { - Names []string -} - -// clear && go test -v -test.run TestIssue85 ...swagger -func TestIssue85(t *testing.T) { - anon := struct{ Datasets []Dataset }{} - testJsonFromStruct(t, anon, `{ - "struct { Datasets ||swagger.Dataset }": { - "id": "struct { Datasets ||swagger.Dataset }", - "required": [ - "Datasets" - ], - "properties": { - "Datasets": { - "type": "array", - "items": { - "$ref": "swagger.Dataset" - } - } - } - }, - "swagger.Dataset": { - "id": "swagger.Dataset", - "required": [ - "Names" - ], - "properties": { - "Names": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }`) -} - -type File struct { - History []File - HistoryPtrs []*File -} - -// go test -v -test.run TestRecursiveStructure ...swagger -func TestRecursiveStructure(t *testing.T) { - testJsonFromStruct(t, File{}, `{ - "swagger.File": { - "id": "swagger.File", - "required": [ - "History", - "HistoryPtrs" - ], - "properties": { - "History": { - "type": "array", - "items": { - "$ref": "swagger.File" - } - }, - "HistoryPtrs": { - "type": "array", - "items": { - "$ref": "swagger.File" - } - } - } - } - }`) -} - -type A1 struct { - B struct { - Id int - Comment string `json:"comment,omitempty"` - } -} - -// go test -v -test.run TestEmbeddedStructA1 ...swagger -func TestEmbeddedStructA1(t *testing.T) { - testJsonFromStruct(t, A1{}, `{ - "swagger.A1": { - "id": "swagger.A1", - "required": [ - "B" - ], - "properties": { - "B": { - "$ref": "swagger.A1.B" - } - } - }, - "swagger.A1.B": { - "id": "swagger.A1.B", - "required": [ - "Id" - ], - "properties": { - "Id": { - "type": "integer", - "format": "int32" - }, - "comment": { - "type": "string" - } - } - } - }`) -} - -type A2 struct { - C -} -type C struct { - Id int `json:"B"` - Comment string `json:"comment,omitempty"` - Secure bool `json:"secure"` -} - -// go test -v -test.run TestEmbeddedStructA2 ...swagger -func TestEmbeddedStructA2(t *testing.T) { - testJsonFromStruct(t, A2{}, `{ - "swagger.A2": { - "id": "swagger.A2", - "required": [ - "B", - "secure" - ], - "properties": { - "B": { - "type": "integer", - "format": "int32" - }, - "comment": { - "type": "string" - }, - "secure": { - "type": "boolean" - } - } - } - }`) -} - -type A3 struct { - B D -} - -type D struct { - Id int -} - -// clear && go test -v -test.run TestStructA3 ...swagger -func TestStructA3(t *testing.T) { - testJsonFromStruct(t, A3{}, `{ - "swagger.A3": { - "id": "swagger.A3", - "required": [ - "B" - ], - "properties": { - "B": { - "$ref": "swagger.D" - } - } - }, - "swagger.D": { - "id": "swagger.D", - "required": [ - "Id" - ], - "properties": { - "Id": { - "type": "integer", - "format": "int32" - } - } - } - }`) -} - -type A4 struct { - D "json:,inline" -} - -// clear && go test -v -test.run TestStructA4 ...swagger -func TestEmbeddedStructA4(t *testing.T) { - testJsonFromStruct(t, A4{}, `{ - "swagger.A4": { - "id": "swagger.A4", - "required": [ - "Id" - ], - "properties": { - "Id": { - "type": "integer", - "format": "int32" - } - } - } - }`) -} - -type A5 struct { - D `json:"d"` -} - -// clear && go test -v -test.run TestStructA5 ...swagger -func TestEmbeddedStructA5(t *testing.T) { - testJsonFromStruct(t, A5{}, `{ - "swagger.A5": { - "id": "swagger.A5", - "required": [ - "d" - ], - "properties": { - "d": { - "$ref": "swagger.D" - } - } - }, - "swagger.D": { - "id": "swagger.D", - "required": [ - "Id" - ], - "properties": { - "Id": { - "type": "integer", - "format": "int32" - } - } - } - }`) -} - -type D2 struct { - id int - D []D -} - -type A6 struct { - D2 "json:,inline" -} - -// clear && go test -v -test.run TestStructA4 ...swagger -func TestEmbeddedStructA6(t *testing.T) { - testJsonFromStruct(t, A6{}, `{ - "swagger.A6": { - "id": "swagger.A6", - "required": [ - "id", - "D" - ], - "properties": { - "D": { - "type": "array", - "items": { - "$ref": "swagger.D" - } - }, - "id": { - "type": "integer", - "format": "int32" - } - } - }, - "swagger.D": { - "id": "swagger.D", - "required": [ - "Id" - ], - "properties": { - "Id": { - "type": "integer", - "format": "int32" - } - } - } - }`) -} - -type ObjectId []byte - -type Region struct { - Id ObjectId `bson:"_id" json:"id"` - Name string `bson:"name" json:"name"` - Type string `bson:"type" json:"type"` -} - -// clear && go test -v -test.run TestRegion_Issue113 ...swagger -func TestRegion_Issue113(t *testing.T) { - testJsonFromStruct(t, []Region{}, `{ - "||swagger.Region": { - "id": "||swagger.Region", - "properties": {} - }, - "swagger.Region": { - "id": "swagger.Region", - "required": [ - "id", - "name", - "type" - ], - "properties": { - "id": { - "type": "array", - "items": { - "type": "integer" - } - }, - "name": { - "type": "string" - }, - "type": { - "type": "string" - } - } - } - }`) -} - -// clear && go test -v -test.run TestIssue158 ...swagger -func TestIssue158(t *testing.T) { - type Address struct { - Country string `json:"country,omitempty"` - } - - type Customer struct { - Name string `json:"name"` - Address Address `json:"address"` - } - expected := `{ - "swagger.Address": { - "id": "swagger.Address", - "properties": { - "country": { - "type": "string" - } - } - }, - "swagger.Customer": { - "id": "swagger.Customer", - "required": [ - "name", - "address" - ], - "properties": { - "address": { - "$ref": "swagger.Address" - }, - "name": { - "type": "string" - } - } - } - }` - testJsonFromStruct(t, Customer{}, expected) -} - -func TestSlices(t *testing.T) { - type Address struct { - Country string `json:"country,omitempty"` - } - expected := `{ - "swagger.Address": { - "id": "swagger.Address", - "properties": { - "country": { - "type": "string" - } - } - }, - "swagger.Customer": { - "id": "swagger.Customer", - "required": [ - "name", - "addresses" - ], - "properties": { - "addresses": { - "type": "array", - "items": { - "$ref": "swagger.Address" - } - }, - "name": { - "type": "string" - } - } - } - }` - // both slices (with pointer value and with type value) should have equal swagger representation - { - type Customer struct { - Name string `json:"name"` - Addresses []Address `json:"addresses"` - } - testJsonFromStruct(t, Customer{}, expected) - } - { - type Customer struct { - Name string `json:"name"` - Addresses []*Address `json:"addresses"` - } - testJsonFromStruct(t, Customer{}, expected) - } - -} - -type Name struct { - Value string -} - -func (n Name) PostBuildModel(m *Model) *Model { - m.Description = "titles must be upcase" - return m -} - -type TOC struct { - Titles []Name -} - -type Discography struct { - Title Name - TOC -} - -// clear && go test -v -test.run TestEmbeddedStructPull204 ...swagger -func TestEmbeddedStructPull204(t *testing.T) { - b := Discography{} - testJsonFromStruct(t, b, ` -{ - "swagger.Discography": { - "id": "swagger.Discography", - "required": [ - "Title", - "Titles" - ], - "properties": { - "Title": { - "$ref": "swagger.Name" - }, - "Titles": { - "type": "array", - "items": { - "$ref": "swagger.Name" - } - } - } - }, - "swagger.Name": { - "id": "swagger.Name", - "required": [ - "Value" - ], - "properties": { - "Value": { - "type": "string" - } - } - } - } -`) -} - -type AddressWithMethod struct { - Country string `json:"country,omitempty"` - PostCode int `json:"postcode,omitempty"` -} - -func (AddressWithMethod) SwaggerDoc() map[string]string { - return map[string]string{ - "": "Address doc", - "country": "Country doc", - "postcode": "PostCode doc", - } -} - -func TestDocInMethodSwaggerDoc(t *testing.T) { - expected := `{ - "swagger.AddressWithMethod": { - "id": "swagger.AddressWithMethod", - "description": "Address doc", - "properties": { - "country": { - "type": "string", - "description": "Country doc" - }, - "postcode": { - "type": "integer", - "format": "int32", - "description": "PostCode doc" - } - } - } - }` - testJsonFromStruct(t, AddressWithMethod{}, expected) -} - -type RefDesc struct { - f1 *int64 `description:"desc"` -} - -func TestPtrDescription(t *testing.T) { - b := RefDesc{} - expected := `{ - "swagger.RefDesc": { - "id": "swagger.RefDesc", - "required": [ - "f1" - ], - "properties": { - "f1": { - "type": "integer", - "format": "int64", - "description": "desc" - } - } - } - }` - testJsonFromStruct(t, b, expected) -} - -type A struct { - B `json:",inline"` - C1 `json:"metadata,omitempty"` -} - -type B struct { - SB string -} - -type C1 struct { - SC string -} - -func (A) SwaggerDoc() map[string]string { - return map[string]string{ - "": "A struct", - "B": "B field", // We should not get anything from this - "metadata": "C1 field", - } -} - -func (B) SwaggerDoc() map[string]string { - return map[string]string{ - "": "B struct", - "SB": "SB field", - } -} - -func (C1) SwaggerDoc() map[string]string { - return map[string]string{ - "": "C1 struct", - "SC": "SC field", - } -} - -func TestNestedStructDescription(t *testing.T) { - expected := ` -{ - "swagger.A": { - "id": "swagger.A", - "description": "A struct", - "required": [ - "SB" - ], - "properties": { - "SB": { - "type": "string", - "description": "SB field" - }, - "metadata": { - "$ref": "swagger.C1", - "description": "C1 field" - } - } - }, - "swagger.C1": { - "id": "swagger.C1", - "description": "C1 struct", - "required": [ - "SC" - ], - "properties": { - "SC": { - "type": "string", - "description": "SC field" - } - } - } - } -` - testJsonFromStruct(t, A{}, expected) -} - -// This tests a primitive with type overrides in the struct tags -type FakeInt int -type E struct { - Id FakeInt `type:"integer"` - IP net.IP `type:"string"` -} - -func TestOverridenTypeTagE1(t *testing.T) { - expected := ` -{ - "swagger.E": { - "id": "swagger.E", - "required": [ - "Id", - "IP" - ], - "properties": { - "Id": { - "type": "integer" - }, - "IP": { - "type": "string" - } - } - } - } -` - testJsonFromStruct(t, E{}, expected) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_list_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_list_test.go deleted file mode 100644 index 9a9ab919b..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_list_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package swagger - -import ( - "encoding/json" - "testing" -) - -func TestModelList(t *testing.T) { - m := Model{} - m.Id = "m" - l := ModelList{} - l.Put("m", m) - k, ok := l.At("m") - if !ok { - t.Error("want model back") - } - if got, want := k.Id, "m"; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestModelList_Marshal(t *testing.T) { - l := ModelList{} - m := Model{Id: "myid"} - l.Put("myid", m) - data, err := json.Marshal(l) - if err != nil { - t.Error(err) - } - if got, want := string(data), `{"myid":{"id":"myid","properties":{}}}`; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestModelList_Unmarshal(t *testing.T) { - data := `{"myid":{"id":"myid","properties":{}}}` - l := ModelList{} - if err := json.Unmarshal([]byte(data), &l); err != nil { - t.Error(err) - } - m, ok := l.At("myid") - if !ok { - t.Error("expected myid") - } - if got, want := m.Id, "myid"; got != want { - t.Errorf("got %v want %v", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_ext_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_ext_test.go deleted file mode 100644 index eff0d59d3..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_ext_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package swagger - -import ( - "net" - "testing" -) - -// clear && go test -v -test.run TestThatExtraTagsAreReadIntoModel ...swagger -func TestThatExtraTagsAreReadIntoModel(t *testing.T) { - type fakeint int - type Anything struct { - Name string `description:"name" modelDescription:"a test"` - Size int `minimum:"0" maximum:"10"` - Stati string `enum:"off|on" default:"on" modelDescription:"more description"` - ID string `unique:"true"` - FakeInt fakeint `type:"integer"` - IP net.IP `type:"string"` - Password string - } - m := modelsFromStruct(Anything{}) - props, _ := m.At("swagger.Anything") - p1, _ := props.Properties.At("Name") - if got, want := p1.Description, "name"; got != want { - t.Errorf("got %v want %v", got, want) - } - p2, _ := props.Properties.At("Size") - if got, want := p2.Minimum, "0"; got != want { - t.Errorf("got %v want %v", got, want) - } - if got, want := p2.Maximum, "10"; got != want { - t.Errorf("got %v want %v", got, want) - } - p3, _ := props.Properties.At("Stati") - if got, want := p3.Enum[0], "off"; got != want { - t.Errorf("got %v want %v", got, want) - } - if got, want := p3.Enum[1], "on"; got != want { - t.Errorf("got %v want %v", got, want) - } - p4, _ := props.Properties.At("ID") - if got, want := *p4.UniqueItems, true; got != want { - t.Errorf("got %v want %v", got, want) - } - p5, _ := props.Properties.At("Password") - if got, want := *p5.Type, "string"; got != want { - t.Errorf("got %v want %v", got, want) - } - p6, _ := props.Properties.At("FakeInt") - if got, want := *p6.Type, "integer"; got != want { - t.Errorf("got %v want %v", got, want) - } - p7, _ := props.Properties.At("IP") - if got, want := *p7.Type, "string"; got != want { - t.Errorf("got %v want %v", got, want) - } - - if got, want := props.Description, "a test\nmore description"; got != want { - t.Errorf("got %v want %v", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_list_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_list_test.go deleted file mode 100644 index 2833ad8fd..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/model_property_list_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package swagger - -import ( - "encoding/json" - "testing" -) - -func TestModelPropertyList(t *testing.T) { - l := ModelPropertyList{} - p := ModelProperty{Description: "d"} - l.Put("p", p) - q, ok := l.At("p") - if !ok { - t.Error("expected p") - } - if got, want := q.Description, "d"; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestModelPropertyList_Marshal(t *testing.T) { - l := ModelPropertyList{} - p := ModelProperty{Description: "d"} - l.Put("p", p) - data, err := json.Marshal(l) - if err != nil { - t.Error(err) - } - if got, want := string(data), `{"p":{"description":"d"}}`; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestModelPropertyList_Unmarshal(t *testing.T) { - data := `{"p":{"description":"d"}}` - l := ModelPropertyList{} - if err := json.Unmarshal([]byte(data), &l); err != nil { - t.Error(err) - } - m, ok := l.At("p") - if !ok { - t.Error("expected p") - } - if got, want := m.Description, "d"; got != want { - t.Errorf("got %v want %v", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/ordered_route_map_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/ordered_route_map_test.go deleted file mode 100644 index 964e7da05..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/ordered_route_map_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package swagger - -import ( - "testing" - - "github.com/emicklei/go-restful" -) - -// go test -v -test.run TestOrderedRouteMap ...swagger -func TestOrderedRouteMap(t *testing.T) { - m := newOrderedRouteMap() - r1 := restful.Route{Path: "/r1"} - r2 := restful.Route{Path: "/r2"} - m.Add("a", r1) - m.Add("b", r2) - m.Add("b", r1) - m.Add("d", r2) - m.Add("c", r2) - order := "" - m.Do(func(k string, routes []restful.Route) { - order += k - if len(routes) == 0 { - t.Fail() - } - }) - if order != "abdc" { - t.Fail() - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/postbuild_model_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/postbuild_model_test.go deleted file mode 100644 index 3e20d2f5b..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/postbuild_model_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package swagger - -import "testing" - -type Boat struct { - Length int `json:"-"` // on default, this makes the fields not required - Weight int `json:"-"` -} - -// PostBuildModel is from swagger.ModelBuildable -func (b Boat) PostBuildModel(m *Model) *Model { - // override required - m.Required = []string{"Length", "Weight"} - - // add model property (just to test is can be added; is this a real usecase?) - extraType := "string" - m.Properties.Put("extra", ModelProperty{ - Description: "extra description", - DataTypeFields: DataTypeFields{ - Type: &extraType, - }, - }) - return m -} - -func TestCustomPostModelBuilde(t *testing.T) { - testJsonFromStruct(t, Boat{}, `{ - "swagger.Boat": { - "id": "swagger.Boat", - "required": [ - "Length", - "Weight" - ], - "properties": { - "extra": { - "type": "string", - "description": "extra description" - } - } - } -}`) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/swagger_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/swagger_test.go deleted file mode 100644 index 78e2d43cc..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/swagger_test.go +++ /dev/null @@ -1,284 +0,0 @@ -package swagger - -import ( - "encoding/json" - "testing" - - "github.com/emicklei/go-restful" - "github.com/emicklei/go-restful/swagger/test_package" -) - -func TestInfoStruct_Issue231(t *testing.T) { - config := Config{ - Info: Info{ - Title: "Title", - Description: "Description", - TermsOfServiceUrl: "http://example.com", - Contact: "example@example.com", - License: "License", - LicenseUrl: "http://example.com/license.txt", - }, - } - sws := newSwaggerService(config) - str, err := json.MarshalIndent(sws.produceListing(), "", " ") - if err != nil { - t.Fatal(err) - } - compareJson(t, string(str), ` - { - "apiVersion": "", - "swaggerVersion": "1.2", - "apis": null, - "info": { - "title": "Title", - "description": "Description", - "termsOfServiceUrl": "http://example.com", - "contact": "example@example.com", - "license": "License", - "licenseUrl": "http://example.com/license.txt" - } - } - `) -} - -// go test -v -test.run TestThatMultiplePathsOnRootAreHandled ...swagger -func TestThatMultiplePathsOnRootAreHandled(t *testing.T) { - ws1 := new(restful.WebService) - ws1.Route(ws1.GET("/_ping").To(dummy)) - ws1.Route(ws1.GET("/version").To(dummy)) - - cfg := Config{ - WebServicesUrl: "http://here.com", - ApiPath: "/apipath", - WebServices: []*restful.WebService{ws1}, - } - sws := newSwaggerService(cfg) - decl := sws.composeDeclaration(ws1, "/") - if got, want := len(decl.Apis), 2; got != want { - t.Errorf("got %v want %v", got, want) - } -} - -func TestWriteSamples(t *testing.T) { - ws1 := new(restful.WebService) - ws1.Route(ws1.GET("/object").To(dummy).Writes(test_package.TestStruct{})) - ws1.Route(ws1.GET("/array").To(dummy).Writes([]test_package.TestStruct{})) - ws1.Route(ws1.GET("/object_and_array").To(dummy).Writes(struct{ Abc test_package.TestStruct }{})) - - cfg := Config{ - WebServicesUrl: "http://here.com", - ApiPath: "/apipath", - WebServices: []*restful.WebService{ws1}, - } - sws := newSwaggerService(cfg) - - decl := sws.composeDeclaration(ws1, "/") - - str, err := json.MarshalIndent(decl.Apis, "", " ") - if err != nil { - t.Fatal(err) - } - - compareJson(t, string(str), ` - [ - { - "path": "/object", - "description": "", - "operations": [ - { - "type": "test_package.TestStruct", - "method": "GET", - "nickname": "dummy", - "parameters": [] - } - ] - }, - { - "path": "/array", - "description": "", - "operations": [ - { - "type": "array", - "items": { - "$ref": "test_package.TestStruct" - }, - "method": "GET", - "nickname": "dummy", - "parameters": [] - } - ] - }, - { - "path": "/object_and_array", - "description": "", - "operations": [ - { - "type": "struct { Abc test_package.TestStruct }", - "method": "GET", - "nickname": "dummy", - "parameters": [] - } - ] - } - ]`) - - str, err = json.MarshalIndent(decl.Models, "", " ") - if err != nil { - t.Fatal(err) - } - compareJson(t, string(str), ` - { - "test_package.TestStruct": { - "id": "test_package.TestStruct", - "required": [ - "TestField" - ], - "properties": { - "TestField": { - "type": "string" - } - } - }, - "||test_package.TestStruct": { - "id": "||test_package.TestStruct", - "properties": {} - }, - "struct { Abc test_package.TestStruct }": { - "id": "struct { Abc test_package.TestStruct }", - "required": [ - "Abc" - ], - "properties": { - "Abc": { - "$ref": "test_package.TestStruct" - } - } - } - }`) -} - -// go test -v -test.run TestServiceToApi ...swagger -func TestServiceToApi(t *testing.T) { - ws := new(restful.WebService) - ws.Path("/tests") - ws.Consumes(restful.MIME_JSON) - ws.Produces(restful.MIME_XML) - ws.Route(ws.GET("/a").To(dummy).Writes(sample{})) - ws.Route(ws.PUT("/b").To(dummy).Writes(sample{})) - ws.Route(ws.POST("/c").To(dummy).Writes(sample{})) - ws.Route(ws.DELETE("/d").To(dummy).Writes(sample{})) - - ws.Route(ws.GET("/d").To(dummy).Writes(sample{})) - ws.Route(ws.PUT("/c").To(dummy).Writes(sample{})) - ws.Route(ws.POST("/b").To(dummy).Writes(sample{})) - ws.Route(ws.DELETE("/a").To(dummy).Writes(sample{})) - ws.ApiVersion("1.2.3") - cfg := Config{ - WebServicesUrl: "http://here.com", - ApiPath: "/apipath", - WebServices: []*restful.WebService{ws}, - PostBuildHandler: func(in *ApiDeclarationList) {}, - } - sws := newSwaggerService(cfg) - decl := sws.composeDeclaration(ws, "/tests") - // checks - if decl.ApiVersion != "1.2.3" { - t.Errorf("got %v want %v", decl.ApiVersion, "1.2.3") - } - if decl.BasePath != "http://here.com" { - t.Errorf("got %v want %v", decl.BasePath, "http://here.com") - } - if len(decl.Apis) != 4 { - t.Errorf("got %v want %v", len(decl.Apis), 4) - } - pathOrder := "" - for _, each := range decl.Apis { - pathOrder += each.Path - for _, other := range each.Operations { - pathOrder += other.Method - } - } - - if pathOrder != "/tests/aGETDELETE/tests/bPUTPOST/tests/cPOSTPUT/tests/dDELETEGET" { - t.Errorf("got %v want %v", pathOrder, "see test source") - } -} - -func dummy(i *restful.Request, o *restful.Response) {} - -// go test -v -test.run TestIssue78 ...swagger -type Response struct { - Code int - Users *[]User - Items *[]TestItem -} -type User struct { - Id, Name string -} -type TestItem struct { - Id, Name string -} - -// clear && go test -v -test.run TestComposeResponseMessages ...swagger -func TestComposeResponseMessages(t *testing.T) { - responseErrors := map[int]restful.ResponseError{} - responseErrors[400] = restful.ResponseError{Code: 400, Message: "Bad Request", Model: TestItem{}} - route := restful.Route{ResponseErrors: responseErrors} - decl := new(ApiDeclaration) - decl.Models = ModelList{} - msgs := composeResponseMessages(route, decl) - if msgs[0].ResponseModel != "swagger.TestItem" { - t.Errorf("got %s want swagger.TestItem", msgs[0].ResponseModel) - } -} - -// clear && go test -v -test.run TestComposeResponseMessageArray ...swagger -func TestComposeResponseMessageArray(t *testing.T) { - responseErrors := map[int]restful.ResponseError{} - responseErrors[400] = restful.ResponseError{Code: 400, Message: "Bad Request", Model: []TestItem{}} - route := restful.Route{ResponseErrors: responseErrors} - decl := new(ApiDeclaration) - decl.Models = ModelList{} - msgs := composeResponseMessages(route, decl) - if msgs[0].ResponseModel != "array[swagger.TestItem]" { - t.Errorf("got %s want swagger.TestItem", msgs[0].ResponseModel) - } -} - -func TestIssue78(t *testing.T) { - sws := newSwaggerService(Config{}) - models := new(ModelList) - sws.addModelFromSampleTo(&Operation{}, true, Response{Items: &[]TestItem{}}, models) - model, ok := models.At("swagger.Response") - if !ok { - t.Fatal("missing response model") - } - if "swagger.Response" != model.Id { - t.Fatal("wrong model id:" + model.Id) - } - code, ok := model.Properties.At("Code") - if !ok { - t.Fatal("missing code") - } - if "integer" != *code.Type { - t.Fatal("wrong code type:" + *code.Type) - } - items, ok := model.Properties.At("Items") - if !ok { - t.Fatal("missing items") - } - if "array" != *items.Type { - t.Fatal("wrong items type:" + *items.Type) - } - items_items := items.Items - if items_items == nil { - t.Fatal("missing items->items") - } - ref := items_items.Ref - if ref == nil { - t.Fatal("missing $ref") - } - if *ref != "swagger.TestItem" { - t.Fatal("wrong $ref:" + *ref) - } -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/test_package/struct.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/test_package/struct.go deleted file mode 100644 index b9a6f9308..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/test_package/struct.go +++ /dev/null @@ -1,5 +0,0 @@ -package test_package - -type TestStruct struct { - TestField string -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/utils_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/utils_test.go deleted file mode 100644 index dab871032..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/swagger/utils_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package swagger - -import ( - "bytes" - "encoding/json" - "fmt" - "reflect" - "strings" - "testing" -) - -func testJsonFromStruct(t *testing.T, sample interface{}, expectedJson string) bool { - m := modelsFromStruct(sample) - data, _ := json.MarshalIndent(m, " ", " ") - return compareJson(t, string(data), expectedJson) -} - -func modelsFromStruct(sample interface{}) *ModelList { - models := new(ModelList) - builder := modelBuilder{models} - builder.addModelFrom(sample) - return models -} - -func compareJson(t *testing.T, actualJsonAsString string, expectedJsonAsString string) bool { - success := false - var actualMap map[string]interface{} - json.Unmarshal([]byte(actualJsonAsString), &actualMap) - var expectedMap map[string]interface{} - err := json.Unmarshal([]byte(expectedJsonAsString), &expectedMap) - if err != nil { - var actualArray []interface{} - json.Unmarshal([]byte(actualJsonAsString), &actualArray) - var expectedArray []interface{} - err := json.Unmarshal([]byte(expectedJsonAsString), &expectedArray) - success = reflect.DeepEqual(actualArray, expectedArray) - if err != nil { - t.Fatalf("Unparsable expected JSON: %s", err) - } - } else { - success = reflect.DeepEqual(actualMap, expectedMap) - } - if !success { - t.Log("---- expected -----") - t.Log(withLineNumbers(expectedJsonAsString)) - t.Log("---- actual -----") - t.Log(withLineNumbers(actualJsonAsString)) - t.Log("---- raw -----") - t.Log(actualJsonAsString) - t.Error("there are differences") - return false - } - return true -} - -func indexOfNonMatchingLine(actual, expected string) int { - a := strings.Split(actual, "\n") - e := strings.Split(expected, "\n") - size := len(a) - if len(e) < len(a) { - size = len(e) - } - for i := 0; i < size; i++ { - if a[i] != e[i] { - return i - } - } - return -1 -} - -func withLineNumbers(content string) string { - var buffer bytes.Buffer - lines := strings.Split(content, "\n") - for i, each := range lines { - buffer.WriteString(fmt.Sprintf("%d:%s\n", i, each)) - } - return buffer.String() -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/tracer_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/tracer_test.go deleted file mode 100644 index 60c1e9fc0..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/tracer_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package restful - -import "testing" - -// Use like this: -// -// TraceLogger(testLogger{t}) -type testLogger struct { - t *testing.T -} - -func (l testLogger) Print(v ...interface{}) { - l.t.Log(v...) -} - -func (l testLogger) Printf(format string, v ...interface{}) { - l.t.Logf(format, v...) -} diff --git a/Godeps/_workspace/src/github.com/emicklei/go-restful/web_service_test.go b/Godeps/_workspace/src/github.com/emicklei/go-restful/web_service_test.go deleted file mode 100644 index 5096cac4b..000000000 --- a/Godeps/_workspace/src/github.com/emicklei/go-restful/web_service_test.go +++ /dev/null @@ -1,297 +0,0 @@ -package restful - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -const ( - pathGetFriends = "/get/{userId}/friends" -) - -func TestParameter(t *testing.T) { - p := &Parameter{&ParameterData{Name: "name", Description: "desc"}} - p.AllowMultiple(true) - p.DataType("int") - p.Required(true) - values := map[string]string{"a": "b"} - p.AllowableValues(values) - p.bePath() - - ws := new(WebService) - ws.Param(p) - if ws.pathParameters[0].Data().Name != "name" { - t.Error("path parameter (or name) invalid") - } -} -func TestWebService_CanCreateParameterKinds(t *testing.T) { - ws := new(WebService) - if ws.BodyParameter("b", "b").Kind() != BodyParameterKind { - t.Error("body parameter expected") - } - if ws.PathParameter("p", "p").Kind() != PathParameterKind { - t.Error("path parameter expected") - } - if ws.QueryParameter("q", "q").Kind() != QueryParameterKind { - t.Error("query parameter expected") - } -} - -func TestCapturePanic(t *testing.T) { - tearDown() - Add(newPanicingService()) - httpRequest, _ := http.NewRequest("GET", "http://here.com/fire", nil) - httpRequest.Header.Set("Accept", "*/*") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 500 != httpWriter.Code { - t.Error("500 expected on fire") - } -} - -func TestCapturePanicWithEncoded(t *testing.T) { - tearDown() - Add(newPanicingService()) - DefaultContainer.EnableContentEncoding(true) - httpRequest, _ := http.NewRequest("GET", "http://here.com/fire", nil) - httpRequest.Header.Set("Accept", "*/*") - httpRequest.Header.Set("Accept-Encoding", "gzip") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 500 != httpWriter.Code { - t.Error("500 expected on fire, got", httpWriter.Code) - } -} - -func TestNotFound(t *testing.T) { - tearDown() - httpRequest, _ := http.NewRequest("GET", "http://here.com/missing", nil) - httpRequest.Header.Set("Accept", "*/*") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 404 != httpWriter.Code { - t.Error("404 expected on missing") - } -} - -func TestMethodNotAllowed(t *testing.T) { - tearDown() - Add(newGetOnlyService()) - httpRequest, _ := http.NewRequest("POST", "http://here.com/get", nil) - httpRequest.Header.Set("Accept", "*/*") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 405 != httpWriter.Code { - t.Error("405 expected method not allowed") - } -} - -func TestSelectedRoutePath_Issue100(t *testing.T) { - tearDown() - Add(newSelectedRouteTestingService()) - httpRequest, _ := http.NewRequest("GET", "http://here.com/get/232452/friends", nil) - httpRequest.Header.Set("Accept", "*/*") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if http.StatusOK != httpWriter.Code { - t.Error(http.StatusOK, "expected,", httpWriter.Code, "received.") - } -} - -func TestContentType415_Issue170(t *testing.T) { - tearDown() - Add(newGetOnlyJsonOnlyService()) - httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 200 != httpWriter.Code { - t.Errorf("Expected 200, got %d", httpWriter.Code) - } -} - -func TestContentType415_POST_Issue170(t *testing.T) { - tearDown() - Add(newPostOnlyJsonOnlyService()) - httpRequest, _ := http.NewRequest("POST", "http://here.com/post", nil) - httpRequest.Header.Set("Content-Type", "application/json") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 200 != httpWriter.Code { - t.Errorf("Expected 200, got %d", httpWriter.Code) - } -} - -// go test -v -test.run TestContentType406PlainJson ...restful -func TestContentType406PlainJson(t *testing.T) { - tearDown() - TraceLogger(testLogger{t}) - Add(newGetPlainTextOrJsonService()) - httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) - httpRequest.Header.Set("Accept", "text/plain") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if got, want := httpWriter.Code, 200; got != want { - t.Errorf("got %v, want %v", got, want) - } -} - -func TestRemoveRoute(t *testing.T) { - tearDown() - TraceLogger(testLogger{t}) - ws := newGetPlainTextOrJsonService() - Add(ws) - httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) - httpRequest.Header.Set("Accept", "text/plain") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if got, want := httpWriter.Code, 200; got != want { - t.Errorf("got %v, want %v", got, want) - } - - // dynamic apis are disabled, should error and do nothing - if err := ws.RemoveRoute("/get", "GET"); err == nil { - t.Error("unexpected non-error") - } - - httpWriter = httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if got, want := httpWriter.Code, 200; got != want { - t.Errorf("got %v, want %v", got, want) - } - - ws.SetDynamicRoutes(true) - if err := ws.RemoveRoute("/get", "GET"); err != nil { - t.Errorf("unexpected error %v", err) - } - - httpWriter = httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if got, want := httpWriter.Code, 404; got != want { - t.Errorf("got %v, want %v", got, want) - } -} -func TestRemoveLastRoute(t *testing.T) { - tearDown() - TraceLogger(testLogger{t}) - ws := newGetPlainTextOrJsonServiceMultiRoute() - Add(ws) - httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) - httpRequest.Header.Set("Accept", "text/plain") - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if got, want := httpWriter.Code, 200; got != want { - t.Errorf("got %v, want %v", got, want) - } - - // dynamic apis are disabled, should error and do nothing - if err := ws.RemoveRoute("/get", "GET"); err == nil { - t.Error("unexpected non-error") - } - - httpWriter = httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if got, want := httpWriter.Code, 200; got != want { - t.Errorf("got %v, want %v", got, want) - } - - ws.SetDynamicRoutes(true) - if err := ws.RemoveRoute("/get", "GET"); err != nil { - t.Errorf("unexpected error %v", err) - } - - httpWriter = httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if got, want := httpWriter.Code, 404; got != want { - t.Errorf("got %v, want %v", got, want) - } -} - -// go test -v -test.run TestContentTypeOctet_Issue170 ...restful -func TestContentTypeOctet_Issue170(t *testing.T) { - tearDown() - Add(newGetConsumingOctetStreamService()) - // with content-type - httpRequest, _ := http.NewRequest("GET", "http://here.com/get", nil) - httpRequest.Header.Set("Content-Type", MIME_OCTET) - httpWriter := httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 200 != httpWriter.Code { - t.Errorf("Expected 200, got %d", httpWriter.Code) - } - // without content-type - httpRequest, _ = http.NewRequest("GET", "http://here.com/get", nil) - httpWriter = httptest.NewRecorder() - DefaultContainer.dispatch(httpWriter, httpRequest) - if 200 != httpWriter.Code { - t.Errorf("Expected 200, got %d", httpWriter.Code) - } -} - -func newPanicingService() *WebService { - ws := new(WebService).Path("") - ws.Route(ws.GET("/fire").To(doPanic)) - return ws -} - -func newGetOnlyService() *WebService { - ws := new(WebService).Path("") - ws.Route(ws.GET("/get").To(doPanic)) - return ws -} - -func newPostOnlyJsonOnlyService() *WebService { - ws := new(WebService).Path("") - ws.Consumes("application/json") - ws.Route(ws.POST("/post").To(doNothing)) - return ws -} - -func newGetOnlyJsonOnlyService() *WebService { - ws := new(WebService).Path("") - ws.Consumes("application/json") - ws.Route(ws.GET("/get").To(doNothing)) - return ws -} - -func newGetPlainTextOrJsonService() *WebService { - ws := new(WebService).Path("") - ws.Produces("text/plain", "application/json") - ws.Route(ws.GET("/get").To(doNothing)) - return ws -} - -func newGetPlainTextOrJsonServiceMultiRoute() *WebService { - ws := new(WebService).Path("") - ws.Produces("text/plain", "application/json") - ws.Route(ws.GET("/get").To(doNothing)) - ws.Route(ws.GET("/status").To(doNothing)) - return ws -} - -func newGetConsumingOctetStreamService() *WebService { - ws := new(WebService).Path("") - ws.Consumes("application/octet-stream") - ws.Route(ws.GET("/get").To(doNothing)) - return ws -} - -func newSelectedRouteTestingService() *WebService { - ws := new(WebService).Path("") - ws.Route(ws.GET(pathGetFriends).To(selectedRouteChecker)) - return ws -} - -func selectedRouteChecker(req *Request, resp *Response) { - if req.SelectedRoutePath() != pathGetFriends { - resp.InternalServerError() - } -} - -func doPanic(req *Request, resp *Response) { - println("lightning...") - panic("fire") -} - -func doNothing(req *Request, resp *Response) { -} diff --git a/Godeps/_workspace/src/github.com/evanphx/json-patch/merge_test.go b/Godeps/_workspace/src/github.com/evanphx/json-patch/merge_test.go deleted file mode 100644 index e9e68ceef..000000000 --- a/Godeps/_workspace/src/github.com/evanphx/json-patch/merge_test.go +++ /dev/null @@ -1,322 +0,0 @@ -package jsonpatch - -import ( - "strings" - "testing" -) - -func mergePatch(doc, patch string) string { - out, err := MergePatch([]byte(doc), []byte(patch)) - - if err != nil { - panic(err) - } - - return string(out) -} - -func TestMergePatchReplaceKey(t *testing.T) { - doc := `{ "title": "hello" }` - pat := `{ "title": "goodbye" }` - - res := mergePatch(doc, pat) - - if !compareJSON(pat, res) { - t.Fatalf("Key was not replaced") - } -} - -func TestMergePatchIgnoresOtherValues(t *testing.T) { - doc := `{ "title": "hello", "age": 18 }` - pat := `{ "title": "goodbye" }` - - res := mergePatch(doc, pat) - - exp := `{ "title": "goodbye", "age": 18 }` - - if !compareJSON(exp, res) { - t.Fatalf("Key was not replaced") - } -} - -func TestMergePatchNilDoc(t *testing.T) { - doc := `{ "title": null }` - pat := `{ "title": {"foo": "bar"} }` - - res := mergePatch(doc, pat) - - exp := `{ "title": {"foo": "bar"} }` - - if !compareJSON(exp, res) { - t.Fatalf("Key was not replaced") - } -} - -func TestMergePatchRecursesIntoObjects(t *testing.T) { - doc := `{ "person": { "title": "hello", "age": 18 } }` - pat := `{ "person": { "title": "goodbye" } }` - - res := mergePatch(doc, pat) - - exp := `{ "person": { "title": "goodbye", "age": 18 } }` - - if !compareJSON(exp, res) { - t.Fatalf("Key was not replaced") - } -} - -type nonObjectCases struct { - doc, pat, res string -} - -func TestMergePatchReplacesNonObjectsWholesale(t *testing.T) { - a1 := `[1]` - a2 := `[2]` - o1 := `{ "a": 1 }` - o2 := `{ "a": 2 }` - o3 := `{ "a": 1, "b": 1 }` - o4 := `{ "a": 2, "b": 1 }` - - cases := []nonObjectCases{ - {a1, a2, a2}, - {o1, a2, a2}, - {a1, o1, o1}, - {o3, o2, o4}, - } - - for _, c := range cases { - act := mergePatch(c.doc, c.pat) - - if !compareJSON(c.res, act) { - t.Errorf("whole object replacement failed") - } - } -} - -func TestMergePatchReturnsErrorOnBadJSON(t *testing.T) { - _, err := MergePatch([]byte(`[[[[`), []byte(`1`)) - - if err == nil { - t.Errorf("Did not return an error for bad json: %s", err) - } - - _, err = MergePatch([]byte(`1`), []byte(`[[[[`)) - - if err == nil { - t.Errorf("Did not return an error for bad json: %s", err) - } -} - -var rfcTests = []struct { - target string - patch string - expected string -}{ - // test cases from https://tools.ietf.org/html/rfc7386#appendix-A - {target: `{"a":"b"}`, patch: `{"a":"c"}`, expected: `{"a":"c"}`}, - {target: `{"a":"b"}`, patch: `{"b":"c"}`, expected: `{"a":"b","b":"c"}`}, - {target: `{"a":"b"}`, patch: `{"a":null}`, expected: `{}`}, - {target: `{"a":"b","b":"c"}`, patch: `{"a":null}`, expected: `{"b":"c"}`}, - {target: `{"a":["b"]}`, patch: `{"a":"c"}`, expected: `{"a":"c"}`}, - {target: `{"a":"c"}`, patch: `{"a":["b"]}`, expected: `{"a":["b"]}`}, - {target: `{"a":{"b": "c"}}`, patch: `{"a": {"b": "d","c": null}}`, expected: `{"a":{"b":"d"}}`}, - {target: `{"a":[{"b":"c"}]}`, patch: `{"a":[1]}`, expected: `{"a":[1]}`}, - {target: `["a","b"]`, patch: `["c","d"]`, expected: `["c","d"]`}, - {target: `{"a":"b"}`, patch: `["c"]`, expected: `["c"]`}, - // {target: `{"a":"foo"}`, patch: `null`, expected: `null`}, - // {target: `{"a":"foo"}`, patch: `"bar"`, expected: `"bar"`}, - {target: `{"e":null}`, patch: `{"a":1}`, expected: `{"a":1,"e":null}`}, - {target: `[1,2]`, patch: `{"a":"b","c":null}`, expected: `{"a":"b"}`}, - {target: `{}`, patch: `{"a":{"bb":{"ccc":null}}}`, expected: `{"a":{"bb":{}}}`}, -} - -func TestMergePatchRFCCases(t *testing.T) { - for i, c := range rfcTests { - out := mergePatch(c.target, c.patch) - - if !compareJSON(out, c.expected) { - t.Errorf("case[%d], patch '%s' did not apply properly to '%s'. expected:\n'%s'\ngot:\n'%s'", i, c.patch, c.target, c.expected, out) - } - } -} - -var rfcFailTests = ` - {"a":"foo"} | null - {"a":"foo"} | "bar" -` - -func TestMergePatchFailRFCCases(t *testing.T) { - tests := strings.Split(rfcFailTests, "\n") - - for _, c := range tests { - if strings.TrimSpace(c) == "" { - continue - } - - parts := strings.SplitN(c, "|", 2) - - doc := strings.TrimSpace(parts[0]) - pat := strings.TrimSpace(parts[1]) - - out, err := MergePatch([]byte(doc), []byte(pat)) - - if err != errBadJSONPatch { - t.Errorf("error not returned properly: %s, %s", err, string(out)) - } - } - -} - -func TestMergeReplaceKey(t *testing.T) { - doc := `{ "title": "hello", "nested": {"one": 1, "two": 2} }` - pat := `{ "title": "goodbye", "nested": {"one": 2, "two": 2} }` - - exp := `{ "title": "goodbye", "nested": {"one": 2} }` - - res, err := CreateMergePatch([]byte(doc), []byte(pat)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - if !compareJSON(exp, string(res)) { - t.Fatalf("Key was not replaced") - } -} - -func TestMergeGetArray(t *testing.T) { - doc := `{ "title": "hello", "array": ["one", "two"], "notmatch": [1, 2, 3] }` - pat := `{ "title": "hello", "array": ["one", "two", "three"], "notmatch": [1, 2, 3] }` - - exp := `{ "array": ["one", "two", "three"] }` - - res, err := CreateMergePatch([]byte(doc), []byte(pat)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - if !compareJSON(exp, string(res)) { - t.Fatalf("Array was not added") - } -} - -func TestMergeGetObjArray(t *testing.T) { - doc := `{ "title": "hello", "array": [{"banana": true}, {"evil": false}], "notmatch": [{"one":1}, {"two":2}, {"three":3}] }` - pat := `{ "title": "hello", "array": [{"banana": false}, {"evil": true}], "notmatch": [{"one":1}, {"two":2}, {"three":3}] }` - - exp := `{ "array": [{"banana": false}, {"evil": true}] }` - - res, err := CreateMergePatch([]byte(doc), []byte(pat)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - if !compareJSON(exp, string(res)) { - t.Fatalf("Object array was not added") - } -} - -func TestMergeDeleteKey(t *testing.T) { - doc := `{ "title": "hello", "nested": {"one": 1, "two": 2} }` - pat := `{ "title": "hello", "nested": {"one": 1} }` - - exp := `{"nested":{"two":null}}` - - res, err := CreateMergePatch([]byte(doc), []byte(pat)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - // We cannot use "compareJSON", since Equals does not report a difference if the value is null - if exp != string(res) { - t.Fatalf("Key was not removed") - } -} - -func TestMergeEmptyArray(t *testing.T) { - doc := `{ "array": null }` - pat := `{ "array": [] }` - - exp := `{"array":[]}` - - res, err := CreateMergePatch([]byte(doc), []byte(pat)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - // We cannot use "compareJSON", since Equals does not report a difference if the value is null - if exp != string(res) { - t.Fatalf("Key was not removed") - } -} - -func TestMergeObjArray(t *testing.T) { - doc := `{ "array": [ {"a": {"b": 2}}, {"a": {"b": 3}} ]}` - exp := `{}` - - res, err := CreateMergePatch([]byte(doc), []byte(doc)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - // We cannot use "compareJSON", since Equals does not report a difference if the value is null - if exp != string(res) { - t.Fatalf("Array was not empty, was " + string(res)) - } -} - -func TestMergeComplexMatch(t *testing.T) { - doc := `{"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4], "nested": {"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4]} }` - empty := `{}` - res, err := CreateMergePatch([]byte(doc), []byte(doc)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - // We cannot use "compareJSON", since Equals does not report a difference if the value is null - if empty != string(res) { - t.Fatalf("Did not get empty result, was:%s", string(res)) - } -} - -func TestMergeComplexAddAll(t *testing.T) { - doc := `{"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4], "nested": {"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4]} }` - empty := `{}` - res, err := CreateMergePatch([]byte(empty), []byte(doc)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - if !compareJSON(doc, string(res)) { - t.Fatalf("Did not get everything as, it was:\n%s", string(res)) - } -} - -func TestMergeComplexRemoveAll(t *testing.T) { - doc := `{"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4], "nested": {"hello": "world","t": true ,"f": false, "n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4]} }` - exp := `{"a":null,"f":null,"hello":null,"i":null,"n":null,"nested":null,"pi":null,"t":null}` - empty := `{}` - res, err := CreateMergePatch([]byte(doc), []byte(empty)) - - if err != nil { - t.Errorf("Unexpected error: %s, %s", err, string(res)) - } - - if exp != string(res) { - t.Fatalf("Did not get result, was:%s", string(res)) - } - - // FIXME: Crashes if using compareJSON like this: - /* - if !compareJSON(doc, string(res)) { - t.Fatalf("Did not get everything as, it was:\n%s", string(res)) - } - */ -} diff --git a/Godeps/_workspace/src/github.com/evanphx/json-patch/patch_test.go b/Godeps/_workspace/src/github.com/evanphx/json-patch/patch_test.go deleted file mode 100644 index 493c4f165..000000000 --- a/Godeps/_workspace/src/github.com/evanphx/json-patch/patch_test.go +++ /dev/null @@ -1,234 +0,0 @@ -package jsonpatch - -import ( - "bytes" - "encoding/json" - "fmt" - "reflect" - "testing" -) - -func reformatJSON(j string) string { - buf := new(bytes.Buffer) - - json.Indent(buf, []byte(j), "", " ") - - return buf.String() -} - -func compareJSON(a, b string) bool { - // return Equal([]byte(a), []byte(b)) - - var obj_a, obj_b map[string]interface{} - json.Unmarshal([]byte(a), &obj_a) - json.Unmarshal([]byte(b), &obj_b) - - // fmt.Printf("Comparing %#v\nagainst %#v\n", obj_a, obj_b) - return reflect.DeepEqual(obj_a, obj_b) -} - -func applyPatch(doc, patch string) (string, error) { - obj, err := DecodePatch([]byte(patch)) - - if err != nil { - panic(err) - } - - out, err := obj.Apply([]byte(doc)) - - if err != nil { - return "", err - } - - return string(out), nil -} - -type Case struct { - doc, patch, result string -} - -var Cases = []Case{ - { - `{ "foo": "bar"}`, - `[ - { "op": "add", "path": "/baz", "value": "qux" } - ]`, - `{ - "baz": "qux", - "foo": "bar" - }`, - }, - { - `{ "foo": [ "bar", "baz" ] }`, - `[ - { "op": "add", "path": "/foo/1", "value": "qux" } - ]`, - `{ "foo": [ "bar", "qux", "baz" ] }`, - }, - { - `{ "baz": "qux", "foo": "bar" }`, - `[ { "op": "remove", "path": "/baz" } ]`, - `{ "foo": "bar" }`, - }, - { - `{ "foo": [ "bar", "qux", "baz" ] }`, - `[ { "op": "remove", "path": "/foo/1" } ]`, - `{ "foo": [ "bar", "baz" ] }`, - }, - { - `{ "baz": "qux", "foo": "bar" }`, - `[ { "op": "replace", "path": "/baz", "value": "boo" } ]`, - `{ "baz": "boo", "foo": "bar" }`, - }, - { - `{ - "foo": { - "bar": "baz", - "waldo": "fred" - }, - "qux": { - "corge": "grault" - } - }`, - `[ { "op": "move", "from": "/foo/waldo", "path": "/qux/thud" } ]`, - `{ - "foo": { - "bar": "baz" - }, - "qux": { - "corge": "grault", - "thud": "fred" - } - }`, - }, - { - `{ "foo": [ "all", "grass", "cows", "eat" ] }`, - `[ { "op": "move", "from": "/foo/1", "path": "/foo/3" } ]`, - `{ "foo": [ "all", "cows", "eat", "grass" ] }`, - }, - { - `{ "foo": "bar" }`, - `[ { "op": "add", "path": "/child", "value": { "grandchild": { } } } ]`, - `{ "foo": "bar", "child": { "grandchild": { } } }`, - }, - { - `{ "foo": ["bar"] }`, - `[ { "op": "add", "path": "/foo/-", "value": ["abc", "def"] } ]`, - `{ "foo": ["bar", ["abc", "def"]] }`, - }, - { - `{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`, - `[ { "op": "remove", "path": "/qux/bar" } ]`, - `{ "foo": "bar", "qux": { "baz": 1 } }`, - }, -} - -type BadCase struct { - doc, patch string -} - -var MutationTestCases = []BadCase{ - { - `{ "foo": "bar", "qux": { "baz": 1, "bar": null } }`, - `[ { "op": "remove", "path": "/qux/bar" } ]`, - }, -} - -var BadCases = []BadCase{ - { - `{ "foo": "bar" }`, - `[ { "op": "add", "path": "/baz/bat", "value": "qux" } ]`, - }, -} - -func TestAllCases(t *testing.T) { - for _, c := range Cases { - out, err := applyPatch(c.doc, c.patch) - - if err != nil { - t.Errorf("Unable to apply patch: %s", err) - } - - if !compareJSON(out, c.result) { - t.Errorf("Patch did not apply. Expected:\n%s\n\nActual:\n%s", - reformatJSON(c.result), reformatJSON(out)) - } - } - - for _, c := range MutationTestCases { - out, err := applyPatch(c.doc, c.patch) - - if err != nil { - t.Errorf("Unable to apply patch: %s", err) - } - - if compareJSON(out, c.doc) { - t.Errorf("Patch did not apply. Original:\n%s\n\nPatched:\n%s", - reformatJSON(c.doc), reformatJSON(out)) - } - } - - for _, c := range BadCases { - _, err := applyPatch(c.doc, c.patch) - - if err == nil { - t.Errorf("Patch should have failed to apply but it did not") - } - } -} - -type TestCase struct { - doc, patch string - result bool - failedPath string -} - -var TestCases = []TestCase{ - { - `{ - "baz": "qux", - "foo": [ "a", 2, "c" ] - }`, - `[ - { "op": "test", "path": "/baz", "value": "qux" }, - { "op": "test", "path": "/foo/1", "value": 2 } - ]`, - true, - "", - }, - { - `{ "baz": "qux" }`, - `[ { "op": "test", "path": "/baz", "value": "bar" } ]`, - false, - "/baz", - }, - { - `{ - "baz": "qux", - "foo": ["a", 2, "c"] - }`, - `[ - { "op": "test", "path": "/baz", "value": "qux" }, - { "op": "test", "path": "/foo/1", "value": "c" } - ]`, - false, - "/foo/1", - }, -} - -func TestAllTest(t *testing.T) { - for _, c := range TestCases { - _, err := applyPatch(c.doc, c.patch) - - if c.result && err != nil { - t.Errorf("Testing failed when it should have passed: %s", err) - } else if !c.result && err == nil { - t.Errorf("Testing passed when it should have faild: %s", err) - } else if !c.result { - expected := fmt.Sprintf("Testing value %s failed", c.failedPath) - if err.Error() != expected { - t.Errorf("Testing failed as expected but invalid message: expected [%s], got [%s]", expected, err) - } - } - } -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/field_test.go b/Godeps/_workspace/src/github.com/fatih/structs/field_test.go deleted file mode 100644 index b77e95120..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/field_test.go +++ /dev/null @@ -1,383 +0,0 @@ -package structs - -import ( - "reflect" - "testing" -) - -// A test struct that defines all cases -type Foo struct { - A string - B int `structs:"y"` - C bool `json:"c"` - d string // not exported - E *Baz - x string `xml:"x"` // not exported, with tag - Y []string - Z map[string]interface{} - *Bar // embedded -} - -type Baz struct { - A string - B int -} - -type Bar struct { - E string - F int - g []string -} - -func newStruct() *Struct { - b := &Bar{ - E: "example", - F: 2, - g: []string{"zeynep", "fatih"}, - } - - // B and x is not initialized for testing - f := &Foo{ - A: "gopher", - C: true, - d: "small", - E: nil, - Y: []string{"example"}, - Z: nil, - } - f.Bar = b - - return New(f) -} - -func TestField_Set(t *testing.T) { - s := newStruct() - - f := s.Field("A") - err := f.Set("fatih") - if err != nil { - t.Error(err) - } - - if f.Value().(string) != "fatih" { - t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih") - } - - f = s.Field("Y") - err = f.Set([]string{"override", "with", "this"}) - if err != nil { - t.Error(err) - } - - sliceLen := len(f.Value().([]string)) - if sliceLen != 3 { - t.Errorf("Setted values slice length is wrong: %d, want: %d", sliceLen, 3) - } - - f = s.Field("C") - err = f.Set(false) - if err != nil { - t.Error(err) - } - - if f.Value().(bool) { - t.Errorf("Setted value is wrong: %t want: %t", f.Value().(bool), false) - } - - // let's pass a different type - f = s.Field("A") - err = f.Set(123) // Field A is of type string, but we are going to pass an integer - if err == nil { - t.Error("Setting a field's value with a different type than the field's type should return an error") - } - - // old value should be still there :) - if f.Value().(string) != "fatih" { - t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih") - } - - // let's access an unexported field, which should give an error - f = s.Field("d") - err = f.Set("large") - if err != errNotExported { - t.Error(err) - } - - // let's set a pointer to struct - b := &Bar{ - E: "gopher", - F: 2, - } - - f = s.Field("Bar") - err = f.Set(b) - if err != nil { - t.Error(err) - } - - baz := &Baz{ - A: "helloWorld", - B: 42, - } - - f = s.Field("E") - err = f.Set(baz) - if err != nil { - t.Error(err) - } - - ba := s.Field("E").Value().(*Baz) - - if ba.A != "helloWorld" { - t.Errorf("could not set baz. Got: %s Want: helloWorld", ba.A) - } -} - -func TestField_Zero(t *testing.T) { - s := newStruct() - - f := s.Field("A") - err := f.Zero() - if err != nil { - t.Error(err) - } - - if f.Value().(string) != "" { - t.Errorf("Zeroed value is wrong: %s want: %s", f.Value().(string), "") - } - - f = s.Field("Y") - err = f.Zero() - if err != nil { - t.Error(err) - } - - sliceLen := len(f.Value().([]string)) - if sliceLen != 0 { - t.Errorf("Zeroed values slice length is wrong: %d, want: %d", sliceLen, 0) - } - - f = s.Field("C") - err = f.Zero() - if err != nil { - t.Error(err) - } - - if f.Value().(bool) { - t.Errorf("Zeroed value is wrong: %t want: %t", f.Value().(bool), false) - } - - // let's access an unexported field, which should give an error - f = s.Field("d") - err = f.Zero() - if err != errNotExported { - t.Error(err) - } - - f = s.Field("Bar") - err = f.Zero() - if err != nil { - t.Error(err) - } - - f = s.Field("E") - err = f.Zero() - if err != nil { - t.Error(err) - } - - v := s.Field("E").value - if !v.IsNil() { - t.Errorf("could not set baz. Got: %s Want: ", v.Interface()) - } -} - -func TestField(t *testing.T) { - s := newStruct() - - defer func() { - err := recover() - if err == nil { - t.Error("Retrieveing a non existing field from the struct should panic") - } - }() - - _ = s.Field("no-field") -} - -func TestField_Kind(t *testing.T) { - s := newStruct() - - f := s.Field("A") - if f.Kind() != reflect.String { - t.Errorf("Field A has wrong kind: %s want: %s", f.Kind(), reflect.String) - } - - f = s.Field("B") - if f.Kind() != reflect.Int { - t.Errorf("Field B has wrong kind: %s want: %s", f.Kind(), reflect.Int) - } - - // unexported - f = s.Field("d") - if f.Kind() != reflect.String { - t.Errorf("Field d has wrong kind: %s want: %s", f.Kind(), reflect.String) - } -} - -func TestField_Tag(t *testing.T) { - s := newStruct() - - v := s.Field("B").Tag("json") - if v != "" { - t.Errorf("Field's tag value of a non existing tag should return empty, got: %s", v) - } - - v = s.Field("C").Tag("json") - if v != "c" { - t.Errorf("Field's tag value of the existing field C should return 'c', got: %s", v) - } - - v = s.Field("d").Tag("json") - if v != "" { - t.Errorf("Field's tag value of a non exported field should return empty, got: %s", v) - } - - v = s.Field("x").Tag("xml") - if v != "x" { - t.Errorf("Field's tag value of a non exported field with a tag should return 'x', got: %s", v) - } - - v = s.Field("A").Tag("json") - if v != "" { - t.Errorf("Field's tag value of a existing field without a tag should return empty, got: %s", v) - } -} - -func TestField_Value(t *testing.T) { - s := newStruct() - - v := s.Field("A").Value() - val, ok := v.(string) - if !ok { - t.Errorf("Field's value of a A should be string") - } - - if val != "gopher" { - t.Errorf("Field's value of a existing tag should return 'gopher', got: %s", val) - } - - defer func() { - err := recover() - if err == nil { - t.Error("Value of a non exported field from the field should panic") - } - }() - - // should panic - _ = s.Field("d").Value() -} - -func TestField_IsEmbedded(t *testing.T) { - s := newStruct() - - if !s.Field("Bar").IsEmbedded() { - t.Errorf("Fields 'Bar' field is an embedded field") - } - - if s.Field("d").IsEmbedded() { - t.Errorf("Fields 'd' field is not an embedded field") - } -} - -func TestField_IsExported(t *testing.T) { - s := newStruct() - - if !s.Field("Bar").IsExported() { - t.Errorf("Fields 'Bar' field is an exported field") - } - - if !s.Field("A").IsExported() { - t.Errorf("Fields 'A' field is an exported field") - } - - if s.Field("d").IsExported() { - t.Errorf("Fields 'd' field is not an exported field") - } -} - -func TestField_IsZero(t *testing.T) { - s := newStruct() - - if s.Field("A").IsZero() { - t.Errorf("Fields 'A' field is an initialized field") - } - - if !s.Field("B").IsZero() { - t.Errorf("Fields 'B' field is not an initialized field") - } -} - -func TestField_Name(t *testing.T) { - s := newStruct() - - if s.Field("A").Name() != "A" { - t.Errorf("Fields 'A' field should have the name 'A'") - } -} - -func TestField_Field(t *testing.T) { - s := newStruct() - - e := s.Field("Bar").Field("E") - - val, ok := e.Value().(string) - if !ok { - t.Error("The value of the field 'e' inside 'Bar' struct should be string") - } - - if val != "example" { - t.Errorf("The value of 'e' should be 'example, got: %s", val) - } - - defer func() { - err := recover() - if err == nil { - t.Error("Field of a non existing nested struct should panic") - } - }() - - _ = s.Field("Bar").Field("e") -} - -func TestField_Fields(t *testing.T) { - s := newStruct() - fields := s.Field("Bar").Fields() - - if len(fields) != 3 { - t.Errorf("We expect 3 fields in embedded struct, was: %d", len(fields)) - } -} - -func TestField_FieldOk(t *testing.T) { - s := newStruct() - - b, ok := s.FieldOk("Bar") - if !ok { - t.Error("The field 'Bar' should exists.") - } - - e, ok := b.FieldOk("E") - if !ok { - t.Error("The field 'E' should exists.") - } - - val, ok := e.Value().(string) - if !ok { - t.Error("The value of the field 'e' inside 'Bar' struct should be string") - } - - if val != "example" { - t.Errorf("The value of 'e' should be 'example, got: %s", val) - } -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go b/Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go deleted file mode 100644 index 32bb82937..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go +++ /dev/null @@ -1,351 +0,0 @@ -package structs - -import ( - "fmt" - "time" -) - -func ExampleNew() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - server := &Server{ - Name: "Arslan", - ID: 123456, - Enabled: true, - } - - s := New(server) - - fmt.Printf("Name : %v\n", s.Name()) - fmt.Printf("Values : %v\n", s.Values()) - fmt.Printf("Value of ID : %v\n", s.Field("ID").Value()) - // Output: - // Name : Server - // Values : [Arslan 123456 true] - // Value of ID : 123456 - -} - -func ExampleMap() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - s := &Server{ - Name: "Arslan", - ID: 123456, - Enabled: true, - } - - m := Map(s) - - fmt.Printf("%#v\n", m["Name"]) - fmt.Printf("%#v\n", m["ID"]) - fmt.Printf("%#v\n", m["Enabled"]) - // Output: - // "Arslan" - // 123456 - // true - -} - -func ExampleMap_tags() { - // Custom tags can change the map keys instead of using the fields name - type Server struct { - Name string `structs:"server_name"` - ID int32 `structs:"server_id"` - Enabled bool `structs:"enabled"` - } - - s := &Server{ - Name: "Zeynep", - ID: 789012, - } - - m := Map(s) - - // access them by the custom tags defined above - fmt.Printf("%#v\n", m["server_name"]) - fmt.Printf("%#v\n", m["server_id"]) - fmt.Printf("%#v\n", m["enabled"]) - // Output: - // "Zeynep" - // 789012 - // false - -} - -func ExampleMap_nested() { - // By default field with struct types are processed too. We can stop - // processing them via "omitnested" tag option. - type Server struct { - Name string `structs:"server_name"` - ID int32 `structs:"server_id"` - Time time.Time `structs:"time,omitnested"` // do not convert to map[string]interface{} - } - - const shortForm = "2006-Jan-02" - t, _ := time.Parse("2006-Jan-02", "2013-Feb-03") - - s := &Server{ - Name: "Zeynep", - ID: 789012, - Time: t, - } - - m := Map(s) - - // access them by the custom tags defined above - fmt.Printf("%v\n", m["server_name"]) - fmt.Printf("%v\n", m["server_id"]) - fmt.Printf("%v\n", m["time"].(time.Time)) - // Output: - // Zeynep - // 789012 - // 2013-02-03 00:00:00 +0000 UTC -} - -func ExampleMap_omitEmpty() { - // By default field with struct types of zero values are processed too. We - // can stop processing them via "omitempty" tag option. - type Server struct { - Name string `structs:",omitempty"` - ID int32 `structs:"server_id,omitempty"` - Location string - } - - // Only add location - s := &Server{ - Location: "Tokyo", - } - - m := Map(s) - - // map contains only the Location field - fmt.Printf("%v\n", m) - // Output: - // map[Location:Tokyo] -} - -func ExampleValues() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - s := &Server{ - Name: "Fatih", - ID: 135790, - Enabled: false, - } - - m := Values(s) - - fmt.Printf("Values: %+v\n", m) - // Output: - // Values: [Fatih 135790 false] -} - -func ExampleValues_omitEmpty() { - // By default field with struct types of zero values are processed too. We - // can stop processing them via "omitempty" tag option. - type Server struct { - Name string `structs:",omitempty"` - ID int32 `structs:"server_id,omitempty"` - Location string - } - - // Only add location - s := &Server{ - Location: "Ankara", - } - - m := Values(s) - - // values contains only the Location field - fmt.Printf("Values: %+v\n", m) - // Output: - // Values: [Ankara] -} - -func ExampleValues_tags() { - type Location struct { - City string - Country string - } - - type Server struct { - Name string - ID int32 - Enabled bool - Location Location `structs:"-"` // values from location are not included anymore - } - - s := &Server{ - Name: "Fatih", - ID: 135790, - Enabled: false, - Location: Location{City: "Ankara", Country: "Turkey"}, - } - - // Let get all values from the struct s. Note that we don't include values - // from the Location field - m := Values(s) - - fmt.Printf("Values: %+v\n", m) - // Output: - // Values: [Fatih 135790 false] -} - -func ExampleFields() { - type Access struct { - Name string - LastAccessed time.Time - Number int - } - - s := &Access{ - Name: "Fatih", - LastAccessed: time.Now(), - Number: 1234567, - } - - fields := Fields(s) - - for i, field := range fields { - fmt.Printf("[%d] %+v\n", i, field.Name()) - } - - // Output: - // [0] Name - // [1] LastAccessed - // [2] Number -} - -func ExampleFields_nested() { - type Person struct { - Name string - Number int - } - - type Access struct { - Person Person - HasPermission bool - LastAccessed time.Time - } - - s := &Access{ - Person: Person{Name: "fatih", Number: 1234567}, - LastAccessed: time.Now(), - HasPermission: true, - } - - // Let's get all fields from the struct s. - fields := Fields(s) - - for _, field := range fields { - if field.Name() == "Person" { - fmt.Printf("Access.Person.Name: %+v\n", field.Field("Name").Value()) - } - } - - // Output: - // Access.Person.Name: fatih -} - -func ExampleField() { - type Person struct { - Name string - Number int - } - - type Access struct { - Person Person - HasPermission bool - LastAccessed time.Time - } - - access := &Access{ - Person: Person{Name: "fatih", Number: 1234567}, - LastAccessed: time.Now(), - HasPermission: true, - } - - // Create a new Struct type - s := New(access) - - // Get the Field type for "Person" field - p := s.Field("Person") - - // Get the underlying "Name field" and print the value of it - name := p.Field("Name") - - fmt.Printf("Value of Person.Access.Name: %+v\n", name.Value()) - - // Output: - // Value of Person.Access.Name: fatih - -} - -func ExampleIsZero() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - // Nothing is initalized - a := &Server{} - isZeroA := IsZero(a) - - // Name and Enabled is initialized, but not ID - b := &Server{ - Name: "Golang", - Enabled: true, - } - isZeroB := IsZero(b) - - fmt.Printf("%#v\n", isZeroA) - fmt.Printf("%#v\n", isZeroB) - // Output: - // true - // false -} - -func ExampleHasZero() { - // Let's define an Access struct. Note that the "Enabled" field is not - // going to be checked because we added the "structs" tag to the field. - type Access struct { - Name string - LastAccessed time.Time - Number int - Enabled bool `structs:"-"` - } - - // Name and Number is not initialized. - a := &Access{ - LastAccessed: time.Now(), - } - hasZeroA := HasZero(a) - - // Name and Number is initialized. - b := &Access{ - Name: "Fatih", - LastAccessed: time.Now(), - Number: 12345, - } - hasZeroB := HasZero(b) - - fmt.Printf("%#v\n", hasZeroA) - fmt.Printf("%#v\n", hasZeroB) - // Output: - // true - // false -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/structs_test.go b/Godeps/_workspace/src/github.com/fatih/structs/structs_test.go deleted file mode 100644 index 14e3de72f..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/structs_test.go +++ /dev/null @@ -1,898 +0,0 @@ -package structs - -import ( - "fmt" - "reflect" - "testing" - "time" -) - -func TestMapNonStruct(t *testing.T) { - foo := []string{"foo"} - - defer func() { - err := recover() - if err == nil { - t.Error("Passing a non struct into Map should panic") - } - }() - - // this should panic. We are going to recover and and test it - _ = Map(foo) -} - -func TestStructIndexes(t *testing.T) { - type C struct { - something int - Props map[string]interface{} - } - - defer func() { - err := recover() - if err != nil { - fmt.Printf("err %+v\n", err) - t.Error("Using mixed indexes should not panic") - } - }() - - // They should not panic - _ = Map(&C{}) - _ = Fields(&C{}) - _ = Values(&C{}) - _ = IsZero(&C{}) - _ = HasZero(&C{}) -} - -func TestMap(t *testing.T) { - var T = struct { - A string - B int - C bool - }{ - A: "a-value", - B: 2, - C: true, - } - - a := Map(T) - - if typ := reflect.TypeOf(a).Kind(); typ != reflect.Map { - t.Errorf("Map should return a map type, got: %v", typ) - } - - // we have three fields - if len(a) != 3 { - t.Errorf("Map should return a map of len 3, got: %d", len(a)) - } - - inMap := func(val interface{}) bool { - for _, v := range a { - if reflect.DeepEqual(v, val) { - return true - } - } - - return false - } - - for _, val := range []interface{}{"a-value", 2, true} { - if !inMap(val) { - t.Errorf("Map should have the value %v", val) - } - } - -} - -func TestMap_Tag(t *testing.T) { - var T = struct { - A string `structs:"x"` - B int `structs:"y"` - C bool `structs:"z"` - }{ - A: "a-value", - B: 2, - C: true, - } - - a := Map(T) - - inMap := func(key interface{}) bool { - for k := range a { - if reflect.DeepEqual(k, key) { - return true - } - } - return false - } - - for _, key := range []string{"x", "y", "z"} { - if !inMap(key) { - t.Errorf("Map should have the key %v", key) - } - } - -} - -func TestMap_CustomTag(t *testing.T) { - var T = struct { - A string `json:"x"` - B int `json:"y"` - C bool `json:"z"` - D struct { - E string `json:"jkl"` - } `json:"nested"` - }{ - A: "a-value", - B: 2, - C: true, - } - T.D.E = "e-value" - - s := New(T) - s.TagName = "json" - - a := s.Map() - - inMap := func(key interface{}) bool { - for k := range a { - if reflect.DeepEqual(k, key) { - return true - } - } - return false - } - - for _, key := range []string{"x", "y", "z"} { - if !inMap(key) { - t.Errorf("Map should have the key %v", key) - } - } - - nested, ok := a["nested"].(map[string]interface{}) - if !ok { - t.Fatalf("Map should contain the D field that is tagged as 'nested'") - } - - e, ok := nested["jkl"].(string) - if !ok { - t.Fatalf("Map should contain the D.E field that is tagged as 'jkl'") - } - - if e != "e-value" { - t.Errorf("D.E field should be equal to 'e-value', got: '%v'", e) - } - -} - -func TestMap_MultipleCustomTag(t *testing.T) { - var A = struct { - X string `aa:"ax"` - }{"a_value"} - - aStruct := New(A) - aStruct.TagName = "aa" - - var B = struct { - X string `bb:"bx"` - }{"b_value"} - - bStruct := New(B) - bStruct.TagName = "bb" - - a, b := aStruct.Map(), bStruct.Map() - if !reflect.DeepEqual(a, map[string]interface{}{"ax": "a_value"}) { - t.Error("Map should have field ax with value a_value") - } - - if !reflect.DeepEqual(b, map[string]interface{}{"bx": "b_value"}) { - t.Error("Map should have field bx with value b_value") - } -} - -func TestMap_OmitEmpty(t *testing.T) { - type A struct { - Name string - Value string `structs:",omitempty"` - Time time.Time `structs:",omitempty"` - } - a := A{} - - m := Map(a) - - _, ok := m["Value"].(map[string]interface{}) - if ok { - t.Error("Map should not contain the Value field that is tagged as omitempty") - } - - _, ok = m["Time"].(map[string]interface{}) - if ok { - t.Error("Map should not contain the Time field that is tagged as omitempty") - } -} - -func TestMap_OmitNested(t *testing.T) { - type A struct { - Name string - Value string - Time time.Time `structs:",omitnested"` - } - a := A{Time: time.Now()} - - type B struct { - Desc string - A A - } - b := &B{A: a} - - m := Map(b) - - in, ok := m["A"].(map[string]interface{}) - if !ok { - t.Error("Map nested structs is not available in the map") - } - - // should not happen - if _, ok := in["Time"].(map[string]interface{}); ok { - t.Error("Map nested struct should omit recursiving parsing of Time") - } - - if _, ok := in["Time"].(time.Time); !ok { - t.Error("Map nested struct should stop parsing of Time at is current value") - } -} - -func TestMap_Nested(t *testing.T) { - type A struct { - Name string - } - a := &A{Name: "example"} - - type B struct { - A *A - } - b := &B{A: a} - - m := Map(b) - - if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { - t.Errorf("Map should return a map type, got: %v", typ) - } - - in, ok := m["A"].(map[string]interface{}) - if !ok { - t.Error("Map nested structs is not available in the map") - } - - if name := in["Name"].(string); name != "example" { - t.Errorf("Map nested struct's name field should give example, got: %s", name) - } -} - -func TestMap_Anonymous(t *testing.T) { - type A struct { - Name string - } - a := &A{Name: "example"} - - type B struct { - *A - } - b := &B{} - b.A = a - - m := Map(b) - - if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { - t.Errorf("Map should return a map type, got: %v", typ) - } - - in, ok := m["A"].(map[string]interface{}) - if !ok { - t.Error("Embedded structs is not available in the map") - } - - if name := in["Name"].(string); name != "example" { - t.Errorf("Embedded A struct's Name field should give example, got: %s", name) - } -} - -func TestStruct(t *testing.T) { - var T = struct{}{} - - if !IsStruct(T) { - t.Errorf("T should be a struct, got: %T", T) - } - - if !IsStruct(&T) { - t.Errorf("T should be a struct, got: %T", T) - } - -} - -func TestValues(t *testing.T) { - var T = struct { - A string - B int - C bool - }{ - A: "a-value", - B: 2, - C: true, - } - - s := Values(T) - - if typ := reflect.TypeOf(s).Kind(); typ != reflect.Slice { - t.Errorf("Values should return a slice type, got: %v", typ) - } - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"a-value", 2, true} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestValues_OmitEmpty(t *testing.T) { - type A struct { - Name string - Value int `structs:",omitempty"` - } - - a := A{Name: "example"} - s := Values(a) - - if len(s) != 1 { - t.Errorf("Values of omitted empty fields should be not counted") - } - - if s[0].(string) != "example" { - t.Errorf("Values of omitted empty fields should left the value example") - } -} - -func TestValues_OmitNested(t *testing.T) { - type A struct { - Name string - Value int - } - - a := A{ - Name: "example", - Value: 123, - } - - type B struct { - A A `structs:",omitnested"` - C int - } - b := &B{A: a, C: 123} - - s := Values(b) - - if len(s) != 2 { - t.Errorf("Values of omitted nested struct should be not counted") - } - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{123, a} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestValues_Nested(t *testing.T) { - type A struct { - Name string - } - a := A{Name: "example"} - - type B struct { - A A - C int - } - b := &B{A: a, C: 123} - - s := Values(b) - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"example", 123} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestValues_Anonymous(t *testing.T) { - type A struct { - Name string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - s := Values(b) - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"example", 123} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestNames(t *testing.T) { - var T = struct { - A string - B int - C bool - }{ - A: "a-value", - B: 2, - C: true, - } - - s := Names(T) - - if len(s) != 3 { - t.Errorf("Names should return a slice of len 3, got: %d", len(s)) - } - - inSlice := func(val string) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []string{"A", "B", "C"} { - if !inSlice(val) { - t.Errorf("Names should have the value %v", val) - } - } -} - -func TestFields(t *testing.T) { - var T = struct { - A string - B int - C bool - }{ - A: "a-value", - B: 2, - C: true, - } - - s := Fields(T) - - if len(s) != 3 { - t.Errorf("Fields should return a slice of len 3, got: %d", len(s)) - } - - inSlice := func(val string) bool { - for _, v := range s { - if reflect.DeepEqual(v.Name(), val) { - return true - } - } - return false - } - - for _, val := range []string{"A", "B", "C"} { - if !inSlice(val) { - t.Errorf("Fields should have the value %v", val) - } - } -} - -func TestFields_OmitNested(t *testing.T) { - type A struct { - Name string - Enabled bool - } - a := A{Name: "example"} - - type B struct { - A A - C int - Value string `structs:"-"` - Number int - } - b := &B{A: a, C: 123} - - s := Fields(b) - - if len(s) != 3 { - t.Errorf("Fields should omit nested struct. Expecting 2 got: %d", len(s)) - } - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v.Name(), val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"A", "C"} { - if !inSlice(val) { - t.Errorf("Fields should have the value %v", val) - } - } -} - -func TestFields_Anonymous(t *testing.T) { - type A struct { - Name string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - s := Fields(b) - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v.Name(), val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"A", "C"} { - if !inSlice(val) { - t.Errorf("Fields should have the value %v", val) - } - } -} - -func TestIsZero(t *testing.T) { - var T = struct { - A string - B int - C bool `structs:"-"` - D []string - }{} - - ok := IsZero(T) - if !ok { - t.Error("IsZero should return true because none of the fields are initialized.") - } - - var X = struct { - A string - F *bool - }{ - A: "a-value", - } - - ok = IsZero(X) - if ok { - t.Error("IsZero should return false because A is initialized") - } - - var Y = struct { - A string - B int - }{ - A: "a-value", - B: 123, - } - - ok = IsZero(Y) - if ok { - t.Error("IsZero should return false because A and B is initialized") - } -} - -func TestIsZero_OmitNested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A `structs:",omitnested"` - C int - } - b := &B{A: a, C: 123} - - ok := IsZero(b) - if ok { - t.Error("IsZero should return false because A, B and C are initialized") - } - - aZero := A{} - bZero := &B{A: aZero} - - ok = IsZero(bZero) - if !ok { - t.Error("IsZero should return true because neither A nor B is initialized") - } - -} - -func TestIsZero_Nested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A - C int - } - b := &B{A: a, C: 123} - - ok := IsZero(b) - if ok { - t.Error("IsZero should return false because A, B and C are initialized") - } - - aZero := A{} - bZero := &B{A: aZero} - - ok = IsZero(bZero) - if !ok { - t.Error("IsZero should return true because neither A nor B is initialized") - } - -} - -func TestIsZero_Anonymous(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - ok := IsZero(b) - if ok { - t.Error("IsZero should return false because A, B and C are initialized") - } - - aZero := A{} - bZero := &B{} - bZero.A = aZero - - ok = IsZero(bZero) - if !ok { - t.Error("IsZero should return true because neither A nor B is initialized") - } -} - -func TestHasZero(t *testing.T) { - var T = struct { - A string - B int - C bool `structs:"-"` - D []string - }{ - A: "a-value", - B: 2, - } - - ok := HasZero(T) - if !ok { - t.Error("HasZero should return true because A and B are initialized.") - } - - var X = struct { - A string - F *bool - }{ - A: "a-value", - } - - ok = HasZero(X) - if !ok { - t.Error("HasZero should return true because A is initialized") - } - - var Y = struct { - A string - B int - }{ - A: "a-value", - B: 123, - } - - ok = HasZero(Y) - if ok { - t.Error("HasZero should return false because A and B is initialized") - } -} - -func TestHasZero_OmitNested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A `structs:",omitnested"` - C int - } - b := &B{A: a, C: 123} - - // Because the Field A inside B is omitted HasZero should return false - // because it will stop iterating deeper andnot going to lookup for D - ok := HasZero(b) - if ok { - t.Error("HasZero should return false because A and C are initialized") - } -} - -func TestHasZero_Nested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A - C int - } - b := &B{A: a, C: 123} - - ok := HasZero(b) - if !ok { - t.Error("HasZero should return true because D is not initialized") - } -} - -func TestHasZero_Anonymous(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - ok := HasZero(b) - if !ok { - t.Error("HasZero should return false because D is not initialized") - } -} - -func TestName(t *testing.T) { - type Foo struct { - A string - B bool - } - f := &Foo{} - - n := Name(f) - if n != "Foo" { - t.Errorf("Name should return Foo, got: %s", n) - } - - unnamed := struct{ Name string }{Name: "Cihangir"} - m := Name(unnamed) - if m != "" { - t.Errorf("Name should return empty string for unnamed struct, got: %s", n) - } - - defer func() { - err := recover() - if err == nil { - t.Error("Name should panic if a non struct is passed") - } - }() - - Name([]string{}) -} - -func TestNestedNilPointer(t *testing.T) { - type Collar struct { - Engraving string - } - - type Dog struct { - Name string - Collar *Collar - } - - type Person struct { - Name string - Dog *Dog - } - - person := &Person{ - Name: "John", - } - - personWithDog := &Person{ - Name: "Ron", - Dog: &Dog{ - Name: "Rover", - }, - } - - personWithDogWithCollar := &Person{ - Name: "Kon", - Dog: &Dog{ - Name: "Ruffles", - Collar: &Collar{ - Engraving: "If lost, call Kon", - }, - }, - } - - defer func() { - err := recover() - if err != nil { - fmt.Printf("err %+v\n", err) - t.Error("Internal nil pointer should not panic") - } - }() - - _ = Map(person) // Panics - _ = Map(personWithDog) // Panics - _ = Map(personWithDogWithCollar) // Doesn't panic -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/tags_test.go b/Godeps/_workspace/src/github.com/fatih/structs/tags_test.go deleted file mode 100644 index 5d12724f1..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/tags_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package structs - -import "testing" - -func TestParseTag_Name(t *testing.T) { - tags := []struct { - tag string - has bool - }{ - {"", false}, - {"name", true}, - {"name,opt", true}, - {"name , opt, opt2", false}, // has a single whitespace - {", opt, opt2", false}, - } - - for _, tag := range tags { - name, _ := parseTag(tag.tag) - - if (name != "name") && tag.has { - t.Errorf("Parse tag should return name: %#v", tag) - } - } -} - -func TestParseTag_Opts(t *testing.T) { - tags := []struct { - opts string - has bool - }{ - {"name", false}, - {"name,opt", true}, - {"name , opt, opt2", false}, // has a single whitespace - {",opt, opt2", true}, - {", opt3, opt4", false}, - } - - // search for "opt" - for _, tag := range tags { - _, opts := parseTag(tag.opts) - - if opts.Has("opt") != tag.has { - t.Errorf("Tag opts should have opt: %#v", tag) - } - } -} diff --git a/Godeps/_workspace/src/github.com/ghodss/yaml/yaml_test.go b/Godeps/_workspace/src/github.com/ghodss/yaml/yaml_test.go deleted file mode 100644 index 0ae0954e9..000000000 --- a/Godeps/_workspace/src/github.com/ghodss/yaml/yaml_test.go +++ /dev/null @@ -1,271 +0,0 @@ -package yaml - -import ( - "fmt" - "math" - "reflect" - "strconv" - "testing" -) - -type MarshalTest struct { - A string - B int64 - // Would like to test float64, but it's not supported in go-yaml. - // (See https://github.com/go-yaml/yaml/issues/83.) - C float32 -} - -func TestMarshal(t *testing.T) { - f32String := strconv.FormatFloat(math.MaxFloat32, 'g', -1, 32) - s := MarshalTest{"a", math.MaxInt64, math.MaxFloat32} - e := []byte(fmt.Sprintf("A: a\nB: %d\nC: %s\n", math.MaxInt64, f32String)) - - y, err := Marshal(s) - if err != nil { - t.Errorf("error marshaling YAML: %v", err) - } - - if !reflect.DeepEqual(y, e) { - t.Errorf("marshal YAML was unsuccessful, expected: %#v, got: %#v", - string(e), string(y)) - } -} - -type UnmarshalString struct { - A string - True string -} - -type UnmarshalStringMap struct { - A map[string]string -} - -type UnmarshalNestedString struct { - A NestedString -} - -type NestedString struct { - A string -} - -type UnmarshalSlice struct { - A []NestedSlice -} - -type NestedSlice struct { - B string - C *string -} - -func TestUnmarshal(t *testing.T) { - y := []byte("a: 1") - s1 := UnmarshalString{} - e1 := UnmarshalString{A: "1"} - unmarshal(t, y, &s1, &e1) - - y = []byte("a: true") - s1 = UnmarshalString{} - e1 = UnmarshalString{A: "true"} - unmarshal(t, y, &s1, &e1) - - y = []byte("true: 1") - s1 = UnmarshalString{} - e1 = UnmarshalString{True: "1"} - unmarshal(t, y, &s1, &e1) - - y = []byte("a:\n a: 1") - s2 := UnmarshalNestedString{} - e2 := UnmarshalNestedString{NestedString{"1"}} - unmarshal(t, y, &s2, &e2) - - y = []byte("a:\n - b: abc\n c: def\n - b: 123\n c: 456\n") - s3 := UnmarshalSlice{} - e3 := UnmarshalSlice{[]NestedSlice{NestedSlice{"abc", strPtr("def")}, NestedSlice{"123", strPtr("456")}}} - unmarshal(t, y, &s3, &e3) - - y = []byte("a:\n b: 1") - s4 := UnmarshalStringMap{} - e4 := UnmarshalStringMap{map[string]string{"b": "1"}} - unmarshal(t, y, &s4, &e4) -} - -func unmarshal(t *testing.T, y []byte, s, e interface{}) { - err := Unmarshal(y, s) - if err != nil { - t.Errorf("error unmarshaling YAML: %v", err) - } - - if !reflect.DeepEqual(s, e) { - t.Errorf("unmarshal YAML was unsuccessful, expected: %+#v, got: %+#v", - e, s) - } -} - -type Case struct { - input string - output string - // By default we test that reversing the output == input. But if there is a - // difference in the reversed output, you can optionally specify it here. - reverse *string -} - -type RunType int - -const ( - RunTypeJSONToYAML RunType = iota - RunTypeYAMLToJSON -) - -func TestJSONToYAML(t *testing.T) { - cases := []Case{ - { - `{"t":"a"}`, - "t: a\n", - nil, - }, { - `{"t":null}`, - "t: null\n", - nil, - }, - } - - runCases(t, RunTypeJSONToYAML, cases) -} - -func TestYAMLToJSON(t *testing.T) { - cases := []Case{ - { - "t: a\n", - `{"t":"a"}`, - nil, - }, { - "t: \n", - `{"t":null}`, - strPtr("t: null\n"), - }, { - "t: null\n", - `{"t":null}`, - nil, - }, { - "1: a\n", - `{"1":"a"}`, - strPtr("\"1\": a\n"), - }, { - "1000000000000000000000000000000000000: a\n", - `{"1e+36":"a"}`, - strPtr("\"1e+36\": a\n"), - }, { - "1e+36: a\n", - `{"1e+36":"a"}`, - strPtr("\"1e+36\": a\n"), - }, { - "\"1e+36\": a\n", - `{"1e+36":"a"}`, - nil, - }, { - "\"1.2\": a\n", - `{"1.2":"a"}`, - nil, - }, { - "- t: a\n", - `[{"t":"a"}]`, - nil, - }, { - "- t: a\n" + - "- t:\n" + - " b: 1\n" + - " c: 2\n", - `[{"t":"a"},{"t":{"b":1,"c":2}}]`, - nil, - }, { - `[{t: a}, {t: {b: 1, c: 2}}]`, - `[{"t":"a"},{"t":{"b":1,"c":2}}]`, - strPtr("- t: a\n" + - "- t:\n" + - " b: 1\n" + - " c: 2\n"), - }, { - "- t: \n", - `[{"t":null}]`, - strPtr("- t: null\n"), - }, { - "- t: null\n", - `[{"t":null}]`, - nil, - }, - } - - // Cases that should produce errors. - _ = []Case{ - { - "~: a", - `{"null":"a"}`, - nil, - }, { - "a: !!binary gIGC\n", - "{\"a\":\"\x80\x81\x82\"}", - nil, - }, - } - - runCases(t, RunTypeYAMLToJSON, cases) -} - -func runCases(t *testing.T, runType RunType, cases []Case) { - var f func([]byte) ([]byte, error) - var invF func([]byte) ([]byte, error) - var msg string - var invMsg string - if runType == RunTypeJSONToYAML { - f = JSONToYAML - invF = YAMLToJSON - msg = "JSON to YAML" - invMsg = "YAML back to JSON" - } else { - f = YAMLToJSON - invF = JSONToYAML - msg = "YAML to JSON" - invMsg = "JSON back to YAML" - } - - for _, c := range cases { - // Convert the string. - t.Logf("converting %s\n", c.input) - output, err := f([]byte(c.input)) - if err != nil { - t.Errorf("Failed to convert %s, input: `%s`, err: %v", msg, c.input, err) - } - - // Check it against the expected output. - if string(output) != c.output { - t.Errorf("Failed to convert %s, input: `%s`, expected `%s`, got `%s`", - msg, c.input, c.output, string(output)) - } - - // Set the string that we will compare the reversed output to. - reverse := c.input - // If a special reverse string was specified, use that instead. - if c.reverse != nil { - reverse = *c.reverse - } - - // Reverse the output. - input, err := invF(output) - if err != nil { - t.Errorf("Failed to convert %s, input: `%s`, err: %v", invMsg, string(output), err) - } - - // Check the reverse is equal to the input (or to *c.reverse). - if string(input) != reverse { - t.Errorf("Failed to convert %s, input: `%s`, expected `%s`, got `%s`", - invMsg, string(output), reverse, string(input)) - } - } - -} - -// To be able to easily fill in the *Case.reverse string above. -func strPtr(s string) *string { - return &s -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/all_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/all_test.go deleted file mode 100644 index dc7633172..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/all_test.go +++ /dev/null @@ -1,2169 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "math/rand" - "reflect" - "runtime/debug" - "strings" - "testing" - "time" - - . "github.com/gogo/protobuf/proto" - . "github.com/gogo/protobuf/proto/testdata" -) - -var globalO *Buffer - -func old() *Buffer { - if globalO == nil { - globalO = NewBuffer(nil) - } - globalO.Reset() - return globalO -} - -func equalbytes(b1, b2 []byte, t *testing.T) { - if len(b1) != len(b2) { - t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2)) - return - } - for i := 0; i < len(b1); i++ { - if b1[i] != b2[i] { - t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2) - } - } -} - -func initGoTestField() *GoTestField { - f := new(GoTestField) - f.Label = String("label") - f.Type = String("type") - return f -} - -// These are all structurally equivalent but the tag numbers differ. -// (It's remarkable that required, optional, and repeated all have -// 8 letters.) -func initGoTest_RequiredGroup() *GoTest_RequiredGroup { - return &GoTest_RequiredGroup{ - RequiredField: String("required"), - } -} - -func initGoTest_OptionalGroup() *GoTest_OptionalGroup { - return &GoTest_OptionalGroup{ - RequiredField: String("optional"), - } -} - -func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { - return &GoTest_RepeatedGroup{ - RequiredField: String("repeated"), - } -} - -func initGoTest(setdefaults bool) *GoTest { - pb := new(GoTest) - if setdefaults { - pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) - pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) - pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) - pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) - pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) - pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) - pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) - pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) - pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) - pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) - pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted - pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) - pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) - } - - pb.Kind = GoTest_TIME.Enum() - pb.RequiredField = initGoTestField() - pb.F_BoolRequired = Bool(true) - pb.F_Int32Required = Int32(3) - pb.F_Int64Required = Int64(6) - pb.F_Fixed32Required = Uint32(32) - pb.F_Fixed64Required = Uint64(64) - pb.F_Uint32Required = Uint32(3232) - pb.F_Uint64Required = Uint64(6464) - pb.F_FloatRequired = Float32(3232) - pb.F_DoubleRequired = Float64(6464) - pb.F_StringRequired = String("string") - pb.F_BytesRequired = []byte("bytes") - pb.F_Sint32Required = Int32(-32) - pb.F_Sint64Required = Int64(-64) - pb.Requiredgroup = initGoTest_RequiredGroup() - - return pb -} - -func fail(msg string, b *bytes.Buffer, s string, t *testing.T) { - data := b.Bytes() - ld := len(data) - ls := len(s) / 2 - - fmt.Printf("fail %s ld=%d ls=%d\n", msg, ld, ls) - - // find the interesting spot - n - n := ls - if ld < ls { - n = ld - } - j := 0 - for i := 0; i < n; i++ { - bs := hex(s[j])*16 + hex(s[j+1]) - j += 2 - if data[i] == bs { - continue - } - n = i - break - } - l := n - 10 - if l < 0 { - l = 0 - } - h := n + 10 - - // find the interesting spot - n - fmt.Printf("is[%d]:", l) - for i := l; i < h; i++ { - if i >= ld { - fmt.Printf(" --") - continue - } - fmt.Printf(" %.2x", data[i]) - } - fmt.Printf("\n") - - fmt.Printf("sb[%d]:", l) - for i := l; i < h; i++ { - if i >= ls { - fmt.Printf(" --") - continue - } - bs := hex(s[j])*16 + hex(s[j+1]) - j += 2 - fmt.Printf(" %.2x", bs) - } - fmt.Printf("\n") - - t.Fail() - - // t.Errorf("%s: \ngood: %s\nbad: %x", msg, s, b.Bytes()) - // Print the output in a partially-decoded format; can - // be helpful when updating the test. It produces the output - // that is pasted, with minor edits, into the argument to verify(). - // data := b.Bytes() - // nesting := 0 - // for b.Len() > 0 { - // start := len(data) - b.Len() - // var u uint64 - // u, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on varint:", err) - // return - // } - // wire := u & 0x7 - // tag := u >> 3 - // switch wire { - // case WireVarint: - // v, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on varint:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireFixed32: - // v, err := DecodeFixed32(b) - // if err != nil { - // fmt.Printf("decode error on fixed32:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireFixed64: - // v, err := DecodeFixed64(b) - // if err != nil { - // fmt.Printf("decode error on fixed64:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireBytes: - // nb, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on bytes:", err) - // return - // } - // after_tag := len(data) - b.Len() - // str := make([]byte, nb) - // _, err = b.Read(str) - // if err != nil { - // fmt.Printf("decode error on bytes:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" \"%x\" // field %d, encoding %d (FIELD)\n", - // data[start:after_tag], str, tag, wire) - // case WireStartGroup: - // nesting++ - // fmt.Printf("\t\t\"%x\"\t\t// start group field %d level %d\n", - // data[start:len(data)-b.Len()], tag, nesting) - // case WireEndGroup: - // fmt.Printf("\t\t\"%x\"\t\t// end group field %d level %d\n", - // data[start:len(data)-b.Len()], tag, nesting) - // nesting-- - // default: - // fmt.Printf("unrecognized wire type %d\n", wire) - // return - // } - // } -} - -func hex(c uint8) uint8 { - if '0' <= c && c <= '9' { - return c - '0' - } - if 'a' <= c && c <= 'f' { - return 10 + c - 'a' - } - if 'A' <= c && c <= 'F' { - return 10 + c - 'A' - } - return 0 -} - -func equal(b []byte, s string, t *testing.T) bool { - if 2*len(b) != len(s) { - // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t) - fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s)) - return false - } - for i, j := 0, 0; i < len(b); i, j = i+1, j+2 { - x := hex(s[j])*16 + hex(s[j+1]) - if b[i] != x { - // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t) - fmt.Printf("bad byte[%d]:%x %x", i, b[i], x) - return false - } - } - return true -} - -func overify(t *testing.T, pb *GoTest, expected string) { - o := old() - err := o.Marshal(pb) - if err != nil { - fmt.Printf("overify marshal-1 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 1", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = o.Unmarshal(pbd) - if err != nil { - t.Fatalf("overify unmarshal err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - o.Reset() - err = o.Marshal(pbd) - if err != nil { - t.Errorf("overify marshal-2 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 2", o.Bytes()) - t.Fatalf("string = %s", expected) - } -} - -// Simple tests for numeric encode/decode primitives (varint, etc.) -func TestNumericPrimitives(t *testing.T) { - for i := uint64(0); i < 1e6; i += 111 { - o := old() - if o.EncodeVarint(i) != nil { - t.Error("EncodeVarint") - break - } - x, e := o.DecodeVarint() - if e != nil { - t.Fatal("DecodeVarint") - } - if x != i { - t.Fatal("varint decode fail:", i, x) - } - - o = old() - if o.EncodeFixed32(i) != nil { - t.Fatal("encFixed32") - } - x, e = o.DecodeFixed32() - if e != nil { - t.Fatal("decFixed32") - } - if x != i { - t.Fatal("fixed32 decode fail:", i, x) - } - - o = old() - if o.EncodeFixed64(i*1234567) != nil { - t.Error("encFixed64") - break - } - x, e = o.DecodeFixed64() - if e != nil { - t.Error("decFixed64") - break - } - if x != i*1234567 { - t.Error("fixed64 decode fail:", i*1234567, x) - break - } - - o = old() - i32 := int32(i - 12345) - if o.EncodeZigzag32(uint64(i32)) != nil { - t.Fatal("EncodeZigzag32") - } - x, e = o.DecodeZigzag32() - if e != nil { - t.Fatal("DecodeZigzag32") - } - if x != uint64(uint32(i32)) { - t.Fatal("zigzag32 decode fail:", i32, x) - } - - o = old() - i64 := int64(i - 12345) - if o.EncodeZigzag64(uint64(i64)) != nil { - t.Fatal("EncodeZigzag64") - } - x, e = o.DecodeZigzag64() - if e != nil { - t.Fatal("DecodeZigzag64") - } - if x != uint64(i64) { - t.Fatal("zigzag64 decode fail:", i64, x) - } - } -} - -// fakeMarshaler is a simple struct implementing Marshaler and Message interfaces. -type fakeMarshaler struct { - b []byte - err error -} - -func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err } -func (f *fakeMarshaler) String() string { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) } -func (f *fakeMarshaler) ProtoMessage() {} -func (f *fakeMarshaler) Reset() {} - -type msgWithFakeMarshaler struct { - M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"` -} - -func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) } -func (m *msgWithFakeMarshaler) ProtoMessage() {} -func (m *msgWithFakeMarshaler) Reset() {} - -// Simple tests for proto messages that implement the Marshaler interface. -func TestMarshalerEncoding(t *testing.T) { - tests := []struct { - name string - m Message - want []byte - wantErr error - }{ - { - name: "Marshaler that fails", - m: &fakeMarshaler{ - err: errors.New("some marshal err"), - b: []byte{5, 6, 7}, - }, - // Since there's an error, nothing should be written to buffer. - want: nil, - wantErr: errors.New("some marshal err"), - }, - { - name: "Marshaler that fails with RequiredNotSetError", - m: &msgWithFakeMarshaler{ - M: &fakeMarshaler{ - err: &RequiredNotSetError{}, - b: []byte{5, 6, 7}, - }, - }, - // Since there's an error that can be continued after, - // the buffer should be written. - want: []byte{ - 10, 3, // for &msgWithFakeMarshaler - 5, 6, 7, // for &fakeMarshaler - }, - wantErr: &RequiredNotSetError{}, - }, - { - name: "Marshaler that succeeds", - m: &fakeMarshaler{ - b: []byte{0, 1, 2, 3, 4, 127, 255}, - }, - want: []byte{0, 1, 2, 3, 4, 127, 255}, - wantErr: nil, - }, - } - for _, test := range tests { - b := NewBuffer(nil) - err := b.Marshal(test.m) - if _, ok := err.(*RequiredNotSetError); ok { - // We're not in package proto, so we can only assert the type in this case. - err = &RequiredNotSetError{} - } - if !reflect.DeepEqual(test.wantErr, err) { - t.Errorf("%s: got err %v wanted %v", test.name, err, test.wantErr) - } - if !reflect.DeepEqual(test.want, b.Bytes()) { - t.Errorf("%s: got bytes %v wanted %v", test.name, b.Bytes(), test.want) - } - } -} - -// Simple tests for bytes -func TestBytesPrimitives(t *testing.T) { - o := old() - bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'} - if o.EncodeRawBytes(bytes) != nil { - t.Error("EncodeRawBytes") - } - decb, e := o.DecodeRawBytes(false) - if e != nil { - t.Error("DecodeRawBytes") - } - equalbytes(bytes, decb, t) -} - -// Simple tests for strings -func TestStringPrimitives(t *testing.T) { - o := old() - s := "now is the time" - if o.EncodeStringBytes(s) != nil { - t.Error("enc_string") - } - decs, e := o.DecodeStringBytes() - if e != nil { - t.Error("dec_string") - } - if s != decs { - t.Error("string encode/decode fail:", s, decs) - } -} - -// Do we catch the "required bit not set" case? -func TestRequiredBit(t *testing.T) { - o := old() - pb := new(GoTest) - err := o.Marshal(pb) - if err == nil { - t.Error("did not catch missing required fields") - } else if strings.Index(err.Error(), "Kind") < 0 { - t.Error("wrong error type:", err) - } -} - -// Check that all fields are nil. -// Clearly silly, and a residue from a more interesting test with an earlier, -// different initialization property, but it once caught a compiler bug so -// it lives. -func checkInitialized(pb *GoTest, t *testing.T) { - if pb.F_BoolDefaulted != nil { - t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted) - } - if pb.F_Int32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted) - } - if pb.F_Int64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted) - } - if pb.F_Fixed32Defaulted != nil { - t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted) - } - if pb.F_Fixed64Defaulted != nil { - t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted) - } - if pb.F_Uint32Defaulted != nil { - t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted) - } - if pb.F_Uint64Defaulted != nil { - t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted) - } - if pb.F_FloatDefaulted != nil { - t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted) - } - if pb.F_DoubleDefaulted != nil { - t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted) - } - if pb.F_StringDefaulted != nil { - t.Error("New or Reset did not set string:", *pb.F_StringDefaulted) - } - if pb.F_BytesDefaulted != nil { - t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted)) - } - if pb.F_Sint32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted) - } - if pb.F_Sint64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted) - } -} - -// Does Reset() reset? -func TestReset(t *testing.T) { - pb := initGoTest(true) - // muck with some values - pb.F_BoolDefaulted = Bool(false) - pb.F_Int32Defaulted = Int32(237) - pb.F_Int64Defaulted = Int64(12346) - pb.F_Fixed32Defaulted = Uint32(32000) - pb.F_Fixed64Defaulted = Uint64(666) - pb.F_Uint32Defaulted = Uint32(323232) - pb.F_Uint64Defaulted = nil - pb.F_FloatDefaulted = nil - pb.F_DoubleDefaulted = Float64(0) - pb.F_StringDefaulted = String("gotcha") - pb.F_BytesDefaulted = []byte("asdfasdf") - pb.F_Sint32Defaulted = Int32(123) - pb.F_Sint64Defaulted = Int64(789) - pb.Reset() - checkInitialized(pb, t) -} - -// All required fields set, no defaults provided. -func TestEncodeDecode1(t *testing.T) { - pb := initGoTest(false) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 0x20 - "714000000000000000"+ // field 14, encoding 1, value 0x40 - "78a019"+ // field 15, encoding 0, value 0xca0 = 3232 - "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string" - "b304"+ // field 70, encoding 3, start group - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // field 70, encoding 4, end group - "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f") // field 103, encoding 0, 0x7f zigzag64 -} - -// All required fields set, defaults provided. -func TestEncodeDecode2(t *testing.T) { - pb := initGoTest(true) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All default fields set to their default value by hand -func TestEncodeDecode3(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolDefaulted = Bool(true) - pb.F_Int32Defaulted = Int32(32) - pb.F_Int64Defaulted = Int64(64) - pb.F_Fixed32Defaulted = Uint32(320) - pb.F_Fixed64Defaulted = Uint64(640) - pb.F_Uint32Defaulted = Uint32(3200) - pb.F_Uint64Defaulted = Uint64(6400) - pb.F_FloatDefaulted = Float32(314159) - pb.F_DoubleDefaulted = Float64(271828) - pb.F_StringDefaulted = String("hello, \"world!\"\n") - pb.F_BytesDefaulted = []byte("Bignose") - pb.F_Sint32Defaulted = Int32(-32) - pb.F_Sint64Defaulted = Int64(-64) - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, defaults provided, all non-defaulted optional fields have values. -func TestEncodeDecode4(t *testing.T) { - pb := initGoTest(true) - pb.Table = String("hello") - pb.Param = Int32(7) - pb.OptionalField = initGoTestField() - pb.F_BoolOptional = Bool(true) - pb.F_Int32Optional = Int32(32) - pb.F_Int64Optional = Int64(64) - pb.F_Fixed32Optional = Uint32(3232) - pb.F_Fixed64Optional = Uint64(6464) - pb.F_Uint32Optional = Uint32(323232) - pb.F_Uint64Optional = Uint64(646464) - pb.F_FloatOptional = Float32(32.) - pb.F_DoubleOptional = Float64(64.) - pb.F_StringOptional = String("hello") - pb.F_BytesOptional = []byte("Bignose") - pb.F_Sint32Optional = Int32(-32) - pb.F_Sint64Optional = Int64(-64) - pb.Optionalgroup = initGoTest_OptionalGroup() - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello" - "1807"+ // field 3, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "f00101"+ // field 30, encoding 0, value 1 - "f80120"+ // field 31, encoding 0, value 32 - "800240"+ // field 32, encoding 0, value 64 - "8d02a00c0000"+ // field 33, encoding 5, value 3232 - "91024019000000000000"+ // field 34, encoding 1, value 6464 - "9802a0dd13"+ // field 35, encoding 0, value 323232 - "a002c0ba27"+ // field 36, encoding 0, value 646464 - "ad0200000042"+ // field 37, encoding 5, value 32.0 - "b1020000000000005040"+ // field 38, encoding 1, value 64.0 - "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "d305"+ // start group field 90 level 1 - "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional" - "d405"+ // end group field 90 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose" - "f0123f"+ // field 302, encoding 0, value 63 - "f8127f"+ // field 303, encoding 0, value 127 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestEncodeDecode5(t *testing.T) { - pb := initGoTest(true) - pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()} - pb.F_BoolRepeated = []bool{false, true} - pb.F_Int32Repeated = []int32{32, 33} - pb.F_Int64Repeated = []int64{64, 65} - pb.F_Fixed32Repeated = []uint32{3232, 3333} - pb.F_Fixed64Repeated = []uint64{6464, 6565} - pb.F_Uint32Repeated = []uint32{323232, 333333} - pb.F_Uint64Repeated = []uint64{646464, 656565} - pb.F_FloatRepeated = []float32{32., 33.} - pb.F_DoubleRepeated = []float64{64., 65.} - pb.F_StringRepeated = []string{"hello", "sailor"} - pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")} - pb.F_Sint32Repeated = []int32{32, -32} - pb.F_Sint64Repeated = []int64{64, -64} - pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "a00100"+ // field 20, encoding 0, value 0 - "a00101"+ // field 20, encoding 0, value 1 - "a80120"+ // field 21, encoding 0, value 32 - "a80121"+ // field 21, encoding 0, value 33 - "b00140"+ // field 22, encoding 0, value 64 - "b00141"+ // field 22, encoding 0, value 65 - "bd01a00c0000"+ // field 23, encoding 5, value 3232 - "bd01050d0000"+ // field 23, encoding 5, value 3333 - "c1014019000000000000"+ // field 24, encoding 1, value 6464 - "c101a519000000000000"+ // field 24, encoding 1, value 6565 - "c801a0dd13"+ // field 25, encoding 0, value 323232 - "c80195ac14"+ // field 25, encoding 0, value 333333 - "d001c0ba27"+ // field 26, encoding 0, value 646464 - "d001b58928"+ // field 26, encoding 0, value 656565 - "dd0100000042"+ // field 27, encoding 5, value 32.0 - "dd0100000442"+ // field 27, encoding 5, value 33.0 - "e1010000000000005040"+ // field 28, encoding 1, value 64.0 - "e1010000000000405040"+ // field 28, encoding 1, value 65.0 - "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello" - "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "ca0c03"+"626967"+ // field 201, encoding 2, string "big" - "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose" - "d00c40"+ // field 202, encoding 0, value 32 - "d00c3f"+ // field 202, encoding 0, value -32 - "d80c8001"+ // field 203, encoding 0, value 64 - "d80c7f"+ // field 203, encoding 0, value -64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, all packed repeated fields given two values. -func TestEncodeDecode6(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolRepeatedPacked = []bool{false, true} - pb.F_Int32RepeatedPacked = []int32{32, 33} - pb.F_Int64RepeatedPacked = []int64{64, 65} - pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333} - pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565} - pb.F_Uint32RepeatedPacked = []uint32{323232, 333333} - pb.F_Uint64RepeatedPacked = []uint64{646464, 656565} - pb.F_FloatRepeatedPacked = []float32{32., 33.} - pb.F_DoubleRepeatedPacked = []float64{64., 65.} - pb.F_Sint32RepeatedPacked = []int32{32, -32} - pb.F_Sint64RepeatedPacked = []int64{64, -64} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1 - "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33 - "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65 - "aa0308"+ // field 53, encoding 2, 8 bytes - "a00c0000050d0000"+ // value 3232, value 3333 - "b20310"+ // field 54, encoding 2, 16 bytes - "4019000000000000a519000000000000"+ // value 6464, value 6565 - "ba0306"+ // field 55, encoding 2, 6 bytes - "a0dd1395ac14"+ // value 323232, value 333333 - "c20306"+ // field 56, encoding 2, 6 bytes - "c0ba27b58928"+ // value 646464, value 656565 - "ca0308"+ // field 57, encoding 2, 8 bytes - "0000004200000442"+ // value 32.0, value 33.0 - "d20310"+ // field 58, encoding 2, 16 bytes - "00000000000050400000000000405040"+ // value 64.0, value 65.0 - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "b21f02"+ // field 502, encoding 2, 2 bytes - "403f"+ // value 32, value -32 - "ba1f03"+ // field 503, encoding 2, 3 bytes - "80017f") // value 64, value -64 -} - -// Test that we can encode empty bytes fields. -func TestEncodeDecodeBytes1(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRequired = []byte{} - pb.F_BytesRepeated = [][]byte{{}} - pb.F_BytesOptional = []byte{} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 { - t.Error("required empty bytes field is incorrect") - } - if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil { - t.Error("repeated empty bytes field is incorrect") - } - if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 { - t.Error("optional empty bytes field is incorrect") - } -} - -// Test that we encode nil-valued fields of a repeated bytes field correctly. -// Since entries in a repeated field cannot be nil, nil must mean empty value. -func TestEncodeDecodeBytes2(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRepeated = [][]byte{nil} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil { - t.Error("Unexpected value for repeated bytes field") - } -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestSkippingUnrecognizedFields(t *testing.T) { - o := old() - pb := initGoTestField() - - // Marshal it normally. - o.Marshal(pb) - - // Now new a GoSkipTest record. - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - // Marshal it into same buffer. - o.Marshal(skip) - - pbd := new(GoTestField) - o.Unmarshal(pbd) - - // The __unrecognized field should be a marshaling of GoSkipTest - skipd := new(GoSkipTest) - - o.SetBuf(pbd.XXX_unrecognized) - o.Unmarshal(skipd) - - if *skipd.SkipInt32 != *skip.SkipInt32 { - t.Error("skip int32", skipd.SkipInt32) - } - if *skipd.SkipFixed32 != *skip.SkipFixed32 { - t.Error("skip fixed32", skipd.SkipFixed32) - } - if *skipd.SkipFixed64 != *skip.SkipFixed64 { - t.Error("skip fixed64", skipd.SkipFixed64) - } - if *skipd.SkipString != *skip.SkipString { - t.Error("skip string", *skipd.SkipString) - } - if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 { - t.Error("skip group int32", skipd.Skipgroup.GroupInt32) - } - if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString { - t.Error("skip group string", *skipd.Skipgroup.GroupString) - } -} - -// Check that unrecognized fields of a submessage are preserved. -func TestSubmessageUnrecognizedFields(t *testing.T) { - nm := &NewMessage{ - Nested: &NewMessage_Nested{ - Name: String("Nigel"), - FoodGroup: String("carbs"), - }, - } - b, err := Marshal(nm) - if err != nil { - t.Fatalf("Marshal of NewMessage: %v", err) - } - - // Unmarshal into an OldMessage. - om := new(OldMessage) - if err := Unmarshal(b, om); err != nil { - t.Fatalf("Unmarshal to OldMessage: %v", err) - } - exp := &OldMessage{ - Nested: &OldMessage_Nested{ - Name: String("Nigel"), - // normal protocol buffer users should not do this - XXX_unrecognized: []byte("\x12\x05carbs"), - }, - } - if !Equal(om, exp) { - t.Errorf("om = %v, want %v", om, exp) - } - - // Clone the OldMessage. - om = Clone(om).(*OldMessage) - if !Equal(om, exp) { - t.Errorf("Clone(om) = %v, want %v", om, exp) - } - - // Marshal the OldMessage, then unmarshal it into an empty NewMessage. - if b, err = Marshal(om); err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - t.Logf("Marshal(%v) -> %q", om, b) - nm2 := new(NewMessage) - if err := Unmarshal(b, nm2); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - if !Equal(nm, nm2) { - t.Errorf("NewMessage round-trip: %v => %v", nm, nm2) - } -} - -// Check that an int32 field can be upgraded to an int64 field. -func TestNegativeInt32(t *testing.T) { - om := &OldMessage{ - Num: Int32(-1), - } - b, err := Marshal(om) - if err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - - // Check the size. It should be 11 bytes; - // 1 for the field/wire type, and 10 for the negative number. - if len(b) != 11 { - t.Errorf("%v marshaled as %q, wanted 11 bytes", om, b) - } - - // Unmarshal into a NewMessage. - nm := new(NewMessage) - if err := Unmarshal(b, nm); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - want := &NewMessage{ - Num: Int64(-1), - } - if !Equal(nm, want) { - t.Errorf("nm = %v, want %v", nm, want) - } -} - -// Check that we can grow an array (repeated field) to have many elements. -// This test doesn't depend only on our encoding; for variety, it makes sure -// we create, encode, and decode the correct contents explicitly. It's therefore -// a bit messier. -// This test also uses (and hence tests) the Marshal/Unmarshal functions -// instead of the methods. -func TestBigRepeated(t *testing.T) { - pb := initGoTest(true) - - // Create the arrays - const N = 50 // Internally the library starts much smaller. - pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N) - pb.F_Sint64Repeated = make([]int64, N) - pb.F_Sint32Repeated = make([]int32, N) - pb.F_BytesRepeated = make([][]byte, N) - pb.F_StringRepeated = make([]string, N) - pb.F_DoubleRepeated = make([]float64, N) - pb.F_FloatRepeated = make([]float32, N) - pb.F_Uint64Repeated = make([]uint64, N) - pb.F_Uint32Repeated = make([]uint32, N) - pb.F_Fixed64Repeated = make([]uint64, N) - pb.F_Fixed32Repeated = make([]uint32, N) - pb.F_Int64Repeated = make([]int64, N) - pb.F_Int32Repeated = make([]int32, N) - pb.F_BoolRepeated = make([]bool, N) - pb.RepeatedField = make([]*GoTestField, N) - - // Fill in the arrays with checkable values. - igtf := initGoTestField() - igtrg := initGoTest_RepeatedGroup() - for i := 0; i < N; i++ { - pb.Repeatedgroup[i] = igtrg - pb.F_Sint64Repeated[i] = int64(i) - pb.F_Sint32Repeated[i] = int32(i) - s := fmt.Sprint(i) - pb.F_BytesRepeated[i] = []byte(s) - pb.F_StringRepeated[i] = s - pb.F_DoubleRepeated[i] = float64(i) - pb.F_FloatRepeated[i] = float32(i) - pb.F_Uint64Repeated[i] = uint64(i) - pb.F_Uint32Repeated[i] = uint32(i) - pb.F_Fixed64Repeated[i] = uint64(i) - pb.F_Fixed32Repeated[i] = uint32(i) - pb.F_Int64Repeated[i] = int64(i) - pb.F_Int32Repeated[i] = int32(i) - pb.F_BoolRepeated[i] = i%2 == 0 - pb.RepeatedField[i] = igtf - } - - // Marshal. - buf, _ := Marshal(pb) - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - Unmarshal(buf, pbd) - - // Check the checkable values - for i := uint64(0); i < N; i++ { - if pbd.Repeatedgroup[i] == nil { // TODO: more checking? - t.Error("pbd.Repeatedgroup bad") - } - var x uint64 - x = uint64(pbd.F_Sint64Repeated[i]) - if x != i { - t.Error("pbd.F_Sint64Repeated bad", x, i) - } - x = uint64(pbd.F_Sint32Repeated[i]) - if x != i { - t.Error("pbd.F_Sint32Repeated bad", x, i) - } - s := fmt.Sprint(i) - equalbytes(pbd.F_BytesRepeated[i], []byte(s), t) - if pbd.F_StringRepeated[i] != s { - t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i) - } - x = uint64(pbd.F_DoubleRepeated[i]) - if x != i { - t.Error("pbd.F_DoubleRepeated bad", x, i) - } - x = uint64(pbd.F_FloatRepeated[i]) - if x != i { - t.Error("pbd.F_FloatRepeated bad", x, i) - } - x = pbd.F_Uint64Repeated[i] - if x != i { - t.Error("pbd.F_Uint64Repeated bad", x, i) - } - x = uint64(pbd.F_Uint32Repeated[i]) - if x != i { - t.Error("pbd.F_Uint32Repeated bad", x, i) - } - x = pbd.F_Fixed64Repeated[i] - if x != i { - t.Error("pbd.F_Fixed64Repeated bad", x, i) - } - x = uint64(pbd.F_Fixed32Repeated[i]) - if x != i { - t.Error("pbd.F_Fixed32Repeated bad", x, i) - } - x = uint64(pbd.F_Int64Repeated[i]) - if x != i { - t.Error("pbd.F_Int64Repeated bad", x, i) - } - x = uint64(pbd.F_Int32Repeated[i]) - if x != i { - t.Error("pbd.F_Int32Repeated bad", x, i) - } - if pbd.F_BoolRepeated[i] != (i%2 == 0) { - t.Error("pbd.F_BoolRepeated bad", x, i) - } - if pbd.RepeatedField[i] == nil { // TODO: more checking? - t.Error("pbd.RepeatedField bad") - } - } -} - -// Verify we give a useful message when decoding to the wrong structure type. -func TestTypeMismatch(t *testing.T) { - pb1 := initGoTest(true) - - // Marshal - o := old() - o.Marshal(pb1) - - // Now Unmarshal it to the wrong type. - pb2 := initGoTestField() - err := o.Unmarshal(pb2) - if err == nil { - t.Error("expected error, got no error") - } else if !strings.Contains(err.Error(), "bad wiretype") { - t.Error("expected bad wiretype error, got", err) - } -} - -func encodeDecode(t *testing.T, in, out Message, msg string) { - buf, err := Marshal(in) - if err != nil { - t.Fatalf("failed marshaling %v: %v", msg, err) - } - if err := Unmarshal(buf, out); err != nil { - t.Fatalf("failed unmarshaling %v: %v", msg, err) - } -} - -func TestPackedNonPackedDecoderSwitching(t *testing.T) { - np, p := new(NonPackedTest), new(PackedTest) - - // non-packed -> packed - np.A = []int32{0, 1, 1, 2, 3, 5} - encodeDecode(t, np, p, "non-packed -> packed") - if !reflect.DeepEqual(np.A, p.B) { - t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B) - } - - // packed -> non-packed - np.Reset() - p.B = []int32{3, 1, 4, 1, 5, 9} - encodeDecode(t, p, np, "packed -> non-packed") - if !reflect.DeepEqual(p.B, np.A) { - t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A) - } -} - -func TestProto1RepeatedGroup(t *testing.T) { - pb := &MessageList{ - Message: []*MessageList_Message{ - { - Name: String("blah"), - Count: Int32(7), - }, - // NOTE: pb.Message[1] is a nil - nil, - }, - } - - o := old() - err := o.Marshal(pb) - if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") { - t.Fatalf("unexpected or no error when marshaling: %v", err) - } -} - -// Test that enums work. Checks for a bug introduced by making enums -// named types instead of int32: newInt32FromUint64 would crash with -// a type mismatch in reflect.PointTo. -func TestEnum(t *testing.T) { - pb := new(GoEnum) - pb.Foo = FOO_FOO1.Enum() - o := old() - if err := o.Marshal(pb); err != nil { - t.Fatal("error encoding enum:", err) - } - pb1 := new(GoEnum) - if err := o.Unmarshal(pb1); err != nil { - t.Fatal("error decoding enum:", err) - } - if *pb1.Foo != FOO_FOO1 { - t.Error("expected 7 but got ", *pb1.Foo) - } -} - -// Enum types have String methods. Check that enum fields can be printed. -// We don't care what the value actually is, just as long as it doesn't crash. -func TestPrintingNilEnumFields(t *testing.T) { - pb := new(GoEnum) - _ = fmt.Sprintf("%+v", pb) -} - -// Verify that absent required fields cause Marshal/Unmarshal to return errors. -func TestRequiredFieldEnforcement(t *testing.T) { - pb := new(GoTestField) - _, err := Marshal(pb) - if err == nil { - t.Error("marshal: expected error, got nil") - } else if strings.Index(err.Error(), "Label") < 0 { - t.Errorf("marshal: bad error type: %v", err) - } - - // A slightly sneaky, yet valid, proto. It encodes the same required field twice, - // so simply counting the required fields is insufficient. - // field 1, encoding 2, value "hi" - buf := []byte("\x0A\x02hi\x0A\x02hi") - err = Unmarshal(buf, pb) - if err == nil { - t.Error("unmarshal: expected error, got nil") - } else if strings.Index(err.Error(), "{Unknown}") < 0 { - t.Errorf("unmarshal: bad error type: %v", err) - } -} - -func TestTypedNilMarshal(t *testing.T) { - // A typed nil should return ErrNil and not crash. - _, err := Marshal((*GoEnum)(nil)) - if err != ErrNil { - t.Errorf("Marshal: got err %v, want ErrNil", err) - } -} - -// A type that implements the Marshaler interface, but is not nillable. -type nonNillableInt uint64 - -func (nni nonNillableInt) Marshal() ([]byte, error) { - return EncodeVarint(uint64(nni)), nil -} - -type NNIMessage struct { - nni nonNillableInt -} - -func (*NNIMessage) Reset() {} -func (*NNIMessage) String() string { return "" } -func (*NNIMessage) ProtoMessage() {} - -// A type that implements the Marshaler interface and is nillable. -type nillableMessage struct { - x uint64 -} - -func (nm *nillableMessage) Marshal() ([]byte, error) { - return EncodeVarint(nm.x), nil -} - -type NMMessage struct { - nm *nillableMessage -} - -func (*NMMessage) Reset() {} -func (*NMMessage) String() string { return "" } -func (*NMMessage) ProtoMessage() {} - -// Verify a type that uses the Marshaler interface, but has a nil pointer. -func TestNilMarshaler(t *testing.T) { - // Try a struct with a Marshaler field that is nil. - // It should be directly marshable. - nmm := new(NMMessage) - if _, err := Marshal(nmm); err != nil { - t.Error("unexpected error marshaling nmm: ", err) - } - - // Try a struct with a Marshaler field that is not nillable. - nnim := new(NNIMessage) - nnim.nni = 7 - var _ Marshaler = nnim.nni // verify it is truly a Marshaler - if _, err := Marshal(nnim); err != nil { - t.Error("unexpected error marshaling nnim: ", err) - } -} - -func TestAllSetDefaults(t *testing.T) { - // Exercise SetDefaults with all scalar field types. - m := &Defaults{ - // NaN != NaN, so override that here. - F_Nan: Float32(1.7), - } - expected := &Defaults{ - F_Bool: Bool(true), - F_Int32: Int32(32), - F_Int64: Int64(64), - F_Fixed32: Uint32(320), - F_Fixed64: Uint64(640), - F_Uint32: Uint32(3200), - F_Uint64: Uint64(6400), - F_Float: Float32(314159), - F_Double: Float64(271828), - F_String: String(`hello, "world!"` + "\n"), - F_Bytes: []byte("Bignose"), - F_Sint32: Int32(-32), - F_Sint64: Int64(-64), - F_Enum: Defaults_GREEN.Enum(), - F_Pinf: Float32(float32(math.Inf(1))), - F_Ninf: Float32(float32(math.Inf(-1))), - F_Nan: Float32(1.7), - StrZero: String(""), - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("SetDefaults failed\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithSetField(t *testing.T) { - // Check that a set value is not overridden. - m := &Defaults{ - F_Int32: Int32(12), - } - SetDefaults(m) - if v := m.GetF_Int32(); v != 12 { - t.Errorf("m.FInt32 = %v, want 12", v) - } -} - -func TestSetDefaultsWithSubMessage(t *testing.T) { - m := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - }, - } - expected := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - Port: Int32(4000), - }, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) { - m := &MyMessage{ - RepInner: []*InnerMessage{{}}, - } - expected := &MyMessage{ - RepInner: []*InnerMessage{{ - Port: Int32(4000), - }}, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultWithRepeatedNonMessage(t *testing.T) { - m := &MyMessage{ - Pet: []string{"turtle", "wombat"}, - } - expected := Clone(m) - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestMaximumTagNumber(t *testing.T) { - m := &MaxTag{ - LastField: String("natural goat essence"), - } - buf, err := Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal failed: %v", err) - } - m2 := new(MaxTag) - if err := Unmarshal(buf, m2); err != nil { - t.Fatalf("proto.Unmarshal failed: %v", err) - } - if got, want := m2.GetLastField(), *m.LastField; got != want { - t.Errorf("got %q, want %q", got, want) - } -} - -func TestJSON(t *testing.T) { - m := &MyMessage{ - Count: Int32(4), - Pet: []string{"bunny", "kitty"}, - Inner: &InnerMessage{ - Host: String("cauchy"), - }, - Bikeshed: MyMessage_GREEN.Enum(), - } - const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":1}` - - b, err := json.Marshal(m) - if err != nil { - t.Fatalf("json.Marshal failed: %v", err) - } - s := string(b) - if s != expected { - t.Errorf("got %s\nwant %s", s, expected) - } - - received := new(MyMessage) - if err := json.Unmarshal(b, received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } - - // Test unmarshalling of JSON with symbolic enum name. - const old = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":"GREEN"}` - received.Reset() - if err := json.Unmarshal([]byte(old), received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } -} - -func TestBadWireType(t *testing.T) { - b := []byte{7<<3 | 6} // field 7, wire type 6 - pb := new(OtherMessage) - if err := Unmarshal(b, pb); err == nil { - t.Errorf("Unmarshal did not fail") - } else if !strings.Contains(err.Error(), "unknown wire type") { - t.Errorf("wrong error: %v", err) - } -} - -func TestBytesWithInvalidLength(t *testing.T) { - // If a byte sequence has an invalid (negative) length, Unmarshal should not panic. - b := []byte{2<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0} - Unmarshal(b, new(MyMessage)) -} - -func TestLengthOverflow(t *testing.T) { - // Overflowing a length should not panic. - b := []byte{2<<3 | WireBytes, 1, 1, 3<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01} - Unmarshal(b, new(MyMessage)) -} - -func TestVarintOverflow(t *testing.T) { - // Overflowing a 64-bit length should not be allowed. - b := []byte{1<<3 | WireVarint, 0x01, 3<<3 | WireBytes, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} - if err := Unmarshal(b, new(MyMessage)); err == nil { - t.Fatalf("Overflowed uint64 length without error") - } -} - -func TestUnmarshalFuzz(t *testing.T) { - const N = 1000 - seed := time.Now().UnixNano() - t.Logf("RNG seed is %d", seed) - rng := rand.New(rand.NewSource(seed)) - buf := make([]byte, 20) - for i := 0; i < N; i++ { - for j := range buf { - buf[j] = byte(rng.Intn(256)) - } - fuzzUnmarshal(t, buf) - } -} - -func TestMergeMessages(t *testing.T) { - pb := &MessageList{Message: []*MessageList_Message{{Name: String("x"), Count: Int32(1)}}} - data, err := Marshal(pb) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - pb1 := new(MessageList) - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("first Unmarshal: %v", err) - } - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("second Unmarshal: %v", err) - } - if len(pb1.Message) != 1 { - t.Errorf("two Unmarshals produced %d Messages, want 1", len(pb1.Message)) - } - - pb2 := new(MessageList) - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("first UnmarshalMerge: %v", err) - } - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("second UnmarshalMerge: %v", err) - } - if len(pb2.Message) != 2 { - t.Errorf("two UnmarshalMerges produced %d Messages, want 2", len(pb2.Message)) - } -} - -func TestExtensionMarshalOrder(t *testing.T) { - m := &MyMessage{Count: Int(123)} - if err := SetExtension(m, E_Ext_More, &Ext{Data: String("alpha")}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Text, String("aleph")); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Number, Int32(1)); err != nil { - t.Fatalf("SetExtension: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - var orig []byte - for i := 0; i < 100; i++ { - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if i == 0 { - orig = b - continue - } - if !bytes.Equal(b, orig) { - t.Errorf("Bytes differ on attempt #%d", i) - } - } -} - -// Many extensions, because small maps might not iterate differently on each iteration. -var exts = []*ExtensionDesc{ - E_X201, - E_X202, - E_X203, - E_X204, - E_X205, - E_X206, - E_X207, - E_X208, - E_X209, - E_X210, - E_X211, - E_X212, - E_X213, - E_X214, - E_X215, - E_X216, - E_X217, - E_X218, - E_X219, - E_X220, - E_X221, - E_X222, - E_X223, - E_X224, - E_X225, - E_X226, - E_X227, - E_X228, - E_X229, - E_X230, - E_X231, - E_X232, - E_X233, - E_X234, - E_X235, - E_X236, - E_X237, - E_X238, - E_X239, - E_X240, - E_X241, - E_X242, - E_X243, - E_X244, - E_X245, - E_X246, - E_X247, - E_X248, - E_X249, - E_X250, -} - -func TestMessageSetMarshalOrder(t *testing.T) { - m := &MyMessageSet{} - for _, x := range exts { - if err := SetExtension(m, x, &Empty{}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - } - - buf, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - for i := 0; i < 10; i++ { - b1, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if !bytes.Equal(b1, buf) { - t.Errorf("Bytes differ on re-Marshal #%d", i) - } - - m2 := &MyMessageSet{} - if err := Unmarshal(buf, m2); err != nil { - t.Errorf("Unmarshal: %v", err) - } - b2, err := Marshal(m2) - if err != nil { - t.Errorf("re-Marshal: %v", err) - } - if !bytes.Equal(b2, buf) { - t.Errorf("Bytes differ on round-trip #%d", i) - } - } -} - -func TestUnmarshalMergesMessages(t *testing.T) { - // If a nested message occurs twice in the input, - // the fields should be merged when decoding. - a := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("polhode"), - Port: Int32(1234), - }, - } - aData, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal(a): %v", err) - } - b := &OtherMessage{ - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Connected: Bool(true), - }, - } - bData, err := Marshal(b) - if err != nil { - t.Fatalf("Marshal(b): %v", err) - } - want := &OtherMessage{ - Key: Int64(123), - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Port: Int32(1234), - Connected: Bool(true), - }, - } - got := new(OtherMessage) - if err := Unmarshal(append(aData, bData...), got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(got, want) { - t.Errorf("\n got %v\nwant %v", got, want) - } -} - -func TestEncodingSizes(t *testing.T) { - tests := []struct { - m Message - n int - }{ - {&Defaults{F_Int32: Int32(math.MaxInt32)}, 6}, - {&Defaults{F_Int32: Int32(math.MinInt32)}, 11}, - {&Defaults{F_Uint32: Uint32(uint32(math.MaxInt32) + 1)}, 6}, - {&Defaults{F_Uint32: Uint32(math.MaxUint32)}, 6}, - } - for _, test := range tests { - b, err := Marshal(test.m) - if err != nil { - t.Errorf("Marshal(%v): %v", test.m, err) - continue - } - if len(b) != test.n { - t.Errorf("Marshal(%v) yielded %d bytes, want %d bytes", test.m, len(b), test.n) - } - } -} - -func TestRequiredNotSetError(t *testing.T) { - pb := initGoTest(false) - pb.RequiredField.Label = nil - pb.F_Int32Required = nil - pb.F_Int64Required = nil - - expected := "0807" + // field 1, encoding 0, value 7 - "2206" + "120474797065" + // field 4, encoding 2 (GoTestField) - "5001" + // field 10, encoding 0, value 1 - "6d20000000" + // field 13, encoding 5, value 0x20 - "714000000000000000" + // field 14, encoding 1, value 0x40 - "78a019" + // field 15, encoding 0, value 0xca0 = 3232 - "8001c032" + // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45" + // field 17, encoding 5, value 3232.0 - "9101000000000040b940" + // field 18, encoding 1, value 6464.0 - "9a0106" + "737472696e67" + // field 19, encoding 2, string "string" - "b304" + // field 70, encoding 3, start group - "ba0408" + "7265717569726564" + // field 71, encoding 2, string "required" - "b404" + // field 70, encoding 4, end group - "aa0605" + "6279746573" + // field 101, encoding 2, string "bytes" - "b0063f" + // field 102, encoding 0, 0x3f zigzag32 - "b8067f" // field 103, encoding 0, 0x7f zigzag64 - - o := old() - bytes, err := Marshal(pb) - if _, ok := err.(*RequiredNotSetError); !ok { - fmt.Printf("marshal-1 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("expected = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.Label") < 0 { - t.Errorf("marshal-1 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 1", bytes) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = Unmarshal(bytes, pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Fatalf("unmarshal err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.{Unknown}") < 0 { - t.Errorf("unmarshal wrong err msg: %v", err) - } - bytes, err = Marshal(pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("marshal-2 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.Label") < 0 { - t.Errorf("marshal-2 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 2", bytes) - t.Fatalf("string = %s", expected) - } -} - -func fuzzUnmarshal(t *testing.T, data []byte) { - defer func() { - if e := recover(); e != nil { - t.Errorf("These bytes caused a panic: %+v", data) - t.Logf("Stack:\n%s", debug.Stack()) - t.FailNow() - } - }() - - pb := new(MyMessage) - Unmarshal(data, pb) -} - -func TestMapFieldMarshal(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // b should be the concatenation of these three byte sequences in some order. - parts := []string{ - "\n\a\b\x01\x12\x03Rob", - "\n\a\b\x04\x12\x03Ian", - "\n\b\b\x08\x12\x04Dave", - } - ok := false - for i := range parts { - for j := range parts { - if j == i { - continue - } - for k := range parts { - if k == i || k == j { - continue - } - try := parts[i] + parts[j] + parts[k] - if bytes.Equal(b, []byte(try)) { - ok = true - break - } - } - } - } - if !ok { - t.Fatalf("Incorrect Marshal output.\n got %q\nwant %q (or a permutation of that)", b, parts[0]+parts[1]+parts[2]) - } - t.Logf("FYI b: %q", b) - - (new(Buffer)).DebugPrint("Dump of b", b) -} - -func TestMapFieldRoundTrips(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - MsgMapping: map[int64]*FloatingPoint{ - 0x7001: {F: Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{ - false: []byte("that's not right!"), - true: []byte("aye, 'tis true!"), - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("FYI b: %q", b) - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - for _, pair := range [][2]interface{}{ - {m.NameMapping, m2.NameMapping}, - {m.MsgMapping, m2.MsgMapping}, - {m.ByteMapping, m2.ByteMapping}, - } { - if !reflect.DeepEqual(pair[0], pair[1]) { - t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", pair[0], pair[1]) - } - } -} - -func TestMapFieldWithNil(t *testing.T) { - m := &MessageWithMap{ - MsgMapping: map[int64]*FloatingPoint{ - 1: nil, - }, - } - b, err := Marshal(m) - if err == nil { - t.Fatalf("Marshal of bad map should have failed, got these bytes: %v", b) - } -} - -func TestOneof(t *testing.T) { - m := &Communique{} - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal of empty message with oneof: %v", err) - } - if len(b) != 0 { - t.Errorf("Marshal of empty message yielded too many bytes: %v", b) - } - - m = &Communique{ - Union: &Communique_Name{"Barry"}, - } - - // Round-trip. - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof: %v", err) - } - if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5) - t.Errorf("Incorrect marshal of message with oneof: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof: %v", err) - } - if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" { - t.Errorf("After round trip, Union = %+v", m.Union) - } - if name := m.GetName(); name != "Barry" { - t.Errorf("After round trip, GetName = %q, want %q", name, "Barry") - } - - // Let's try with a message in the oneof. - m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}} - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof set to message: %v", err) - } - if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16) - t.Errorf("Incorrect marshal of message with oneof set to message: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof set to message: %v", err) - } - ss, ok := m.Union.(*Communique_Msg) - if !ok || ss.Msg.GetStringField() != "deep deep string" { - t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union) - } -} - -func TestInefficientPackedBool(t *testing.T) { - // https://github.com/golang/protobuf/issues/76 - inp := []byte{ - 0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes - // Usually a bool should take a single byte, - // but it is permitted to be any varint. - 0xb9, 0x30, - } - if err := Unmarshal(inp, new(MoreRepeated)); err != nil { - t.Error(err) - } -} - -// Benchmarks - -func testMsg() *GoTest { - pb := initGoTest(true) - const N = 1000 // Internally the library starts much smaller. - pb.F_Int32Repeated = make([]int32, N) - pb.F_DoubleRepeated = make([]float64, N) - for i := 0; i < N; i++ { - pb.F_Int32Repeated[i] = int32(i) - pb.F_DoubleRepeated[i] = float64(i) - } - return pb -} - -func bytesMsg() *GoTest { - pb := initGoTest(true) - buf := make([]byte, 4000) - for i := range buf { - buf[i] = byte(i) - } - pb.F_BytesDefaulted = buf - return pb -} - -func benchmarkMarshal(b *testing.B, pb Message, marshal func(Message) ([]byte, error)) { - d, _ := marshal(pb) - b.SetBytes(int64(len(d))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - marshal(pb) - } -} - -func benchmarkBufferMarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - p.Reset() - err := p.Marshal(pb0) - return p.Bytes(), err - }) -} - -func benchmarkSize(b *testing.B, pb Message) { - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - Size(pb) - return nil, nil - }) -} - -func newOf(pb Message) Message { - in := reflect.ValueOf(pb) - if in.IsNil() { - return pb - } - return reflect.New(in.Type().Elem()).Interface().(Message) -} - -func benchmarkUnmarshal(b *testing.B, pb Message, unmarshal func([]byte, Message) error) { - d, _ := Marshal(pb) - b.SetBytes(int64(len(d))) - pbd := newOf(pb) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - unmarshal(d, pbd) - } -} - -func benchmarkBufferUnmarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkUnmarshal(b, pb, func(d []byte, pb0 Message) error { - p.SetBuf(d) - return p.Unmarshal(pb0) - }) -} - -// Benchmark{Marshal,BufferMarshal,Size,Unmarshal,BufferUnmarshal}{,Bytes} - -func BenchmarkMarshal(b *testing.B) { - benchmarkMarshal(b, testMsg(), Marshal) -} - -func BenchmarkBufferMarshal(b *testing.B) { - benchmarkBufferMarshal(b, testMsg()) -} - -func BenchmarkSize(b *testing.B) { - benchmarkSize(b, testMsg()) -} - -func BenchmarkUnmarshal(b *testing.B) { - benchmarkUnmarshal(b, testMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshal(b *testing.B) { - benchmarkBufferUnmarshal(b, testMsg()) -} - -func BenchmarkMarshalBytes(b *testing.B) { - benchmarkMarshal(b, bytesMsg(), Marshal) -} - -func BenchmarkBufferMarshalBytes(b *testing.B) { - benchmarkBufferMarshal(b, bytesMsg()) -} - -func BenchmarkSizeBytes(b *testing.B) { - benchmarkSize(b, bytesMsg()) -} - -func BenchmarkUnmarshalBytes(b *testing.B) { - benchmarkUnmarshal(b, bytesMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshalBytes(b *testing.B) { - benchmarkBufferUnmarshal(b, bytesMsg()) -} - -func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) { - b.StopTimer() - pb := initGoTestField() - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - pbd := new(GoTestField) - p := NewBuffer(nil) - p.Marshal(pb) - p.Marshal(skip) - p2 := NewBuffer(nil) - - b.StartTimer() - for i := 0; i < b.N; i++ { - p2.SetBuf(p.Bytes()) - p2.Unmarshal(pbd) - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/clone_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/clone_test.go deleted file mode 100644 index f065210b8..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/clone_test.go +++ /dev/null @@ -1,267 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - "github.com/gogo/protobuf/proto" - - proto3pb "github.com/gogo/protobuf/proto/proto3_proto" - pb "github.com/gogo/protobuf/proto/testdata" -) - -var cloneTestMessage = &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, -} - -func init() { - ext := &pb.Ext{ - Data: proto.String("extension"), - } - if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { - panic("SetExtension: " + err.Error()) - } -} - -func TestClone(t *testing.T) { - m := proto.Clone(cloneTestMessage).(*pb.MyMessage) - if !proto.Equal(m, cloneTestMessage) { - t.Errorf("Clone(%v) = %v", cloneTestMessage, m) - } - - // Verify it was a deep copy. - *m.Inner.Port++ - if proto.Equal(m, cloneTestMessage) { - t.Error("Mutating clone changed the original") - } - // Byte fields and repeated fields should be copied. - if &m.Pet[0] == &cloneTestMessage.Pet[0] { - t.Error("Pet: repeated field not copied") - } - if &m.Others[0] == &cloneTestMessage.Others[0] { - t.Error("Others: repeated field not copied") - } - if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] { - t.Error("Others[0].Value: bytes field not copied") - } - if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] { - t.Error("RepBytes: repeated field not copied") - } - if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] { - t.Error("RepBytes[0]: bytes field not copied") - } -} - -func TestCloneNil(t *testing.T) { - var m *pb.MyMessage - if c := proto.Clone(m); !proto.Equal(m, c) { - t.Errorf("Clone(%v) = %v", m, c) - } -} - -var mergeTests = []struct { - src, dst, want proto.Message -}{ - { - src: &pb.MyMessage{ - Count: proto.Int32(42), - }, - dst: &pb.MyMessage{ - Name: proto.String("Dave"), - }, - want: &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - }, - }, - { - src: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - }, - Pet: []string{"horsey"}, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - }, - dst: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - { - // Explicitly test a src=nil field - Inner: nil, - }, - }, - }, - want: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty", "horsey"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - {}, - { - Value: []byte("some bytes"), - }, - }, - }, - }, - { - src: &pb.MyMessage{ - RepBytes: [][]byte{[]byte("wow")}, - }, - dst: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham")}, - }, - want: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, - }, - }, - // Check that a scalar bytes field replaces rather than appends. - { - src: &pb.OtherMessage{Value: []byte("foo")}, - dst: &pb.OtherMessage{Value: []byte("bar")}, - want: &pb.OtherMessage{Value: []byte("foo")}, - }, - { - src: &pb.MessageWithMap{ - NameMapping: map[int32]string{6: "Nigel"}, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: {F: proto.Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - dst: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Bruce", // should be overwritten - 7: "Andrew", - }, - }, - want: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Nigel", - 7: "Andrew", - }, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: {F: proto.Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - }, - // proto3 shouldn't merge zero values, - // in the same way that proto2 shouldn't merge nils. - { - src: &proto3pb.Message{ - Name: "Aaron", - Data: []byte(""), // zero value, but not nil - }, - dst: &proto3pb.Message{ - HeightInCm: 176, - Data: []byte("texas!"), - }, - want: &proto3pb.Message{ - Name: "Aaron", - HeightInCm: 176, - Data: []byte("texas!"), - }, - }, - // Oneof fields should merge by assignment. - { - src: &pb.Communique{ - Union: &pb.Communique_Number{Number: 41}, - }, - dst: &pb.Communique{ - Union: &pb.Communique_Name{Name: "Bobby Tables"}, - }, - want: &pb.Communique{ - Union: &pb.Communique_Number{Number: 41}, - }, - }, - // Oneof nil is the same as not set. - { - src: &pb.Communique{}, - dst: &pb.Communique{ - Union: &pb.Communique_Name{Name: "Bobby Tables"}, - }, - want: &pb.Communique{ - Union: &pb.Communique_Name{Name: "Bobby Tables"}, - }, - }, -} - -func TestMerge(t *testing.T) { - for _, m := range mergeTests { - got := proto.Clone(m.dst) - proto.Merge(got, m.src) - if !proto.Equal(got, m.want) { - t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want) - } - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/equal_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/equal_test.go deleted file mode 100644 index 7cb36d378..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/equal_test.go +++ /dev/null @@ -1,209 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - . "github.com/gogo/protobuf/proto" - pb "github.com/gogo/protobuf/proto/testdata" -) - -// Four identical base messages. -// The init function adds extensions to some of them. -var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)} - -// Two messages with non-message extensions. -var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)} -var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)} - -func init() { - ext1 := &pb.Ext{Data: String("Kirk")} - ext2 := &pb.Ext{Data: String("Picard")} - - // messageWithExtension1a has ext1, but never marshals it. - if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil { - panic("SetExtension on 1a failed: " + err.Error()) - } - - // messageWithExtension1b is the unmarshaled form of messageWithExtension1a. - if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil { - panic("SetExtension on 1b failed: " + err.Error()) - } - buf, err := Marshal(messageWithExtension1b) - if err != nil { - panic("Marshal of 1b failed: " + err.Error()) - } - messageWithExtension1b.Reset() - if err := Unmarshal(buf, messageWithExtension1b); err != nil { - panic("Unmarshal of 1b failed: " + err.Error()) - } - - // messageWithExtension2 has ext2. - if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil { - panic("SetExtension on 2 failed: " + err.Error()) - } - - if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil { - panic("SetExtension on Int32-1 failed: " + err.Error()) - } - if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil { - panic("SetExtension on Int32-2 failed: " + err.Error()) - } -} - -var EqualTests = []struct { - desc string - a, b Message - exp bool -}{ - {"different types", &pb.GoEnum{}, &pb.GoTestField{}, false}, - {"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true}, - {"nil vs nil", nil, nil, true}, - {"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true}, - {"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false}, - {"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false}, - - {"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false}, - {"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false}, - {"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false}, - {"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true}, - - {"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false}, - {"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false}, - {"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false}, - {"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true}, - {"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true}, - {"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true}, - {"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true}, - - { - "nested, different", - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}}, - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}}, - false, - }, - { - "nested, equal", - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, - true, - }, - - {"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true}, - {"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true}, - {"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false}, - { - "repeated bytes", - &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, - &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, - true, - }, - - {"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false}, - {"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true}, - {"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false}, - - {"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true}, - {"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false}, - - { - "message with group", - &pb.MyMessage{ - Count: Int32(1), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: Int32(5), - }, - }, - &pb.MyMessage{ - Count: Int32(1), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: Int32(5), - }, - }, - true, - }, - - { - "map same", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - true, - }, - { - "map different entry", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}}, - false, - }, - { - "map different key only", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}}, - false, - }, - { - "map different value only", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}}, - false, - }, - { - "oneof same", - &pb.Communique{Union: &pb.Communique_Number{Number: 41}}, - &pb.Communique{Union: &pb.Communique_Number{Number: 41}}, - true, - }, - { - "oneof one nil", - &pb.Communique{Union: &pb.Communique_Number{Number: 41}}, - &pb.Communique{}, - false, - }, - { - "oneof different", - &pb.Communique{Union: &pb.Communique_Number{Number: 41}}, - &pb.Communique{Union: &pb.Communique_Name{Name: "Bobby Tables"}}, - false, - }, -} - -func TestEqual(t *testing.T) { - for _, tc := range EqualTests { - if res := Equal(tc.a, tc.b); res != tc.exp { - t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp) - } - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/extensions_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/extensions_test.go deleted file mode 100644 index 86e3006d7..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/extensions_test.go +++ /dev/null @@ -1,292 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/gogo/protobuf/proto" - pb "github.com/gogo/protobuf/proto/testdata" -) - -func TestGetExtensionsWithMissingExtensions(t *testing.T) { - msg := &pb.MyMessage{} - ext1 := &pb.Ext{} - if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { - t.Fatalf("Could not set ext1: %s", ext1) - } - exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{ - pb.E_Ext_More, - pb.E_Ext_Text, - }) - if err != nil { - t.Fatalf("GetExtensions() failed: %s", err) - } - if exts[0] != ext1 { - t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0]) - } - if exts[1] != nil { - t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1]) - } -} - -func TestGetExtensionStability(t *testing.T) { - check := func(m *pb.MyMessage) bool { - ext1, err := proto.GetExtension(m, pb.E_Ext_More) - if err != nil { - t.Fatalf("GetExtension() failed: %s", err) - } - ext2, err := proto.GetExtension(m, pb.E_Ext_More) - if err != nil { - t.Fatalf("GetExtension() failed: %s", err) - } - return ext1 == ext2 - } - msg := &pb.MyMessage{Count: proto.Int32(4)} - ext0 := &pb.Ext{} - if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil { - t.Fatalf("Could not set ext1: %s", ext0) - } - if !check(msg) { - t.Errorf("GetExtension() not stable before marshaling") - } - bb, err := proto.Marshal(msg) - if err != nil { - t.Fatalf("Marshal() failed: %s", err) - } - msg1 := &pb.MyMessage{} - err = proto.Unmarshal(bb, msg1) - if err != nil { - t.Fatalf("Unmarshal() failed: %s", err) - } - if !check(msg1) { - t.Errorf("GetExtension() not stable after unmarshaling") - } -} - -func TestGetExtensionDefaults(t *testing.T) { - var setFloat64 float64 = 1 - var setFloat32 float32 = 2 - var setInt32 int32 = 3 - var setInt64 int64 = 4 - var setUint32 uint32 = 5 - var setUint64 uint64 = 6 - var setBool = true - var setBool2 = false - var setString = "Goodnight string" - var setBytes = []byte("Goodnight bytes") - var setEnum = pb.DefaultsMessage_TWO - - type testcase struct { - ext *proto.ExtensionDesc // Extension we are testing. - want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail). - def interface{} // Expected value of extension after ClearExtension(). - } - tests := []testcase{ - {pb.E_NoDefaultDouble, setFloat64, nil}, - {pb.E_NoDefaultFloat, setFloat32, nil}, - {pb.E_NoDefaultInt32, setInt32, nil}, - {pb.E_NoDefaultInt64, setInt64, nil}, - {pb.E_NoDefaultUint32, setUint32, nil}, - {pb.E_NoDefaultUint64, setUint64, nil}, - {pb.E_NoDefaultSint32, setInt32, nil}, - {pb.E_NoDefaultSint64, setInt64, nil}, - {pb.E_NoDefaultFixed32, setUint32, nil}, - {pb.E_NoDefaultFixed64, setUint64, nil}, - {pb.E_NoDefaultSfixed32, setInt32, nil}, - {pb.E_NoDefaultSfixed64, setInt64, nil}, - {pb.E_NoDefaultBool, setBool, nil}, - {pb.E_NoDefaultBool, setBool2, nil}, - {pb.E_NoDefaultString, setString, nil}, - {pb.E_NoDefaultBytes, setBytes, nil}, - {pb.E_NoDefaultEnum, setEnum, nil}, - {pb.E_DefaultDouble, setFloat64, float64(3.1415)}, - {pb.E_DefaultFloat, setFloat32, float32(3.14)}, - {pb.E_DefaultInt32, setInt32, int32(42)}, - {pb.E_DefaultInt64, setInt64, int64(43)}, - {pb.E_DefaultUint32, setUint32, uint32(44)}, - {pb.E_DefaultUint64, setUint64, uint64(45)}, - {pb.E_DefaultSint32, setInt32, int32(46)}, - {pb.E_DefaultSint64, setInt64, int64(47)}, - {pb.E_DefaultFixed32, setUint32, uint32(48)}, - {pb.E_DefaultFixed64, setUint64, uint64(49)}, - {pb.E_DefaultSfixed32, setInt32, int32(50)}, - {pb.E_DefaultSfixed64, setInt64, int64(51)}, - {pb.E_DefaultBool, setBool, true}, - {pb.E_DefaultBool, setBool2, true}, - {pb.E_DefaultString, setString, "Hello, string"}, - {pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")}, - {pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE}, - } - - checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error { - val, err := proto.GetExtension(msg, test.ext) - if err != nil { - if valWant != nil { - return fmt.Errorf("GetExtension(): %s", err) - } - if want := proto.ErrMissingExtension; err != want { - return fmt.Errorf("Unexpected error: got %v, want %v", err, want) - } - return nil - } - - // All proto2 extension values are either a pointer to a value or a slice of values. - ty := reflect.TypeOf(val) - tyWant := reflect.TypeOf(test.ext.ExtensionType) - if got, want := ty, tyWant; got != want { - return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want) - } - tye := ty.Elem() - tyeWant := tyWant.Elem() - if got, want := tye, tyeWant; got != want { - return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want) - } - - // Check the name of the type of the value. - // If it is an enum it will be type int32 with the name of the enum. - if got, want := tye.Name(), tye.Name(); got != want { - return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want) - } - - // Check that value is what we expect. - // If we have a pointer in val, get the value it points to. - valExp := val - if ty.Kind() == reflect.Ptr { - valExp = reflect.ValueOf(val).Elem().Interface() - } - if got, want := valExp, valWant; !reflect.DeepEqual(got, want) { - return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want) - } - - return nil - } - - setTo := func(test testcase) interface{} { - setTo := reflect.ValueOf(test.want) - if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr { - setTo = reflect.New(typ).Elem() - setTo.Set(reflect.New(setTo.Type().Elem())) - setTo.Elem().Set(reflect.ValueOf(test.want)) - } - return setTo.Interface() - } - - for _, test := range tests { - msg := &pb.DefaultsMessage{} - name := test.ext.Name - - // Check the initial value. - if err := checkVal(test, msg, test.def); err != nil { - t.Errorf("%s: %v", name, err) - } - - // Set the per-type value and check value. - name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want) - if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil { - t.Errorf("%s: SetExtension(): %v", name, err) - continue - } - if err := checkVal(test, msg, test.want); err != nil { - t.Errorf("%s: %v", name, err) - continue - } - - // Set and check the value. - name += " (cleared)" - proto.ClearExtension(msg, test.ext) - if err := checkVal(test, msg, test.def); err != nil { - t.Errorf("%s: %v", name, err) - } - } -} - -func TestExtensionsRoundTrip(t *testing.T) { - msg := &pb.MyMessage{} - ext1 := &pb.Ext{ - Data: proto.String("hi"), - } - ext2 := &pb.Ext{ - Data: proto.String("there"), - } - exists := proto.HasExtension(msg, pb.E_Ext_More) - if exists { - t.Error("Extension More present unexpectedly") - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { - t.Error(err) - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil { - t.Error(err) - } - e, err := proto.GetExtension(msg, pb.E_Ext_More) - if err != nil { - t.Error(err) - } - x, ok := e.(*pb.Ext) - if !ok { - t.Errorf("e has type %T, expected testdata.Ext", e) - } else if *x.Data != "there" { - t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x) - } - proto.ClearExtension(msg, pb.E_Ext_More) - if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension { - t.Errorf("got %v, expected ErrMissingExtension", e) - } - if _, err := proto.GetExtension(msg, pb.E_X215); err == nil { - t.Error("expected bad extension error, got nil") - } - if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil { - t.Error("expected extension err") - } - if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil { - t.Error("expected some sort of type mismatch error, got nil") - } -} - -func TestNilExtension(t *testing.T) { - msg := &pb.MyMessage{ - Count: proto.Int32(1), - } - if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil { - t.Fatal(err) - } - if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil { - t.Error("expected SetExtension to fail due to a nil extension") - } else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want { - t.Errorf("expected error %v, got %v", want, err) - } - // Note: if the behavior of Marshal is ever changed to ignore nil extensions, update - // this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal. -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/message_set_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/message_set_test.go deleted file mode 100644 index ab8ac2f0e..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/message_set_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "bytes" - "testing" -) - -func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { - // Check that a repeated message set entry will be concatenated. - in := &messageSet{ - Item: []*_MessageSet_Item{ - {TypeId: Int32(12345), Message: []byte("hoo")}, - {TypeId: Int32(12345), Message: []byte("hah")}, - }, - } - b, err := Marshal(in) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("Marshaled bytes: %q", b) - - m := make(map[int32]Extension) - if err := UnmarshalMessageSet(b, m); err != nil { - t.Fatalf("UnmarshalMessageSet: %v", err) - } - ext, ok := m[12345] - if !ok { - t.Fatalf("Didn't retrieve extension 12345; map is %v", m) - } - // Skip wire type/field number and length varints. - got := skipVarint(skipVarint(ext.enc)) - if want := []byte("hoohah"); !bytes.Equal(got, want) { - t.Errorf("Combined extension is %q, want %q", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.pb.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.pb.go deleted file mode 100644 index 0de701e88..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.pb.go +++ /dev/null @@ -1,129 +0,0 @@ -// Code generated by protoc-gen-gogo. -// source: proto3_proto/proto3.proto -// DO NOT EDIT! - -/* -Package proto3_proto is a generated protocol buffer package. - -It is generated from these files: - proto3_proto/proto3.proto - -It has these top-level messages: - Message - Nested - MessageWithMap -*/ -package proto3_proto - -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" -import testdata "github.com/gogo/protobuf/proto/testdata" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -type Message_Humour int32 - -const ( - Message_UNKNOWN Message_Humour = 0 - Message_PUNS Message_Humour = 1 - Message_SLAPSTICK Message_Humour = 2 - Message_BILL_BAILEY Message_Humour = 3 -) - -var Message_Humour_name = map[int32]string{ - 0: "UNKNOWN", - 1: "PUNS", - 2: "SLAPSTICK", - 3: "BILL_BAILEY", -} -var Message_Humour_value = map[string]int32{ - "UNKNOWN": 0, - "PUNS": 1, - "SLAPSTICK": 2, - "BILL_BAILEY": 3, -} - -func (x Message_Humour) String() string { - return proto.EnumName(Message_Humour_name, int32(x)) -} - -type Message struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,proto3,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` - HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,proto3" json:"height_in_cm,omitempty"` - Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` - ResultCount int64 `protobuf:"varint,7,opt,name=result_count,proto3" json:"result_count,omitempty"` - TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,proto3" json:"true_scotsman,omitempty"` - Score float32 `protobuf:"fixed32,9,opt,name=score,proto3" json:"score,omitempty"` - Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"` - Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"` - Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"` - Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field" json:"proto2_field,omitempty"` - Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"` -} - -func (m *Message) Reset() { *m = Message{} } -func (m *Message) String() string { return proto.CompactTextString(m) } -func (*Message) ProtoMessage() {} - -func (m *Message) GetNested() *Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *Message) GetTerrain() map[string]*Nested { - if m != nil { - return m.Terrain - } - return nil -} - -func (m *Message) GetProto2Field() *testdata.SubDefaults { - if m != nil { - return m.Proto2Field - } - return nil -} - -func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults { - if m != nil { - return m.Proto2Value - } - return nil -} - -type Nested struct { - Bunny string `protobuf:"bytes,1,opt,name=bunny,proto3" json:"bunny,omitempty"` -} - -func (m *Nested) Reset() { *m = Nested{} } -func (m *Nested) String() string { return proto.CompactTextString(m) } -func (*Nested) ProtoMessage() {} - -type MessageWithMap struct { - ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } -func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } -func (*MessageWithMap) ProtoMessage() {} - -func (m *MessageWithMap) GetByteMapping() map[bool][]byte { - if m != nil { - return m.ByteMapping - } - return nil -} - -func init() { - proto.RegisterType((*Message)(nil), "proto3_proto.Message") - proto.RegisterType((*Nested)(nil), "proto3_proto.Nested") - proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap") - proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.proto b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.proto deleted file mode 100644 index ca670015a..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_proto/proto3.proto +++ /dev/null @@ -1,68 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -package proto3_proto; - -import "github.com/gogo/protobuf/proto/testdata/test.proto"; - -message Message { - enum Humour { - UNKNOWN = 0; - PUNS = 1; - SLAPSTICK = 2; - BILL_BAILEY = 3; - } - - string name = 1; - Humour hilarity = 2; - uint32 height_in_cm = 3; - bytes data = 4; - int64 result_count = 7; - bool true_scotsman = 8; - float score = 9; - - repeated uint64 key = 5; - Nested nested = 6; - - map terrain = 10; - testdata.SubDefaults proto2_field = 11; - map proto2_value = 13; -} - -message Nested { - string bunny = 1; -} - -message MessageWithMap { - map byte_mapping = 1; -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_test.go deleted file mode 100644 index 6f9cddc3f..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/proto3_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - "github.com/gogo/protobuf/proto" - pb "github.com/gogo/protobuf/proto/proto3_proto" - tpb "github.com/gogo/protobuf/proto/testdata" -) - -func TestProto3ZeroValues(t *testing.T) { - tests := []struct { - desc string - m proto.Message - }{ - {"zero message", &pb.Message{}}, - {"empty bytes field", &pb.Message{Data: []byte{}}}, - } - for _, test := range tests { - b, err := proto.Marshal(test.m) - if err != nil { - t.Errorf("%s: proto.Marshal: %v", test.desc, err) - continue - } - if len(b) > 0 { - t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) - } - } -} - -func TestRoundTripProto3(t *testing.T) { - m := &pb.Message{ - Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" - Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 - HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 - Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" - ResultCount: 47, // (0 | 7<<3): 0x38 0x2f - TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 - Score: 8.1, // (5 | 9<<3): 0x4d <8.1> - - Key: []uint64{1, 0xdeadbeef}, - Nested: &pb.Nested{ - Bunny: "Monty", - }, - } - t.Logf(" m: %v", m) - - b, err := proto.Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal: %v", err) - } - t.Logf(" b: %q", b) - - m2 := new(pb.Message) - if err := proto.Unmarshal(b, m2); err != nil { - t.Fatalf("proto.Unmarshal: %v", err) - } - t.Logf("m2: %v", m2) - - if !proto.Equal(m, m2) { - t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) - } -} - -func TestProto3SetDefaults(t *testing.T) { - in := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: new(tpb.SubDefaults), - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": new(tpb.SubDefaults), - }, - } - - got := proto.Clone(in).(*pb.Message) - proto.SetDefaults(got) - - // There are no defaults in proto3. Everything should be the zero value, but - // we need to remember to set defaults for nested proto2 messages. - want := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": {N: proto.Int64(7)}, - }, - } - - if !proto.Equal(got, want) { - t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/size2_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/size2_test.go deleted file mode 100644 index a2729c39a..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/size2_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "testing" -) - -// This is a separate file and package from size_test.go because that one uses -// generated messages and thus may not be in package proto without having a circular -// dependency, whereas this file tests unexported details of size.go. - -func TestVarintSize(t *testing.T) { - // Check the edge cases carefully. - testCases := []struct { - n uint64 - size int - }{ - {0, 1}, - {1, 1}, - {127, 1}, - {128, 2}, - {16383, 2}, - {16384, 3}, - {1<<63 - 1, 9}, - {1 << 63, 10}, - } - for _, tc := range testCases { - size := sizeVarint(tc.n) - if size != tc.size { - t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) - } - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/size_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/size_test.go deleted file mode 100644 index f4b8b8e3a..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/size_test.go +++ /dev/null @@ -1,147 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "log" - "strings" - "testing" - - . "github.com/gogo/protobuf/proto" - proto3pb "github.com/gogo/protobuf/proto/proto3_proto" - pb "github.com/gogo/protobuf/proto/testdata" -) - -var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)} - -// messageWithExtension2 is in equal_test.go. -var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)} - -func init() { - if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - - // Force messageWithExtension3 to have the extension encoded. - Marshal(messageWithExtension3) - -} - -var SizeTests = []struct { - desc string - pb Message -}{ - {"empty", &pb.OtherMessage{}}, - // Basic types. - {"bool", &pb.Defaults{F_Bool: Bool(true)}}, - {"int32", &pb.Defaults{F_Int32: Int32(12)}}, - {"negative int32", &pb.Defaults{F_Int32: Int32(-1)}}, - {"small int64", &pb.Defaults{F_Int64: Int64(1)}}, - {"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}}, - {"negative int64", &pb.Defaults{F_Int64: Int64(-1)}}, - {"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}}, - {"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}}, - {"uint32", &pb.Defaults{F_Uint32: Uint32(123)}}, - {"uint64", &pb.Defaults{F_Uint64: Uint64(124)}}, - {"float", &pb.Defaults{F_Float: Float32(12.6)}}, - {"double", &pb.Defaults{F_Double: Float64(13.9)}}, - {"string", &pb.Defaults{F_String: String("niles")}}, - {"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}}, - {"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}}, - {"sint32", &pb.Defaults{F_Sint32: Int32(65)}}, - {"sint64", &pb.Defaults{F_Sint64: Int64(67)}}, - {"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}}, - // Repeated. - {"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}}, - {"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}}, - {"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}}, - {"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}}, - {"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}}, - {"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{ - // Need enough large numbers to verify that the header is counting the number of bytes - // for the field, not the number of elements. - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - }}}, - {"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}}, - {"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}}, - // Nested. - {"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}}, - {"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}}, - // Other things. - {"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}}, - {"extension (unencoded)", messageWithExtension1}, - {"extension (encoded)", messageWithExtension3}, - // proto3 message - {"proto3 empty", &proto3pb.Message{}}, - {"proto3 bool", &proto3pb.Message{TrueScotsman: true}}, - {"proto3 int64", &proto3pb.Message{ResultCount: 1}}, - {"proto3 uint32", &proto3pb.Message{HeightInCm: 123}}, - {"proto3 float", &proto3pb.Message{Score: 12.6}}, - {"proto3 string", &proto3pb.Message{Name: "Snezana"}}, - {"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}}, - {"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}}, - {"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, - {"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: {}}}}, - - {"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}}, - {"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: {F: Float64(2.0)}}}}, - {"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}}, - {"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: {}}}}, - - {"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}}, - {"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}}, - {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, - - {"oneof not set", &pb.Communique{}}, - {"oneof zero int32", &pb.Communique{Union: &pb.Communique_Number{Number: 0}}}, - {"oneof int32", &pb.Communique{Union: &pb.Communique_Number{Number: 3}}}, - {"oneof string", &pb.Communique{Union: &pb.Communique_Name{Name: "Rhythmic Fman"}}}, -} - -func TestSize(t *testing.T) { - for _, tc := range SizeTests { - size := Size(tc.pb) - b, err := Marshal(tc.pb) - if err != nil { - t.Errorf("%v: Marshal failed: %v", tc.desc, err) - continue - } - if size != len(b) { - t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b)) - t.Logf("%v: bytes: %#v", tc.desc, b) - } - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/Makefile b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/Makefile deleted file mode 100644 index 31d83277c..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# Go support for Protocol Buffers - Google's data interchange format -# -# Copyright 2010 The Go Authors. All rights reserved. -# https://github.com/golang/protobuf -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -all: regenerate - -regenerate: - go install github.com/gogo/protobuf/protoc-min-version - protoc-min-version --version="3.0.0" --gogo_out=. test.proto - diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/golden_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/golden_test.go deleted file mode 100644 index 8e8451537..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/golden_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Verify that the compiler output for test.proto is unchanged. - -package testdata - -import ( - "crypto/sha1" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "testing" -) - -// sum returns in string form (for easy comparison) the SHA-1 hash of the named file. -func sum(t *testing.T, name string) string { - data, err := ioutil.ReadFile(name) - if err != nil { - t.Fatal(err) - } - t.Logf("sum(%q): length is %d", name, len(data)) - hash := sha1.New() - _, err = hash.Write(data) - if err != nil { - t.Fatal(err) - } - return fmt.Sprintf("% x", hash.Sum(nil)) -} - -func run(t *testing.T, name string, args ...string) { - cmd := exec.Command(name, args...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() - if err != nil { - t.Fatal(err) - } -} - -func TestGolden(t *testing.T) { - // Compute the original checksum. - goldenSum := sum(t, "test.pb.go") - // Run the proto compiler. - run(t, "protoc", "--gogo_out="+os.TempDir(), "test.proto") - newFile := filepath.Join(os.TempDir(), "test.pb.go") - defer os.Remove(newFile) - // Compute the new checksum. - newSum := sum(t, newFile) - // Verify - if newSum != goldenSum { - run(t, "diff", "-u", "test.pb.go", newFile) - t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go") - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go deleted file mode 100644 index e92056955..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go +++ /dev/null @@ -1,2985 +0,0 @@ -// Code generated by protoc-gen-gogo. -// source: test.proto -// DO NOT EDIT! - -/* -Package testdata is a generated protocol buffer package. - -It is generated from these files: - test.proto - -It has these top-level messages: - GoEnum - GoTestField - GoTest - GoSkipTest - NonPackedTest - PackedTest - MaxTag - OldMessage - NewMessage - InnerMessage - OtherMessage - MyMessage - Ext - DefaultsMessage - MyMessageSet - Empty - MessageList - Strings - Defaults - SubDefaults - RepeatedEnum - MoreRepeated - GroupOld - GroupNew - FloatingPoint - MessageWithMap - Communique -*/ -package testdata - -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -type FOO int32 - -const ( - FOO_FOO1 FOO = 1 -) - -var FOO_name = map[int32]string{ - 1: "FOO1", -} -var FOO_value = map[string]int32{ - "FOO1": 1, -} - -func (x FOO) Enum() *FOO { - p := new(FOO) - *p = x - return p -} -func (x FOO) String() string { - return proto.EnumName(FOO_name, int32(x)) -} -func (x *FOO) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO") - if err != nil { - return err - } - *x = FOO(value) - return nil -} - -// An enum, for completeness. -type GoTest_KIND int32 - -const ( - GoTest_VOID GoTest_KIND = 0 - // Basic types - GoTest_BOOL GoTest_KIND = 1 - GoTest_BYTES GoTest_KIND = 2 - GoTest_FINGERPRINT GoTest_KIND = 3 - GoTest_FLOAT GoTest_KIND = 4 - GoTest_INT GoTest_KIND = 5 - GoTest_STRING GoTest_KIND = 6 - GoTest_TIME GoTest_KIND = 7 - // Groupings - GoTest_TUPLE GoTest_KIND = 8 - GoTest_ARRAY GoTest_KIND = 9 - GoTest_MAP GoTest_KIND = 10 - // Table types - GoTest_TABLE GoTest_KIND = 11 - // Functions - GoTest_FUNCTION GoTest_KIND = 12 -) - -var GoTest_KIND_name = map[int32]string{ - 0: "VOID", - 1: "BOOL", - 2: "BYTES", - 3: "FINGERPRINT", - 4: "FLOAT", - 5: "INT", - 6: "STRING", - 7: "TIME", - 8: "TUPLE", - 9: "ARRAY", - 10: "MAP", - 11: "TABLE", - 12: "FUNCTION", -} -var GoTest_KIND_value = map[string]int32{ - "VOID": 0, - "BOOL": 1, - "BYTES": 2, - "FINGERPRINT": 3, - "FLOAT": 4, - "INT": 5, - "STRING": 6, - "TIME": 7, - "TUPLE": 8, - "ARRAY": 9, - "MAP": 10, - "TABLE": 11, - "FUNCTION": 12, -} - -func (x GoTest_KIND) Enum() *GoTest_KIND { - p := new(GoTest_KIND) - *p = x - return p -} -func (x GoTest_KIND) String() string { - return proto.EnumName(GoTest_KIND_name, int32(x)) -} -func (x *GoTest_KIND) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(GoTest_KIND_value, data, "GoTest_KIND") - if err != nil { - return err - } - *x = GoTest_KIND(value) - return nil -} - -type MyMessage_Color int32 - -const ( - MyMessage_RED MyMessage_Color = 0 - MyMessage_GREEN MyMessage_Color = 1 - MyMessage_BLUE MyMessage_Color = 2 -) - -var MyMessage_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var MyMessage_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x MyMessage_Color) Enum() *MyMessage_Color { - p := new(MyMessage_Color) - *p = x - return p -} -func (x MyMessage_Color) String() string { - return proto.EnumName(MyMessage_Color_name, int32(x)) -} -func (x *MyMessage_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MyMessage_Color_value, data, "MyMessage_Color") - if err != nil { - return err - } - *x = MyMessage_Color(value) - return nil -} - -type DefaultsMessage_DefaultsEnum int32 - -const ( - DefaultsMessage_ZERO DefaultsMessage_DefaultsEnum = 0 - DefaultsMessage_ONE DefaultsMessage_DefaultsEnum = 1 - DefaultsMessage_TWO DefaultsMessage_DefaultsEnum = 2 -) - -var DefaultsMessage_DefaultsEnum_name = map[int32]string{ - 0: "ZERO", - 1: "ONE", - 2: "TWO", -} -var DefaultsMessage_DefaultsEnum_value = map[string]int32{ - "ZERO": 0, - "ONE": 1, - "TWO": 2, -} - -func (x DefaultsMessage_DefaultsEnum) Enum() *DefaultsMessage_DefaultsEnum { - p := new(DefaultsMessage_DefaultsEnum) - *p = x - return p -} -func (x DefaultsMessage_DefaultsEnum) String() string { - return proto.EnumName(DefaultsMessage_DefaultsEnum_name, int32(x)) -} -func (x *DefaultsMessage_DefaultsEnum) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(DefaultsMessage_DefaultsEnum_value, data, "DefaultsMessage_DefaultsEnum") - if err != nil { - return err - } - *x = DefaultsMessage_DefaultsEnum(value) - return nil -} - -type Defaults_Color int32 - -const ( - Defaults_RED Defaults_Color = 0 - Defaults_GREEN Defaults_Color = 1 - Defaults_BLUE Defaults_Color = 2 -) - -var Defaults_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var Defaults_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x Defaults_Color) Enum() *Defaults_Color { - p := new(Defaults_Color) - *p = x - return p -} -func (x Defaults_Color) String() string { - return proto.EnumName(Defaults_Color_name, int32(x)) -} -func (x *Defaults_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Defaults_Color_value, data, "Defaults_Color") - if err != nil { - return err - } - *x = Defaults_Color(value) - return nil -} - -type RepeatedEnum_Color int32 - -const ( - RepeatedEnum_RED RepeatedEnum_Color = 1 -) - -var RepeatedEnum_Color_name = map[int32]string{ - 1: "RED", -} -var RepeatedEnum_Color_value = map[string]int32{ - "RED": 1, -} - -func (x RepeatedEnum_Color) Enum() *RepeatedEnum_Color { - p := new(RepeatedEnum_Color) - *p = x - return p -} -func (x RepeatedEnum_Color) String() string { - return proto.EnumName(RepeatedEnum_Color_name, int32(x)) -} -func (x *RepeatedEnum_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RepeatedEnum_Color_value, data, "RepeatedEnum_Color") - if err != nil { - return err - } - *x = RepeatedEnum_Color(value) - return nil -} - -type GoEnum struct { - Foo *FOO `protobuf:"varint,1,req,name=foo,enum=testdata.FOO" json:"foo,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoEnum) Reset() { *m = GoEnum{} } -func (m *GoEnum) String() string { return proto.CompactTextString(m) } -func (*GoEnum) ProtoMessage() {} - -func (m *GoEnum) GetFoo() FOO { - if m != nil && m.Foo != nil { - return *m.Foo - } - return FOO_FOO1 -} - -type GoTestField struct { - Label *string `protobuf:"bytes,1,req,name=Label" json:"Label,omitempty"` - Type *string `protobuf:"bytes,2,req,name=Type" json:"Type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTestField) Reset() { *m = GoTestField{} } -func (m *GoTestField) String() string { return proto.CompactTextString(m) } -func (*GoTestField) ProtoMessage() {} - -func (m *GoTestField) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *GoTestField) GetType() string { - if m != nil && m.Type != nil { - return *m.Type - } - return "" -} - -type GoTest struct { - // Some typical parameters - Kind *GoTest_KIND `protobuf:"varint,1,req,name=Kind,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` - Table *string `protobuf:"bytes,2,opt,name=Table" json:"Table,omitempty"` - Param *int32 `protobuf:"varint,3,opt,name=Param" json:"Param,omitempty"` - // Required, repeated and optional foreign fields. - RequiredField *GoTestField `protobuf:"bytes,4,req,name=RequiredField" json:"RequiredField,omitempty"` - RepeatedField []*GoTestField `protobuf:"bytes,5,rep,name=RepeatedField" json:"RepeatedField,omitempty"` - OptionalField *GoTestField `protobuf:"bytes,6,opt,name=OptionalField" json:"OptionalField,omitempty"` - // Required fields of all basic types - F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required" json:"F_Bool_required,omitempty"` - F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required" json:"F_Int32_required,omitempty"` - F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required" json:"F_Int64_required,omitempty"` - F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required" json:"F_Fixed32_required,omitempty"` - F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required" json:"F_Fixed64_required,omitempty"` - F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required" json:"F_Uint32_required,omitempty"` - F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required" json:"F_Uint64_required,omitempty"` - F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required" json:"F_Float_required,omitempty"` - F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required" json:"F_Double_required,omitempty"` - F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required" json:"F_String_required,omitempty"` - F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required" json:"F_Bytes_required,omitempty"` - F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required" json:"F_Sint32_required,omitempty"` - F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required" json:"F_Sint64_required,omitempty"` - // Repeated fields of all basic types - F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated" json:"F_Bool_repeated,omitempty"` - F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated" json:"F_Int32_repeated,omitempty"` - F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated" json:"F_Int64_repeated,omitempty"` - F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated" json:"F_Fixed32_repeated,omitempty"` - F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated" json:"F_Fixed64_repeated,omitempty"` - F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated" json:"F_Uint32_repeated,omitempty"` - F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated" json:"F_Uint64_repeated,omitempty"` - F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated" json:"F_Float_repeated,omitempty"` - F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated" json:"F_Double_repeated,omitempty"` - F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated" json:"F_String_repeated,omitempty"` - F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated" json:"F_Bytes_repeated,omitempty"` - F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated" json:"F_Sint32_repeated,omitempty"` - F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated" json:"F_Sint64_repeated,omitempty"` - // Optional fields of all basic types - F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional" json:"F_Bool_optional,omitempty"` - F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional" json:"F_Int32_optional,omitempty"` - F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional" json:"F_Int64_optional,omitempty"` - F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional" json:"F_Fixed32_optional,omitempty"` - F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional" json:"F_Fixed64_optional,omitempty"` - F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional" json:"F_Uint32_optional,omitempty"` - F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional" json:"F_Uint64_optional,omitempty"` - F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional" json:"F_Float_optional,omitempty"` - F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional" json:"F_Double_optional,omitempty"` - F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional" json:"F_String_optional,omitempty"` - F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional" json:"F_Bytes_optional,omitempty"` - F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional" json:"F_Sint32_optional,omitempty"` - F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional" json:"F_Sint64_optional,omitempty"` - // Default-valued fields of all basic types - F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,def=1" json:"F_Bool_defaulted,omitempty"` - F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,def=32" json:"F_Int32_defaulted,omitempty"` - F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,def=64" json:"F_Int64_defaulted,omitempty"` - F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,def=320" json:"F_Fixed32_defaulted,omitempty"` - F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,def=640" json:"F_Fixed64_defaulted,omitempty"` - F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,def=3200" json:"F_Uint32_defaulted,omitempty"` - F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,def=6400" json:"F_Uint64_defaulted,omitempty"` - F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,def=314159" json:"F_Float_defaulted,omitempty"` - F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,def=271828" json:"F_Double_defaulted,omitempty"` - F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,def=hello, \"world!\"\n" json:"F_String_defaulted,omitempty"` - F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,def=Bignose" json:"F_Bytes_defaulted,omitempty"` - F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,def=-32" json:"F_Sint32_defaulted,omitempty"` - F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,def=-64" json:"F_Sint64_defaulted,omitempty"` - // Packed repeated fields (no string or bytes). - F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed" json:"F_Bool_repeated_packed,omitempty"` - F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed" json:"F_Int32_repeated_packed,omitempty"` - F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed" json:"F_Int64_repeated_packed,omitempty"` - F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed" json:"F_Fixed32_repeated_packed,omitempty"` - F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed" json:"F_Fixed64_repeated_packed,omitempty"` - F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed" json:"F_Uint32_repeated_packed,omitempty"` - F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed" json:"F_Uint64_repeated_packed,omitempty"` - F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed" json:"F_Float_repeated_packed,omitempty"` - F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed" json:"F_Double_repeated_packed,omitempty"` - F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed" json:"F_Sint32_repeated_packed,omitempty"` - F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed" json:"F_Sint64_repeated_packed,omitempty"` - Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup" json:"requiredgroup,omitempty"` - Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup" json:"repeatedgroup,omitempty"` - Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest) Reset() { *m = GoTest{} } -func (m *GoTest) String() string { return proto.CompactTextString(m) } -func (*GoTest) ProtoMessage() {} - -const Default_GoTest_F_BoolDefaulted bool = true -const Default_GoTest_F_Int32Defaulted int32 = 32 -const Default_GoTest_F_Int64Defaulted int64 = 64 -const Default_GoTest_F_Fixed32Defaulted uint32 = 320 -const Default_GoTest_F_Fixed64Defaulted uint64 = 640 -const Default_GoTest_F_Uint32Defaulted uint32 = 3200 -const Default_GoTest_F_Uint64Defaulted uint64 = 6400 -const Default_GoTest_F_FloatDefaulted float32 = 314159 -const Default_GoTest_F_DoubleDefaulted float64 = 271828 -const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n" - -var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose") - -const Default_GoTest_F_Sint32Defaulted int32 = -32 -const Default_GoTest_F_Sint64Defaulted int64 = -64 - -func (m *GoTest) GetKind() GoTest_KIND { - if m != nil && m.Kind != nil { - return *m.Kind - } - return GoTest_VOID -} - -func (m *GoTest) GetTable() string { - if m != nil && m.Table != nil { - return *m.Table - } - return "" -} - -func (m *GoTest) GetParam() int32 { - if m != nil && m.Param != nil { - return *m.Param - } - return 0 -} - -func (m *GoTest) GetRequiredField() *GoTestField { - if m != nil { - return m.RequiredField - } - return nil -} - -func (m *GoTest) GetRepeatedField() []*GoTestField { - if m != nil { - return m.RepeatedField - } - return nil -} - -func (m *GoTest) GetOptionalField() *GoTestField { - if m != nil { - return m.OptionalField - } - return nil -} - -func (m *GoTest) GetF_BoolRequired() bool { - if m != nil && m.F_BoolRequired != nil { - return *m.F_BoolRequired - } - return false -} - -func (m *GoTest) GetF_Int32Required() int32 { - if m != nil && m.F_Int32Required != nil { - return *m.F_Int32Required - } - return 0 -} - -func (m *GoTest) GetF_Int64Required() int64 { - if m != nil && m.F_Int64Required != nil { - return *m.F_Int64Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Required() uint32 { - if m != nil && m.F_Fixed32Required != nil { - return *m.F_Fixed32Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Required() uint64 { - if m != nil && m.F_Fixed64Required != nil { - return *m.F_Fixed64Required - } - return 0 -} - -func (m *GoTest) GetF_Uint32Required() uint32 { - if m != nil && m.F_Uint32Required != nil { - return *m.F_Uint32Required - } - return 0 -} - -func (m *GoTest) GetF_Uint64Required() uint64 { - if m != nil && m.F_Uint64Required != nil { - return *m.F_Uint64Required - } - return 0 -} - -func (m *GoTest) GetF_FloatRequired() float32 { - if m != nil && m.F_FloatRequired != nil { - return *m.F_FloatRequired - } - return 0 -} - -func (m *GoTest) GetF_DoubleRequired() float64 { - if m != nil && m.F_DoubleRequired != nil { - return *m.F_DoubleRequired - } - return 0 -} - -func (m *GoTest) GetF_StringRequired() string { - if m != nil && m.F_StringRequired != nil { - return *m.F_StringRequired - } - return "" -} - -func (m *GoTest) GetF_BytesRequired() []byte { - if m != nil { - return m.F_BytesRequired - } - return nil -} - -func (m *GoTest) GetF_Sint32Required() int32 { - if m != nil && m.F_Sint32Required != nil { - return *m.F_Sint32Required - } - return 0 -} - -func (m *GoTest) GetF_Sint64Required() int64 { - if m != nil && m.F_Sint64Required != nil { - return *m.F_Sint64Required - } - return 0 -} - -func (m *GoTest) GetF_BoolRepeated() []bool { - if m != nil { - return m.F_BoolRepeated - } - return nil -} - -func (m *GoTest) GetF_Int32Repeated() []int32 { - if m != nil { - return m.F_Int32Repeated - } - return nil -} - -func (m *GoTest) GetF_Int64Repeated() []int64 { - if m != nil { - return m.F_Int64Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed32Repeated() []uint32 { - if m != nil { - return m.F_Fixed32Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed64Repeated() []uint64 { - if m != nil { - return m.F_Fixed64Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint32Repeated() []uint32 { - if m != nil { - return m.F_Uint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint64Repeated() []uint64 { - if m != nil { - return m.F_Uint64Repeated - } - return nil -} - -func (m *GoTest) GetF_FloatRepeated() []float32 { - if m != nil { - return m.F_FloatRepeated - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeated() []float64 { - if m != nil { - return m.F_DoubleRepeated - } - return nil -} - -func (m *GoTest) GetF_StringRepeated() []string { - if m != nil { - return m.F_StringRepeated - } - return nil -} - -func (m *GoTest) GetF_BytesRepeated() [][]byte { - if m != nil { - return m.F_BytesRepeated - } - return nil -} - -func (m *GoTest) GetF_Sint32Repeated() []int32 { - if m != nil { - return m.F_Sint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Sint64Repeated() []int64 { - if m != nil { - return m.F_Sint64Repeated - } - return nil -} - -func (m *GoTest) GetF_BoolOptional() bool { - if m != nil && m.F_BoolOptional != nil { - return *m.F_BoolOptional - } - return false -} - -func (m *GoTest) GetF_Int32Optional() int32 { - if m != nil && m.F_Int32Optional != nil { - return *m.F_Int32Optional - } - return 0 -} - -func (m *GoTest) GetF_Int64Optional() int64 { - if m != nil && m.F_Int64Optional != nil { - return *m.F_Int64Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Optional() uint32 { - if m != nil && m.F_Fixed32Optional != nil { - return *m.F_Fixed32Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Optional() uint64 { - if m != nil && m.F_Fixed64Optional != nil { - return *m.F_Fixed64Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint32Optional() uint32 { - if m != nil && m.F_Uint32Optional != nil { - return *m.F_Uint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint64Optional() uint64 { - if m != nil && m.F_Uint64Optional != nil { - return *m.F_Uint64Optional - } - return 0 -} - -func (m *GoTest) GetF_FloatOptional() float32 { - if m != nil && m.F_FloatOptional != nil { - return *m.F_FloatOptional - } - return 0 -} - -func (m *GoTest) GetF_DoubleOptional() float64 { - if m != nil && m.F_DoubleOptional != nil { - return *m.F_DoubleOptional - } - return 0 -} - -func (m *GoTest) GetF_StringOptional() string { - if m != nil && m.F_StringOptional != nil { - return *m.F_StringOptional - } - return "" -} - -func (m *GoTest) GetF_BytesOptional() []byte { - if m != nil { - return m.F_BytesOptional - } - return nil -} - -func (m *GoTest) GetF_Sint32Optional() int32 { - if m != nil && m.F_Sint32Optional != nil { - return *m.F_Sint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Sint64Optional() int64 { - if m != nil && m.F_Sint64Optional != nil { - return *m.F_Sint64Optional - } - return 0 -} - -func (m *GoTest) GetF_BoolDefaulted() bool { - if m != nil && m.F_BoolDefaulted != nil { - return *m.F_BoolDefaulted - } - return Default_GoTest_F_BoolDefaulted -} - -func (m *GoTest) GetF_Int32Defaulted() int32 { - if m != nil && m.F_Int32Defaulted != nil { - return *m.F_Int32Defaulted - } - return Default_GoTest_F_Int32Defaulted -} - -func (m *GoTest) GetF_Int64Defaulted() int64 { - if m != nil && m.F_Int64Defaulted != nil { - return *m.F_Int64Defaulted - } - return Default_GoTest_F_Int64Defaulted -} - -func (m *GoTest) GetF_Fixed32Defaulted() uint32 { - if m != nil && m.F_Fixed32Defaulted != nil { - return *m.F_Fixed32Defaulted - } - return Default_GoTest_F_Fixed32Defaulted -} - -func (m *GoTest) GetF_Fixed64Defaulted() uint64 { - if m != nil && m.F_Fixed64Defaulted != nil { - return *m.F_Fixed64Defaulted - } - return Default_GoTest_F_Fixed64Defaulted -} - -func (m *GoTest) GetF_Uint32Defaulted() uint32 { - if m != nil && m.F_Uint32Defaulted != nil { - return *m.F_Uint32Defaulted - } - return Default_GoTest_F_Uint32Defaulted -} - -func (m *GoTest) GetF_Uint64Defaulted() uint64 { - if m != nil && m.F_Uint64Defaulted != nil { - return *m.F_Uint64Defaulted - } - return Default_GoTest_F_Uint64Defaulted -} - -func (m *GoTest) GetF_FloatDefaulted() float32 { - if m != nil && m.F_FloatDefaulted != nil { - return *m.F_FloatDefaulted - } - return Default_GoTest_F_FloatDefaulted -} - -func (m *GoTest) GetF_DoubleDefaulted() float64 { - if m != nil && m.F_DoubleDefaulted != nil { - return *m.F_DoubleDefaulted - } - return Default_GoTest_F_DoubleDefaulted -} - -func (m *GoTest) GetF_StringDefaulted() string { - if m != nil && m.F_StringDefaulted != nil { - return *m.F_StringDefaulted - } - return Default_GoTest_F_StringDefaulted -} - -func (m *GoTest) GetF_BytesDefaulted() []byte { - if m != nil && m.F_BytesDefaulted != nil { - return m.F_BytesDefaulted - } - return append([]byte(nil), Default_GoTest_F_BytesDefaulted...) -} - -func (m *GoTest) GetF_Sint32Defaulted() int32 { - if m != nil && m.F_Sint32Defaulted != nil { - return *m.F_Sint32Defaulted - } - return Default_GoTest_F_Sint32Defaulted -} - -func (m *GoTest) GetF_Sint64Defaulted() int64 { - if m != nil && m.F_Sint64Defaulted != nil { - return *m.F_Sint64Defaulted - } - return Default_GoTest_F_Sint64Defaulted -} - -func (m *GoTest) GetF_BoolRepeatedPacked() []bool { - if m != nil { - return m.F_BoolRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int32RepeatedPacked() []int32 { - if m != nil { - return m.F_Int32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int64RepeatedPacked() []int64 { - if m != nil { - return m.F_Int64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Fixed32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Fixed64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Uint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Uint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_FloatRepeatedPacked() []float32 { - if m != nil { - return m.F_FloatRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeatedPacked() []float64 { - if m != nil { - return m.F_DoubleRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint32RepeatedPacked() []int32 { - if m != nil { - return m.F_Sint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint64RepeatedPacked() []int64 { - if m != nil { - return m.F_Sint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetRequiredgroup() *GoTest_RequiredGroup { - if m != nil { - return m.Requiredgroup - } - return nil -} - -func (m *GoTest) GetRepeatedgroup() []*GoTest_RepeatedGroup { - if m != nil { - return m.Repeatedgroup - } - return nil -} - -func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup { - if m != nil { - return m.Optionalgroup - } - return nil -} - -// Required, repeated, and optional groups. -type GoTest_RequiredGroup struct { - RequiredField *string `protobuf:"bytes,71,req,name=RequiredField" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RequiredGroup) Reset() { *m = GoTest_RequiredGroup{} } -func (m *GoTest_RequiredGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_RequiredGroup) ProtoMessage() {} - -func (m *GoTest_RequiredGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_RepeatedGroup struct { - RequiredField *string `protobuf:"bytes,81,req,name=RequiredField" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RepeatedGroup) Reset() { *m = GoTest_RepeatedGroup{} } -func (m *GoTest_RepeatedGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_RepeatedGroup) ProtoMessage() {} - -func (m *GoTest_RepeatedGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_OptionalGroup struct { - RequiredField *string `protobuf:"bytes,91,req,name=RequiredField" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_OptionalGroup) Reset() { *m = GoTest_OptionalGroup{} } -func (m *GoTest_OptionalGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_OptionalGroup) ProtoMessage() {} - -func (m *GoTest_OptionalGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -// For testing skipping of unrecognized fields. -// Numbers are all big, larger than tag numbers in GoTestField, -// the message used in the corresponding test. -type GoSkipTest struct { - SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32" json:"skip_int32,omitempty"` - SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32" json:"skip_fixed32,omitempty"` - SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64" json:"skip_fixed64,omitempty"` - SkipString *string `protobuf:"bytes,14,req,name=skip_string" json:"skip_string,omitempty"` - Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup" json:"skipgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest) Reset() { *m = GoSkipTest{} } -func (m *GoSkipTest) String() string { return proto.CompactTextString(m) } -func (*GoSkipTest) ProtoMessage() {} - -func (m *GoSkipTest) GetSkipInt32() int32 { - if m != nil && m.SkipInt32 != nil { - return *m.SkipInt32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed32() uint32 { - if m != nil && m.SkipFixed32 != nil { - return *m.SkipFixed32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed64() uint64 { - if m != nil && m.SkipFixed64 != nil { - return *m.SkipFixed64 - } - return 0 -} - -func (m *GoSkipTest) GetSkipString() string { - if m != nil && m.SkipString != nil { - return *m.SkipString - } - return "" -} - -func (m *GoSkipTest) GetSkipgroup() *GoSkipTest_SkipGroup { - if m != nil { - return m.Skipgroup - } - return nil -} - -type GoSkipTest_SkipGroup struct { - GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32" json:"group_int32,omitempty"` - GroupString *string `protobuf:"bytes,17,req,name=group_string" json:"group_string,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest_SkipGroup) Reset() { *m = GoSkipTest_SkipGroup{} } -func (m *GoSkipTest_SkipGroup) String() string { return proto.CompactTextString(m) } -func (*GoSkipTest_SkipGroup) ProtoMessage() {} - -func (m *GoSkipTest_SkipGroup) GetGroupInt32() int32 { - if m != nil && m.GroupInt32 != nil { - return *m.GroupInt32 - } - return 0 -} - -func (m *GoSkipTest_SkipGroup) GetGroupString() string { - if m != nil && m.GroupString != nil { - return *m.GroupString - } - return "" -} - -// For testing packed/non-packed decoder switching. -// A serialized instance of one should be deserializable as the other. -type NonPackedTest struct { - A []int32 `protobuf:"varint,1,rep,name=a" json:"a,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NonPackedTest) Reset() { *m = NonPackedTest{} } -func (m *NonPackedTest) String() string { return proto.CompactTextString(m) } -func (*NonPackedTest) ProtoMessage() {} - -func (m *NonPackedTest) GetA() []int32 { - if m != nil { - return m.A - } - return nil -} - -type PackedTest struct { - B []int32 `protobuf:"varint,1,rep,packed,name=b" json:"b,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PackedTest) Reset() { *m = PackedTest{} } -func (m *PackedTest) String() string { return proto.CompactTextString(m) } -func (*PackedTest) ProtoMessage() {} - -func (m *PackedTest) GetB() []int32 { - if m != nil { - return m.B - } - return nil -} - -type MaxTag struct { - // Maximum possible tag number. - LastField *string `protobuf:"bytes,536870911,opt,name=last_field" json:"last_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MaxTag) Reset() { *m = MaxTag{} } -func (m *MaxTag) String() string { return proto.CompactTextString(m) } -func (*MaxTag) ProtoMessage() {} - -func (m *MaxTag) GetLastField() string { - if m != nil && m.LastField != nil { - return *m.LastField - } - return "" -} - -type OldMessage struct { - Nested *OldMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - Num *int32 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage) Reset() { *m = OldMessage{} } -func (m *OldMessage) String() string { return proto.CompactTextString(m) } -func (*OldMessage) ProtoMessage() {} - -func (m *OldMessage) GetNested() *OldMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *OldMessage) GetNum() int32 { - if m != nil && m.Num != nil { - return *m.Num - } - return 0 -} - -type OldMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage_Nested) Reset() { *m = OldMessage_Nested{} } -func (m *OldMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*OldMessage_Nested) ProtoMessage() {} - -func (m *OldMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// NewMessage is wire compatible with OldMessage; -// imagine it as a future version. -type NewMessage struct { - Nested *NewMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - // This is an int32 in OldMessage. - Num *int64 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage) Reset() { *m = NewMessage{} } -func (m *NewMessage) String() string { return proto.CompactTextString(m) } -func (*NewMessage) ProtoMessage() {} - -func (m *NewMessage) GetNested() *NewMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *NewMessage) GetNum() int64 { - if m != nil && m.Num != nil { - return *m.Num - } - return 0 -} - -type NewMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - FoodGroup *string `protobuf:"bytes,2,opt,name=food_group" json:"food_group,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage_Nested) Reset() { *m = NewMessage_Nested{} } -func (m *NewMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*NewMessage_Nested) ProtoMessage() {} - -func (m *NewMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *NewMessage_Nested) GetFoodGroup() string { - if m != nil && m.FoodGroup != nil { - return *m.FoodGroup - } - return "" -} - -type InnerMessage struct { - Host *string `protobuf:"bytes,1,req,name=host" json:"host,omitempty"` - Port *int32 `protobuf:"varint,2,opt,name=port,def=4000" json:"port,omitempty"` - Connected *bool `protobuf:"varint,3,opt,name=connected" json:"connected,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *InnerMessage) Reset() { *m = InnerMessage{} } -func (m *InnerMessage) String() string { return proto.CompactTextString(m) } -func (*InnerMessage) ProtoMessage() {} - -const Default_InnerMessage_Port int32 = 4000 - -func (m *InnerMessage) GetHost() string { - if m != nil && m.Host != nil { - return *m.Host - } - return "" -} - -func (m *InnerMessage) GetPort() int32 { - if m != nil && m.Port != nil { - return *m.Port - } - return Default_InnerMessage_Port -} - -func (m *InnerMessage) GetConnected() bool { - if m != nil && m.Connected != nil { - return *m.Connected - } - return false -} - -type OtherMessage struct { - Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"` - Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OtherMessage) Reset() { *m = OtherMessage{} } -func (m *OtherMessage) String() string { return proto.CompactTextString(m) } -func (*OtherMessage) ProtoMessage() {} - -func (m *OtherMessage) GetKey() int64 { - if m != nil && m.Key != nil { - return *m.Key - } - return 0 -} - -func (m *OtherMessage) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *OtherMessage) GetWeight() float32 { - if m != nil && m.Weight != nil { - return *m.Weight - } - return 0 -} - -func (m *OtherMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -type MyMessage struct { - Count *int32 `protobuf:"varint,1,req,name=count" json:"count,omitempty"` - Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` - Quote *string `protobuf:"bytes,3,opt,name=quote" json:"quote,omitempty"` - Pet []string `protobuf:"bytes,4,rep,name=pet" json:"pet,omitempty"` - Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner" json:"inner,omitempty"` - Others []*OtherMessage `protobuf:"bytes,6,rep,name=others" json:"others,omitempty"` - RepInner []*InnerMessage `protobuf:"bytes,12,rep,name=rep_inner" json:"rep_inner,omitempty"` - Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"` - Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup" json:"somegroup,omitempty"` - // This field becomes [][]byte in the generated code. - RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes" json:"rep_bytes,omitempty"` - Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage) Reset() { *m = MyMessage{} } -func (m *MyMessage) String() string { return proto.CompactTextString(m) } -func (*MyMessage) ProtoMessage() {} - -var extRange_MyMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_MyMessage -} -func (m *MyMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -func (m *MyMessage) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *MyMessage) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MyMessage) GetQuote() string { - if m != nil && m.Quote != nil { - return *m.Quote - } - return "" -} - -func (m *MyMessage) GetPet() []string { - if m != nil { - return m.Pet - } - return nil -} - -func (m *MyMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -func (m *MyMessage) GetOthers() []*OtherMessage { - if m != nil { - return m.Others - } - return nil -} - -func (m *MyMessage) GetRepInner() []*InnerMessage { - if m != nil { - return m.RepInner - } - return nil -} - -func (m *MyMessage) GetBikeshed() MyMessage_Color { - if m != nil && m.Bikeshed != nil { - return *m.Bikeshed - } - return MyMessage_RED -} - -func (m *MyMessage) GetSomegroup() *MyMessage_SomeGroup { - if m != nil { - return m.Somegroup - } - return nil -} - -func (m *MyMessage) GetRepBytes() [][]byte { - if m != nil { - return m.RepBytes - } - return nil -} - -func (m *MyMessage) GetBigfloat() float64 { - if m != nil && m.Bigfloat != nil { - return *m.Bigfloat - } - return 0 -} - -type MyMessage_SomeGroup struct { - GroupField *int32 `protobuf:"varint,9,opt,name=group_field" json:"group_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage_SomeGroup) Reset() { *m = MyMessage_SomeGroup{} } -func (m *MyMessage_SomeGroup) String() string { return proto.CompactTextString(m) } -func (*MyMessage_SomeGroup) ProtoMessage() {} - -func (m *MyMessage_SomeGroup) GetGroupField() int32 { - if m != nil && m.GroupField != nil { - return *m.GroupField - } - return 0 -} - -type Ext struct { - Data *string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Ext) Reset() { *m = Ext{} } -func (m *Ext) String() string { return proto.CompactTextString(m) } -func (*Ext) ProtoMessage() {} - -func (m *Ext) GetData() string { - if m != nil && m.Data != nil { - return *m.Data - } - return "" -} - -var E_Ext_More = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*Ext)(nil), - Field: 103, - Name: "testdata.Ext.more", - Tag: "bytes,103,opt,name=more", -} - -var E_Ext_Text = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*string)(nil), - Field: 104, - Name: "testdata.Ext.text", - Tag: "bytes,104,opt,name=text", -} - -var E_Ext_Number = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 105, - Name: "testdata.Ext.number", - Tag: "varint,105,opt,name=number", -} - -type DefaultsMessage struct { - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DefaultsMessage) Reset() { *m = DefaultsMessage{} } -func (m *DefaultsMessage) String() string { return proto.CompactTextString(m) } -func (*DefaultsMessage) ProtoMessage() {} - -var extRange_DefaultsMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_DefaultsMessage -} -func (m *DefaultsMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -type MyMessageSet struct { - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessageSet) Reset() { *m = MyMessageSet{} } -func (m *MyMessageSet) String() string { return proto.CompactTextString(m) } -func (*MyMessageSet) ProtoMessage() {} - -func (m *MyMessageSet) Marshal() ([]byte, error) { - return proto.MarshalMessageSet(m.ExtensionMap()) -} -func (m *MyMessageSet) Unmarshal(buf []byte) error { - return proto.UnmarshalMessageSet(buf, m.ExtensionMap()) -} -func (m *MyMessageSet) MarshalJSON() ([]byte, error) { - return proto.MarshalMessageSetJSON(m.XXX_extensions) -} -func (m *MyMessageSet) UnmarshalJSON(buf []byte) error { - return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions) -} - -// ensure MyMessageSet satisfies proto.Marshaler and proto.Unmarshaler -var _ proto.Marshaler = (*MyMessageSet)(nil) -var _ proto.Unmarshaler = (*MyMessageSet)(nil) - -var extRange_MyMessageSet = []proto.ExtensionRange{ - {100, 2147483646}, -} - -func (*MyMessageSet) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_MyMessageSet -} -func (m *MyMessageSet) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -type Empty struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} - -type MessageList struct { - Message []*MessageList_Message `protobuf:"group,1,rep,name=Message" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList) Reset() { *m = MessageList{} } -func (m *MessageList) String() string { return proto.CompactTextString(m) } -func (*MessageList) ProtoMessage() {} - -func (m *MessageList) GetMessage() []*MessageList_Message { - if m != nil { - return m.Message - } - return nil -} - -type MessageList_Message struct { - Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` - Count *int32 `protobuf:"varint,3,req,name=count" json:"count,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList_Message) Reset() { *m = MessageList_Message{} } -func (m *MessageList_Message) String() string { return proto.CompactTextString(m) } -func (*MessageList_Message) ProtoMessage() {} - -func (m *MessageList_Message) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MessageList_Message) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -type Strings struct { - StringField *string `protobuf:"bytes,1,opt,name=string_field" json:"string_field,omitempty"` - BytesField []byte `protobuf:"bytes,2,opt,name=bytes_field" json:"bytes_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Strings) Reset() { *m = Strings{} } -func (m *Strings) String() string { return proto.CompactTextString(m) } -func (*Strings) ProtoMessage() {} - -func (m *Strings) GetStringField() string { - if m != nil && m.StringField != nil { - return *m.StringField - } - return "" -} - -func (m *Strings) GetBytesField() []byte { - if m != nil { - return m.BytesField - } - return nil -} - -type Defaults struct { - // Default-valued fields of all basic types. - // Same as GoTest, but copied here to make testing easier. - F_Bool *bool `protobuf:"varint,1,opt,name=F_Bool,def=1" json:"F_Bool,omitempty"` - F_Int32 *int32 `protobuf:"varint,2,opt,name=F_Int32,def=32" json:"F_Int32,omitempty"` - F_Int64 *int64 `protobuf:"varint,3,opt,name=F_Int64,def=64" json:"F_Int64,omitempty"` - F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,def=320" json:"F_Fixed32,omitempty"` - F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,def=640" json:"F_Fixed64,omitempty"` - F_Uint32 *uint32 `protobuf:"varint,6,opt,name=F_Uint32,def=3200" json:"F_Uint32,omitempty"` - F_Uint64 *uint64 `protobuf:"varint,7,opt,name=F_Uint64,def=6400" json:"F_Uint64,omitempty"` - F_Float *float32 `protobuf:"fixed32,8,opt,name=F_Float,def=314159" json:"F_Float,omitempty"` - F_Double *float64 `protobuf:"fixed64,9,opt,name=F_Double,def=271828" json:"F_Double,omitempty"` - F_String *string `protobuf:"bytes,10,opt,name=F_String,def=hello, \"world!\"\n" json:"F_String,omitempty"` - F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,def=Bignose" json:"F_Bytes,omitempty"` - F_Sint32 *int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,def=-32" json:"F_Sint32,omitempty"` - F_Sint64 *int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,def=-64" json:"F_Sint64,omitempty"` - F_Enum *Defaults_Color `protobuf:"varint,14,opt,name=F_Enum,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` - // More fields with crazy defaults. - F_Pinf *float32 `protobuf:"fixed32,15,opt,name=F_Pinf,def=inf" json:"F_Pinf,omitempty"` - F_Ninf *float32 `protobuf:"fixed32,16,opt,name=F_Ninf,def=-inf" json:"F_Ninf,omitempty"` - F_Nan *float32 `protobuf:"fixed32,17,opt,name=F_Nan,def=nan" json:"F_Nan,omitempty"` - // Sub-message. - Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"` - // Redundant but explicit defaults. - StrZero *string `protobuf:"bytes,19,opt,name=str_zero,def=" json:"str_zero,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Defaults) Reset() { *m = Defaults{} } -func (m *Defaults) String() string { return proto.CompactTextString(m) } -func (*Defaults) ProtoMessage() {} - -const Default_Defaults_F_Bool bool = true -const Default_Defaults_F_Int32 int32 = 32 -const Default_Defaults_F_Int64 int64 = 64 -const Default_Defaults_F_Fixed32 uint32 = 320 -const Default_Defaults_F_Fixed64 uint64 = 640 -const Default_Defaults_F_Uint32 uint32 = 3200 -const Default_Defaults_F_Uint64 uint64 = 6400 -const Default_Defaults_F_Float float32 = 314159 -const Default_Defaults_F_Double float64 = 271828 -const Default_Defaults_F_String string = "hello, \"world!\"\n" - -var Default_Defaults_F_Bytes []byte = []byte("Bignose") - -const Default_Defaults_F_Sint32 int32 = -32 -const Default_Defaults_F_Sint64 int64 = -64 -const Default_Defaults_F_Enum Defaults_Color = Defaults_GREEN - -var Default_Defaults_F_Pinf float32 = float32(math.Inf(1)) -var Default_Defaults_F_Ninf float32 = float32(math.Inf(-1)) -var Default_Defaults_F_Nan float32 = float32(math.NaN()) - -func (m *Defaults) GetF_Bool() bool { - if m != nil && m.F_Bool != nil { - return *m.F_Bool - } - return Default_Defaults_F_Bool -} - -func (m *Defaults) GetF_Int32() int32 { - if m != nil && m.F_Int32 != nil { - return *m.F_Int32 - } - return Default_Defaults_F_Int32 -} - -func (m *Defaults) GetF_Int64() int64 { - if m != nil && m.F_Int64 != nil { - return *m.F_Int64 - } - return Default_Defaults_F_Int64 -} - -func (m *Defaults) GetF_Fixed32() uint32 { - if m != nil && m.F_Fixed32 != nil { - return *m.F_Fixed32 - } - return Default_Defaults_F_Fixed32 -} - -func (m *Defaults) GetF_Fixed64() uint64 { - if m != nil && m.F_Fixed64 != nil { - return *m.F_Fixed64 - } - return Default_Defaults_F_Fixed64 -} - -func (m *Defaults) GetF_Uint32() uint32 { - if m != nil && m.F_Uint32 != nil { - return *m.F_Uint32 - } - return Default_Defaults_F_Uint32 -} - -func (m *Defaults) GetF_Uint64() uint64 { - if m != nil && m.F_Uint64 != nil { - return *m.F_Uint64 - } - return Default_Defaults_F_Uint64 -} - -func (m *Defaults) GetF_Float() float32 { - if m != nil && m.F_Float != nil { - return *m.F_Float - } - return Default_Defaults_F_Float -} - -func (m *Defaults) GetF_Double() float64 { - if m != nil && m.F_Double != nil { - return *m.F_Double - } - return Default_Defaults_F_Double -} - -func (m *Defaults) GetF_String() string { - if m != nil && m.F_String != nil { - return *m.F_String - } - return Default_Defaults_F_String -} - -func (m *Defaults) GetF_Bytes() []byte { - if m != nil && m.F_Bytes != nil { - return m.F_Bytes - } - return append([]byte(nil), Default_Defaults_F_Bytes...) -} - -func (m *Defaults) GetF_Sint32() int32 { - if m != nil && m.F_Sint32 != nil { - return *m.F_Sint32 - } - return Default_Defaults_F_Sint32 -} - -func (m *Defaults) GetF_Sint64() int64 { - if m != nil && m.F_Sint64 != nil { - return *m.F_Sint64 - } - return Default_Defaults_F_Sint64 -} - -func (m *Defaults) GetF_Enum() Defaults_Color { - if m != nil && m.F_Enum != nil { - return *m.F_Enum - } - return Default_Defaults_F_Enum -} - -func (m *Defaults) GetF_Pinf() float32 { - if m != nil && m.F_Pinf != nil { - return *m.F_Pinf - } - return Default_Defaults_F_Pinf -} - -func (m *Defaults) GetF_Ninf() float32 { - if m != nil && m.F_Ninf != nil { - return *m.F_Ninf - } - return Default_Defaults_F_Ninf -} - -func (m *Defaults) GetF_Nan() float32 { - if m != nil && m.F_Nan != nil { - return *m.F_Nan - } - return Default_Defaults_F_Nan -} - -func (m *Defaults) GetSub() *SubDefaults { - if m != nil { - return m.Sub - } - return nil -} - -func (m *Defaults) GetStrZero() string { - if m != nil && m.StrZero != nil { - return *m.StrZero - } - return "" -} - -type SubDefaults struct { - N *int64 `protobuf:"varint,1,opt,name=n,def=7" json:"n,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SubDefaults) Reset() { *m = SubDefaults{} } -func (m *SubDefaults) String() string { return proto.CompactTextString(m) } -func (*SubDefaults) ProtoMessage() {} - -const Default_SubDefaults_N int64 = 7 - -func (m *SubDefaults) GetN() int64 { - if m != nil && m.N != nil { - return *m.N - } - return Default_SubDefaults_N -} - -type RepeatedEnum struct { - Color []RepeatedEnum_Color `protobuf:"varint,1,rep,name=color,enum=testdata.RepeatedEnum_Color" json:"color,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RepeatedEnum) Reset() { *m = RepeatedEnum{} } -func (m *RepeatedEnum) String() string { return proto.CompactTextString(m) } -func (*RepeatedEnum) ProtoMessage() {} - -func (m *RepeatedEnum) GetColor() []RepeatedEnum_Color { - if m != nil { - return m.Color - } - return nil -} - -type MoreRepeated struct { - Bools []bool `protobuf:"varint,1,rep,name=bools" json:"bools,omitempty"` - BoolsPacked []bool `protobuf:"varint,2,rep,packed,name=bools_packed" json:"bools_packed,omitempty"` - Ints []int32 `protobuf:"varint,3,rep,name=ints" json:"ints,omitempty"` - IntsPacked []int32 `protobuf:"varint,4,rep,packed,name=ints_packed" json:"ints_packed,omitempty"` - Int64SPacked []int64 `protobuf:"varint,7,rep,packed,name=int64s_packed" json:"int64s_packed,omitempty"` - Strings []string `protobuf:"bytes,5,rep,name=strings" json:"strings,omitempty"` - Fixeds []uint32 `protobuf:"fixed32,6,rep,name=fixeds" json:"fixeds,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MoreRepeated) Reset() { *m = MoreRepeated{} } -func (m *MoreRepeated) String() string { return proto.CompactTextString(m) } -func (*MoreRepeated) ProtoMessage() {} - -func (m *MoreRepeated) GetBools() []bool { - if m != nil { - return m.Bools - } - return nil -} - -func (m *MoreRepeated) GetBoolsPacked() []bool { - if m != nil { - return m.BoolsPacked - } - return nil -} - -func (m *MoreRepeated) GetInts() []int32 { - if m != nil { - return m.Ints - } - return nil -} - -func (m *MoreRepeated) GetIntsPacked() []int32 { - if m != nil { - return m.IntsPacked - } - return nil -} - -func (m *MoreRepeated) GetInt64SPacked() []int64 { - if m != nil { - return m.Int64SPacked - } - return nil -} - -func (m *MoreRepeated) GetStrings() []string { - if m != nil { - return m.Strings - } - return nil -} - -func (m *MoreRepeated) GetFixeds() []uint32 { - if m != nil { - return m.Fixeds - } - return nil -} - -type GroupOld struct { - G *GroupOld_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld) Reset() { *m = GroupOld{} } -func (m *GroupOld) String() string { return proto.CompactTextString(m) } -func (*GroupOld) ProtoMessage() {} - -func (m *GroupOld) GetG() *GroupOld_G { - if m != nil { - return m.G - } - return nil -} - -type GroupOld_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld_G) Reset() { *m = GroupOld_G{} } -func (m *GroupOld_G) String() string { return proto.CompactTextString(m) } -func (*GroupOld_G) ProtoMessage() {} - -func (m *GroupOld_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -type GroupNew struct { - G *GroupNew_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew) Reset() { *m = GroupNew{} } -func (m *GroupNew) String() string { return proto.CompactTextString(m) } -func (*GroupNew) ProtoMessage() {} - -func (m *GroupNew) GetG() *GroupNew_G { - if m != nil { - return m.G - } - return nil -} - -type GroupNew_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - Y *int32 `protobuf:"varint,3,opt,name=y" json:"y,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew_G) Reset() { *m = GroupNew_G{} } -func (m *GroupNew_G) String() string { return proto.CompactTextString(m) } -func (*GroupNew_G) ProtoMessage() {} - -func (m *GroupNew_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -func (m *GroupNew_G) GetY() int32 { - if m != nil && m.Y != nil { - return *m.Y - } - return 0 -} - -type FloatingPoint struct { - F *float64 `protobuf:"fixed64,1,req,name=f" json:"f,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *FloatingPoint) Reset() { *m = FloatingPoint{} } -func (m *FloatingPoint) String() string { return proto.CompactTextString(m) } -func (*FloatingPoint) ProtoMessage() {} - -func (m *FloatingPoint) GetF() float64 { - if m != nil && m.F != nil { - return *m.F - } - return 0 -} - -type MessageWithMap struct { - NameMapping map[int32]string `protobuf:"bytes,1,rep,name=name_mapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - MsgMapping map[int64]*FloatingPoint `protobuf:"bytes,2,rep,name=msg_mapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - ByteMapping map[bool][]byte `protobuf:"bytes,3,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - StrToStr map[string]string `protobuf:"bytes,4,rep,name=str_to_str" json:"str_to_str,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } -func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } -func (*MessageWithMap) ProtoMessage() {} - -func (m *MessageWithMap) GetNameMapping() map[int32]string { - if m != nil { - return m.NameMapping - } - return nil -} - -func (m *MessageWithMap) GetMsgMapping() map[int64]*FloatingPoint { - if m != nil { - return m.MsgMapping - } - return nil -} - -func (m *MessageWithMap) GetByteMapping() map[bool][]byte { - if m != nil { - return m.ByteMapping - } - return nil -} - -func (m *MessageWithMap) GetStrToStr() map[string]string { - if m != nil { - return m.StrToStr - } - return nil -} - -type Communique struct { - MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry" json:"make_me_cry,omitempty"` - // This is a oneof, called "union". - // - // Types that are valid to be assigned to Union: - // *Communique_Number - // *Communique_Name - // *Communique_Data - // *Communique_TempC - // *Communique_Col - // *Communique_Msg - Union isCommunique_Union `protobuf_oneof:"union"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Communique) Reset() { *m = Communique{} } -func (m *Communique) String() string { return proto.CompactTextString(m) } -func (*Communique) ProtoMessage() {} - -type isCommunique_Union interface { - isCommunique_Union() -} - -type Communique_Number struct { - Number int32 `protobuf:"varint,5,opt,name=number,oneof"` -} -type Communique_Name struct { - Name string `protobuf:"bytes,6,opt,name=name,oneof"` -} -type Communique_Data struct { - Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` -} -type Communique_TempC struct { - TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,oneof"` -} -type Communique_Col struct { - Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color,oneof"` -} -type Communique_Msg struct { - Msg *Strings `protobuf:"bytes,10,opt,name=msg,oneof"` -} - -func (*Communique_Number) isCommunique_Union() {} -func (*Communique_Name) isCommunique_Union() {} -func (*Communique_Data) isCommunique_Union() {} -func (*Communique_TempC) isCommunique_Union() {} -func (*Communique_Col) isCommunique_Union() {} -func (*Communique_Msg) isCommunique_Union() {} - -func (m *Communique) GetUnion() isCommunique_Union { - if m != nil { - return m.Union - } - return nil -} - -func (m *Communique) GetMakeMeCry() bool { - if m != nil && m.MakeMeCry != nil { - return *m.MakeMeCry - } - return false -} - -func (m *Communique) GetNumber() int32 { - if x, ok := m.GetUnion().(*Communique_Number); ok { - return x.Number - } - return 0 -} - -func (m *Communique) GetName() string { - if x, ok := m.GetUnion().(*Communique_Name); ok { - return x.Name - } - return "" -} - -func (m *Communique) GetData() []byte { - if x, ok := m.GetUnion().(*Communique_Data); ok { - return x.Data - } - return nil -} - -func (m *Communique) GetTempC() float64 { - if x, ok := m.GetUnion().(*Communique_TempC); ok { - return x.TempC - } - return 0 -} - -func (m *Communique) GetCol() MyMessage_Color { - if x, ok := m.GetUnion().(*Communique_Col); ok { - return x.Col - } - return MyMessage_RED -} - -func (m *Communique) GetMsg() *Strings { - if x, ok := m.GetUnion().(*Communique_Msg); ok { - return x.Msg - } - return nil -} - -// XXX_OneofFuncs is for the internal use of the proto package. -func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), []interface{}) { - return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, []interface{}{ - (*Communique_Number)(nil), - (*Communique_Name)(nil), - (*Communique_Data)(nil), - (*Communique_TempC)(nil), - (*Communique_Col)(nil), - (*Communique_Msg)(nil), - } -} - -func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { - m := msg.(*Communique) - // union - switch x := m.Union.(type) { - case *Communique_Number: - _ = b.EncodeVarint(5<<3 | proto.WireVarint) - _ = b.EncodeVarint(uint64(x.Number)) - case *Communique_Name: - _ = b.EncodeVarint(6<<3 | proto.WireBytes) - _ = b.EncodeStringBytes(x.Name) - case *Communique_Data: - _ = b.EncodeVarint(7<<3 | proto.WireBytes) - _ = b.EncodeRawBytes(x.Data) - case *Communique_TempC: - _ = b.EncodeVarint(8<<3 | proto.WireFixed64) - _ = b.EncodeFixed64(math.Float64bits(x.TempC)) - case *Communique_Col: - _ = b.EncodeVarint(9<<3 | proto.WireVarint) - _ = b.EncodeVarint(uint64(x.Col)) - case *Communique_Msg: - _ = b.EncodeVarint(10<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Msg); err != nil { - return err - } - case nil: - default: - return fmt.Errorf("Communique.Union has unexpected type %T", x) - } - return nil -} - -func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { - m := msg.(*Communique) - switch tag { - case 5: // union.number - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Communique_Number{int32(x)} - return true, err - case 6: // union.name - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeStringBytes() - m.Union = &Communique_Name{x} - return true, err - case 7: // union.data - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeRawBytes(true) - m.Union = &Communique_Data{x} - return true, err - case 8: // union.temp_c - if wire != proto.WireFixed64 { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeFixed64() - m.Union = &Communique_TempC{math.Float64frombits(x)} - return true, err - case 9: // union.col - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Communique_Col{MyMessage_Color(x)} - return true, err - case 10: // union.msg - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(Strings) - err := b.DecodeMessage(msg) - m.Union = &Communique_Msg{msg} - return true, err - default: - return false, nil - } -} - -var E_Greeting = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: ([]string)(nil), - Field: 106, - Name: "testdata.greeting", - Tag: "bytes,106,rep,name=greeting", -} - -var E_NoDefaultDouble = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float64)(nil), - Field: 101, - Name: "testdata.no_default_double", - Tag: "fixed64,101,opt,name=no_default_double", -} - -var E_NoDefaultFloat = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float32)(nil), - Field: 102, - Name: "testdata.no_default_float", - Tag: "fixed32,102,opt,name=no_default_float", -} - -var E_NoDefaultInt32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 103, - Name: "testdata.no_default_int32", - Tag: "varint,103,opt,name=no_default_int32", -} - -var E_NoDefaultInt64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 104, - Name: "testdata.no_default_int64", - Tag: "varint,104,opt,name=no_default_int64", -} - -var E_NoDefaultUint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 105, - Name: "testdata.no_default_uint32", - Tag: "varint,105,opt,name=no_default_uint32", -} - -var E_NoDefaultUint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 106, - Name: "testdata.no_default_uint64", - Tag: "varint,106,opt,name=no_default_uint64", -} - -var E_NoDefaultSint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 107, - Name: "testdata.no_default_sint32", - Tag: "zigzag32,107,opt,name=no_default_sint32", -} - -var E_NoDefaultSint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 108, - Name: "testdata.no_default_sint64", - Tag: "zigzag64,108,opt,name=no_default_sint64", -} - -var E_NoDefaultFixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 109, - Name: "testdata.no_default_fixed32", - Tag: "fixed32,109,opt,name=no_default_fixed32", -} - -var E_NoDefaultFixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 110, - Name: "testdata.no_default_fixed64", - Tag: "fixed64,110,opt,name=no_default_fixed64", -} - -var E_NoDefaultSfixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 111, - Name: "testdata.no_default_sfixed32", - Tag: "fixed32,111,opt,name=no_default_sfixed32", -} - -var E_NoDefaultSfixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 112, - Name: "testdata.no_default_sfixed64", - Tag: "fixed64,112,opt,name=no_default_sfixed64", -} - -var E_NoDefaultBool = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 113, - Name: "testdata.no_default_bool", - Tag: "varint,113,opt,name=no_default_bool", -} - -var E_NoDefaultString = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*string)(nil), - Field: 114, - Name: "testdata.no_default_string", - Tag: "bytes,114,opt,name=no_default_string", -} - -var E_NoDefaultBytes = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: ([]byte)(nil), - Field: 115, - Name: "testdata.no_default_bytes", - Tag: "bytes,115,opt,name=no_default_bytes", -} - -var E_NoDefaultEnum = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), - Field: 116, - Name: "testdata.no_default_enum", - Tag: "varint,116,opt,name=no_default_enum,enum=testdata.DefaultsMessage_DefaultsEnum", -} - -var E_DefaultDouble = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float64)(nil), - Field: 201, - Name: "testdata.default_double", - Tag: "fixed64,201,opt,name=default_double,def=3.1415", -} - -var E_DefaultFloat = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float32)(nil), - Field: 202, - Name: "testdata.default_float", - Tag: "fixed32,202,opt,name=default_float,def=3.14", -} - -var E_DefaultInt32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 203, - Name: "testdata.default_int32", - Tag: "varint,203,opt,name=default_int32,def=42", -} - -var E_DefaultInt64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 204, - Name: "testdata.default_int64", - Tag: "varint,204,opt,name=default_int64,def=43", -} - -var E_DefaultUint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 205, - Name: "testdata.default_uint32", - Tag: "varint,205,opt,name=default_uint32,def=44", -} - -var E_DefaultUint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 206, - Name: "testdata.default_uint64", - Tag: "varint,206,opt,name=default_uint64,def=45", -} - -var E_DefaultSint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 207, - Name: "testdata.default_sint32", - Tag: "zigzag32,207,opt,name=default_sint32,def=46", -} - -var E_DefaultSint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 208, - Name: "testdata.default_sint64", - Tag: "zigzag64,208,opt,name=default_sint64,def=47", -} - -var E_DefaultFixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 209, - Name: "testdata.default_fixed32", - Tag: "fixed32,209,opt,name=default_fixed32,def=48", -} - -var E_DefaultFixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 210, - Name: "testdata.default_fixed64", - Tag: "fixed64,210,opt,name=default_fixed64,def=49", -} - -var E_DefaultSfixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 211, - Name: "testdata.default_sfixed32", - Tag: "fixed32,211,opt,name=default_sfixed32,def=50", -} - -var E_DefaultSfixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 212, - Name: "testdata.default_sfixed64", - Tag: "fixed64,212,opt,name=default_sfixed64,def=51", -} - -var E_DefaultBool = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 213, - Name: "testdata.default_bool", - Tag: "varint,213,opt,name=default_bool,def=1", -} - -var E_DefaultString = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*string)(nil), - Field: 214, - Name: "testdata.default_string", - Tag: "bytes,214,opt,name=default_string,def=Hello, string", -} - -var E_DefaultBytes = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: ([]byte)(nil), - Field: 215, - Name: "testdata.default_bytes", - Tag: "bytes,215,opt,name=default_bytes,def=Hello, bytes", -} - -var E_DefaultEnum = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), - Field: 216, - Name: "testdata.default_enum", - Tag: "varint,216,opt,name=default_enum,enum=testdata.DefaultsMessage_DefaultsEnum,def=1", -} - -var E_X201 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 201, - Name: "testdata.x201", - Tag: "bytes,201,opt,name=x201", -} - -var E_X202 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 202, - Name: "testdata.x202", - Tag: "bytes,202,opt,name=x202", -} - -var E_X203 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 203, - Name: "testdata.x203", - Tag: "bytes,203,opt,name=x203", -} - -var E_X204 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 204, - Name: "testdata.x204", - Tag: "bytes,204,opt,name=x204", -} - -var E_X205 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 205, - Name: "testdata.x205", - Tag: "bytes,205,opt,name=x205", -} - -var E_X206 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 206, - Name: "testdata.x206", - Tag: "bytes,206,opt,name=x206", -} - -var E_X207 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 207, - Name: "testdata.x207", - Tag: "bytes,207,opt,name=x207", -} - -var E_X208 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 208, - Name: "testdata.x208", - Tag: "bytes,208,opt,name=x208", -} - -var E_X209 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 209, - Name: "testdata.x209", - Tag: "bytes,209,opt,name=x209", -} - -var E_X210 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 210, - Name: "testdata.x210", - Tag: "bytes,210,opt,name=x210", -} - -var E_X211 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 211, - Name: "testdata.x211", - Tag: "bytes,211,opt,name=x211", -} - -var E_X212 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 212, - Name: "testdata.x212", - Tag: "bytes,212,opt,name=x212", -} - -var E_X213 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 213, - Name: "testdata.x213", - Tag: "bytes,213,opt,name=x213", -} - -var E_X214 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 214, - Name: "testdata.x214", - Tag: "bytes,214,opt,name=x214", -} - -var E_X215 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 215, - Name: "testdata.x215", - Tag: "bytes,215,opt,name=x215", -} - -var E_X216 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 216, - Name: "testdata.x216", - Tag: "bytes,216,opt,name=x216", -} - -var E_X217 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 217, - Name: "testdata.x217", - Tag: "bytes,217,opt,name=x217", -} - -var E_X218 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 218, - Name: "testdata.x218", - Tag: "bytes,218,opt,name=x218", -} - -var E_X219 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 219, - Name: "testdata.x219", - Tag: "bytes,219,opt,name=x219", -} - -var E_X220 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 220, - Name: "testdata.x220", - Tag: "bytes,220,opt,name=x220", -} - -var E_X221 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 221, - Name: "testdata.x221", - Tag: "bytes,221,opt,name=x221", -} - -var E_X222 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 222, - Name: "testdata.x222", - Tag: "bytes,222,opt,name=x222", -} - -var E_X223 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 223, - Name: "testdata.x223", - Tag: "bytes,223,opt,name=x223", -} - -var E_X224 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 224, - Name: "testdata.x224", - Tag: "bytes,224,opt,name=x224", -} - -var E_X225 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 225, - Name: "testdata.x225", - Tag: "bytes,225,opt,name=x225", -} - -var E_X226 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 226, - Name: "testdata.x226", - Tag: "bytes,226,opt,name=x226", -} - -var E_X227 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 227, - Name: "testdata.x227", - Tag: "bytes,227,opt,name=x227", -} - -var E_X228 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 228, - Name: "testdata.x228", - Tag: "bytes,228,opt,name=x228", -} - -var E_X229 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 229, - Name: "testdata.x229", - Tag: "bytes,229,opt,name=x229", -} - -var E_X230 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 230, - Name: "testdata.x230", - Tag: "bytes,230,opt,name=x230", -} - -var E_X231 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 231, - Name: "testdata.x231", - Tag: "bytes,231,opt,name=x231", -} - -var E_X232 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 232, - Name: "testdata.x232", - Tag: "bytes,232,opt,name=x232", -} - -var E_X233 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 233, - Name: "testdata.x233", - Tag: "bytes,233,opt,name=x233", -} - -var E_X234 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 234, - Name: "testdata.x234", - Tag: "bytes,234,opt,name=x234", -} - -var E_X235 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 235, - Name: "testdata.x235", - Tag: "bytes,235,opt,name=x235", -} - -var E_X236 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 236, - Name: "testdata.x236", - Tag: "bytes,236,opt,name=x236", -} - -var E_X237 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 237, - Name: "testdata.x237", - Tag: "bytes,237,opt,name=x237", -} - -var E_X238 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 238, - Name: "testdata.x238", - Tag: "bytes,238,opt,name=x238", -} - -var E_X239 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 239, - Name: "testdata.x239", - Tag: "bytes,239,opt,name=x239", -} - -var E_X240 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 240, - Name: "testdata.x240", - Tag: "bytes,240,opt,name=x240", -} - -var E_X241 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 241, - Name: "testdata.x241", - Tag: "bytes,241,opt,name=x241", -} - -var E_X242 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 242, - Name: "testdata.x242", - Tag: "bytes,242,opt,name=x242", -} - -var E_X243 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 243, - Name: "testdata.x243", - Tag: "bytes,243,opt,name=x243", -} - -var E_X244 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 244, - Name: "testdata.x244", - Tag: "bytes,244,opt,name=x244", -} - -var E_X245 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 245, - Name: "testdata.x245", - Tag: "bytes,245,opt,name=x245", -} - -var E_X246 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 246, - Name: "testdata.x246", - Tag: "bytes,246,opt,name=x246", -} - -var E_X247 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 247, - Name: "testdata.x247", - Tag: "bytes,247,opt,name=x247", -} - -var E_X248 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 248, - Name: "testdata.x248", - Tag: "bytes,248,opt,name=x248", -} - -var E_X249 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 249, - Name: "testdata.x249", - Tag: "bytes,249,opt,name=x249", -} - -var E_X250 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 250, - Name: "testdata.x250", - Tag: "bytes,250,opt,name=x250", -} - -func init() { - proto.RegisterType((*GoEnum)(nil), "testdata.GoEnum") - proto.RegisterType((*GoTestField)(nil), "testdata.GoTestField") - proto.RegisterType((*GoTest)(nil), "testdata.GoTest") - proto.RegisterType((*GoTest_RequiredGroup)(nil), "testdata.GoTest.RequiredGroup") - proto.RegisterType((*GoTest_RepeatedGroup)(nil), "testdata.GoTest.RepeatedGroup") - proto.RegisterType((*GoTest_OptionalGroup)(nil), "testdata.GoTest.OptionalGroup") - proto.RegisterType((*GoSkipTest)(nil), "testdata.GoSkipTest") - proto.RegisterType((*GoSkipTest_SkipGroup)(nil), "testdata.GoSkipTest.SkipGroup") - proto.RegisterType((*NonPackedTest)(nil), "testdata.NonPackedTest") - proto.RegisterType((*PackedTest)(nil), "testdata.PackedTest") - proto.RegisterType((*MaxTag)(nil), "testdata.MaxTag") - proto.RegisterType((*OldMessage)(nil), "testdata.OldMessage") - proto.RegisterType((*OldMessage_Nested)(nil), "testdata.OldMessage.Nested") - proto.RegisterType((*NewMessage)(nil), "testdata.NewMessage") - proto.RegisterType((*NewMessage_Nested)(nil), "testdata.NewMessage.Nested") - proto.RegisterType((*InnerMessage)(nil), "testdata.InnerMessage") - proto.RegisterType((*OtherMessage)(nil), "testdata.OtherMessage") - proto.RegisterType((*MyMessage)(nil), "testdata.MyMessage") - proto.RegisterType((*MyMessage_SomeGroup)(nil), "testdata.MyMessage.SomeGroup") - proto.RegisterType((*Ext)(nil), "testdata.Ext") - proto.RegisterType((*DefaultsMessage)(nil), "testdata.DefaultsMessage") - proto.RegisterType((*MyMessageSet)(nil), "testdata.MyMessageSet") - proto.RegisterType((*Empty)(nil), "testdata.Empty") - proto.RegisterType((*MessageList)(nil), "testdata.MessageList") - proto.RegisterType((*MessageList_Message)(nil), "testdata.MessageList.Message") - proto.RegisterType((*Strings)(nil), "testdata.Strings") - proto.RegisterType((*Defaults)(nil), "testdata.Defaults") - proto.RegisterType((*SubDefaults)(nil), "testdata.SubDefaults") - proto.RegisterType((*RepeatedEnum)(nil), "testdata.RepeatedEnum") - proto.RegisterType((*MoreRepeated)(nil), "testdata.MoreRepeated") - proto.RegisterType((*GroupOld)(nil), "testdata.GroupOld") - proto.RegisterType((*GroupOld_G)(nil), "testdata.GroupOld.G") - proto.RegisterType((*GroupNew)(nil), "testdata.GroupNew") - proto.RegisterType((*GroupNew_G)(nil), "testdata.GroupNew.G") - proto.RegisterType((*FloatingPoint)(nil), "testdata.FloatingPoint") - proto.RegisterType((*MessageWithMap)(nil), "testdata.MessageWithMap") - proto.RegisterType((*Communique)(nil), "testdata.Communique") - proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value) - proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value) - proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value) - proto.RegisterEnum("testdata.DefaultsMessage_DefaultsEnum", DefaultsMessage_DefaultsEnum_name, DefaultsMessage_DefaultsEnum_value) - proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value) - proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value) - proto.RegisterExtension(E_Ext_More) - proto.RegisterExtension(E_Ext_Text) - proto.RegisterExtension(E_Ext_Number) - proto.RegisterExtension(E_Greeting) - proto.RegisterExtension(E_NoDefaultDouble) - proto.RegisterExtension(E_NoDefaultFloat) - proto.RegisterExtension(E_NoDefaultInt32) - proto.RegisterExtension(E_NoDefaultInt64) - proto.RegisterExtension(E_NoDefaultUint32) - proto.RegisterExtension(E_NoDefaultUint64) - proto.RegisterExtension(E_NoDefaultSint32) - proto.RegisterExtension(E_NoDefaultSint64) - proto.RegisterExtension(E_NoDefaultFixed32) - proto.RegisterExtension(E_NoDefaultFixed64) - proto.RegisterExtension(E_NoDefaultSfixed32) - proto.RegisterExtension(E_NoDefaultSfixed64) - proto.RegisterExtension(E_NoDefaultBool) - proto.RegisterExtension(E_NoDefaultString) - proto.RegisterExtension(E_NoDefaultBytes) - proto.RegisterExtension(E_NoDefaultEnum) - proto.RegisterExtension(E_DefaultDouble) - proto.RegisterExtension(E_DefaultFloat) - proto.RegisterExtension(E_DefaultInt32) - proto.RegisterExtension(E_DefaultInt64) - proto.RegisterExtension(E_DefaultUint32) - proto.RegisterExtension(E_DefaultUint64) - proto.RegisterExtension(E_DefaultSint32) - proto.RegisterExtension(E_DefaultSint64) - proto.RegisterExtension(E_DefaultFixed32) - proto.RegisterExtension(E_DefaultFixed64) - proto.RegisterExtension(E_DefaultSfixed32) - proto.RegisterExtension(E_DefaultSfixed64) - proto.RegisterExtension(E_DefaultBool) - proto.RegisterExtension(E_DefaultString) - proto.RegisterExtension(E_DefaultBytes) - proto.RegisterExtension(E_DefaultEnum) - proto.RegisterExtension(E_X201) - proto.RegisterExtension(E_X202) - proto.RegisterExtension(E_X203) - proto.RegisterExtension(E_X204) - proto.RegisterExtension(E_X205) - proto.RegisterExtension(E_X206) - proto.RegisterExtension(E_X207) - proto.RegisterExtension(E_X208) - proto.RegisterExtension(E_X209) - proto.RegisterExtension(E_X210) - proto.RegisterExtension(E_X211) - proto.RegisterExtension(E_X212) - proto.RegisterExtension(E_X213) - proto.RegisterExtension(E_X214) - proto.RegisterExtension(E_X215) - proto.RegisterExtension(E_X216) - proto.RegisterExtension(E_X217) - proto.RegisterExtension(E_X218) - proto.RegisterExtension(E_X219) - proto.RegisterExtension(E_X220) - proto.RegisterExtension(E_X221) - proto.RegisterExtension(E_X222) - proto.RegisterExtension(E_X223) - proto.RegisterExtension(E_X224) - proto.RegisterExtension(E_X225) - proto.RegisterExtension(E_X226) - proto.RegisterExtension(E_X227) - proto.RegisterExtension(E_X228) - proto.RegisterExtension(E_X229) - proto.RegisterExtension(E_X230) - proto.RegisterExtension(E_X231) - proto.RegisterExtension(E_X232) - proto.RegisterExtension(E_X233) - proto.RegisterExtension(E_X234) - proto.RegisterExtension(E_X235) - proto.RegisterExtension(E_X236) - proto.RegisterExtension(E_X237) - proto.RegisterExtension(E_X238) - proto.RegisterExtension(E_X239) - proto.RegisterExtension(E_X240) - proto.RegisterExtension(E_X241) - proto.RegisterExtension(E_X242) - proto.RegisterExtension(E_X243) - proto.RegisterExtension(E_X244) - proto.RegisterExtension(E_X245) - proto.RegisterExtension(E_X246) - proto.RegisterExtension(E_X247) - proto.RegisterExtension(E_X248) - proto.RegisterExtension(E_X249) - proto.RegisterExtension(E_X250) -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go.golden b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go.golden deleted file mode 100644 index 0387853d5..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.pb.go.golden +++ /dev/null @@ -1,1737 +0,0 @@ -// Code generated by protoc-gen-gogo. -// source: test.proto -// DO NOT EDIT! - -package testdata - -import proto "github.com/gogo/protobuf/proto" -import json "encoding/json" -import math "math" - -import () - -// Reference proto, json, and math imports to suppress error if they are not otherwise used. -var _ = proto.Marshal -var _ = &json.SyntaxError{} -var _ = math.Inf - -type FOO int32 - -const ( - FOO_FOO1 FOO = 1 -) - -var FOO_name = map[int32]string{ - 1: "FOO1", -} -var FOO_value = map[string]int32{ - "FOO1": 1, -} - -func (x FOO) Enum() *FOO { - p := new(FOO) - *p = x - return p -} -func (x FOO) String() string { - return proto.EnumName(FOO_name, int32(x)) -} -func (x FOO) MarshalJSON() ([]byte, error) { - return json.Marshal(x.String()) -} -func (x *FOO) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO") - if err != nil { - return err - } - *x = FOO(value) - return nil -} - -type GoTest_KIND int32 - -const ( - GoTest_VOID GoTest_KIND = 0 - GoTest_BOOL GoTest_KIND = 1 - GoTest_BYTES GoTest_KIND = 2 - GoTest_FINGERPRINT GoTest_KIND = 3 - GoTest_FLOAT GoTest_KIND = 4 - GoTest_INT GoTest_KIND = 5 - GoTest_STRING GoTest_KIND = 6 - GoTest_TIME GoTest_KIND = 7 - GoTest_TUPLE GoTest_KIND = 8 - GoTest_ARRAY GoTest_KIND = 9 - GoTest_MAP GoTest_KIND = 10 - GoTest_TABLE GoTest_KIND = 11 - GoTest_FUNCTION GoTest_KIND = 12 -) - -var GoTest_KIND_name = map[int32]string{ - 0: "VOID", - 1: "BOOL", - 2: "BYTES", - 3: "FINGERPRINT", - 4: "FLOAT", - 5: "INT", - 6: "STRING", - 7: "TIME", - 8: "TUPLE", - 9: "ARRAY", - 10: "MAP", - 11: "TABLE", - 12: "FUNCTION", -} -var GoTest_KIND_value = map[string]int32{ - "VOID": 0, - "BOOL": 1, - "BYTES": 2, - "FINGERPRINT": 3, - "FLOAT": 4, - "INT": 5, - "STRING": 6, - "TIME": 7, - "TUPLE": 8, - "ARRAY": 9, - "MAP": 10, - "TABLE": 11, - "FUNCTION": 12, -} - -func (x GoTest_KIND) Enum() *GoTest_KIND { - p := new(GoTest_KIND) - *p = x - return p -} -func (x GoTest_KIND) String() string { - return proto.EnumName(GoTest_KIND_name, int32(x)) -} -func (x GoTest_KIND) MarshalJSON() ([]byte, error) { - return json.Marshal(x.String()) -} -func (x *GoTest_KIND) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(GoTest_KIND_value, data, "GoTest_KIND") - if err != nil { - return err - } - *x = GoTest_KIND(value) - return nil -} - -type MyMessage_Color int32 - -const ( - MyMessage_RED MyMessage_Color = 0 - MyMessage_GREEN MyMessage_Color = 1 - MyMessage_BLUE MyMessage_Color = 2 -) - -var MyMessage_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var MyMessage_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x MyMessage_Color) Enum() *MyMessage_Color { - p := new(MyMessage_Color) - *p = x - return p -} -func (x MyMessage_Color) String() string { - return proto.EnumName(MyMessage_Color_name, int32(x)) -} -func (x MyMessage_Color) MarshalJSON() ([]byte, error) { - return json.Marshal(x.String()) -} -func (x *MyMessage_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MyMessage_Color_value, data, "MyMessage_Color") - if err != nil { - return err - } - *x = MyMessage_Color(value) - return nil -} - -type Defaults_Color int32 - -const ( - Defaults_RED Defaults_Color = 0 - Defaults_GREEN Defaults_Color = 1 - Defaults_BLUE Defaults_Color = 2 -) - -var Defaults_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var Defaults_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x Defaults_Color) Enum() *Defaults_Color { - p := new(Defaults_Color) - *p = x - return p -} -func (x Defaults_Color) String() string { - return proto.EnumName(Defaults_Color_name, int32(x)) -} -func (x Defaults_Color) MarshalJSON() ([]byte, error) { - return json.Marshal(x.String()) -} -func (x *Defaults_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Defaults_Color_value, data, "Defaults_Color") - if err != nil { - return err - } - *x = Defaults_Color(value) - return nil -} - -type RepeatedEnum_Color int32 - -const ( - RepeatedEnum_RED RepeatedEnum_Color = 1 -) - -var RepeatedEnum_Color_name = map[int32]string{ - 1: "RED", -} -var RepeatedEnum_Color_value = map[string]int32{ - "RED": 1, -} - -func (x RepeatedEnum_Color) Enum() *RepeatedEnum_Color { - p := new(RepeatedEnum_Color) - *p = x - return p -} -func (x RepeatedEnum_Color) String() string { - return proto.EnumName(RepeatedEnum_Color_name, int32(x)) -} -func (x RepeatedEnum_Color) MarshalJSON() ([]byte, error) { - return json.Marshal(x.String()) -} -func (x *RepeatedEnum_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RepeatedEnum_Color_value, data, "RepeatedEnum_Color") - if err != nil { - return err - } - *x = RepeatedEnum_Color(value) - return nil -} - -type GoEnum struct { - Foo *FOO `protobuf:"varint,1,req,name=foo,enum=testdata.FOO" json:"foo,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoEnum) Reset() { *m = GoEnum{} } -func (m *GoEnum) String() string { return proto.CompactTextString(m) } -func (*GoEnum) ProtoMessage() {} - -func (m *GoEnum) GetFoo() FOO { - if m != nil && m.Foo != nil { - return *m.Foo - } - return 0 -} - -type GoTestField struct { - Label *string `protobuf:"bytes,1,req" json:"Label,omitempty"` - Type *string `protobuf:"bytes,2,req" json:"Type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTestField) Reset() { *m = GoTestField{} } -func (m *GoTestField) String() string { return proto.CompactTextString(m) } -func (*GoTestField) ProtoMessage() {} - -func (m *GoTestField) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *GoTestField) GetType() string { - if m != nil && m.Type != nil { - return *m.Type - } - return "" -} - -type GoTest struct { - Kind *GoTest_KIND `protobuf:"varint,1,req,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` - Table *string `protobuf:"bytes,2,opt" json:"Table,omitempty"` - Param *int32 `protobuf:"varint,3,opt" json:"Param,omitempty"` - RequiredField *GoTestField `protobuf:"bytes,4,req" json:"RequiredField,omitempty"` - RepeatedField []*GoTestField `protobuf:"bytes,5,rep" json:"RepeatedField,omitempty"` - OptionalField *GoTestField `protobuf:"bytes,6,opt" json:"OptionalField,omitempty"` - F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required" json:"F_Bool_required,omitempty"` - F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required" json:"F_Int32_required,omitempty"` - F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required" json:"F_Int64_required,omitempty"` - F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required" json:"F_Fixed32_required,omitempty"` - F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required" json:"F_Fixed64_required,omitempty"` - F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required" json:"F_Uint32_required,omitempty"` - F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required" json:"F_Uint64_required,omitempty"` - F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required" json:"F_Float_required,omitempty"` - F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required" json:"F_Double_required,omitempty"` - F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required" json:"F_String_required,omitempty"` - F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required" json:"F_Bytes_required,omitempty"` - F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required" json:"F_Sint32_required,omitempty"` - F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required" json:"F_Sint64_required,omitempty"` - F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated" json:"F_Bool_repeated,omitempty"` - F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated" json:"F_Int32_repeated,omitempty"` - F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated" json:"F_Int64_repeated,omitempty"` - F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated" json:"F_Fixed32_repeated,omitempty"` - F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated" json:"F_Fixed64_repeated,omitempty"` - F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated" json:"F_Uint32_repeated,omitempty"` - F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated" json:"F_Uint64_repeated,omitempty"` - F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated" json:"F_Float_repeated,omitempty"` - F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated" json:"F_Double_repeated,omitempty"` - F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated" json:"F_String_repeated,omitempty"` - F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated" json:"F_Bytes_repeated,omitempty"` - F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated" json:"F_Sint32_repeated,omitempty"` - F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated" json:"F_Sint64_repeated,omitempty"` - F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional" json:"F_Bool_optional,omitempty"` - F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional" json:"F_Int32_optional,omitempty"` - F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional" json:"F_Int64_optional,omitempty"` - F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional" json:"F_Fixed32_optional,omitempty"` - F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional" json:"F_Fixed64_optional,omitempty"` - F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional" json:"F_Uint32_optional,omitempty"` - F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional" json:"F_Uint64_optional,omitempty"` - F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional" json:"F_Float_optional,omitempty"` - F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional" json:"F_Double_optional,omitempty"` - F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional" json:"F_String_optional,omitempty"` - F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional" json:"F_Bytes_optional,omitempty"` - F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional" json:"F_Sint32_optional,omitempty"` - F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional" json:"F_Sint64_optional,omitempty"` - F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,def=1" json:"F_Bool_defaulted,omitempty"` - F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,def=32" json:"F_Int32_defaulted,omitempty"` - F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,def=64" json:"F_Int64_defaulted,omitempty"` - F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,def=320" json:"F_Fixed32_defaulted,omitempty"` - F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,def=640" json:"F_Fixed64_defaulted,omitempty"` - F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,def=3200" json:"F_Uint32_defaulted,omitempty"` - F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,def=6400" json:"F_Uint64_defaulted,omitempty"` - F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,def=314159" json:"F_Float_defaulted,omitempty"` - F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,def=271828" json:"F_Double_defaulted,omitempty"` - F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,def=hello, \"world!\"\n" json:"F_String_defaulted,omitempty"` - F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,def=Bignose" json:"F_Bytes_defaulted,omitempty"` - F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,def=-32" json:"F_Sint32_defaulted,omitempty"` - F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,def=-64" json:"F_Sint64_defaulted,omitempty"` - F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed" json:"F_Bool_repeated_packed,omitempty"` - F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed" json:"F_Int32_repeated_packed,omitempty"` - F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed" json:"F_Int64_repeated_packed,omitempty"` - F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed" json:"F_Fixed32_repeated_packed,omitempty"` - F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed" json:"F_Fixed64_repeated_packed,omitempty"` - F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed" json:"F_Uint32_repeated_packed,omitempty"` - F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed" json:"F_Uint64_repeated_packed,omitempty"` - F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed" json:"F_Float_repeated_packed,omitempty"` - F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed" json:"F_Double_repeated_packed,omitempty"` - F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed" json:"F_Sint32_repeated_packed,omitempty"` - F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed" json:"F_Sint64_repeated_packed,omitempty"` - Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup" json:"requiredgroup,omitempty"` - Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup" json:"repeatedgroup,omitempty"` - Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest) Reset() { *m = GoTest{} } -func (m *GoTest) String() string { return proto.CompactTextString(m) } -func (*GoTest) ProtoMessage() {} - -const Default_GoTest_F_BoolDefaulted bool = true -const Default_GoTest_F_Int32Defaulted int32 = 32 -const Default_GoTest_F_Int64Defaulted int64 = 64 -const Default_GoTest_F_Fixed32Defaulted uint32 = 320 -const Default_GoTest_F_Fixed64Defaulted uint64 = 640 -const Default_GoTest_F_Uint32Defaulted uint32 = 3200 -const Default_GoTest_F_Uint64Defaulted uint64 = 6400 -const Default_GoTest_F_FloatDefaulted float32 = 314159 -const Default_GoTest_F_DoubleDefaulted float64 = 271828 -const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n" - -var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose") - -const Default_GoTest_F_Sint32Defaulted int32 = -32 -const Default_GoTest_F_Sint64Defaulted int64 = -64 - -func (m *GoTest) GetKind() GoTest_KIND { - if m != nil && m.Kind != nil { - return *m.Kind - } - return 0 -} - -func (m *GoTest) GetTable() string { - if m != nil && m.Table != nil { - return *m.Table - } - return "" -} - -func (m *GoTest) GetParam() int32 { - if m != nil && m.Param != nil { - return *m.Param - } - return 0 -} - -func (m *GoTest) GetRequiredField() *GoTestField { - if m != nil { - return m.RequiredField - } - return nil -} - -func (m *GoTest) GetRepeatedField() []*GoTestField { - if m != nil { - return m.RepeatedField - } - return nil -} - -func (m *GoTest) GetOptionalField() *GoTestField { - if m != nil { - return m.OptionalField - } - return nil -} - -func (m *GoTest) GetF_BoolRequired() bool { - if m != nil && m.F_BoolRequired != nil { - return *m.F_BoolRequired - } - return false -} - -func (m *GoTest) GetF_Int32Required() int32 { - if m != nil && m.F_Int32Required != nil { - return *m.F_Int32Required - } - return 0 -} - -func (m *GoTest) GetF_Int64Required() int64 { - if m != nil && m.F_Int64Required != nil { - return *m.F_Int64Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Required() uint32 { - if m != nil && m.F_Fixed32Required != nil { - return *m.F_Fixed32Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Required() uint64 { - if m != nil && m.F_Fixed64Required != nil { - return *m.F_Fixed64Required - } - return 0 -} - -func (m *GoTest) GetF_Uint32Required() uint32 { - if m != nil && m.F_Uint32Required != nil { - return *m.F_Uint32Required - } - return 0 -} - -func (m *GoTest) GetF_Uint64Required() uint64 { - if m != nil && m.F_Uint64Required != nil { - return *m.F_Uint64Required - } - return 0 -} - -func (m *GoTest) GetF_FloatRequired() float32 { - if m != nil && m.F_FloatRequired != nil { - return *m.F_FloatRequired - } - return 0 -} - -func (m *GoTest) GetF_DoubleRequired() float64 { - if m != nil && m.F_DoubleRequired != nil { - return *m.F_DoubleRequired - } - return 0 -} - -func (m *GoTest) GetF_StringRequired() string { - if m != nil && m.F_StringRequired != nil { - return *m.F_StringRequired - } - return "" -} - -func (m *GoTest) GetF_BytesRequired() []byte { - if m != nil { - return m.F_BytesRequired - } - return nil -} - -func (m *GoTest) GetF_Sint32Required() int32 { - if m != nil && m.F_Sint32Required != nil { - return *m.F_Sint32Required - } - return 0 -} - -func (m *GoTest) GetF_Sint64Required() int64 { - if m != nil && m.F_Sint64Required != nil { - return *m.F_Sint64Required - } - return 0 -} - -func (m *GoTest) GetF_BoolRepeated() []bool { - if m != nil { - return m.F_BoolRepeated - } - return nil -} - -func (m *GoTest) GetF_Int32Repeated() []int32 { - if m != nil { - return m.F_Int32Repeated - } - return nil -} - -func (m *GoTest) GetF_Int64Repeated() []int64 { - if m != nil { - return m.F_Int64Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed32Repeated() []uint32 { - if m != nil { - return m.F_Fixed32Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed64Repeated() []uint64 { - if m != nil { - return m.F_Fixed64Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint32Repeated() []uint32 { - if m != nil { - return m.F_Uint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint64Repeated() []uint64 { - if m != nil { - return m.F_Uint64Repeated - } - return nil -} - -func (m *GoTest) GetF_FloatRepeated() []float32 { - if m != nil { - return m.F_FloatRepeated - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeated() []float64 { - if m != nil { - return m.F_DoubleRepeated - } - return nil -} - -func (m *GoTest) GetF_StringRepeated() []string { - if m != nil { - return m.F_StringRepeated - } - return nil -} - -func (m *GoTest) GetF_BytesRepeated() [][]byte { - if m != nil { - return m.F_BytesRepeated - } - return nil -} - -func (m *GoTest) GetF_Sint32Repeated() []int32 { - if m != nil { - return m.F_Sint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Sint64Repeated() []int64 { - if m != nil { - return m.F_Sint64Repeated - } - return nil -} - -func (m *GoTest) GetF_BoolOptional() bool { - if m != nil && m.F_BoolOptional != nil { - return *m.F_BoolOptional - } - return false -} - -func (m *GoTest) GetF_Int32Optional() int32 { - if m != nil && m.F_Int32Optional != nil { - return *m.F_Int32Optional - } - return 0 -} - -func (m *GoTest) GetF_Int64Optional() int64 { - if m != nil && m.F_Int64Optional != nil { - return *m.F_Int64Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Optional() uint32 { - if m != nil && m.F_Fixed32Optional != nil { - return *m.F_Fixed32Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Optional() uint64 { - if m != nil && m.F_Fixed64Optional != nil { - return *m.F_Fixed64Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint32Optional() uint32 { - if m != nil && m.F_Uint32Optional != nil { - return *m.F_Uint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint64Optional() uint64 { - if m != nil && m.F_Uint64Optional != nil { - return *m.F_Uint64Optional - } - return 0 -} - -func (m *GoTest) GetF_FloatOptional() float32 { - if m != nil && m.F_FloatOptional != nil { - return *m.F_FloatOptional - } - return 0 -} - -func (m *GoTest) GetF_DoubleOptional() float64 { - if m != nil && m.F_DoubleOptional != nil { - return *m.F_DoubleOptional - } - return 0 -} - -func (m *GoTest) GetF_StringOptional() string { - if m != nil && m.F_StringOptional != nil { - return *m.F_StringOptional - } - return "" -} - -func (m *GoTest) GetF_BytesOptional() []byte { - if m != nil { - return m.F_BytesOptional - } - return nil -} - -func (m *GoTest) GetF_Sint32Optional() int32 { - if m != nil && m.F_Sint32Optional != nil { - return *m.F_Sint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Sint64Optional() int64 { - if m != nil && m.F_Sint64Optional != nil { - return *m.F_Sint64Optional - } - return 0 -} - -func (m *GoTest) GetF_BoolDefaulted() bool { - if m != nil && m.F_BoolDefaulted != nil { - return *m.F_BoolDefaulted - } - return Default_GoTest_F_BoolDefaulted -} - -func (m *GoTest) GetF_Int32Defaulted() int32 { - if m != nil && m.F_Int32Defaulted != nil { - return *m.F_Int32Defaulted - } - return Default_GoTest_F_Int32Defaulted -} - -func (m *GoTest) GetF_Int64Defaulted() int64 { - if m != nil && m.F_Int64Defaulted != nil { - return *m.F_Int64Defaulted - } - return Default_GoTest_F_Int64Defaulted -} - -func (m *GoTest) GetF_Fixed32Defaulted() uint32 { - if m != nil && m.F_Fixed32Defaulted != nil { - return *m.F_Fixed32Defaulted - } - return Default_GoTest_F_Fixed32Defaulted -} - -func (m *GoTest) GetF_Fixed64Defaulted() uint64 { - if m != nil && m.F_Fixed64Defaulted != nil { - return *m.F_Fixed64Defaulted - } - return Default_GoTest_F_Fixed64Defaulted -} - -func (m *GoTest) GetF_Uint32Defaulted() uint32 { - if m != nil && m.F_Uint32Defaulted != nil { - return *m.F_Uint32Defaulted - } - return Default_GoTest_F_Uint32Defaulted -} - -func (m *GoTest) GetF_Uint64Defaulted() uint64 { - if m != nil && m.F_Uint64Defaulted != nil { - return *m.F_Uint64Defaulted - } - return Default_GoTest_F_Uint64Defaulted -} - -func (m *GoTest) GetF_FloatDefaulted() float32 { - if m != nil && m.F_FloatDefaulted != nil { - return *m.F_FloatDefaulted - } - return Default_GoTest_F_FloatDefaulted -} - -func (m *GoTest) GetF_DoubleDefaulted() float64 { - if m != nil && m.F_DoubleDefaulted != nil { - return *m.F_DoubleDefaulted - } - return Default_GoTest_F_DoubleDefaulted -} - -func (m *GoTest) GetF_StringDefaulted() string { - if m != nil && m.F_StringDefaulted != nil { - return *m.F_StringDefaulted - } - return Default_GoTest_F_StringDefaulted -} - -func (m *GoTest) GetF_BytesDefaulted() []byte { - if m != nil && m.F_BytesDefaulted != nil { - return m.F_BytesDefaulted - } - return append([]byte(nil), Default_GoTest_F_BytesDefaulted...) -} - -func (m *GoTest) GetF_Sint32Defaulted() int32 { - if m != nil && m.F_Sint32Defaulted != nil { - return *m.F_Sint32Defaulted - } - return Default_GoTest_F_Sint32Defaulted -} - -func (m *GoTest) GetF_Sint64Defaulted() int64 { - if m != nil && m.F_Sint64Defaulted != nil { - return *m.F_Sint64Defaulted - } - return Default_GoTest_F_Sint64Defaulted -} - -func (m *GoTest) GetF_BoolRepeatedPacked() []bool { - if m != nil { - return m.F_BoolRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int32RepeatedPacked() []int32 { - if m != nil { - return m.F_Int32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int64RepeatedPacked() []int64 { - if m != nil { - return m.F_Int64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Fixed32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Fixed64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Uint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Uint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_FloatRepeatedPacked() []float32 { - if m != nil { - return m.F_FloatRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeatedPacked() []float64 { - if m != nil { - return m.F_DoubleRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint32RepeatedPacked() []int32 { - if m != nil { - return m.F_Sint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint64RepeatedPacked() []int64 { - if m != nil { - return m.F_Sint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetRequiredgroup() *GoTest_RequiredGroup { - if m != nil { - return m.Requiredgroup - } - return nil -} - -func (m *GoTest) GetRepeatedgroup() []*GoTest_RepeatedGroup { - if m != nil { - return m.Repeatedgroup - } - return nil -} - -func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup { - if m != nil { - return m.Optionalgroup - } - return nil -} - -type GoTest_RequiredGroup struct { - RequiredField *string `protobuf:"bytes,71,req" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RequiredGroup) Reset() { *m = GoTest_RequiredGroup{} } - -func (m *GoTest_RequiredGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_RepeatedGroup struct { - RequiredField *string `protobuf:"bytes,81,req" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RepeatedGroup) Reset() { *m = GoTest_RepeatedGroup{} } - -func (m *GoTest_RepeatedGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_OptionalGroup struct { - RequiredField *string `protobuf:"bytes,91,req" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_OptionalGroup) Reset() { *m = GoTest_OptionalGroup{} } - -func (m *GoTest_OptionalGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoSkipTest struct { - SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32" json:"skip_int32,omitempty"` - SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32" json:"skip_fixed32,omitempty"` - SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64" json:"skip_fixed64,omitempty"` - SkipString *string `protobuf:"bytes,14,req,name=skip_string" json:"skip_string,omitempty"` - Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup" json:"skipgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest) Reset() { *m = GoSkipTest{} } -func (m *GoSkipTest) String() string { return proto.CompactTextString(m) } -func (*GoSkipTest) ProtoMessage() {} - -func (m *GoSkipTest) GetSkipInt32() int32 { - if m != nil && m.SkipInt32 != nil { - return *m.SkipInt32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed32() uint32 { - if m != nil && m.SkipFixed32 != nil { - return *m.SkipFixed32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed64() uint64 { - if m != nil && m.SkipFixed64 != nil { - return *m.SkipFixed64 - } - return 0 -} - -func (m *GoSkipTest) GetSkipString() string { - if m != nil && m.SkipString != nil { - return *m.SkipString - } - return "" -} - -func (m *GoSkipTest) GetSkipgroup() *GoSkipTest_SkipGroup { - if m != nil { - return m.Skipgroup - } - return nil -} - -type GoSkipTest_SkipGroup struct { - GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32" json:"group_int32,omitempty"` - GroupString *string `protobuf:"bytes,17,req,name=group_string" json:"group_string,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest_SkipGroup) Reset() { *m = GoSkipTest_SkipGroup{} } - -func (m *GoSkipTest_SkipGroup) GetGroupInt32() int32 { - if m != nil && m.GroupInt32 != nil { - return *m.GroupInt32 - } - return 0 -} - -func (m *GoSkipTest_SkipGroup) GetGroupString() string { - if m != nil && m.GroupString != nil { - return *m.GroupString - } - return "" -} - -type NonPackedTest struct { - A []int32 `protobuf:"varint,1,rep,name=a" json:"a,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NonPackedTest) Reset() { *m = NonPackedTest{} } -func (m *NonPackedTest) String() string { return proto.CompactTextString(m) } -func (*NonPackedTest) ProtoMessage() {} - -func (m *NonPackedTest) GetA() []int32 { - if m != nil { - return m.A - } - return nil -} - -type PackedTest struct { - B []int32 `protobuf:"varint,1,rep,packed,name=b" json:"b,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PackedTest) Reset() { *m = PackedTest{} } -func (m *PackedTest) String() string { return proto.CompactTextString(m) } -func (*PackedTest) ProtoMessage() {} - -func (m *PackedTest) GetB() []int32 { - if m != nil { - return m.B - } - return nil -} - -type MaxTag struct { - LastField *string `protobuf:"bytes,536870911,opt,name=last_field" json:"last_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MaxTag) Reset() { *m = MaxTag{} } -func (m *MaxTag) String() string { return proto.CompactTextString(m) } -func (*MaxTag) ProtoMessage() {} - -func (m *MaxTag) GetLastField() string { - if m != nil && m.LastField != nil { - return *m.LastField - } - return "" -} - -type OldMessage struct { - Nested *OldMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage) Reset() { *m = OldMessage{} } -func (m *OldMessage) String() string { return proto.CompactTextString(m) } -func (*OldMessage) ProtoMessage() {} - -func (m *OldMessage) GetNested() *OldMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -type OldMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage_Nested) Reset() { *m = OldMessage_Nested{} } -func (m *OldMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*OldMessage_Nested) ProtoMessage() {} - -func (m *OldMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -type NewMessage struct { - Nested *NewMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage) Reset() { *m = NewMessage{} } -func (m *NewMessage) String() string { return proto.CompactTextString(m) } -func (*NewMessage) ProtoMessage() {} - -func (m *NewMessage) GetNested() *NewMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -type NewMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - FoodGroup *string `protobuf:"bytes,2,opt,name=food_group" json:"food_group,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage_Nested) Reset() { *m = NewMessage_Nested{} } -func (m *NewMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*NewMessage_Nested) ProtoMessage() {} - -func (m *NewMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *NewMessage_Nested) GetFoodGroup() string { - if m != nil && m.FoodGroup != nil { - return *m.FoodGroup - } - return "" -} - -type InnerMessage struct { - Host *string `protobuf:"bytes,1,req,name=host" json:"host,omitempty"` - Port *int32 `protobuf:"varint,2,opt,name=port,def=4000" json:"port,omitempty"` - Connected *bool `protobuf:"varint,3,opt,name=connected" json:"connected,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *InnerMessage) Reset() { *m = InnerMessage{} } -func (m *InnerMessage) String() string { return proto.CompactTextString(m) } -func (*InnerMessage) ProtoMessage() {} - -const Default_InnerMessage_Port int32 = 4000 - -func (m *InnerMessage) GetHost() string { - if m != nil && m.Host != nil { - return *m.Host - } - return "" -} - -func (m *InnerMessage) GetPort() int32 { - if m != nil && m.Port != nil { - return *m.Port - } - return Default_InnerMessage_Port -} - -func (m *InnerMessage) GetConnected() bool { - if m != nil && m.Connected != nil { - return *m.Connected - } - return false -} - -type OtherMessage struct { - Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"` - Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OtherMessage) Reset() { *m = OtherMessage{} } -func (m *OtherMessage) String() string { return proto.CompactTextString(m) } -func (*OtherMessage) ProtoMessage() {} - -func (m *OtherMessage) GetKey() int64 { - if m != nil && m.Key != nil { - return *m.Key - } - return 0 -} - -func (m *OtherMessage) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *OtherMessage) GetWeight() float32 { - if m != nil && m.Weight != nil { - return *m.Weight - } - return 0 -} - -func (m *OtherMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -type MyMessage struct { - Count *int32 `protobuf:"varint,1,req,name=count" json:"count,omitempty"` - Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` - Quote *string `protobuf:"bytes,3,opt,name=quote" json:"quote,omitempty"` - Pet []string `protobuf:"bytes,4,rep,name=pet" json:"pet,omitempty"` - Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner" json:"inner,omitempty"` - Others []*OtherMessage `protobuf:"bytes,6,rep,name=others" json:"others,omitempty"` - Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"` - Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup" json:"somegroup,omitempty"` - RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes" json:"rep_bytes,omitempty"` - Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage) Reset() { *m = MyMessage{} } -func (m *MyMessage) String() string { return proto.CompactTextString(m) } -func (*MyMessage) ProtoMessage() {} - -var extRange_MyMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_MyMessage -} -func (m *MyMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -func (m *MyMessage) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *MyMessage) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MyMessage) GetQuote() string { - if m != nil && m.Quote != nil { - return *m.Quote - } - return "" -} - -func (m *MyMessage) GetPet() []string { - if m != nil { - return m.Pet - } - return nil -} - -func (m *MyMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -func (m *MyMessage) GetOthers() []*OtherMessage { - if m != nil { - return m.Others - } - return nil -} - -func (m *MyMessage) GetBikeshed() MyMessage_Color { - if m != nil && m.Bikeshed != nil { - return *m.Bikeshed - } - return 0 -} - -func (m *MyMessage) GetSomegroup() *MyMessage_SomeGroup { - if m != nil { - return m.Somegroup - } - return nil -} - -func (m *MyMessage) GetRepBytes() [][]byte { - if m != nil { - return m.RepBytes - } - return nil -} - -func (m *MyMessage) GetBigfloat() float64 { - if m != nil && m.Bigfloat != nil { - return *m.Bigfloat - } - return 0 -} - -type MyMessage_SomeGroup struct { - GroupField *int32 `protobuf:"varint,9,opt,name=group_field" json:"group_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage_SomeGroup) Reset() { *m = MyMessage_SomeGroup{} } - -func (m *MyMessage_SomeGroup) GetGroupField() int32 { - if m != nil && m.GroupField != nil { - return *m.GroupField - } - return 0 -} - -type Ext struct { - Data *string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Ext) Reset() { *m = Ext{} } -func (m *Ext) String() string { return proto.CompactTextString(m) } -func (*Ext) ProtoMessage() {} - -func (m *Ext) GetData() string { - if m != nil && m.Data != nil { - return *m.Data - } - return "" -} - -var E_Ext_More = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*Ext)(nil), - Field: 103, - Name: "testdata.Ext.more", - Tag: "bytes,103,opt,name=more", -} - -var E_Ext_Text = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*string)(nil), - Field: 104, - Name: "testdata.Ext.text", - Tag: "bytes,104,opt,name=text", -} - -var E_Ext_Number = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 105, - Name: "testdata.Ext.number", - Tag: "varint,105,opt,name=number", -} - -type MessageList struct { - Message []*MessageList_Message `protobuf:"group,1,rep" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList) Reset() { *m = MessageList{} } -func (m *MessageList) String() string { return proto.CompactTextString(m) } -func (*MessageList) ProtoMessage() {} - -func (m *MessageList) GetMessage() []*MessageList_Message { - if m != nil { - return m.Message - } - return nil -} - -type MessageList_Message struct { - Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` - Count *int32 `protobuf:"varint,3,req,name=count" json:"count,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList_Message) Reset() { *m = MessageList_Message{} } - -func (m *MessageList_Message) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MessageList_Message) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -type Strings struct { - StringField *string `protobuf:"bytes,1,opt,name=string_field" json:"string_field,omitempty"` - BytesField []byte `protobuf:"bytes,2,opt,name=bytes_field" json:"bytes_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Strings) Reset() { *m = Strings{} } -func (m *Strings) String() string { return proto.CompactTextString(m) } -func (*Strings) ProtoMessage() {} - -func (m *Strings) GetStringField() string { - if m != nil && m.StringField != nil { - return *m.StringField - } - return "" -} - -func (m *Strings) GetBytesField() []byte { - if m != nil { - return m.BytesField - } - return nil -} - -type Defaults struct { - F_Bool *bool `protobuf:"varint,1,opt,def=1" json:"F_Bool,omitempty"` - F_Int32 *int32 `protobuf:"varint,2,opt,def=32" json:"F_Int32,omitempty"` - F_Int64 *int64 `protobuf:"varint,3,opt,def=64" json:"F_Int64,omitempty"` - F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,def=320" json:"F_Fixed32,omitempty"` - F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,def=640" json:"F_Fixed64,omitempty"` - F_Uint32 *uint32 `protobuf:"varint,6,opt,def=3200" json:"F_Uint32,omitempty"` - F_Uint64 *uint64 `protobuf:"varint,7,opt,def=6400" json:"F_Uint64,omitempty"` - F_Float *float32 `protobuf:"fixed32,8,opt,def=314159" json:"F_Float,omitempty"` - F_Double *float64 `protobuf:"fixed64,9,opt,def=271828" json:"F_Double,omitempty"` - F_String *string `protobuf:"bytes,10,opt,def=hello, \"world!\"\n" json:"F_String,omitempty"` - F_Bytes []byte `protobuf:"bytes,11,opt,def=Bignose" json:"F_Bytes,omitempty"` - F_Sint32 *int32 `protobuf:"zigzag32,12,opt,def=-32" json:"F_Sint32,omitempty"` - F_Sint64 *int64 `protobuf:"zigzag64,13,opt,def=-64" json:"F_Sint64,omitempty"` - F_Enum *Defaults_Color `protobuf:"varint,14,opt,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` - F_Pinf *float32 `protobuf:"fixed32,15,opt,def=inf" json:"F_Pinf,omitempty"` - F_Ninf *float32 `protobuf:"fixed32,16,opt,def=-inf" json:"F_Ninf,omitempty"` - F_Nan *float32 `protobuf:"fixed32,17,opt,def=nan" json:"F_Nan,omitempty"` - Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Defaults) Reset() { *m = Defaults{} } -func (m *Defaults) String() string { return proto.CompactTextString(m) } -func (*Defaults) ProtoMessage() {} - -const Default_Defaults_F_Bool bool = true -const Default_Defaults_F_Int32 int32 = 32 -const Default_Defaults_F_Int64 int64 = 64 -const Default_Defaults_F_Fixed32 uint32 = 320 -const Default_Defaults_F_Fixed64 uint64 = 640 -const Default_Defaults_F_Uint32 uint32 = 3200 -const Default_Defaults_F_Uint64 uint64 = 6400 -const Default_Defaults_F_Float float32 = 314159 -const Default_Defaults_F_Double float64 = 271828 -const Default_Defaults_F_String string = "hello, \"world!\"\n" - -var Default_Defaults_F_Bytes []byte = []byte("Bignose") - -const Default_Defaults_F_Sint32 int32 = -32 -const Default_Defaults_F_Sint64 int64 = -64 -const Default_Defaults_F_Enum Defaults_Color = Defaults_GREEN - -var Default_Defaults_F_Pinf float32 = float32(math.Inf(1)) -var Default_Defaults_F_Ninf float32 = float32(math.Inf(-1)) -var Default_Defaults_F_Nan float32 = float32(math.NaN()) - -func (m *Defaults) GetF_Bool() bool { - if m != nil && m.F_Bool != nil { - return *m.F_Bool - } - return Default_Defaults_F_Bool -} - -func (m *Defaults) GetF_Int32() int32 { - if m != nil && m.F_Int32 != nil { - return *m.F_Int32 - } - return Default_Defaults_F_Int32 -} - -func (m *Defaults) GetF_Int64() int64 { - if m != nil && m.F_Int64 != nil { - return *m.F_Int64 - } - return Default_Defaults_F_Int64 -} - -func (m *Defaults) GetF_Fixed32() uint32 { - if m != nil && m.F_Fixed32 != nil { - return *m.F_Fixed32 - } - return Default_Defaults_F_Fixed32 -} - -func (m *Defaults) GetF_Fixed64() uint64 { - if m != nil && m.F_Fixed64 != nil { - return *m.F_Fixed64 - } - return Default_Defaults_F_Fixed64 -} - -func (m *Defaults) GetF_Uint32() uint32 { - if m != nil && m.F_Uint32 != nil { - return *m.F_Uint32 - } - return Default_Defaults_F_Uint32 -} - -func (m *Defaults) GetF_Uint64() uint64 { - if m != nil && m.F_Uint64 != nil { - return *m.F_Uint64 - } - return Default_Defaults_F_Uint64 -} - -func (m *Defaults) GetF_Float() float32 { - if m != nil && m.F_Float != nil { - return *m.F_Float - } - return Default_Defaults_F_Float -} - -func (m *Defaults) GetF_Double() float64 { - if m != nil && m.F_Double != nil { - return *m.F_Double - } - return Default_Defaults_F_Double -} - -func (m *Defaults) GetF_String() string { - if m != nil && m.F_String != nil { - return *m.F_String - } - return Default_Defaults_F_String -} - -func (m *Defaults) GetF_Bytes() []byte { - if m != nil && m.F_Bytes != nil { - return m.F_Bytes - } - return append([]byte(nil), Default_Defaults_F_Bytes...) -} - -func (m *Defaults) GetF_Sint32() int32 { - if m != nil && m.F_Sint32 != nil { - return *m.F_Sint32 - } - return Default_Defaults_F_Sint32 -} - -func (m *Defaults) GetF_Sint64() int64 { - if m != nil && m.F_Sint64 != nil { - return *m.F_Sint64 - } - return Default_Defaults_F_Sint64 -} - -func (m *Defaults) GetF_Enum() Defaults_Color { - if m != nil && m.F_Enum != nil { - return *m.F_Enum - } - return Default_Defaults_F_Enum -} - -func (m *Defaults) GetF_Pinf() float32 { - if m != nil && m.F_Pinf != nil { - return *m.F_Pinf - } - return Default_Defaults_F_Pinf -} - -func (m *Defaults) GetF_Ninf() float32 { - if m != nil && m.F_Ninf != nil { - return *m.F_Ninf - } - return Default_Defaults_F_Ninf -} - -func (m *Defaults) GetF_Nan() float32 { - if m != nil && m.F_Nan != nil { - return *m.F_Nan - } - return Default_Defaults_F_Nan -} - -func (m *Defaults) GetSub() *SubDefaults { - if m != nil { - return m.Sub - } - return nil -} - -type SubDefaults struct { - N *int64 `protobuf:"varint,1,opt,name=n,def=7" json:"n,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SubDefaults) Reset() { *m = SubDefaults{} } -func (m *SubDefaults) String() string { return proto.CompactTextString(m) } -func (*SubDefaults) ProtoMessage() {} - -const Default_SubDefaults_N int64 = 7 - -func (m *SubDefaults) GetN() int64 { - if m != nil && m.N != nil { - return *m.N - } - return Default_SubDefaults_N -} - -type RepeatedEnum struct { - Color []RepeatedEnum_Color `protobuf:"varint,1,rep,name=color,enum=testdata.RepeatedEnum_Color" json:"color,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RepeatedEnum) Reset() { *m = RepeatedEnum{} } -func (m *RepeatedEnum) String() string { return proto.CompactTextString(m) } -func (*RepeatedEnum) ProtoMessage() {} - -func (m *RepeatedEnum) GetColor() []RepeatedEnum_Color { - if m != nil { - return m.Color - } - return nil -} - -type MoreRepeated struct { - Bools []bool `protobuf:"varint,1,rep,name=bools" json:"bools,omitempty"` - BoolsPacked []bool `protobuf:"varint,2,rep,packed,name=bools_packed" json:"bools_packed,omitempty"` - Ints []int32 `protobuf:"varint,3,rep,name=ints" json:"ints,omitempty"` - IntsPacked []int32 `protobuf:"varint,4,rep,packed,name=ints_packed" json:"ints_packed,omitempty"` - Strings []string `protobuf:"bytes,5,rep,name=strings" json:"strings,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MoreRepeated) Reset() { *m = MoreRepeated{} } -func (m *MoreRepeated) String() string { return proto.CompactTextString(m) } -func (*MoreRepeated) ProtoMessage() {} - -func (m *MoreRepeated) GetBools() []bool { - if m != nil { - return m.Bools - } - return nil -} - -func (m *MoreRepeated) GetBoolsPacked() []bool { - if m != nil { - return m.BoolsPacked - } - return nil -} - -func (m *MoreRepeated) GetInts() []int32 { - if m != nil { - return m.Ints - } - return nil -} - -func (m *MoreRepeated) GetIntsPacked() []int32 { - if m != nil { - return m.IntsPacked - } - return nil -} - -func (m *MoreRepeated) GetStrings() []string { - if m != nil { - return m.Strings - } - return nil -} - -type GroupOld struct { - G *GroupOld_G `protobuf:"group,1,opt" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld) Reset() { *m = GroupOld{} } -func (m *GroupOld) String() string { return proto.CompactTextString(m) } -func (*GroupOld) ProtoMessage() {} - -func (m *GroupOld) GetG() *GroupOld_G { - if m != nil { - return m.G - } - return nil -} - -type GroupOld_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld_G) Reset() { *m = GroupOld_G{} } - -func (m *GroupOld_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -type GroupNew struct { - G *GroupNew_G `protobuf:"group,1,opt" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew) Reset() { *m = GroupNew{} } -func (m *GroupNew) String() string { return proto.CompactTextString(m) } -func (*GroupNew) ProtoMessage() {} - -func (m *GroupNew) GetG() *GroupNew_G { - if m != nil { - return m.G - } - return nil -} - -type GroupNew_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - Y *int32 `protobuf:"varint,3,opt,name=y" json:"y,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew_G) Reset() { *m = GroupNew_G{} } - -func (m *GroupNew_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -func (m *GroupNew_G) GetY() int32 { - if m != nil && m.Y != nil { - return *m.Y - } - return 0 -} - -var E_Greeting = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: ([]string)(nil), - Field: 106, - Name: "testdata.greeting", - Tag: "bytes,106,rep,name=greeting", -} - -func init() { - proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value) - proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value) - proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value) - proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value) - proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value) - proto.RegisterExtension(E_Ext_More) - proto.RegisterExtension(E_Ext_Text) - proto.RegisterExtension(E_Ext_Number) - proto.RegisterExtension(E_Greeting) -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.proto b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.proto deleted file mode 100644 index 3d1cbb675..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/testdata/test.proto +++ /dev/null @@ -1,494 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// A feature-rich test file for the protocol compiler and libraries. - -syntax = "proto2"; - -package testdata; - -enum FOO { FOO1 = 1; }; - -message GoEnum { - required FOO foo = 1; -} - -message GoTestField { - required string Label = 1; - required string Type = 2; -} - -message GoTest { - // An enum, for completeness. - enum KIND { - VOID = 0; - - // Basic types - BOOL = 1; - BYTES = 2; - FINGERPRINT = 3; - FLOAT = 4; - INT = 5; - STRING = 6; - TIME = 7; - - // Groupings - TUPLE = 8; - ARRAY = 9; - MAP = 10; - - // Table types - TABLE = 11; - - // Functions - FUNCTION = 12; // last tag - }; - - // Some typical parameters - required KIND Kind = 1; - optional string Table = 2; - optional int32 Param = 3; - - // Required, repeated and optional foreign fields. - required GoTestField RequiredField = 4; - repeated GoTestField RepeatedField = 5; - optional GoTestField OptionalField = 6; - - // Required fields of all basic types - required bool F_Bool_required = 10; - required int32 F_Int32_required = 11; - required int64 F_Int64_required = 12; - required fixed32 F_Fixed32_required = 13; - required fixed64 F_Fixed64_required = 14; - required uint32 F_Uint32_required = 15; - required uint64 F_Uint64_required = 16; - required float F_Float_required = 17; - required double F_Double_required = 18; - required string F_String_required = 19; - required bytes F_Bytes_required = 101; - required sint32 F_Sint32_required = 102; - required sint64 F_Sint64_required = 103; - - // Repeated fields of all basic types - repeated bool F_Bool_repeated = 20; - repeated int32 F_Int32_repeated = 21; - repeated int64 F_Int64_repeated = 22; - repeated fixed32 F_Fixed32_repeated = 23; - repeated fixed64 F_Fixed64_repeated = 24; - repeated uint32 F_Uint32_repeated = 25; - repeated uint64 F_Uint64_repeated = 26; - repeated float F_Float_repeated = 27; - repeated double F_Double_repeated = 28; - repeated string F_String_repeated = 29; - repeated bytes F_Bytes_repeated = 201; - repeated sint32 F_Sint32_repeated = 202; - repeated sint64 F_Sint64_repeated = 203; - - // Optional fields of all basic types - optional bool F_Bool_optional = 30; - optional int32 F_Int32_optional = 31; - optional int64 F_Int64_optional = 32; - optional fixed32 F_Fixed32_optional = 33; - optional fixed64 F_Fixed64_optional = 34; - optional uint32 F_Uint32_optional = 35; - optional uint64 F_Uint64_optional = 36; - optional float F_Float_optional = 37; - optional double F_Double_optional = 38; - optional string F_String_optional = 39; - optional bytes F_Bytes_optional = 301; - optional sint32 F_Sint32_optional = 302; - optional sint64 F_Sint64_optional = 303; - - // Default-valued fields of all basic types - optional bool F_Bool_defaulted = 40 [default=true]; - optional int32 F_Int32_defaulted = 41 [default=32]; - optional int64 F_Int64_defaulted = 42 [default=64]; - optional fixed32 F_Fixed32_defaulted = 43 [default=320]; - optional fixed64 F_Fixed64_defaulted = 44 [default=640]; - optional uint32 F_Uint32_defaulted = 45 [default=3200]; - optional uint64 F_Uint64_defaulted = 46 [default=6400]; - optional float F_Float_defaulted = 47 [default=314159.]; - optional double F_Double_defaulted = 48 [default=271828.]; - optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"]; - optional bytes F_Bytes_defaulted = 401 [default="Bignose"]; - optional sint32 F_Sint32_defaulted = 402 [default = -32]; - optional sint64 F_Sint64_defaulted = 403 [default = -64]; - - // Packed repeated fields (no string or bytes). - repeated bool F_Bool_repeated_packed = 50 [packed=true]; - repeated int32 F_Int32_repeated_packed = 51 [packed=true]; - repeated int64 F_Int64_repeated_packed = 52 [packed=true]; - repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true]; - repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true]; - repeated uint32 F_Uint32_repeated_packed = 55 [packed=true]; - repeated uint64 F_Uint64_repeated_packed = 56 [packed=true]; - repeated float F_Float_repeated_packed = 57 [packed=true]; - repeated double F_Double_repeated_packed = 58 [packed=true]; - repeated sint32 F_Sint32_repeated_packed = 502 [packed=true]; - repeated sint64 F_Sint64_repeated_packed = 503 [packed=true]; - - // Required, repeated, and optional groups. - required group RequiredGroup = 70 { - required string RequiredField = 71; - }; - - repeated group RepeatedGroup = 80 { - required string RequiredField = 81; - }; - - optional group OptionalGroup = 90 { - required string RequiredField = 91; - }; -} - -// For testing skipping of unrecognized fields. -// Numbers are all big, larger than tag numbers in GoTestField, -// the message used in the corresponding test. -message GoSkipTest { - required int32 skip_int32 = 11; - required fixed32 skip_fixed32 = 12; - required fixed64 skip_fixed64 = 13; - required string skip_string = 14; - required group SkipGroup = 15 { - required int32 group_int32 = 16; - required string group_string = 17; - } -} - -// For testing packed/non-packed decoder switching. -// A serialized instance of one should be deserializable as the other. -message NonPackedTest { - repeated int32 a = 1; -} - -message PackedTest { - repeated int32 b = 1 [packed=true]; -} - -message MaxTag { - // Maximum possible tag number. - optional string last_field = 536870911; -} - -message OldMessage { - message Nested { - optional string name = 1; - } - optional Nested nested = 1; - - optional int32 num = 2; -} - -// NewMessage is wire compatible with OldMessage; -// imagine it as a future version. -message NewMessage { - message Nested { - optional string name = 1; - optional string food_group = 2; - } - optional Nested nested = 1; - - // This is an int32 in OldMessage. - optional int64 num = 2; -} - -// Smaller tests for ASCII formatting. - -message InnerMessage { - required string host = 1; - optional int32 port = 2 [default=4000]; - optional bool connected = 3; -} - -message OtherMessage { - optional int64 key = 1; - optional bytes value = 2; - optional float weight = 3; - optional InnerMessage inner = 4; -} - -message MyMessage { - required int32 count = 1; - optional string name = 2; - optional string quote = 3; - repeated string pet = 4; - optional InnerMessage inner = 5; - repeated OtherMessage others = 6; - repeated InnerMessage rep_inner = 12; - - enum Color { - RED = 0; - GREEN = 1; - BLUE = 2; - }; - optional Color bikeshed = 7; - - optional group SomeGroup = 8 { - optional int32 group_field = 9; - } - - // This field becomes [][]byte in the generated code. - repeated bytes rep_bytes = 10; - - optional double bigfloat = 11; - - extensions 100 to max; -} - -message Ext { - extend MyMessage { - optional Ext more = 103; - optional string text = 104; - optional int32 number = 105; - } - - optional string data = 1; -} - -extend MyMessage { - repeated string greeting = 106; -} - -message DefaultsMessage { - enum DefaultsEnum { - ZERO = 0; - ONE = 1; - TWO = 2; - }; - extensions 100 to max; -} - -extend DefaultsMessage { - optional double no_default_double = 101; - optional float no_default_float = 102; - optional int32 no_default_int32 = 103; - optional int64 no_default_int64 = 104; - optional uint32 no_default_uint32 = 105; - optional uint64 no_default_uint64 = 106; - optional sint32 no_default_sint32 = 107; - optional sint64 no_default_sint64 = 108; - optional fixed32 no_default_fixed32 = 109; - optional fixed64 no_default_fixed64 = 110; - optional sfixed32 no_default_sfixed32 = 111; - optional sfixed64 no_default_sfixed64 = 112; - optional bool no_default_bool = 113; - optional string no_default_string = 114; - optional bytes no_default_bytes = 115; - optional DefaultsMessage.DefaultsEnum no_default_enum = 116; - - optional double default_double = 201 [default = 3.1415]; - optional float default_float = 202 [default = 3.14]; - optional int32 default_int32 = 203 [default = 42]; - optional int64 default_int64 = 204 [default = 43]; - optional uint32 default_uint32 = 205 [default = 44]; - optional uint64 default_uint64 = 206 [default = 45]; - optional sint32 default_sint32 = 207 [default = 46]; - optional sint64 default_sint64 = 208 [default = 47]; - optional fixed32 default_fixed32 = 209 [default = 48]; - optional fixed64 default_fixed64 = 210 [default = 49]; - optional sfixed32 default_sfixed32 = 211 [default = 50]; - optional sfixed64 default_sfixed64 = 212 [default = 51]; - optional bool default_bool = 213 [default = true]; - optional string default_string = 214 [default = "Hello, string"]; - optional bytes default_bytes = 215 [default = "Hello, bytes"]; - optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE]; -} - -message MyMessageSet { - option message_set_wire_format = true; - extensions 100 to max; -} - -message Empty { -} - -extend MyMessageSet { - optional Empty x201 = 201; - optional Empty x202 = 202; - optional Empty x203 = 203; - optional Empty x204 = 204; - optional Empty x205 = 205; - optional Empty x206 = 206; - optional Empty x207 = 207; - optional Empty x208 = 208; - optional Empty x209 = 209; - optional Empty x210 = 210; - optional Empty x211 = 211; - optional Empty x212 = 212; - optional Empty x213 = 213; - optional Empty x214 = 214; - optional Empty x215 = 215; - optional Empty x216 = 216; - optional Empty x217 = 217; - optional Empty x218 = 218; - optional Empty x219 = 219; - optional Empty x220 = 220; - optional Empty x221 = 221; - optional Empty x222 = 222; - optional Empty x223 = 223; - optional Empty x224 = 224; - optional Empty x225 = 225; - optional Empty x226 = 226; - optional Empty x227 = 227; - optional Empty x228 = 228; - optional Empty x229 = 229; - optional Empty x230 = 230; - optional Empty x231 = 231; - optional Empty x232 = 232; - optional Empty x233 = 233; - optional Empty x234 = 234; - optional Empty x235 = 235; - optional Empty x236 = 236; - optional Empty x237 = 237; - optional Empty x238 = 238; - optional Empty x239 = 239; - optional Empty x240 = 240; - optional Empty x241 = 241; - optional Empty x242 = 242; - optional Empty x243 = 243; - optional Empty x244 = 244; - optional Empty x245 = 245; - optional Empty x246 = 246; - optional Empty x247 = 247; - optional Empty x248 = 248; - optional Empty x249 = 249; - optional Empty x250 = 250; -} - -message MessageList { - repeated group Message = 1 { - required string name = 2; - required int32 count = 3; - } -} - -message Strings { - optional string string_field = 1; - optional bytes bytes_field = 2; -} - -message Defaults { - enum Color { - RED = 0; - GREEN = 1; - BLUE = 2; - } - - // Default-valued fields of all basic types. - // Same as GoTest, but copied here to make testing easier. - optional bool F_Bool = 1 [default=true]; - optional int32 F_Int32 = 2 [default=32]; - optional int64 F_Int64 = 3 [default=64]; - optional fixed32 F_Fixed32 = 4 [default=320]; - optional fixed64 F_Fixed64 = 5 [default=640]; - optional uint32 F_Uint32 = 6 [default=3200]; - optional uint64 F_Uint64 = 7 [default=6400]; - optional float F_Float = 8 [default=314159.]; - optional double F_Double = 9 [default=271828.]; - optional string F_String = 10 [default="hello, \"world!\"\n"]; - optional bytes F_Bytes = 11 [default="Bignose"]; - optional sint32 F_Sint32 = 12 [default=-32]; - optional sint64 F_Sint64 = 13 [default=-64]; - optional Color F_Enum = 14 [default=GREEN]; - - // More fields with crazy defaults. - optional float F_Pinf = 15 [default=inf]; - optional float F_Ninf = 16 [default=-inf]; - optional float F_Nan = 17 [default=nan]; - - // Sub-message. - optional SubDefaults sub = 18; - - // Redundant but explicit defaults. - optional string str_zero = 19 [default=""]; -} - -message SubDefaults { - optional int64 n = 1 [default=7]; -} - -message RepeatedEnum { - enum Color { - RED = 1; - } - repeated Color color = 1; -} - -message MoreRepeated { - repeated bool bools = 1; - repeated bool bools_packed = 2 [packed=true]; - repeated int32 ints = 3; - repeated int32 ints_packed = 4 [packed=true]; - repeated int64 int64s_packed = 7 [packed=true]; - repeated string strings = 5; - repeated fixed32 fixeds = 6; -} - -// GroupOld and GroupNew have the same wire format. -// GroupNew has a new field inside a group. - -message GroupOld { - optional group G = 101 { - optional int32 x = 2; - } -} - -message GroupNew { - optional group G = 101 { - optional int32 x = 2; - optional int32 y = 3; - } -} - -message FloatingPoint { - required double f = 1; -} - -message MessageWithMap { - map name_mapping = 1; - map msg_mapping = 2; - map byte_mapping = 3; - map str_to_str = 4; -} - -message Communique { - optional bool make_me_cry = 1; - - // This is a oneof, called "union". - oneof union { - int32 number = 5; - string name = 6; - bytes data = 7; - double temp_c = 8; - MyMessage.Color col = 9; - Strings msg = 10; - } -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_parser_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_parser_test.go deleted file mode 100644 index 664846c40..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_parser_test.go +++ /dev/null @@ -1,532 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "math" - "reflect" - "testing" - - . "github.com/gogo/protobuf/proto" - proto3pb "github.com/gogo/protobuf/proto/proto3_proto" - . "github.com/gogo/protobuf/proto/testdata" -) - -type UnmarshalTextTest struct { - in string - err string // if "", no error expected - out *MyMessage -} - -func buildExtStructTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_More, &Ext{ - Data: String("Hello, world!"), - }) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtDataTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_Text, String("Hello, world!")) - SetExtension(msg, E_Ext_Number, Int32(1729)) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtRepStringTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil { - panic(err) - } - return UnmarshalTextTest{in: text, out: msg} -} - -var unMarshalTextTests = []UnmarshalTextTest{ - // Basic - { - in: " count:42\n name:\"Dave\" ", - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - }, - }, - - // Empty quoted string - { - in: `count:42 name:""`, - out: &MyMessage{ - Count: Int32(42), - Name: String(""), - }, - }, - - // Quoted string concatenation - { - in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string with escaped apostrophe - { - in: `count:42 name: "HOLIDAY - New Year\'s Day"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("HOLIDAY - New Year's Day"), - }, - }, - - // Quoted string with single quote - { - in: `count:42 name: 'Roger "The Ramster" Ramjet'`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`Roger "The Ramster" Ramjet`), - }, - }, - - // Quoted string with all the accepted special characters from the C++ test - { - in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"), - }, - }, - - // Quoted string with quoted backslash - { - in: `count:42 name: "\\'xyz"`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`\'xyz`), - }, - }, - - // Quoted string with UTF-8 bytes. - { - in: "count:42 name: '\303\277\302\201\xAB'", - out: &MyMessage{ - Count: Int32(42), - Name: String("\303\277\302\201\xAB"), - }, - }, - - // Bad quoted string - { - in: `inner: < host: "\0" >` + "\n", - err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`, - }, - - // Number too large for int64 - { - in: "count: 1 others { key: 123456789012345678901 }", - err: "line 1.23: invalid int64: 123456789012345678901", - }, - - // Number too large for int32 - { - in: "count: 1234567890123", - err: "line 1.7: invalid int32: 1234567890123", - }, - - // Number in hexadecimal - { - in: "count: 0x2beef", - out: &MyMessage{ - Count: Int32(0x2beef), - }, - }, - - // Number in octal - { - in: "count: 024601", - out: &MyMessage{ - Count: Int32(024601), - }, - }, - - // Floating point number with "f" suffix - { - in: "count: 4 others:< weight: 17.0f >", - out: &MyMessage{ - Count: Int32(4), - Others: []*OtherMessage{ - { - Weight: Float32(17), - }, - }, - }, - }, - - // Floating point positive infinity - { - in: "count: 4 bigfloat: inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(1)), - }, - }, - - // Floating point negative infinity - { - in: "count: 4 bigfloat: -inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(-1)), - }, - }, - - // Number too large for float32 - { - in: "others:< weight: 12345678901234567890123456789012345678901234567890 >", - err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890", - }, - - // Number posing as a quoted string - { - in: `inner: < host: 12 >` + "\n", - err: `line 1.15: invalid string: 12`, - }, - - // Quoted string posing as int32 - { - in: `count: "12"`, - err: `line 1.7: invalid int32: "12"`, - }, - - // Quoted string posing a float32 - { - in: `others:< weight: "17.4" >`, - err: `line 1.17: invalid float32: "17.4"`, - }, - - // Enum - { - in: `count:42 bikeshed: BLUE`, - out: &MyMessage{ - Count: Int32(42), - Bikeshed: MyMessage_BLUE.Enum(), - }, - }, - - // Repeated field - { - in: `count:42 pet: "horsey" pet:"bunny"`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated field with list notation - { - in: `count:42 pet: ["horsey", "bunny"]`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated message with/without colon and <>/{} - { - in: `count:42 others:{} others{} others:<> others:{}`, - out: &MyMessage{ - Count: Int32(42), - Others: []*OtherMessage{ - {}, - {}, - {}, - {}, - }, - }, - }, - - // Missing colon for inner message - { - in: `count:42 inner < host: "cauchy.syd" >`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("cauchy.syd"), - }, - }, - }, - - // Missing colon for string field - { - in: `name "Dave"`, - err: `line 1.5: expected ':', found "\"Dave\""`, - }, - - // Missing colon for int32 field - { - in: `count 42`, - err: `line 1.6: expected ':', found "42"`, - }, - - // Missing required field - { - in: `name: "Pawel"`, - err: `proto: required field "testdata.MyMessage.count" not set`, - out: &MyMessage{ - Name: String("Pawel"), - }, - }, - - // Repeated non-repeated field - { - in: `name: "Rob" name: "Russ"`, - err: `line 1.12: non-repeated field "name" was repeated`, - }, - - // Group - { - in: `count: 17 SomeGroup { group_field: 12 }`, - out: &MyMessage{ - Count: Int32(17), - Somegroup: &MyMessage_SomeGroup{ - GroupField: Int32(12), - }, - }, - }, - - // Semicolon between fields - { - in: `count:3;name:"Calvin"`, - out: &MyMessage{ - Count: Int32(3), - Name: String("Calvin"), - }, - }, - // Comma between fields - { - in: `count:4,name:"Ezekiel"`, - out: &MyMessage{ - Count: Int32(4), - Name: String("Ezekiel"), - }, - }, - - // Extension - buildExtStructTest(`count: 42 [testdata.Ext.more]:`), - buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`), - buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`), - buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`), - - // Big all-in-one - { - in: "count:42 # Meaning\n" + - `name:"Dave" ` + - `quote:"\"I didn't want to go.\"" ` + - `pet:"bunny" ` + - `pet:"kitty" ` + - `pet:"horsey" ` + - `inner:<` + - ` host:"footrest.syd" ` + - ` port:7001 ` + - ` connected:true ` + - `> ` + - `others:<` + - ` key:3735928559 ` + - ` value:"\x01A\a\f" ` + - `> ` + - `others:<` + - " weight:58.9 # Atomic weight of Co\n" + - ` inner:<` + - ` host:"lesha.mtv" ` + - ` port:8002 ` + - ` >` + - `>`, - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - Quote: String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &InnerMessage{ - Host: String("footrest.syd"), - Port: Int32(7001), - Connected: Bool(true), - }, - Others: []*OtherMessage{ - { - Key: Int64(3735928559), - Value: []byte{0x1, 'A', '\a', '\f'}, - }, - { - Weight: Float32(58.9), - Inner: &InnerMessage{ - Host: String("lesha.mtv"), - Port: Int32(8002), - }, - }, - }, - }, - }, -} - -func TestUnmarshalText(t *testing.T) { - for i, test := range unMarshalTextTests { - pb := new(MyMessage) - err := UnmarshalText(test.in, pb) - if test.err == "" { - // We don't expect failure. - if err != nil { - t.Errorf("Test %d: Unexpected error: %v", i, err) - } else if !reflect.DeepEqual(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } else { - // We do expect failure. - if err == nil { - t.Errorf("Test %d: Didn't get expected error: %v", i, test.err) - } else if err.Error() != test.err { - t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v", - i, err.Error(), test.err) - } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } - } -} - -func TestUnmarshalTextCustomMessage(t *testing.T) { - msg := &textMessage{} - if err := UnmarshalText("custom", msg); err != nil { - t.Errorf("Unexpected error from custom unmarshal: %v", err) - } - if UnmarshalText("not custom", msg) == nil { - t.Errorf("Didn't get expected error from custom unmarshal") - } -} - -// Regression test; this caused a panic. -func TestRepeatedEnum(t *testing.T) { - pb := new(RepeatedEnum) - if err := UnmarshalText("color: RED", pb); err != nil { - t.Fatal(err) - } - exp := &RepeatedEnum{ - Color: []RepeatedEnum_Color{RepeatedEnum_RED}, - } - if !Equal(pb, exp) { - t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp) - } -} - -func TestProto3TextParsing(t *testing.T) { - m := new(proto3pb.Message) - const in = `name: "Wallace" true_scotsman: true` - want := &proto3pb.Message{ - Name: "Wallace", - TrueScotsman: true, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestMapParsing(t *testing.T) { - m := new(MessageWithMap) - const in = `name_mapping: name_mapping:` + - `msg_mapping:,>` + // separating commas are okay - `msg_mapping>` + // no colon after "value" - `byte_mapping:` - want := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Beatles", - 1234: "Feist", - }, - MsgMapping: map[int64]*FloatingPoint{ - -4: {F: Float64(2.0)}, - -2: {F: Float64(4.0)}, - }, - ByteMapping: map[bool][]byte{ - true: []byte("so be it"), - }, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestOneofParsing(t *testing.T) { - const in = `name:"Shrek"` - m := new(Communique) - want := &Communique{Union: &Communique_Name{"Shrek"}} - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -var benchInput string - -func init() { - benchInput = "count: 4\n" - for i := 0; i < 1000; i++ { - benchInput += "pet: \"fido\"\n" - } - - // Check it is valid input. - pb := new(MyMessage) - err := UnmarshalText(benchInput, pb) - if err != nil { - panic("Bad benchmark input: " + err.Error()) - } -} - -func BenchmarkUnmarshalText(b *testing.B) { - pb := new(MyMessage) - for i := 0; i < b.N; i++ { - UnmarshalText(benchInput, pb) - } - b.SetBytes(int64(len(benchInput))) -} diff --git a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_test.go b/Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_test.go deleted file mode 100644 index 652404842..000000000 --- a/Godeps/_workspace/src/github.com/gogo/protobuf/proto/text_test.go +++ /dev/null @@ -1,474 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "errors" - "io/ioutil" - "math" - "strings" - "testing" - - "github.com/gogo/protobuf/proto" - - proto3pb "github.com/gogo/protobuf/proto/proto3_proto" - pb "github.com/gogo/protobuf/proto/testdata" -) - -// textMessage implements the methods that allow it to marshal and unmarshal -// itself as text. -type textMessage struct { -} - -func (*textMessage) MarshalText() ([]byte, error) { - return []byte("custom"), nil -} - -func (*textMessage) UnmarshalText(bytes []byte) error { - if string(bytes) != "custom" { - return errors.New("expected 'custom'") - } - return nil -} - -func (*textMessage) Reset() {} -func (*textMessage) String() string { return "" } -func (*textMessage) ProtoMessage() {} - -func newTestMessage() *pb.MyMessage { - msg := &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Quote: proto.String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("footrest.syd"), - Port: proto.Int32(7001), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(0xdeadbeef), - Value: []byte{1, 65, 7, 12}, - }, - { - Weight: proto.Float32(6.022), - Inner: &pb.InnerMessage{ - Host: proto.String("lesha.mtv"), - Port: proto.Int32(8002), - }, - }, - }, - Bikeshed: pb.MyMessage_BLUE.Enum(), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(8), - }, - // One normally wouldn't do this. - // This is an undeclared tag 13, as a varint (wire type 0) with value 4. - XXX_unrecognized: []byte{13<<3 | 0, 4}, - } - ext := &pb.Ext{ - Data: proto.String("Big gobs for big rats"), - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { - panic(err) - } - greetings := []string{"adg", "easy", "cow"} - if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { - panic(err) - } - - // Add an unknown extension. We marshal a pb.Ext, and fake the ID. - b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) - if err != nil { - panic(err) - } - b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) - proto.SetRawExtension(msg, 201, b) - - // Extensions can be plain fields, too, so let's test that. - b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) - proto.SetRawExtension(msg, 202, b) - - return msg -} - -const text = `count: 42 -name: "Dave" -quote: "\"I didn't want to go.\"" -pet: "bunny" -pet: "kitty" -pet: "horsey" -inner: < - host: "footrest.syd" - port: 7001 - connected: true -> -others: < - key: 3735928559 - value: "\001A\007\014" -> -others: < - weight: 6.022 - inner: < - host: "lesha.mtv" - port: 8002 - > -> -bikeshed: BLUE -SomeGroup { - group_field: 8 -} -/* 2 unknown bytes */ -13: 4 -[testdata.Ext.more]: < - data: "Big gobs for big rats" -> -[testdata.greeting]: "adg" -[testdata.greeting]: "easy" -[testdata.greeting]: "cow" -/* 13 unknown bytes */ -201: "\t3G skiing" -/* 3 unknown bytes */ -202: 19 -` - -func TestMarshalText(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, newTestMessage()); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != text { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text) - } -} - -func TestMarshalTextCustomMessage(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, &textMessage{}); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != "custom" { - t.Errorf("Got %q, expected %q", s, "custom") - } -} -func TestMarshalTextNil(t *testing.T) { - want := "" - tests := []proto.Message{nil, (*pb.MyMessage)(nil)} - for i, test := range tests { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, test); err != nil { - t.Fatal(err) - } - if got := buf.String(); got != want { - t.Errorf("%d: got %q want %q", i, got, want) - } - } -} - -func TestMarshalTextUnknownEnum(t *testing.T) { - // The Color enum only specifies values 0-2. - m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()} - got := m.String() - const want = `bikeshed:3 ` - if got != want { - t.Errorf("\n got %q\nwant %q", got, want) - } -} - -func TestTextOneof(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&pb.Communique{}, ``}, - // scalar field - {&pb.Communique{Union: &pb.Communique_Number{Number: 4}}, `number:4`}, - // message field - {&pb.Communique{Union: &pb.Communique_Msg{ - Msg: &pb.Strings{StringField: proto.String("why hello!")}, - }}, `msg:`}, - // bad oneof (should not panic) - {&pb.Communique{Union: &pb.Communique_Msg{Msg: nil}}, `msg:/* nil */`}, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} - -func BenchmarkMarshalTextBuffered(b *testing.B) { - buf := new(bytes.Buffer) - m := newTestMessage() - for i := 0; i < b.N; i++ { - buf.Reset() - proto.MarshalText(buf, m) - } -} - -func BenchmarkMarshalTextUnbuffered(b *testing.B) { - w := ioutil.Discard - m := newTestMessage() - for i := 0; i < b.N; i++ { - proto.MarshalText(w, m) - } -} - -func compact(src string) string { - // s/[ \n]+/ /g; s/ $//; - dst := make([]byte, len(src)) - space, comment := false, false - j := 0 - for i := 0; i < len(src); i++ { - if strings.HasPrefix(src[i:], "/*") { - comment = true - i++ - continue - } - if comment && strings.HasPrefix(src[i:], "*/") { - comment = false - i++ - continue - } - if comment { - continue - } - c := src[i] - if c == ' ' || c == '\n' { - space = true - continue - } - if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') { - space = false - } - if c == '{' { - space = false - } - if space { - dst[j] = ' ' - j++ - space = false - } - dst[j] = c - j++ - } - if space { - dst[j] = ' ' - j++ - } - return string(dst[0:j]) -} - -var compactText = compact(text) - -func TestCompactText(t *testing.T) { - s := proto.CompactTextString(newTestMessage()) - if s != compactText { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText) - } -} - -func TestStringEscaping(t *testing.T) { - testCases := []struct { - in *pb.Strings - out string - }{ - { - // Test data from C++ test (TextFormatTest.StringEscape). - // Single divergence: we don't escape apostrophes. - &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, - "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", - }, - { - // Test data from the same C++ test. - &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, - "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", - }, - { - // Some UTF-8. - &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, - `string_field: "\000\001\377\201"` + "\n", - }, - } - - for i, tc := range testCases { - var buf bytes.Buffer - if err := proto.MarshalText(&buf, tc.in); err != nil { - t.Errorf("proto.MarsalText: %v", err) - continue - } - s := buf.String() - if s != tc.out { - t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) - continue - } - - // Check round-trip. - pb := new(pb.Strings) - if err := proto.UnmarshalText(s, pb); err != nil { - t.Errorf("#%d: UnmarshalText: %v", i, err) - continue - } - if !proto.Equal(pb, tc.in) { - t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) - } - } -} - -// A limitedWriter accepts some output before it fails. -// This is a proxy for something like a nearly-full or imminently-failing disk, -// or a network connection that is about to die. -type limitedWriter struct { - b bytes.Buffer - limit int -} - -var outOfSpace = errors.New("proto: insufficient space") - -func (w *limitedWriter) Write(p []byte) (n int, err error) { - var avail = w.limit - w.b.Len() - if avail <= 0 { - return 0, outOfSpace - } - if len(p) <= avail { - return w.b.Write(p) - } - n, _ = w.b.Write(p[:avail]) - return n, outOfSpace -} - -func TestMarshalTextFailing(t *testing.T) { - // Try lots of different sizes to exercise more error code-paths. - for lim := 0; lim < len(text); lim++ { - buf := new(limitedWriter) - buf.limit = lim - err := proto.MarshalText(buf, newTestMessage()) - // We expect a certain error, but also some partial results in the buffer. - if err != outOfSpace { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace) - } - s := buf.b.String() - x := text[:buf.limit] - if s != x { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x) - } - } -} - -func TestFloats(t *testing.T) { - tests := []struct { - f float64 - want string - }{ - {0, "0"}, - {4.7, "4.7"}, - {math.Inf(1), "inf"}, - {math.Inf(-1), "-inf"}, - {math.NaN(), "nan"}, - } - for _, test := range tests { - msg := &pb.FloatingPoint{F: &test.f} - got := strings.TrimSpace(msg.String()) - want := `f:` + test.want - if got != want { - t.Errorf("f=%f: got %q, want %q", test.f, got, want) - } - } -} - -func TestRepeatedNilText(t *testing.T) { - m := &pb.MessageList{ - Message: []*pb.MessageList_Message{ - nil, - { - Name: proto.String("Horse"), - }, - nil, - }, - } - want := `Message -Message { - name: "Horse" -} -Message -` - if s := proto.MarshalTextString(m); s != want { - t.Errorf(" got: %s\nwant: %s", s, want) - } -} - -func TestProto3Text(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&proto3pb.Message{}, ``}, - // zero message except for an empty byte slice - {&proto3pb.Message{Data: []byte{}}, ``}, - // trivial case - {&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`}, - // empty map - {&pb.MessageWithMap{}, ``}, - // non-empty map; map format is the same as a repeated struct, - // and they are sorted by key (numerically for numeric keys). - { - &pb.MessageWithMap{NameMapping: map[int32]string{ - -1: "Negatory", - 7: "Lucky", - 1234: "Feist", - 6345789: "Otis", - }}, - `name_mapping: ` + - `name_mapping: ` + - `name_mapping: ` + - `name_mapping:`, - }, - // map with nil value; not well-defined, but we shouldn't crash - { - &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}}, - `msg_mapping:`, - }, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/glog/glog_test.go b/Godeps/_workspace/src/github.com/golang/glog/glog_test.go deleted file mode 100644 index 0fb376e1f..000000000 --- a/Godeps/_workspace/src/github.com/golang/glog/glog_test.go +++ /dev/null @@ -1,415 +0,0 @@ -// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ -// -// Copyright 2013 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 glog - -import ( - "bytes" - "fmt" - stdLog "log" - "path/filepath" - "runtime" - "strconv" - "strings" - "testing" - "time" -) - -// Test that shortHostname works as advertised. -func TestShortHostname(t *testing.T) { - for hostname, expect := range map[string]string{ - "": "", - "host": "host", - "host.google.com": "host", - } { - if got := shortHostname(hostname); expect != got { - t.Errorf("shortHostname(%q): expected %q, got %q", hostname, expect, got) - } - } -} - -// flushBuffer wraps a bytes.Buffer to satisfy flushSyncWriter. -type flushBuffer struct { - bytes.Buffer -} - -func (f *flushBuffer) Flush() error { - return nil -} - -func (f *flushBuffer) Sync() error { - return nil -} - -// swap sets the log writers and returns the old array. -func (l *loggingT) swap(writers [numSeverity]flushSyncWriter) (old [numSeverity]flushSyncWriter) { - l.mu.Lock() - defer l.mu.Unlock() - old = l.file - for i, w := range writers { - logging.file[i] = w - } - return -} - -// newBuffers sets the log writers to all new byte buffers and returns the old array. -func (l *loggingT) newBuffers() [numSeverity]flushSyncWriter { - return l.swap([numSeverity]flushSyncWriter{new(flushBuffer), new(flushBuffer), new(flushBuffer), new(flushBuffer)}) -} - -// contents returns the specified log value as a string. -func contents(s severity) string { - return logging.file[s].(*flushBuffer).String() -} - -// contains reports whether the string is contained in the log. -func contains(s severity, str string, t *testing.T) bool { - return strings.Contains(contents(s), str) -} - -// setFlags configures the logging flags how the test expects them. -func setFlags() { - logging.toStderr = false -} - -// Test that Info works as advertised. -func TestInfo(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - Info("test") - if !contains(infoLog, "I", t) { - t.Errorf("Info has wrong character: %q", contents(infoLog)) - } - if !contains(infoLog, "test", t) { - t.Error("Info failed") - } -} - -func TestInfoDepth(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - - f := func() { InfoDepth(1, "depth-test1") } - - // The next three lines must stay together - _, _, wantLine, _ := runtime.Caller(0) - InfoDepth(0, "depth-test0") - f() - - msgs := strings.Split(strings.TrimSuffix(contents(infoLog), "\n"), "\n") - if len(msgs) != 2 { - t.Fatalf("Got %d lines, expected 2", len(msgs)) - } - - for i, m := range msgs { - if !strings.HasPrefix(m, "I") { - t.Errorf("InfoDepth[%d] has wrong character: %q", i, m) - } - w := fmt.Sprintf("depth-test%d", i) - if !strings.Contains(m, w) { - t.Errorf("InfoDepth[%d] missing %q: %q", i, w, m) - } - - // pull out the line number (between : and ]) - msg := m[strings.LastIndex(m, ":")+1:] - x := strings.Index(msg, "]") - if x < 0 { - t.Errorf("InfoDepth[%d]: missing ']': %q", i, m) - continue - } - line, err := strconv.Atoi(msg[:x]) - if err != nil { - t.Errorf("InfoDepth[%d]: bad line number: %q", i, m) - continue - } - wantLine++ - if wantLine != line { - t.Errorf("InfoDepth[%d]: got line %d, want %d", i, line, wantLine) - } - } -} - -func init() { - CopyStandardLogTo("INFO") -} - -// Test that CopyStandardLogTo panics on bad input. -func TestCopyStandardLogToPanic(t *testing.T) { - defer func() { - if s, ok := recover().(string); !ok || !strings.Contains(s, "LOG") { - t.Errorf(`CopyStandardLogTo("LOG") should have panicked: %v`, s) - } - }() - CopyStandardLogTo("LOG") -} - -// Test that using the standard log package logs to INFO. -func TestStandardLog(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - stdLog.Print("test") - if !contains(infoLog, "I", t) { - t.Errorf("Info has wrong character: %q", contents(infoLog)) - } - if !contains(infoLog, "test", t) { - t.Error("Info failed") - } -} - -// Test that the header has the correct format. -func TestHeader(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - defer func(previous func() time.Time) { timeNow = previous }(timeNow) - timeNow = func() time.Time { - return time.Date(2006, 1, 2, 15, 4, 5, .067890e9, time.Local) - } - pid = 1234 - Info("test") - var line int - format := "I0102 15:04:05.067890 1234 glog_test.go:%d] test\n" - n, err := fmt.Sscanf(contents(infoLog), format, &line) - if n != 1 || err != nil { - t.Errorf("log format error: %d elements, error %s:\n%s", n, err, contents(infoLog)) - } - // Scanf treats multiple spaces as equivalent to a single space, - // so check for correct space-padding also. - want := fmt.Sprintf(format, line) - if contents(infoLog) != want { - t.Errorf("log format error: got:\n\t%q\nwant:\t%q", contents(infoLog), want) - } -} - -// Test that an Error log goes to Warning and Info. -// Even in the Info log, the source character will be E, so the data should -// all be identical. -func TestError(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - Error("test") - if !contains(errorLog, "E", t) { - t.Errorf("Error has wrong character: %q", contents(errorLog)) - } - if !contains(errorLog, "test", t) { - t.Error("Error failed") - } - str := contents(errorLog) - if !contains(warningLog, str, t) { - t.Error("Warning failed") - } - if !contains(infoLog, str, t) { - t.Error("Info failed") - } -} - -// Test that a Warning log goes to Info. -// Even in the Info log, the source character will be W, so the data should -// all be identical. -func TestWarning(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - Warning("test") - if !contains(warningLog, "W", t) { - t.Errorf("Warning has wrong character: %q", contents(warningLog)) - } - if !contains(warningLog, "test", t) { - t.Error("Warning failed") - } - str := contents(warningLog) - if !contains(infoLog, str, t) { - t.Error("Info failed") - } -} - -// Test that a V log goes to Info. -func TestV(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - logging.verbosity.Set("2") - defer logging.verbosity.Set("0") - V(2).Info("test") - if !contains(infoLog, "I", t) { - t.Errorf("Info has wrong character: %q", contents(infoLog)) - } - if !contains(infoLog, "test", t) { - t.Error("Info failed") - } -} - -// Test that a vmodule enables a log in this file. -func TestVmoduleOn(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - logging.vmodule.Set("glog_test=2") - defer logging.vmodule.Set("") - if !V(1) { - t.Error("V not enabled for 1") - } - if !V(2) { - t.Error("V not enabled for 2") - } - if V(3) { - t.Error("V enabled for 3") - } - V(2).Info("test") - if !contains(infoLog, "I", t) { - t.Errorf("Info has wrong character: %q", contents(infoLog)) - } - if !contains(infoLog, "test", t) { - t.Error("Info failed") - } -} - -// Test that a vmodule of another file does not enable a log in this file. -func TestVmoduleOff(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - logging.vmodule.Set("notthisfile=2") - defer logging.vmodule.Set("") - for i := 1; i <= 3; i++ { - if V(Level(i)) { - t.Errorf("V enabled for %d", i) - } - } - V(2).Info("test") - if contents(infoLog) != "" { - t.Error("V logged incorrectly") - } -} - -// vGlobs are patterns that match/don't match this file at V=2. -var vGlobs = map[string]bool{ - // Easy to test the numeric match here. - "glog_test=1": false, // If -vmodule sets V to 1, V(2) will fail. - "glog_test=2": true, - "glog_test=3": true, // If -vmodule sets V to 1, V(3) will succeed. - // These all use 2 and check the patterns. All are true. - "*=2": true, - "?l*=2": true, - "????_*=2": true, - "??[mno]?_*t=2": true, - // These all use 2 and check the patterns. All are false. - "*x=2": false, - "m*=2": false, - "??_*=2": false, - "?[abc]?_*t=2": false, -} - -// Test that vmodule globbing works as advertised. -func testVmoduleGlob(pat string, match bool, t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - defer logging.vmodule.Set("") - logging.vmodule.Set(pat) - if V(2) != Verbose(match) { - t.Errorf("incorrect match for %q: got %t expected %t", pat, V(2), match) - } -} - -// Test that a vmodule globbing works as advertised. -func TestVmoduleGlob(t *testing.T) { - for glob, match := range vGlobs { - testVmoduleGlob(glob, match, t) - } -} - -func TestRollover(t *testing.T) { - setFlags() - var err error - defer func(previous func(error)) { logExitFunc = previous }(logExitFunc) - logExitFunc = func(e error) { - err = e - } - defer func(previous uint64) { MaxSize = previous }(MaxSize) - MaxSize = 512 - - Info("x") // Be sure we have a file. - info, ok := logging.file[infoLog].(*syncBuffer) - if !ok { - t.Fatal("info wasn't created") - } - if err != nil { - t.Fatalf("info has initial error: %v", err) - } - fname0 := info.file.Name() - Info(strings.Repeat("x", int(MaxSize))) // force a rollover - if err != nil { - t.Fatalf("info has error after big write: %v", err) - } - - // Make sure the next log file gets a file name with a different - // time stamp. - // - // TODO: determine whether we need to support subsecond log - // rotation. C++ does not appear to handle this case (nor does it - // handle Daylight Savings Time properly). - time.Sleep(1 * time.Second) - - Info("x") // create a new file - if err != nil { - t.Fatalf("error after rotation: %v", err) - } - fname1 := info.file.Name() - if fname0 == fname1 { - t.Errorf("info.f.Name did not change: %v", fname0) - } - if info.nbytes >= MaxSize { - t.Errorf("file size was not reset: %d", info.nbytes) - } -} - -func TestLogBacktraceAt(t *testing.T) { - setFlags() - defer logging.swap(logging.newBuffers()) - // The peculiar style of this code simplifies line counting and maintenance of the - // tracing block below. - var infoLine string - setTraceLocation := func(file string, line int, ok bool, delta int) { - if !ok { - t.Fatal("could not get file:line") - } - _, file = filepath.Split(file) - infoLine = fmt.Sprintf("%s:%d", file, line+delta) - err := logging.traceLocation.Set(infoLine) - if err != nil { - t.Fatal("error setting log_backtrace_at: ", err) - } - } - { - // Start of tracing block. These lines know about each other's relative position. - _, file, line, ok := runtime.Caller(0) - setTraceLocation(file, line, ok, +2) // Two lines between Caller and Info calls. - Info("we want a stack trace here") - } - numAppearances := strings.Count(contents(infoLog), infoLine) - if numAppearances < 2 { - // Need 2 appearances, one in the log header and one in the trace: - // log_test.go:281: I0511 16:36:06.952398 02238 log_test.go:280] we want a stack trace here - // ... - // github.com/glog/glog_test.go:280 (0x41ba91) - // ... - // We could be more precise but that would require knowing the details - // of the traceback format, which may not be dependable. - t.Fatal("got no trace back; log is ", contents(infoLog)) - } -} - -func BenchmarkHeader(b *testing.B) { - for i := 0; i < b.N; i++ { - buf, _, _ := logging.header(infoLog, 0) - logging.putBuffer(buf) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru_test.go b/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru_test.go deleted file mode 100644 index 98a2656e8..000000000 --- a/Godeps/_workspace/src/github.com/golang/groupcache/lru/lru_test.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2013 Google Inc. - -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 lru - -import ( - "testing" -) - -type simpleStruct struct { - int - string -} - -type complexStruct struct { - int - simpleStruct -} - -var getTests = []struct { - name string - keyToAdd interface{} - keyToGet interface{} - expectedOk bool -}{ - {"string_hit", "myKey", "myKey", true}, - {"string_miss", "myKey", "nonsense", false}, - {"simple_struct_hit", simpleStruct{1, "two"}, simpleStruct{1, "two"}, true}, - {"simeple_struct_miss", simpleStruct{1, "two"}, simpleStruct{0, "noway"}, false}, - {"complex_struct_hit", complexStruct{1, simpleStruct{2, "three"}}, - complexStruct{1, simpleStruct{2, "three"}}, true}, -} - -func TestGet(t *testing.T) { - for _, tt := range getTests { - lru := New(0) - lru.Add(tt.keyToAdd, 1234) - val, ok := lru.Get(tt.keyToGet) - if ok != tt.expectedOk { - t.Fatalf("%s: cache hit = %v; want %v", tt.name, ok, !ok) - } else if ok && val != 1234 { - t.Fatalf("%s expected get to return 1234 but got %v", tt.name, val) - } - } -} - -func TestRemove(t *testing.T) { - lru := New(0) - lru.Add("myKey", 1234) - if val, ok := lru.Get("myKey"); !ok { - t.Fatal("TestRemove returned no match") - } else if val != 1234 { - t.Fatalf("TestRemove failed. Expected %d, got %v", 1234, val) - } - - lru.Remove("myKey") - if _, ok := lru.Get("myKey"); ok { - t.Fatal("TestRemove returned a removed entry") - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go deleted file mode 100644 index f68f913df..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/all_test.go +++ /dev/null @@ -1,2169 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "math/rand" - "reflect" - "runtime/debug" - "strings" - "testing" - "time" - - . "github.com/golang/protobuf/proto" - . "github.com/golang/protobuf/proto/testdata" -) - -var globalO *Buffer - -func old() *Buffer { - if globalO == nil { - globalO = NewBuffer(nil) - } - globalO.Reset() - return globalO -} - -func equalbytes(b1, b2 []byte, t *testing.T) { - if len(b1) != len(b2) { - t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2)) - return - } - for i := 0; i < len(b1); i++ { - if b1[i] != b2[i] { - t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2) - } - } -} - -func initGoTestField() *GoTestField { - f := new(GoTestField) - f.Label = String("label") - f.Type = String("type") - return f -} - -// These are all structurally equivalent but the tag numbers differ. -// (It's remarkable that required, optional, and repeated all have -// 8 letters.) -func initGoTest_RequiredGroup() *GoTest_RequiredGroup { - return &GoTest_RequiredGroup{ - RequiredField: String("required"), - } -} - -func initGoTest_OptionalGroup() *GoTest_OptionalGroup { - return &GoTest_OptionalGroup{ - RequiredField: String("optional"), - } -} - -func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { - return &GoTest_RepeatedGroup{ - RequiredField: String("repeated"), - } -} - -func initGoTest(setdefaults bool) *GoTest { - pb := new(GoTest) - if setdefaults { - pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) - pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) - pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) - pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) - pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) - pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) - pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) - pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) - pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) - pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) - pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted - pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) - pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) - } - - pb.Kind = GoTest_TIME.Enum() - pb.RequiredField = initGoTestField() - pb.F_BoolRequired = Bool(true) - pb.F_Int32Required = Int32(3) - pb.F_Int64Required = Int64(6) - pb.F_Fixed32Required = Uint32(32) - pb.F_Fixed64Required = Uint64(64) - pb.F_Uint32Required = Uint32(3232) - pb.F_Uint64Required = Uint64(6464) - pb.F_FloatRequired = Float32(3232) - pb.F_DoubleRequired = Float64(6464) - pb.F_StringRequired = String("string") - pb.F_BytesRequired = []byte("bytes") - pb.F_Sint32Required = Int32(-32) - pb.F_Sint64Required = Int64(-64) - pb.Requiredgroup = initGoTest_RequiredGroup() - - return pb -} - -func fail(msg string, b *bytes.Buffer, s string, t *testing.T) { - data := b.Bytes() - ld := len(data) - ls := len(s) / 2 - - fmt.Printf("fail %s ld=%d ls=%d\n", msg, ld, ls) - - // find the interesting spot - n - n := ls - if ld < ls { - n = ld - } - j := 0 - for i := 0; i < n; i++ { - bs := hex(s[j])*16 + hex(s[j+1]) - j += 2 - if data[i] == bs { - continue - } - n = i - break - } - l := n - 10 - if l < 0 { - l = 0 - } - h := n + 10 - - // find the interesting spot - n - fmt.Printf("is[%d]:", l) - for i := l; i < h; i++ { - if i >= ld { - fmt.Printf(" --") - continue - } - fmt.Printf(" %.2x", data[i]) - } - fmt.Printf("\n") - - fmt.Printf("sb[%d]:", l) - for i := l; i < h; i++ { - if i >= ls { - fmt.Printf(" --") - continue - } - bs := hex(s[j])*16 + hex(s[j+1]) - j += 2 - fmt.Printf(" %.2x", bs) - } - fmt.Printf("\n") - - t.Fail() - - // t.Errorf("%s: \ngood: %s\nbad: %x", msg, s, b.Bytes()) - // Print the output in a partially-decoded format; can - // be helpful when updating the test. It produces the output - // that is pasted, with minor edits, into the argument to verify(). - // data := b.Bytes() - // nesting := 0 - // for b.Len() > 0 { - // start := len(data) - b.Len() - // var u uint64 - // u, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on varint:", err) - // return - // } - // wire := u & 0x7 - // tag := u >> 3 - // switch wire { - // case WireVarint: - // v, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on varint:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireFixed32: - // v, err := DecodeFixed32(b) - // if err != nil { - // fmt.Printf("decode error on fixed32:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireFixed64: - // v, err := DecodeFixed64(b) - // if err != nil { - // fmt.Printf("decode error on fixed64:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", - // data[start:len(data)-b.Len()], tag, wire, v) - // case WireBytes: - // nb, err := DecodeVarint(b) - // if err != nil { - // fmt.Printf("decode error on bytes:", err) - // return - // } - // after_tag := len(data) - b.Len() - // str := make([]byte, nb) - // _, err = b.Read(str) - // if err != nil { - // fmt.Printf("decode error on bytes:", err) - // return - // } - // fmt.Printf("\t\t\"%x\" \"%x\" // field %d, encoding %d (FIELD)\n", - // data[start:after_tag], str, tag, wire) - // case WireStartGroup: - // nesting++ - // fmt.Printf("\t\t\"%x\"\t\t// start group field %d level %d\n", - // data[start:len(data)-b.Len()], tag, nesting) - // case WireEndGroup: - // fmt.Printf("\t\t\"%x\"\t\t// end group field %d level %d\n", - // data[start:len(data)-b.Len()], tag, nesting) - // nesting-- - // default: - // fmt.Printf("unrecognized wire type %d\n", wire) - // return - // } - // } -} - -func hex(c uint8) uint8 { - if '0' <= c && c <= '9' { - return c - '0' - } - if 'a' <= c && c <= 'f' { - return 10 + c - 'a' - } - if 'A' <= c && c <= 'F' { - return 10 + c - 'A' - } - return 0 -} - -func equal(b []byte, s string, t *testing.T) bool { - if 2*len(b) != len(s) { - // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t) - fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s)) - return false - } - for i, j := 0, 0; i < len(b); i, j = i+1, j+2 { - x := hex(s[j])*16 + hex(s[j+1]) - if b[i] != x { - // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t) - fmt.Printf("bad byte[%d]:%x %x", i, b[i], x) - return false - } - } - return true -} - -func overify(t *testing.T, pb *GoTest, expected string) { - o := old() - err := o.Marshal(pb) - if err != nil { - fmt.Printf("overify marshal-1 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 1", o.Bytes()) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = o.Unmarshal(pbd) - if err != nil { - t.Fatalf("overify unmarshal err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - o.Reset() - err = o.Marshal(pbd) - if err != nil { - t.Errorf("overify marshal-2 err = %v", err) - o.DebugPrint("", o.Bytes()) - t.Fatalf("string = %s", expected) - } - if !equal(o.Bytes(), expected, t) { - o.DebugPrint("overify neq 2", o.Bytes()) - t.Fatalf("string = %s", expected) - } -} - -// Simple tests for numeric encode/decode primitives (varint, etc.) -func TestNumericPrimitives(t *testing.T) { - for i := uint64(0); i < 1e6; i += 111 { - o := old() - if o.EncodeVarint(i) != nil { - t.Error("EncodeVarint") - break - } - x, e := o.DecodeVarint() - if e != nil { - t.Fatal("DecodeVarint") - } - if x != i { - t.Fatal("varint decode fail:", i, x) - } - - o = old() - if o.EncodeFixed32(i) != nil { - t.Fatal("encFixed32") - } - x, e = o.DecodeFixed32() - if e != nil { - t.Fatal("decFixed32") - } - if x != i { - t.Fatal("fixed32 decode fail:", i, x) - } - - o = old() - if o.EncodeFixed64(i*1234567) != nil { - t.Error("encFixed64") - break - } - x, e = o.DecodeFixed64() - if e != nil { - t.Error("decFixed64") - break - } - if x != i*1234567 { - t.Error("fixed64 decode fail:", i*1234567, x) - break - } - - o = old() - i32 := int32(i - 12345) - if o.EncodeZigzag32(uint64(i32)) != nil { - t.Fatal("EncodeZigzag32") - } - x, e = o.DecodeZigzag32() - if e != nil { - t.Fatal("DecodeZigzag32") - } - if x != uint64(uint32(i32)) { - t.Fatal("zigzag32 decode fail:", i32, x) - } - - o = old() - i64 := int64(i - 12345) - if o.EncodeZigzag64(uint64(i64)) != nil { - t.Fatal("EncodeZigzag64") - } - x, e = o.DecodeZigzag64() - if e != nil { - t.Fatal("DecodeZigzag64") - } - if x != uint64(i64) { - t.Fatal("zigzag64 decode fail:", i64, x) - } - } -} - -// fakeMarshaler is a simple struct implementing Marshaler and Message interfaces. -type fakeMarshaler struct { - b []byte - err error -} - -func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err } -func (f *fakeMarshaler) String() string { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) } -func (f *fakeMarshaler) ProtoMessage() {} -func (f *fakeMarshaler) Reset() {} - -type msgWithFakeMarshaler struct { - M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"` -} - -func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) } -func (m *msgWithFakeMarshaler) ProtoMessage() {} -func (m *msgWithFakeMarshaler) Reset() {} - -// Simple tests for proto messages that implement the Marshaler interface. -func TestMarshalerEncoding(t *testing.T) { - tests := []struct { - name string - m Message - want []byte - wantErr error - }{ - { - name: "Marshaler that fails", - m: &fakeMarshaler{ - err: errors.New("some marshal err"), - b: []byte{5, 6, 7}, - }, - // Since there's an error, nothing should be written to buffer. - want: nil, - wantErr: errors.New("some marshal err"), - }, - { - name: "Marshaler that fails with RequiredNotSetError", - m: &msgWithFakeMarshaler{ - M: &fakeMarshaler{ - err: &RequiredNotSetError{}, - b: []byte{5, 6, 7}, - }, - }, - // Since there's an error that can be continued after, - // the buffer should be written. - want: []byte{ - 10, 3, // for &msgWithFakeMarshaler - 5, 6, 7, // for &fakeMarshaler - }, - wantErr: &RequiredNotSetError{}, - }, - { - name: "Marshaler that succeeds", - m: &fakeMarshaler{ - b: []byte{0, 1, 2, 3, 4, 127, 255}, - }, - want: []byte{0, 1, 2, 3, 4, 127, 255}, - wantErr: nil, - }, - } - for _, test := range tests { - b := NewBuffer(nil) - err := b.Marshal(test.m) - if _, ok := err.(*RequiredNotSetError); ok { - // We're not in package proto, so we can only assert the type in this case. - err = &RequiredNotSetError{} - } - if !reflect.DeepEqual(test.wantErr, err) { - t.Errorf("%s: got err %v wanted %v", test.name, err, test.wantErr) - } - if !reflect.DeepEqual(test.want, b.Bytes()) { - t.Errorf("%s: got bytes %v wanted %v", test.name, b.Bytes(), test.want) - } - } -} - -// Simple tests for bytes -func TestBytesPrimitives(t *testing.T) { - o := old() - bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'} - if o.EncodeRawBytes(bytes) != nil { - t.Error("EncodeRawBytes") - } - decb, e := o.DecodeRawBytes(false) - if e != nil { - t.Error("DecodeRawBytes") - } - equalbytes(bytes, decb, t) -} - -// Simple tests for strings -func TestStringPrimitives(t *testing.T) { - o := old() - s := "now is the time" - if o.EncodeStringBytes(s) != nil { - t.Error("enc_string") - } - decs, e := o.DecodeStringBytes() - if e != nil { - t.Error("dec_string") - } - if s != decs { - t.Error("string encode/decode fail:", s, decs) - } -} - -// Do we catch the "required bit not set" case? -func TestRequiredBit(t *testing.T) { - o := old() - pb := new(GoTest) - err := o.Marshal(pb) - if err == nil { - t.Error("did not catch missing required fields") - } else if strings.Index(err.Error(), "Kind") < 0 { - t.Error("wrong error type:", err) - } -} - -// Check that all fields are nil. -// Clearly silly, and a residue from a more interesting test with an earlier, -// different initialization property, but it once caught a compiler bug so -// it lives. -func checkInitialized(pb *GoTest, t *testing.T) { - if pb.F_BoolDefaulted != nil { - t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted) - } - if pb.F_Int32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted) - } - if pb.F_Int64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted) - } - if pb.F_Fixed32Defaulted != nil { - t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted) - } - if pb.F_Fixed64Defaulted != nil { - t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted) - } - if pb.F_Uint32Defaulted != nil { - t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted) - } - if pb.F_Uint64Defaulted != nil { - t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted) - } - if pb.F_FloatDefaulted != nil { - t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted) - } - if pb.F_DoubleDefaulted != nil { - t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted) - } - if pb.F_StringDefaulted != nil { - t.Error("New or Reset did not set string:", *pb.F_StringDefaulted) - } - if pb.F_BytesDefaulted != nil { - t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted)) - } - if pb.F_Sint32Defaulted != nil { - t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted) - } - if pb.F_Sint64Defaulted != nil { - t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted) - } -} - -// Does Reset() reset? -func TestReset(t *testing.T) { - pb := initGoTest(true) - // muck with some values - pb.F_BoolDefaulted = Bool(false) - pb.F_Int32Defaulted = Int32(237) - pb.F_Int64Defaulted = Int64(12346) - pb.F_Fixed32Defaulted = Uint32(32000) - pb.F_Fixed64Defaulted = Uint64(666) - pb.F_Uint32Defaulted = Uint32(323232) - pb.F_Uint64Defaulted = nil - pb.F_FloatDefaulted = nil - pb.F_DoubleDefaulted = Float64(0) - pb.F_StringDefaulted = String("gotcha") - pb.F_BytesDefaulted = []byte("asdfasdf") - pb.F_Sint32Defaulted = Int32(123) - pb.F_Sint64Defaulted = Int64(789) - pb.Reset() - checkInitialized(pb, t) -} - -// All required fields set, no defaults provided. -func TestEncodeDecode1(t *testing.T) { - pb := initGoTest(false) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 0x20 - "714000000000000000"+ // field 14, encoding 1, value 0x40 - "78a019"+ // field 15, encoding 0, value 0xca0 = 3232 - "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string" - "b304"+ // field 70, encoding 3, start group - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // field 70, encoding 4, end group - "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f") // field 103, encoding 0, 0x7f zigzag64 -} - -// All required fields set, defaults provided. -func TestEncodeDecode2(t *testing.T) { - pb := initGoTest(true) - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All default fields set to their default value by hand -func TestEncodeDecode3(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolDefaulted = Bool(true) - pb.F_Int32Defaulted = Int32(32) - pb.F_Int64Defaulted = Int64(64) - pb.F_Fixed32Defaulted = Uint32(320) - pb.F_Fixed64Defaulted = Uint64(640) - pb.F_Uint32Defaulted = Uint32(3200) - pb.F_Uint64Defaulted = Uint64(6400) - pb.F_FloatDefaulted = Float32(314159) - pb.F_DoubleDefaulted = Float64(271828) - pb.F_StringDefaulted = String("hello, \"world!\"\n") - pb.F_BytesDefaulted = []byte("Bignose") - pb.F_Sint32Defaulted = Int32(-32) - pb.F_Sint64Defaulted = Int64(-64) - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, defaults provided, all non-defaulted optional fields have values. -func TestEncodeDecode4(t *testing.T) { - pb := initGoTest(true) - pb.Table = String("hello") - pb.Param = Int32(7) - pb.OptionalField = initGoTestField() - pb.F_BoolOptional = Bool(true) - pb.F_Int32Optional = Int32(32) - pb.F_Int64Optional = Int64(64) - pb.F_Fixed32Optional = Uint32(3232) - pb.F_Fixed64Optional = Uint64(6464) - pb.F_Uint32Optional = Uint32(323232) - pb.F_Uint64Optional = Uint64(646464) - pb.F_FloatOptional = Float32(32.) - pb.F_DoubleOptional = Float64(64.) - pb.F_StringOptional = String("hello") - pb.F_BytesOptional = []byte("Bignose") - pb.F_Sint32Optional = Int32(-32) - pb.F_Sint64Optional = Int64(-64) - pb.Optionalgroup = initGoTest_OptionalGroup() - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello" - "1807"+ // field 3, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "f00101"+ // field 30, encoding 0, value 1 - "f80120"+ // field 31, encoding 0, value 32 - "800240"+ // field 32, encoding 0, value 64 - "8d02a00c0000"+ // field 33, encoding 5, value 3232 - "91024019000000000000"+ // field 34, encoding 1, value 6464 - "9802a0dd13"+ // field 35, encoding 0, value 323232 - "a002c0ba27"+ // field 36, encoding 0, value 646464 - "ad0200000042"+ // field 37, encoding 5, value 32.0 - "b1020000000000005040"+ // field 38, encoding 1, value 64.0 - "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "d305"+ // start group field 90 level 1 - "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional" - "d405"+ // end group field 90 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose" - "f0123f"+ // field 302, encoding 0, value 63 - "f8127f"+ // field 303, encoding 0, value 127 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestEncodeDecode5(t *testing.T) { - pb := initGoTest(true) - pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()} - pb.F_BoolRepeated = []bool{false, true} - pb.F_Int32Repeated = []int32{32, 33} - pb.F_Int64Repeated = []int64{64, 65} - pb.F_Fixed32Repeated = []uint32{3232, 3333} - pb.F_Fixed64Repeated = []uint64{6464, 6565} - pb.F_Uint32Repeated = []uint32{323232, 333333} - pb.F_Uint64Repeated = []uint64{646464, 656565} - pb.F_FloatRepeated = []float32{32., 33.} - pb.F_DoubleRepeated = []float64{64., 65.} - pb.F_StringRepeated = []string{"hello", "sailor"} - pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")} - pb.F_Sint32Repeated = []int32{32, -32} - pb.F_Sint64Repeated = []int64{64, -64} - pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "a00100"+ // field 20, encoding 0, value 0 - "a00101"+ // field 20, encoding 0, value 1 - "a80120"+ // field 21, encoding 0, value 32 - "a80121"+ // field 21, encoding 0, value 33 - "b00140"+ // field 22, encoding 0, value 64 - "b00141"+ // field 22, encoding 0, value 65 - "bd01a00c0000"+ // field 23, encoding 5, value 3232 - "bd01050d0000"+ // field 23, encoding 5, value 3333 - "c1014019000000000000"+ // field 24, encoding 1, value 6464 - "c101a519000000000000"+ // field 24, encoding 1, value 6565 - "c801a0dd13"+ // field 25, encoding 0, value 323232 - "c80195ac14"+ // field 25, encoding 0, value 333333 - "d001c0ba27"+ // field 26, encoding 0, value 646464 - "d001b58928"+ // field 26, encoding 0, value 656565 - "dd0100000042"+ // field 27, encoding 5, value 32.0 - "dd0100000442"+ // field 27, encoding 5, value 33.0 - "e1010000000000005040"+ // field 28, encoding 1, value 64.0 - "e1010000000000405040"+ // field 28, encoding 1, value 65.0 - "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello" - "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor" - "c00201"+ // field 40, encoding 0, value 1 - "c80220"+ // field 41, encoding 0, value 32 - "d00240"+ // field 42, encoding 0, value 64 - "dd0240010000"+ // field 43, encoding 5, value 320 - "e1028002000000000000"+ // field 44, encoding 1, value 640 - "e8028019"+ // field 45, encoding 0, value 3200 - "f0028032"+ // field 46, encoding 0, value 6400 - "fd02e0659948"+ // field 47, encoding 5, value 314159.0 - "81030000000050971041"+ // field 48, encoding 1, value 271828.0 - "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "8305"+ // start group field 80 level 1 - "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" - "8405"+ // end group field 80 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "ca0c03"+"626967"+ // field 201, encoding 2, string "big" - "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose" - "d00c40"+ // field 202, encoding 0, value 32 - "d00c3f"+ // field 202, encoding 0, value -32 - "d80c8001"+ // field 203, encoding 0, value 64 - "d80c7f"+ // field 203, encoding 0, value -64 - "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" - "90193f"+ // field 402, encoding 0, value 63 - "98197f") // field 403, encoding 0, value 127 - -} - -// All required fields set, all packed repeated fields given two values. -func TestEncodeDecode6(t *testing.T) { - pb := initGoTest(false) - pb.F_BoolRepeatedPacked = []bool{false, true} - pb.F_Int32RepeatedPacked = []int32{32, 33} - pb.F_Int64RepeatedPacked = []int64{64, 65} - pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333} - pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565} - pb.F_Uint32RepeatedPacked = []uint32{323232, 333333} - pb.F_Uint64RepeatedPacked = []uint64{646464, 656565} - pb.F_FloatRepeatedPacked = []float32{32., 33.} - pb.F_DoubleRepeatedPacked = []float64{64., 65.} - pb.F_Sint32RepeatedPacked = []int32{32, -32} - pb.F_Sint64RepeatedPacked = []int64{64, -64} - - overify(t, pb, - "0807"+ // field 1, encoding 0, value 7 - "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) - "5001"+ // field 10, encoding 0, value 1 - "5803"+ // field 11, encoding 0, value 3 - "6006"+ // field 12, encoding 0, value 6 - "6d20000000"+ // field 13, encoding 5, value 32 - "714000000000000000"+ // field 14, encoding 1, value 64 - "78a019"+ // field 15, encoding 0, value 3232 - "8001c032"+ // field 16, encoding 0, value 6464 - "8d0100004a45"+ // field 17, encoding 5, value 3232.0 - "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 - "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" - "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1 - "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33 - "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65 - "aa0308"+ // field 53, encoding 2, 8 bytes - "a00c0000050d0000"+ // value 3232, value 3333 - "b20310"+ // field 54, encoding 2, 16 bytes - "4019000000000000a519000000000000"+ // value 6464, value 6565 - "ba0306"+ // field 55, encoding 2, 6 bytes - "a0dd1395ac14"+ // value 323232, value 333333 - "c20306"+ // field 56, encoding 2, 6 bytes - "c0ba27b58928"+ // value 646464, value 656565 - "ca0308"+ // field 57, encoding 2, 8 bytes - "0000004200000442"+ // value 32.0, value 33.0 - "d20310"+ // field 58, encoding 2, 16 bytes - "00000000000050400000000000405040"+ // value 64.0, value 65.0 - "b304"+ // start group field 70 level 1 - "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" - "b404"+ // end group field 70 level 1 - "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" - "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 - "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 - "b21f02"+ // field 502, encoding 2, 2 bytes - "403f"+ // value 32, value -32 - "ba1f03"+ // field 503, encoding 2, 3 bytes - "80017f") // value 64, value -64 -} - -// Test that we can encode empty bytes fields. -func TestEncodeDecodeBytes1(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRequired = []byte{} - pb.F_BytesRepeated = [][]byte{{}} - pb.F_BytesOptional = []byte{} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 { - t.Error("required empty bytes field is incorrect") - } - if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil { - t.Error("repeated empty bytes field is incorrect") - } - if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 { - t.Error("optional empty bytes field is incorrect") - } -} - -// Test that we encode nil-valued fields of a repeated bytes field correctly. -// Since entries in a repeated field cannot be nil, nil must mean empty value. -func TestEncodeDecodeBytes2(t *testing.T) { - pb := initGoTest(false) - - // Create our bytes - pb.F_BytesRepeated = [][]byte{nil} - - d, err := Marshal(pb) - if err != nil { - t.Error(err) - } - - pbd := new(GoTest) - if err := Unmarshal(d, pbd); err != nil { - t.Error(err) - } - - if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil { - t.Error("Unexpected value for repeated bytes field") - } -} - -// All required fields set, defaults provided, all repeated fields given two values. -func TestSkippingUnrecognizedFields(t *testing.T) { - o := old() - pb := initGoTestField() - - // Marshal it normally. - o.Marshal(pb) - - // Now new a GoSkipTest record. - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - // Marshal it into same buffer. - o.Marshal(skip) - - pbd := new(GoTestField) - o.Unmarshal(pbd) - - // The __unrecognized field should be a marshaling of GoSkipTest - skipd := new(GoSkipTest) - - o.SetBuf(pbd.XXX_unrecognized) - o.Unmarshal(skipd) - - if *skipd.SkipInt32 != *skip.SkipInt32 { - t.Error("skip int32", skipd.SkipInt32) - } - if *skipd.SkipFixed32 != *skip.SkipFixed32 { - t.Error("skip fixed32", skipd.SkipFixed32) - } - if *skipd.SkipFixed64 != *skip.SkipFixed64 { - t.Error("skip fixed64", skipd.SkipFixed64) - } - if *skipd.SkipString != *skip.SkipString { - t.Error("skip string", *skipd.SkipString) - } - if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 { - t.Error("skip group int32", skipd.Skipgroup.GroupInt32) - } - if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString { - t.Error("skip group string", *skipd.Skipgroup.GroupString) - } -} - -// Check that unrecognized fields of a submessage are preserved. -func TestSubmessageUnrecognizedFields(t *testing.T) { - nm := &NewMessage{ - Nested: &NewMessage_Nested{ - Name: String("Nigel"), - FoodGroup: String("carbs"), - }, - } - b, err := Marshal(nm) - if err != nil { - t.Fatalf("Marshal of NewMessage: %v", err) - } - - // Unmarshal into an OldMessage. - om := new(OldMessage) - if err := Unmarshal(b, om); err != nil { - t.Fatalf("Unmarshal to OldMessage: %v", err) - } - exp := &OldMessage{ - Nested: &OldMessage_Nested{ - Name: String("Nigel"), - // normal protocol buffer users should not do this - XXX_unrecognized: []byte("\x12\x05carbs"), - }, - } - if !Equal(om, exp) { - t.Errorf("om = %v, want %v", om, exp) - } - - // Clone the OldMessage. - om = Clone(om).(*OldMessage) - if !Equal(om, exp) { - t.Errorf("Clone(om) = %v, want %v", om, exp) - } - - // Marshal the OldMessage, then unmarshal it into an empty NewMessage. - if b, err = Marshal(om); err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - t.Logf("Marshal(%v) -> %q", om, b) - nm2 := new(NewMessage) - if err := Unmarshal(b, nm2); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - if !Equal(nm, nm2) { - t.Errorf("NewMessage round-trip: %v => %v", nm, nm2) - } -} - -// Check that an int32 field can be upgraded to an int64 field. -func TestNegativeInt32(t *testing.T) { - om := &OldMessage{ - Num: Int32(-1), - } - b, err := Marshal(om) - if err != nil { - t.Fatalf("Marshal of OldMessage: %v", err) - } - - // Check the size. It should be 11 bytes; - // 1 for the field/wire type, and 10 for the negative number. - if len(b) != 11 { - t.Errorf("%v marshaled as %q, wanted 11 bytes", om, b) - } - - // Unmarshal into a NewMessage. - nm := new(NewMessage) - if err := Unmarshal(b, nm); err != nil { - t.Fatalf("Unmarshal to NewMessage: %v", err) - } - want := &NewMessage{ - Num: Int64(-1), - } - if !Equal(nm, want) { - t.Errorf("nm = %v, want %v", nm, want) - } -} - -// Check that we can grow an array (repeated field) to have many elements. -// This test doesn't depend only on our encoding; for variety, it makes sure -// we create, encode, and decode the correct contents explicitly. It's therefore -// a bit messier. -// This test also uses (and hence tests) the Marshal/Unmarshal functions -// instead of the methods. -func TestBigRepeated(t *testing.T) { - pb := initGoTest(true) - - // Create the arrays - const N = 50 // Internally the library starts much smaller. - pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N) - pb.F_Sint64Repeated = make([]int64, N) - pb.F_Sint32Repeated = make([]int32, N) - pb.F_BytesRepeated = make([][]byte, N) - pb.F_StringRepeated = make([]string, N) - pb.F_DoubleRepeated = make([]float64, N) - pb.F_FloatRepeated = make([]float32, N) - pb.F_Uint64Repeated = make([]uint64, N) - pb.F_Uint32Repeated = make([]uint32, N) - pb.F_Fixed64Repeated = make([]uint64, N) - pb.F_Fixed32Repeated = make([]uint32, N) - pb.F_Int64Repeated = make([]int64, N) - pb.F_Int32Repeated = make([]int32, N) - pb.F_BoolRepeated = make([]bool, N) - pb.RepeatedField = make([]*GoTestField, N) - - // Fill in the arrays with checkable values. - igtf := initGoTestField() - igtrg := initGoTest_RepeatedGroup() - for i := 0; i < N; i++ { - pb.Repeatedgroup[i] = igtrg - pb.F_Sint64Repeated[i] = int64(i) - pb.F_Sint32Repeated[i] = int32(i) - s := fmt.Sprint(i) - pb.F_BytesRepeated[i] = []byte(s) - pb.F_StringRepeated[i] = s - pb.F_DoubleRepeated[i] = float64(i) - pb.F_FloatRepeated[i] = float32(i) - pb.F_Uint64Repeated[i] = uint64(i) - pb.F_Uint32Repeated[i] = uint32(i) - pb.F_Fixed64Repeated[i] = uint64(i) - pb.F_Fixed32Repeated[i] = uint32(i) - pb.F_Int64Repeated[i] = int64(i) - pb.F_Int32Repeated[i] = int32(i) - pb.F_BoolRepeated[i] = i%2 == 0 - pb.RepeatedField[i] = igtf - } - - // Marshal. - buf, _ := Marshal(pb) - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - Unmarshal(buf, pbd) - - // Check the checkable values - for i := uint64(0); i < N; i++ { - if pbd.Repeatedgroup[i] == nil { // TODO: more checking? - t.Error("pbd.Repeatedgroup bad") - } - var x uint64 - x = uint64(pbd.F_Sint64Repeated[i]) - if x != i { - t.Error("pbd.F_Sint64Repeated bad", x, i) - } - x = uint64(pbd.F_Sint32Repeated[i]) - if x != i { - t.Error("pbd.F_Sint32Repeated bad", x, i) - } - s := fmt.Sprint(i) - equalbytes(pbd.F_BytesRepeated[i], []byte(s), t) - if pbd.F_StringRepeated[i] != s { - t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i) - } - x = uint64(pbd.F_DoubleRepeated[i]) - if x != i { - t.Error("pbd.F_DoubleRepeated bad", x, i) - } - x = uint64(pbd.F_FloatRepeated[i]) - if x != i { - t.Error("pbd.F_FloatRepeated bad", x, i) - } - x = pbd.F_Uint64Repeated[i] - if x != i { - t.Error("pbd.F_Uint64Repeated bad", x, i) - } - x = uint64(pbd.F_Uint32Repeated[i]) - if x != i { - t.Error("pbd.F_Uint32Repeated bad", x, i) - } - x = pbd.F_Fixed64Repeated[i] - if x != i { - t.Error("pbd.F_Fixed64Repeated bad", x, i) - } - x = uint64(pbd.F_Fixed32Repeated[i]) - if x != i { - t.Error("pbd.F_Fixed32Repeated bad", x, i) - } - x = uint64(pbd.F_Int64Repeated[i]) - if x != i { - t.Error("pbd.F_Int64Repeated bad", x, i) - } - x = uint64(pbd.F_Int32Repeated[i]) - if x != i { - t.Error("pbd.F_Int32Repeated bad", x, i) - } - if pbd.F_BoolRepeated[i] != (i%2 == 0) { - t.Error("pbd.F_BoolRepeated bad", x, i) - } - if pbd.RepeatedField[i] == nil { // TODO: more checking? - t.Error("pbd.RepeatedField bad") - } - } -} - -// Verify we give a useful message when decoding to the wrong structure type. -func TestTypeMismatch(t *testing.T) { - pb1 := initGoTest(true) - - // Marshal - o := old() - o.Marshal(pb1) - - // Now Unmarshal it to the wrong type. - pb2 := initGoTestField() - err := o.Unmarshal(pb2) - if err == nil { - t.Error("expected error, got no error") - } else if !strings.Contains(err.Error(), "bad wiretype") { - t.Error("expected bad wiretype error, got", err) - } -} - -func encodeDecode(t *testing.T, in, out Message, msg string) { - buf, err := Marshal(in) - if err != nil { - t.Fatalf("failed marshaling %v: %v", msg, err) - } - if err := Unmarshal(buf, out); err != nil { - t.Fatalf("failed unmarshaling %v: %v", msg, err) - } -} - -func TestPackedNonPackedDecoderSwitching(t *testing.T) { - np, p := new(NonPackedTest), new(PackedTest) - - // non-packed -> packed - np.A = []int32{0, 1, 1, 2, 3, 5} - encodeDecode(t, np, p, "non-packed -> packed") - if !reflect.DeepEqual(np.A, p.B) { - t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B) - } - - // packed -> non-packed - np.Reset() - p.B = []int32{3, 1, 4, 1, 5, 9} - encodeDecode(t, p, np, "packed -> non-packed") - if !reflect.DeepEqual(p.B, np.A) { - t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A) - } -} - -func TestProto1RepeatedGroup(t *testing.T) { - pb := &MessageList{ - Message: []*MessageList_Message{ - { - Name: String("blah"), - Count: Int32(7), - }, - // NOTE: pb.Message[1] is a nil - nil, - }, - } - - o := old() - err := o.Marshal(pb) - if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") { - t.Fatalf("unexpected or no error when marshaling: %v", err) - } -} - -// Test that enums work. Checks for a bug introduced by making enums -// named types instead of int32: newInt32FromUint64 would crash with -// a type mismatch in reflect.PointTo. -func TestEnum(t *testing.T) { - pb := new(GoEnum) - pb.Foo = FOO_FOO1.Enum() - o := old() - if err := o.Marshal(pb); err != nil { - t.Fatal("error encoding enum:", err) - } - pb1 := new(GoEnum) - if err := o.Unmarshal(pb1); err != nil { - t.Fatal("error decoding enum:", err) - } - if *pb1.Foo != FOO_FOO1 { - t.Error("expected 7 but got ", *pb1.Foo) - } -} - -// Enum types have String methods. Check that enum fields can be printed. -// We don't care what the value actually is, just as long as it doesn't crash. -func TestPrintingNilEnumFields(t *testing.T) { - pb := new(GoEnum) - fmt.Sprintf("%+v", pb) -} - -// Verify that absent required fields cause Marshal/Unmarshal to return errors. -func TestRequiredFieldEnforcement(t *testing.T) { - pb := new(GoTestField) - _, err := Marshal(pb) - if err == nil { - t.Error("marshal: expected error, got nil") - } else if strings.Index(err.Error(), "Label") < 0 { - t.Errorf("marshal: bad error type: %v", err) - } - - // A slightly sneaky, yet valid, proto. It encodes the same required field twice, - // so simply counting the required fields is insufficient. - // field 1, encoding 2, value "hi" - buf := []byte("\x0A\x02hi\x0A\x02hi") - err = Unmarshal(buf, pb) - if err == nil { - t.Error("unmarshal: expected error, got nil") - } else if strings.Index(err.Error(), "{Unknown}") < 0 { - t.Errorf("unmarshal: bad error type: %v", err) - } -} - -func TestTypedNilMarshal(t *testing.T) { - // A typed nil should return ErrNil and not crash. - _, err := Marshal((*GoEnum)(nil)) - if err != ErrNil { - t.Errorf("Marshal: got err %v, want ErrNil", err) - } -} - -// A type that implements the Marshaler interface, but is not nillable. -type nonNillableInt uint64 - -func (nni nonNillableInt) Marshal() ([]byte, error) { - return EncodeVarint(uint64(nni)), nil -} - -type NNIMessage struct { - nni nonNillableInt -} - -func (*NNIMessage) Reset() {} -func (*NNIMessage) String() string { return "" } -func (*NNIMessage) ProtoMessage() {} - -// A type that implements the Marshaler interface and is nillable. -type nillableMessage struct { - x uint64 -} - -func (nm *nillableMessage) Marshal() ([]byte, error) { - return EncodeVarint(nm.x), nil -} - -type NMMessage struct { - nm *nillableMessage -} - -func (*NMMessage) Reset() {} -func (*NMMessage) String() string { return "" } -func (*NMMessage) ProtoMessage() {} - -// Verify a type that uses the Marshaler interface, but has a nil pointer. -func TestNilMarshaler(t *testing.T) { - // Try a struct with a Marshaler field that is nil. - // It should be directly marshable. - nmm := new(NMMessage) - if _, err := Marshal(nmm); err != nil { - t.Error("unexpected error marshaling nmm: ", err) - } - - // Try a struct with a Marshaler field that is not nillable. - nnim := new(NNIMessage) - nnim.nni = 7 - var _ Marshaler = nnim.nni // verify it is truly a Marshaler - if _, err := Marshal(nnim); err != nil { - t.Error("unexpected error marshaling nnim: ", err) - } -} - -func TestAllSetDefaults(t *testing.T) { - // Exercise SetDefaults with all scalar field types. - m := &Defaults{ - // NaN != NaN, so override that here. - F_Nan: Float32(1.7), - } - expected := &Defaults{ - F_Bool: Bool(true), - F_Int32: Int32(32), - F_Int64: Int64(64), - F_Fixed32: Uint32(320), - F_Fixed64: Uint64(640), - F_Uint32: Uint32(3200), - F_Uint64: Uint64(6400), - F_Float: Float32(314159), - F_Double: Float64(271828), - F_String: String(`hello, "world!"` + "\n"), - F_Bytes: []byte("Bignose"), - F_Sint32: Int32(-32), - F_Sint64: Int64(-64), - F_Enum: Defaults_GREEN.Enum(), - F_Pinf: Float32(float32(math.Inf(1))), - F_Ninf: Float32(float32(math.Inf(-1))), - F_Nan: Float32(1.7), - StrZero: String(""), - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("SetDefaults failed\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithSetField(t *testing.T) { - // Check that a set value is not overridden. - m := &Defaults{ - F_Int32: Int32(12), - } - SetDefaults(m) - if v := m.GetF_Int32(); v != 12 { - t.Errorf("m.FInt32 = %v, want 12", v) - } -} - -func TestSetDefaultsWithSubMessage(t *testing.T) { - m := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - }, - } - expected := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("gopher"), - Port: Int32(4000), - }, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) { - m := &MyMessage{ - RepInner: []*InnerMessage{{}}, - } - expected := &MyMessage{ - RepInner: []*InnerMessage{{ - Port: Int32(4000), - }}, - } - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestSetDefaultWithRepeatedNonMessage(t *testing.T) { - m := &MyMessage{ - Pet: []string{"turtle", "wombat"}, - } - expected := Clone(m) - SetDefaults(m) - if !Equal(m, expected) { - t.Errorf("\n got %v\nwant %v", m, expected) - } -} - -func TestMaximumTagNumber(t *testing.T) { - m := &MaxTag{ - LastField: String("natural goat essence"), - } - buf, err := Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal failed: %v", err) - } - m2 := new(MaxTag) - if err := Unmarshal(buf, m2); err != nil { - t.Fatalf("proto.Unmarshal failed: %v", err) - } - if got, want := m2.GetLastField(), *m.LastField; got != want { - t.Errorf("got %q, want %q", got, want) - } -} - -func TestJSON(t *testing.T) { - m := &MyMessage{ - Count: Int32(4), - Pet: []string{"bunny", "kitty"}, - Inner: &InnerMessage{ - Host: String("cauchy"), - }, - Bikeshed: MyMessage_GREEN.Enum(), - } - const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":1}` - - b, err := json.Marshal(m) - if err != nil { - t.Fatalf("json.Marshal failed: %v", err) - } - s := string(b) - if s != expected { - t.Errorf("got %s\nwant %s", s, expected) - } - - received := new(MyMessage) - if err := json.Unmarshal(b, received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } - - // Test unmarshalling of JSON with symbolic enum name. - const old = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":"GREEN"}` - received.Reset() - if err := json.Unmarshal([]byte(old), received); err != nil { - t.Fatalf("json.Unmarshal failed: %v", err) - } - if !Equal(received, m) { - t.Fatalf("got %s, want %s", received, m) - } -} - -func TestBadWireType(t *testing.T) { - b := []byte{7<<3 | 6} // field 7, wire type 6 - pb := new(OtherMessage) - if err := Unmarshal(b, pb); err == nil { - t.Errorf("Unmarshal did not fail") - } else if !strings.Contains(err.Error(), "unknown wire type") { - t.Errorf("wrong error: %v", err) - } -} - -func TestBytesWithInvalidLength(t *testing.T) { - // If a byte sequence has an invalid (negative) length, Unmarshal should not panic. - b := []byte{2<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0} - Unmarshal(b, new(MyMessage)) -} - -func TestLengthOverflow(t *testing.T) { - // Overflowing a length should not panic. - b := []byte{2<<3 | WireBytes, 1, 1, 3<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01} - Unmarshal(b, new(MyMessage)) -} - -func TestVarintOverflow(t *testing.T) { - // Overflowing a 64-bit length should not be allowed. - b := []byte{1<<3 | WireVarint, 0x01, 3<<3 | WireBytes, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} - if err := Unmarshal(b, new(MyMessage)); err == nil { - t.Fatalf("Overflowed uint64 length without error") - } -} - -func TestUnmarshalFuzz(t *testing.T) { - const N = 1000 - seed := time.Now().UnixNano() - t.Logf("RNG seed is %d", seed) - rng := rand.New(rand.NewSource(seed)) - buf := make([]byte, 20) - for i := 0; i < N; i++ { - for j := range buf { - buf[j] = byte(rng.Intn(256)) - } - fuzzUnmarshal(t, buf) - } -} - -func TestMergeMessages(t *testing.T) { - pb := &MessageList{Message: []*MessageList_Message{{Name: String("x"), Count: Int32(1)}}} - data, err := Marshal(pb) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - pb1 := new(MessageList) - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("first Unmarshal: %v", err) - } - if err := Unmarshal(data, pb1); err != nil { - t.Fatalf("second Unmarshal: %v", err) - } - if len(pb1.Message) != 1 { - t.Errorf("two Unmarshals produced %d Messages, want 1", len(pb1.Message)) - } - - pb2 := new(MessageList) - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("first UnmarshalMerge: %v", err) - } - if err := UnmarshalMerge(data, pb2); err != nil { - t.Fatalf("second UnmarshalMerge: %v", err) - } - if len(pb2.Message) != 2 { - t.Errorf("two UnmarshalMerges produced %d Messages, want 2", len(pb2.Message)) - } -} - -func TestExtensionMarshalOrder(t *testing.T) { - m := &MyMessage{Count: Int(123)} - if err := SetExtension(m, E_Ext_More, &Ext{Data: String("alpha")}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Text, String("aleph")); err != nil { - t.Fatalf("SetExtension: %v", err) - } - if err := SetExtension(m, E_Ext_Number, Int32(1)); err != nil { - t.Fatalf("SetExtension: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - var orig []byte - for i := 0; i < 100; i++ { - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if i == 0 { - orig = b - continue - } - if !bytes.Equal(b, orig) { - t.Errorf("Bytes differ on attempt #%d", i) - } - } -} - -// Many extensions, because small maps might not iterate differently on each iteration. -var exts = []*ExtensionDesc{ - E_X201, - E_X202, - E_X203, - E_X204, - E_X205, - E_X206, - E_X207, - E_X208, - E_X209, - E_X210, - E_X211, - E_X212, - E_X213, - E_X214, - E_X215, - E_X216, - E_X217, - E_X218, - E_X219, - E_X220, - E_X221, - E_X222, - E_X223, - E_X224, - E_X225, - E_X226, - E_X227, - E_X228, - E_X229, - E_X230, - E_X231, - E_X232, - E_X233, - E_X234, - E_X235, - E_X236, - E_X237, - E_X238, - E_X239, - E_X240, - E_X241, - E_X242, - E_X243, - E_X244, - E_X245, - E_X246, - E_X247, - E_X248, - E_X249, - E_X250, -} - -func TestMessageSetMarshalOrder(t *testing.T) { - m := &MyMessageSet{} - for _, x := range exts { - if err := SetExtension(m, x, &Empty{}); err != nil { - t.Fatalf("SetExtension: %v", err) - } - } - - buf, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // Serialize m several times, and check we get the same bytes each time. - for i := 0; i < 10; i++ { - b1, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - if !bytes.Equal(b1, buf) { - t.Errorf("Bytes differ on re-Marshal #%d", i) - } - - m2 := &MyMessageSet{} - if err := Unmarshal(buf, m2); err != nil { - t.Errorf("Unmarshal: %v", err) - } - b2, err := Marshal(m2) - if err != nil { - t.Errorf("re-Marshal: %v", err) - } - if !bytes.Equal(b2, buf) { - t.Errorf("Bytes differ on round-trip #%d", i) - } - } -} - -func TestUnmarshalMergesMessages(t *testing.T) { - // If a nested message occurs twice in the input, - // the fields should be merged when decoding. - a := &OtherMessage{ - Key: Int64(123), - Inner: &InnerMessage{ - Host: String("polhode"), - Port: Int32(1234), - }, - } - aData, err := Marshal(a) - if err != nil { - t.Fatalf("Marshal(a): %v", err) - } - b := &OtherMessage{ - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Connected: Bool(true), - }, - } - bData, err := Marshal(b) - if err != nil { - t.Fatalf("Marshal(b): %v", err) - } - want := &OtherMessage{ - Key: Int64(123), - Weight: Float32(1.2), - Inner: &InnerMessage{ - Host: String("herpolhode"), - Port: Int32(1234), - Connected: Bool(true), - }, - } - got := new(OtherMessage) - if err := Unmarshal(append(aData, bData...), got); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !Equal(got, want) { - t.Errorf("\n got %v\nwant %v", got, want) - } -} - -func TestEncodingSizes(t *testing.T) { - tests := []struct { - m Message - n int - }{ - {&Defaults{F_Int32: Int32(math.MaxInt32)}, 6}, - {&Defaults{F_Int32: Int32(math.MinInt32)}, 11}, - {&Defaults{F_Uint32: Uint32(uint32(math.MaxInt32) + 1)}, 6}, - {&Defaults{F_Uint32: Uint32(math.MaxUint32)}, 6}, - } - for _, test := range tests { - b, err := Marshal(test.m) - if err != nil { - t.Errorf("Marshal(%v): %v", test.m, err) - continue - } - if len(b) != test.n { - t.Errorf("Marshal(%v) yielded %d bytes, want %d bytes", test.m, len(b), test.n) - } - } -} - -func TestRequiredNotSetError(t *testing.T) { - pb := initGoTest(false) - pb.RequiredField.Label = nil - pb.F_Int32Required = nil - pb.F_Int64Required = nil - - expected := "0807" + // field 1, encoding 0, value 7 - "2206" + "120474797065" + // field 4, encoding 2 (GoTestField) - "5001" + // field 10, encoding 0, value 1 - "6d20000000" + // field 13, encoding 5, value 0x20 - "714000000000000000" + // field 14, encoding 1, value 0x40 - "78a019" + // field 15, encoding 0, value 0xca0 = 3232 - "8001c032" + // field 16, encoding 0, value 0x1940 = 6464 - "8d0100004a45" + // field 17, encoding 5, value 3232.0 - "9101000000000040b940" + // field 18, encoding 1, value 6464.0 - "9a0106" + "737472696e67" + // field 19, encoding 2, string "string" - "b304" + // field 70, encoding 3, start group - "ba0408" + "7265717569726564" + // field 71, encoding 2, string "required" - "b404" + // field 70, encoding 4, end group - "aa0605" + "6279746573" + // field 101, encoding 2, string "bytes" - "b0063f" + // field 102, encoding 0, 0x3f zigzag32 - "b8067f" // field 103, encoding 0, 0x7f zigzag64 - - o := old() - bytes, err := Marshal(pb) - if _, ok := err.(*RequiredNotSetError); !ok { - fmt.Printf("marshal-1 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("expected = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.Label") < 0 { - t.Errorf("marshal-1 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 1", bytes) - t.Fatalf("expected = %s", expected) - } - - // Now test Unmarshal by recreating the original buffer. - pbd := new(GoTest) - err = Unmarshal(bytes, pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Fatalf("unmarshal err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.{Unknown}") < 0 { - t.Errorf("unmarshal wrong err msg: %v", err) - } - bytes, err = Marshal(pbd) - if _, ok := err.(*RequiredNotSetError); !ok { - t.Errorf("marshal-2 err = %v, want *RequiredNotSetError", err) - o.DebugPrint("", bytes) - t.Fatalf("string = %s", expected) - } - if strings.Index(err.Error(), "RequiredField.Label") < 0 { - t.Errorf("marshal-2 wrong err msg: %v", err) - } - if !equal(bytes, expected, t) { - o.DebugPrint("neq 2", bytes) - t.Fatalf("string = %s", expected) - } -} - -func fuzzUnmarshal(t *testing.T, data []byte) { - defer func() { - if e := recover(); e != nil { - t.Errorf("These bytes caused a panic: %+v", data) - t.Logf("Stack:\n%s", debug.Stack()) - t.FailNow() - } - }() - - pb := new(MyMessage) - Unmarshal(data, pb) -} - -func TestMapFieldMarshal(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - - // b should be the concatenation of these three byte sequences in some order. - parts := []string{ - "\n\a\b\x01\x12\x03Rob", - "\n\a\b\x04\x12\x03Ian", - "\n\b\b\x08\x12\x04Dave", - } - ok := false - for i := range parts { - for j := range parts { - if j == i { - continue - } - for k := range parts { - if k == i || k == j { - continue - } - try := parts[i] + parts[j] + parts[k] - if bytes.Equal(b, []byte(try)) { - ok = true - break - } - } - } - } - if !ok { - t.Fatalf("Incorrect Marshal output.\n got %q\nwant %q (or a permutation of that)", b, parts[0]+parts[1]+parts[2]) - } - t.Logf("FYI b: %q", b) - - (new(Buffer)).DebugPrint("Dump of b", b) -} - -func TestMapFieldRoundTrips(t *testing.T) { - m := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Rob", - 4: "Ian", - 8: "Dave", - }, - MsgMapping: map[int64]*FloatingPoint{ - 0x7001: &FloatingPoint{F: Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{ - false: []byte("that's not right!"), - true: []byte("aye, 'tis true!"), - }, - } - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("FYI b: %q", b) - m2 := new(MessageWithMap) - if err := Unmarshal(b, m2); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - for _, pair := range [][2]interface{}{ - {m.NameMapping, m2.NameMapping}, - {m.MsgMapping, m2.MsgMapping}, - {m.ByteMapping, m2.ByteMapping}, - } { - if !reflect.DeepEqual(pair[0], pair[1]) { - t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", pair[0], pair[1]) - } - } -} - -func TestMapFieldWithNil(t *testing.T) { - m := &MessageWithMap{ - MsgMapping: map[int64]*FloatingPoint{ - 1: nil, - }, - } - b, err := Marshal(m) - if err == nil { - t.Fatalf("Marshal of bad map should have failed, got these bytes: %v", b) - } -} - -func TestOneof(t *testing.T) { - m := &Communique{} - b, err := Marshal(m) - if err != nil { - t.Fatalf("Marshal of empty message with oneof: %v", err) - } - if len(b) != 0 { - t.Errorf("Marshal of empty message yielded too many bytes: %v", b) - } - - m = &Communique{ - Union: &Communique_Name{"Barry"}, - } - - // Round-trip. - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof: %v", err) - } - if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5) - t.Errorf("Incorrect marshal of message with oneof: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof: %v", err) - } - if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" { - t.Errorf("After round trip, Union = %+v", m.Union) - } - if name := m.GetName(); name != "Barry" { - t.Errorf("After round trip, GetName = %q, want %q", name, "Barry") - } - - // Let's try with a message in the oneof. - m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}} - b, err = Marshal(m) - if err != nil { - t.Fatalf("Marshal of message with oneof set to message: %v", err) - } - if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16) - t.Errorf("Incorrect marshal of message with oneof set to message: %v", b) - } - m.Reset() - if err := Unmarshal(b, m); err != nil { - t.Fatalf("Unmarshal of message with oneof set to message: %v", err) - } - ss, ok := m.Union.(*Communique_Msg) - if !ok || ss.Msg.GetStringField() != "deep deep string" { - t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union) - } -} - -func TestInefficientPackedBool(t *testing.T) { - // https://github.com/golang/protobuf/issues/76 - inp := []byte{ - 0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes - // Usually a bool should take a single byte, - // but it is permitted to be any varint. - 0xb9, 0x30, - } - if err := Unmarshal(inp, new(MoreRepeated)); err != nil { - t.Error(err) - } -} - -// Benchmarks - -func testMsg() *GoTest { - pb := initGoTest(true) - const N = 1000 // Internally the library starts much smaller. - pb.F_Int32Repeated = make([]int32, N) - pb.F_DoubleRepeated = make([]float64, N) - for i := 0; i < N; i++ { - pb.F_Int32Repeated[i] = int32(i) - pb.F_DoubleRepeated[i] = float64(i) - } - return pb -} - -func bytesMsg() *GoTest { - pb := initGoTest(true) - buf := make([]byte, 4000) - for i := range buf { - buf[i] = byte(i) - } - pb.F_BytesDefaulted = buf - return pb -} - -func benchmarkMarshal(b *testing.B, pb Message, marshal func(Message) ([]byte, error)) { - d, _ := marshal(pb) - b.SetBytes(int64(len(d))) - b.ResetTimer() - for i := 0; i < b.N; i++ { - marshal(pb) - } -} - -func benchmarkBufferMarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - p.Reset() - err := p.Marshal(pb0) - return p.Bytes(), err - }) -} - -func benchmarkSize(b *testing.B, pb Message) { - benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { - Size(pb) - return nil, nil - }) -} - -func newOf(pb Message) Message { - in := reflect.ValueOf(pb) - if in.IsNil() { - return pb - } - return reflect.New(in.Type().Elem()).Interface().(Message) -} - -func benchmarkUnmarshal(b *testing.B, pb Message, unmarshal func([]byte, Message) error) { - d, _ := Marshal(pb) - b.SetBytes(int64(len(d))) - pbd := newOf(pb) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - unmarshal(d, pbd) - } -} - -func benchmarkBufferUnmarshal(b *testing.B, pb Message) { - p := NewBuffer(nil) - benchmarkUnmarshal(b, pb, func(d []byte, pb0 Message) error { - p.SetBuf(d) - return p.Unmarshal(pb0) - }) -} - -// Benchmark{Marshal,BufferMarshal,Size,Unmarshal,BufferUnmarshal}{,Bytes} - -func BenchmarkMarshal(b *testing.B) { - benchmarkMarshal(b, testMsg(), Marshal) -} - -func BenchmarkBufferMarshal(b *testing.B) { - benchmarkBufferMarshal(b, testMsg()) -} - -func BenchmarkSize(b *testing.B) { - benchmarkSize(b, testMsg()) -} - -func BenchmarkUnmarshal(b *testing.B) { - benchmarkUnmarshal(b, testMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshal(b *testing.B) { - benchmarkBufferUnmarshal(b, testMsg()) -} - -func BenchmarkMarshalBytes(b *testing.B) { - benchmarkMarshal(b, bytesMsg(), Marshal) -} - -func BenchmarkBufferMarshalBytes(b *testing.B) { - benchmarkBufferMarshal(b, bytesMsg()) -} - -func BenchmarkSizeBytes(b *testing.B) { - benchmarkSize(b, bytesMsg()) -} - -func BenchmarkUnmarshalBytes(b *testing.B) { - benchmarkUnmarshal(b, bytesMsg(), Unmarshal) -} - -func BenchmarkBufferUnmarshalBytes(b *testing.B) { - benchmarkBufferUnmarshal(b, bytesMsg()) -} - -func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) { - b.StopTimer() - pb := initGoTestField() - skip := &GoSkipTest{ - SkipInt32: Int32(32), - SkipFixed32: Uint32(3232), - SkipFixed64: Uint64(6464), - SkipString: String("skipper"), - Skipgroup: &GoSkipTest_SkipGroup{ - GroupInt32: Int32(75), - GroupString: String("wxyz"), - }, - } - - pbd := new(GoTestField) - p := NewBuffer(nil) - p.Marshal(pb) - p.Marshal(skip) - p2 := NewBuffer(nil) - - b.StartTimer() - for i := 0; i < b.N; i++ { - p2.SetBuf(p.Bytes()) - p2.Unmarshal(pbd) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go deleted file mode 100644 index 76720f18b..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/clone_test.go +++ /dev/null @@ -1,267 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -var cloneTestMessage = &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, -} - -func init() { - ext := &pb.Ext{ - Data: proto.String("extension"), - } - if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { - panic("SetExtension: " + err.Error()) - } -} - -func TestClone(t *testing.T) { - m := proto.Clone(cloneTestMessage).(*pb.MyMessage) - if !proto.Equal(m, cloneTestMessage) { - t.Errorf("Clone(%v) = %v", cloneTestMessage, m) - } - - // Verify it was a deep copy. - *m.Inner.Port++ - if proto.Equal(m, cloneTestMessage) { - t.Error("Mutating clone changed the original") - } - // Byte fields and repeated fields should be copied. - if &m.Pet[0] == &cloneTestMessage.Pet[0] { - t.Error("Pet: repeated field not copied") - } - if &m.Others[0] == &cloneTestMessage.Others[0] { - t.Error("Others: repeated field not copied") - } - if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] { - t.Error("Others[0].Value: bytes field not copied") - } - if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] { - t.Error("RepBytes: repeated field not copied") - } - if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] { - t.Error("RepBytes[0]: bytes field not copied") - } -} - -func TestCloneNil(t *testing.T) { - var m *pb.MyMessage - if c := proto.Clone(m); !proto.Equal(m, c) { - t.Errorf("Clone(%v) = %v", m, c) - } -} - -var mergeTests = []struct { - src, dst, want proto.Message -}{ - { - src: &pb.MyMessage{ - Count: proto.Int32(42), - }, - dst: &pb.MyMessage{ - Name: proto.String("Dave"), - }, - want: &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - }, - }, - { - src: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - }, - Pet: []string{"horsey"}, - Others: []*pb.OtherMessage{ - { - Value: []byte("some bytes"), - }, - }, - }, - dst: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("niles"), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - { - // Explicitly test a src=nil field - Inner: nil, - }, - }, - }, - want: &pb.MyMessage{ - Inner: &pb.InnerMessage{ - Host: proto.String("hey"), - Connected: proto.Bool(true), - Port: proto.Int32(9099), - }, - Pet: []string{"bunny", "kitty", "horsey"}, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(31415926535), - }, - {}, - { - Value: []byte("some bytes"), - }, - }, - }, - }, - { - src: &pb.MyMessage{ - RepBytes: [][]byte{[]byte("wow")}, - }, - dst: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham")}, - }, - want: &pb.MyMessage{ - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(6), - }, - RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, - }, - }, - // Check that a scalar bytes field replaces rather than appends. - { - src: &pb.OtherMessage{Value: []byte("foo")}, - dst: &pb.OtherMessage{Value: []byte("bar")}, - want: &pb.OtherMessage{Value: []byte("foo")}, - }, - { - src: &pb.MessageWithMap{ - NameMapping: map[int32]string{6: "Nigel"}, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - dst: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Bruce", // should be overwritten - 7: "Andrew", - }, - }, - want: &pb.MessageWithMap{ - NameMapping: map[int32]string{ - 6: "Nigel", - 7: "Andrew", - }, - MsgMapping: map[int64]*pb.FloatingPoint{ - 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, - }, - ByteMapping: map[bool][]byte{true: []byte("wowsa")}, - }, - }, - // proto3 shouldn't merge zero values, - // in the same way that proto2 shouldn't merge nils. - { - src: &proto3pb.Message{ - Name: "Aaron", - Data: []byte(""), // zero value, but not nil - }, - dst: &proto3pb.Message{ - HeightInCm: 176, - Data: []byte("texas!"), - }, - want: &proto3pb.Message{ - Name: "Aaron", - HeightInCm: 176, - Data: []byte("texas!"), - }, - }, - // Oneof fields should merge by assignment. - { - src: &pb.Communique{ - Union: &pb.Communique_Number{41}, - }, - dst: &pb.Communique{ - Union: &pb.Communique_Name{"Bobby Tables"}, - }, - want: &pb.Communique{ - Union: &pb.Communique_Number{41}, - }, - }, - // Oneof nil is the same as not set. - { - src: &pb.Communique{}, - dst: &pb.Communique{ - Union: &pb.Communique_Name{"Bobby Tables"}, - }, - want: &pb.Communique{ - Union: &pb.Communique_Name{"Bobby Tables"}, - }, - }, -} - -func TestMerge(t *testing.T) { - for _, m := range mergeTests { - got := proto.Clone(m.dst) - proto.Merge(got, m.src) - if !proto.Equal(got, m.want) { - t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go deleted file mode 100644 index 7b45eaa6d..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/equal_test.go +++ /dev/null @@ -1,212 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2011 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -// Four identical base messages. -// The init function adds extensions to some of them. -var messageWithoutExtension = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension1a = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension1b = &pb.MyMessage{Count: Int32(7)} -var messageWithExtension2 = &pb.MyMessage{Count: Int32(7)} - -// Two messages with non-message extensions. -var messageWithInt32Extension1 = &pb.MyMessage{Count: Int32(8)} -var messageWithInt32Extension2 = &pb.MyMessage{Count: Int32(8)} - -func init() { - ext1 := &pb.Ext{Data: String("Kirk")} - ext2 := &pb.Ext{Data: String("Picard")} - - // messageWithExtension1a has ext1, but never marshals it. - if err := SetExtension(messageWithExtension1a, pb.E_Ext_More, ext1); err != nil { - panic("SetExtension on 1a failed: " + err.Error()) - } - - // messageWithExtension1b is the unmarshaled form of messageWithExtension1a. - if err := SetExtension(messageWithExtension1b, pb.E_Ext_More, ext1); err != nil { - panic("SetExtension on 1b failed: " + err.Error()) - } - buf, err := Marshal(messageWithExtension1b) - if err != nil { - panic("Marshal of 1b failed: " + err.Error()) - } - messageWithExtension1b.Reset() - if err := Unmarshal(buf, messageWithExtension1b); err != nil { - panic("Unmarshal of 1b failed: " + err.Error()) - } - - // messageWithExtension2 has ext2. - if err := SetExtension(messageWithExtension2, pb.E_Ext_More, ext2); err != nil { - panic("SetExtension on 2 failed: " + err.Error()) - } - - if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(23)); err != nil { - panic("SetExtension on Int32-1 failed: " + err.Error()) - } - if err := SetExtension(messageWithInt32Extension1, pb.E_Ext_Number, Int32(24)); err != nil { - panic("SetExtension on Int32-2 failed: " + err.Error()) - } -} - -var EqualTests = []struct { - desc string - a, b Message - exp bool -}{ - {"different types", &pb.GoEnum{}, &pb.GoTestField{}, false}, - {"equal empty", &pb.GoEnum{}, &pb.GoEnum{}, true}, - {"nil vs nil", nil, nil, true}, - {"typed nil vs typed nil", (*pb.GoEnum)(nil), (*pb.GoEnum)(nil), true}, - {"typed nil vs empty", (*pb.GoEnum)(nil), &pb.GoEnum{}, false}, - {"different typed nil", (*pb.GoEnum)(nil), (*pb.GoTestField)(nil), false}, - - {"one set field, one unset field", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{}, false}, - {"one set field zero, one unset field", &pb.GoTest{Param: Int32(0)}, &pb.GoTest{}, false}, - {"different set fields", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("bar")}, false}, - {"equal set", &pb.GoTestField{Label: String("foo")}, &pb.GoTestField{Label: String("foo")}, true}, - - {"repeated, one set", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{}, false}, - {"repeated, different length", &pb.GoTest{F_Int32Repeated: []int32{2, 3}}, &pb.GoTest{F_Int32Repeated: []int32{2}}, false}, - {"repeated, different value", &pb.GoTest{F_Int32Repeated: []int32{2}}, &pb.GoTest{F_Int32Repeated: []int32{3}}, false}, - {"repeated, equal", &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, &pb.GoTest{F_Int32Repeated: []int32{2, 4}}, true}, - {"repeated, nil equal nil", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: nil}, true}, - {"repeated, nil equal empty", &pb.GoTest{F_Int32Repeated: nil}, &pb.GoTest{F_Int32Repeated: []int32{}}, true}, - {"repeated, empty equal nil", &pb.GoTest{F_Int32Repeated: []int32{}}, &pb.GoTest{F_Int32Repeated: nil}, true}, - - { - "nested, different", - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("foo")}}, - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("bar")}}, - false, - }, - { - "nested, equal", - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, - &pb.GoTest{RequiredField: &pb.GoTestField{Label: String("wow")}}, - true, - }, - - {"bytes", &pb.OtherMessage{Value: []byte("foo")}, &pb.OtherMessage{Value: []byte("foo")}, true}, - {"bytes, empty", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: []byte{}}, true}, - {"bytes, empty vs nil", &pb.OtherMessage{Value: []byte{}}, &pb.OtherMessage{Value: nil}, false}, - { - "repeated bytes", - &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, - &pb.MyMessage{RepBytes: [][]byte{[]byte("sham"), []byte("wow")}}, - true, - }, - // In proto3, []byte{} and []byte(nil) are equal. - {"proto3 bytes, empty vs nil", &proto3pb.Message{Data: []byte{}}, &proto3pb.Message{Data: nil}, true}, - - {"extension vs. no extension", messageWithoutExtension, messageWithExtension1a, false}, - {"extension vs. same extension", messageWithExtension1a, messageWithExtension1b, true}, - {"extension vs. different extension", messageWithExtension1a, messageWithExtension2, false}, - - {"int32 extension vs. itself", messageWithInt32Extension1, messageWithInt32Extension1, true}, - {"int32 extension vs. a different int32", messageWithInt32Extension1, messageWithInt32Extension2, false}, - - { - "message with group", - &pb.MyMessage{ - Count: Int32(1), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: Int32(5), - }, - }, - &pb.MyMessage{ - Count: Int32(1), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: Int32(5), - }, - }, - true, - }, - - { - "map same", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - true, - }, - { - "map different entry", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{2: "Rob"}}, - false, - }, - { - "map different key only", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{2: "Ken"}}, - false, - }, - { - "map different value only", - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Ken"}}, - &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob"}}, - false, - }, - { - "oneof same", - &pb.Communique{Union: &pb.Communique_Number{41}}, - &pb.Communique{Union: &pb.Communique_Number{41}}, - true, - }, - { - "oneof one nil", - &pb.Communique{Union: &pb.Communique_Number{41}}, - &pb.Communique{}, - false, - }, - { - "oneof different", - &pb.Communique{Union: &pb.Communique_Number{41}}, - &pb.Communique{Union: &pb.Communique_Name{"Bobby Tables"}}, - false, - }, -} - -func TestEqual(t *testing.T) { - for _, tc := range EqualTests { - if res := Equal(tc.a, tc.b); res != tc.exp { - t.Errorf("%v: Equal(%v, %v) = %v, want %v", tc.desc, tc.a, tc.b, res, tc.exp) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go deleted file mode 100644 index 80122108b..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/extensions_test.go +++ /dev/null @@ -1,430 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "fmt" - "reflect" - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -func TestGetExtensionsWithMissingExtensions(t *testing.T) { - msg := &pb.MyMessage{} - ext1 := &pb.Ext{} - if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { - t.Fatalf("Could not set ext1: %s", ext1) - } - exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{ - pb.E_Ext_More, - pb.E_Ext_Text, - }) - if err != nil { - t.Fatalf("GetExtensions() failed: %s", err) - } - if exts[0] != ext1 { - t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0]) - } - if exts[1] != nil { - t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1]) - } -} - -func TestGetExtensionStability(t *testing.T) { - check := func(m *pb.MyMessage) bool { - ext1, err := proto.GetExtension(m, pb.E_Ext_More) - if err != nil { - t.Fatalf("GetExtension() failed: %s", err) - } - ext2, err := proto.GetExtension(m, pb.E_Ext_More) - if err != nil { - t.Fatalf("GetExtension() failed: %s", err) - } - return ext1 == ext2 - } - msg := &pb.MyMessage{Count: proto.Int32(4)} - ext0 := &pb.Ext{} - if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil { - t.Fatalf("Could not set ext1: %s", ext0) - } - if !check(msg) { - t.Errorf("GetExtension() not stable before marshaling") - } - bb, err := proto.Marshal(msg) - if err != nil { - t.Fatalf("Marshal() failed: %s", err) - } - msg1 := &pb.MyMessage{} - err = proto.Unmarshal(bb, msg1) - if err != nil { - t.Fatalf("Unmarshal() failed: %s", err) - } - if !check(msg1) { - t.Errorf("GetExtension() not stable after unmarshaling") - } -} - -func TestGetExtensionDefaults(t *testing.T) { - var setFloat64 float64 = 1 - var setFloat32 float32 = 2 - var setInt32 int32 = 3 - var setInt64 int64 = 4 - var setUint32 uint32 = 5 - var setUint64 uint64 = 6 - var setBool = true - var setBool2 = false - var setString = "Goodnight string" - var setBytes = []byte("Goodnight bytes") - var setEnum = pb.DefaultsMessage_TWO - - type testcase struct { - ext *proto.ExtensionDesc // Extension we are testing. - want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail). - def interface{} // Expected value of extension after ClearExtension(). - } - tests := []testcase{ - {pb.E_NoDefaultDouble, setFloat64, nil}, - {pb.E_NoDefaultFloat, setFloat32, nil}, - {pb.E_NoDefaultInt32, setInt32, nil}, - {pb.E_NoDefaultInt64, setInt64, nil}, - {pb.E_NoDefaultUint32, setUint32, nil}, - {pb.E_NoDefaultUint64, setUint64, nil}, - {pb.E_NoDefaultSint32, setInt32, nil}, - {pb.E_NoDefaultSint64, setInt64, nil}, - {pb.E_NoDefaultFixed32, setUint32, nil}, - {pb.E_NoDefaultFixed64, setUint64, nil}, - {pb.E_NoDefaultSfixed32, setInt32, nil}, - {pb.E_NoDefaultSfixed64, setInt64, nil}, - {pb.E_NoDefaultBool, setBool, nil}, - {pb.E_NoDefaultBool, setBool2, nil}, - {pb.E_NoDefaultString, setString, nil}, - {pb.E_NoDefaultBytes, setBytes, nil}, - {pb.E_NoDefaultEnum, setEnum, nil}, - {pb.E_DefaultDouble, setFloat64, float64(3.1415)}, - {pb.E_DefaultFloat, setFloat32, float32(3.14)}, - {pb.E_DefaultInt32, setInt32, int32(42)}, - {pb.E_DefaultInt64, setInt64, int64(43)}, - {pb.E_DefaultUint32, setUint32, uint32(44)}, - {pb.E_DefaultUint64, setUint64, uint64(45)}, - {pb.E_DefaultSint32, setInt32, int32(46)}, - {pb.E_DefaultSint64, setInt64, int64(47)}, - {pb.E_DefaultFixed32, setUint32, uint32(48)}, - {pb.E_DefaultFixed64, setUint64, uint64(49)}, - {pb.E_DefaultSfixed32, setInt32, int32(50)}, - {pb.E_DefaultSfixed64, setInt64, int64(51)}, - {pb.E_DefaultBool, setBool, true}, - {pb.E_DefaultBool, setBool2, true}, - {pb.E_DefaultString, setString, "Hello, string"}, - {pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")}, - {pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE}, - } - - checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error { - val, err := proto.GetExtension(msg, test.ext) - if err != nil { - if valWant != nil { - return fmt.Errorf("GetExtension(): %s", err) - } - if want := proto.ErrMissingExtension; err != want { - return fmt.Errorf("Unexpected error: got %v, want %v", err, want) - } - return nil - } - - // All proto2 extension values are either a pointer to a value or a slice of values. - ty := reflect.TypeOf(val) - tyWant := reflect.TypeOf(test.ext.ExtensionType) - if got, want := ty, tyWant; got != want { - return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want) - } - tye := ty.Elem() - tyeWant := tyWant.Elem() - if got, want := tye, tyeWant; got != want { - return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want) - } - - // Check the name of the type of the value. - // If it is an enum it will be type int32 with the name of the enum. - if got, want := tye.Name(), tye.Name(); got != want { - return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want) - } - - // Check that value is what we expect. - // If we have a pointer in val, get the value it points to. - valExp := val - if ty.Kind() == reflect.Ptr { - valExp = reflect.ValueOf(val).Elem().Interface() - } - if got, want := valExp, valWant; !reflect.DeepEqual(got, want) { - return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want) - } - - return nil - } - - setTo := func(test testcase) interface{} { - setTo := reflect.ValueOf(test.want) - if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr { - setTo = reflect.New(typ).Elem() - setTo.Set(reflect.New(setTo.Type().Elem())) - setTo.Elem().Set(reflect.ValueOf(test.want)) - } - return setTo.Interface() - } - - for _, test := range tests { - msg := &pb.DefaultsMessage{} - name := test.ext.Name - - // Check the initial value. - if err := checkVal(test, msg, test.def); err != nil { - t.Errorf("%s: %v", name, err) - } - - // Set the per-type value and check value. - name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want) - if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil { - t.Errorf("%s: SetExtension(): %v", name, err) - continue - } - if err := checkVal(test, msg, test.want); err != nil { - t.Errorf("%s: %v", name, err) - continue - } - - // Set and check the value. - name += " (cleared)" - proto.ClearExtension(msg, test.ext) - if err := checkVal(test, msg, test.def); err != nil { - t.Errorf("%s: %v", name, err) - } - } -} - -func TestExtensionsRoundTrip(t *testing.T) { - msg := &pb.MyMessage{} - ext1 := &pb.Ext{ - Data: proto.String("hi"), - } - ext2 := &pb.Ext{ - Data: proto.String("there"), - } - exists := proto.HasExtension(msg, pb.E_Ext_More) - if exists { - t.Error("Extension More present unexpectedly") - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { - t.Error(err) - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil { - t.Error(err) - } - e, err := proto.GetExtension(msg, pb.E_Ext_More) - if err != nil { - t.Error(err) - } - x, ok := e.(*pb.Ext) - if !ok { - t.Errorf("e has type %T, expected testdata.Ext", e) - } else if *x.Data != "there" { - t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x) - } - proto.ClearExtension(msg, pb.E_Ext_More) - if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension { - t.Errorf("got %v, expected ErrMissingExtension", e) - } - if _, err := proto.GetExtension(msg, pb.E_X215); err == nil { - t.Error("expected bad extension error, got nil") - } - if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil { - t.Error("expected extension err") - } - if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil { - t.Error("expected some sort of type mismatch error, got nil") - } -} - -func TestNilExtension(t *testing.T) { - msg := &pb.MyMessage{ - Count: proto.Int32(1), - } - if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil { - t.Fatal(err) - } - if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil { - t.Error("expected SetExtension to fail due to a nil extension") - } else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want { - t.Errorf("expected error %v, got %v", want, err) - } - // Note: if the behavior of Marshal is ever changed to ignore nil extensions, update - // this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal. -} - -func TestMarshalUnmarshalRepeatedExtension(t *testing.T) { - // Add a repeated extension to the result. - tests := []struct { - name string - ext []*pb.ComplexExtension - }{ - { - "two fields", - []*pb.ComplexExtension{ - {First: proto.Int32(7)}, - {Second: proto.Int32(11)}, - }, - }, - { - "repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {Third: []int32{2000}}, - }, - }, - { - "two fields and repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {First: proto.Int32(9)}, - {Second: proto.Int32(21)}, - {Third: []int32{2000}}, - }, - }, - } - for _, test := range tests { - // Marshal message with a repeated extension. - msg1 := new(pb.OtherMessage) - err := proto.SetExtension(msg1, pb.E_RComplex, test.ext) - if err != nil { - t.Fatalf("[%s] Error setting extension: %v", test.name, err) - } - b, err := proto.Marshal(msg1) - if err != nil { - t.Fatalf("[%s] Error marshaling message: %v", test.name, err) - } - - // Unmarshal and read the merged proto. - msg2 := new(pb.OtherMessage) - err = proto.Unmarshal(b, msg2) - if err != nil { - t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) - } - e, err := proto.GetExtension(msg2, pb.E_RComplex) - if err != nil { - t.Fatalf("[%s] Error getting extension: %v", test.name, err) - } - ext := e.([]*pb.ComplexExtension) - if ext == nil { - t.Fatalf("[%s] Invalid extension", test.name) - } - if !reflect.DeepEqual(ext, test.ext) { - t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext) - } - } -} - -func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) { - // We may see multiple instances of the same extension in the wire - // format. For example, the proto compiler may encode custom options in - // this way. Here, we verify that we merge the extensions together. - tests := []struct { - name string - ext []*pb.ComplexExtension - }{ - { - "two fields", - []*pb.ComplexExtension{ - {First: proto.Int32(7)}, - {Second: proto.Int32(11)}, - }, - }, - { - "repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {Third: []int32{2000}}, - }, - }, - { - "two fields and repeated field", - []*pb.ComplexExtension{ - {Third: []int32{1000}}, - {First: proto.Int32(9)}, - {Second: proto.Int32(21)}, - {Third: []int32{2000}}, - }, - }, - } - for _, test := range tests { - var buf bytes.Buffer - var want pb.ComplexExtension - - // Generate a serialized representation of a repeated extension - // by catenating bytes together. - for i, e := range test.ext { - // Merge to create the wanted proto. - proto.Merge(&want, e) - - // serialize the message - msg := new(pb.OtherMessage) - err := proto.SetExtension(msg, pb.E_Complex, e) - if err != nil { - t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err) - } - b, err := proto.Marshal(msg) - if err != nil { - t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err) - } - buf.Write(b) - } - - // Unmarshal and read the merged proto. - msg2 := new(pb.OtherMessage) - err := proto.Unmarshal(buf.Bytes(), msg2) - if err != nil { - t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) - } - e, err := proto.GetExtension(msg2, pb.E_Complex) - if err != nil { - t.Fatalf("[%s] Error getting extension: %v", test.name, err) - } - ext := e.(*pb.ComplexExtension) - if ext == nil { - t.Fatalf("[%s] Invalid extension", test.name) - } - if !reflect.DeepEqual(*ext, want) { - t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, want) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go deleted file mode 100644 index ab8ac2f0e..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/message_set_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "bytes" - "testing" -) - -func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { - // Check that a repeated message set entry will be concatenated. - in := &messageSet{ - Item: []*_MessageSet_Item{ - {TypeId: Int32(12345), Message: []byte("hoo")}, - {TypeId: Int32(12345), Message: []byte("hah")}, - }, - } - b, err := Marshal(in) - if err != nil { - t.Fatalf("Marshal: %v", err) - } - t.Logf("Marshaled bytes: %q", b) - - m := make(map[int32]Extension) - if err := UnmarshalMessageSet(b, m); err != nil { - t.Fatalf("UnmarshalMessageSet: %v", err) - } - ext, ok := m[12345] - if !ok { - t.Fatalf("Didn't retrieve extension 12345; map is %v", m) - } - // Skip wire type/field number and length varints. - got := skipVarint(skipVarint(ext.enc)) - if want := []byte("hoohah"); !bytes.Equal(got, want) { - t.Errorf("Combined extension is %q, want %q", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go deleted file mode 100644 index 37c778209..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go +++ /dev/null @@ -1,122 +0,0 @@ -// Code generated by protoc-gen-go. -// source: proto3_proto/proto3.proto -// DO NOT EDIT! - -/* -Package proto3_proto is a generated protocol buffer package. - -It is generated from these files: - proto3_proto/proto3.proto - -It has these top-level messages: - Message - Nested - MessageWithMap -*/ -package proto3_proto - -import proto "github.com/golang/protobuf/proto" -import testdata "github.com/golang/protobuf/proto/testdata" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal - -type Message_Humour int32 - -const ( - Message_UNKNOWN Message_Humour = 0 - Message_PUNS Message_Humour = 1 - Message_SLAPSTICK Message_Humour = 2 - Message_BILL_BAILEY Message_Humour = 3 -) - -var Message_Humour_name = map[int32]string{ - 0: "UNKNOWN", - 1: "PUNS", - 2: "SLAPSTICK", - 3: "BILL_BAILEY", -} -var Message_Humour_value = map[string]int32{ - "UNKNOWN": 0, - "PUNS": 1, - "SLAPSTICK": 2, - "BILL_BAILEY": 3, -} - -func (x Message_Humour) String() string { - return proto.EnumName(Message_Humour_name, int32(x)) -} - -type Message struct { - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` - HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm" json:"height_in_cm,omitempty"` - Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` - ResultCount int64 `protobuf:"varint,7,opt,name=result_count" json:"result_count,omitempty"` - TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman" json:"true_scotsman,omitempty"` - Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"` - Key []uint64 `protobuf:"varint,5,rep,name=key" json:"key,omitempty"` - Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"` - Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field" json:"proto2_field,omitempty"` - Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` -} - -func (m *Message) Reset() { *m = Message{} } -func (m *Message) String() string { return proto.CompactTextString(m) } -func (*Message) ProtoMessage() {} - -func (m *Message) GetNested() *Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *Message) GetTerrain() map[string]*Nested { - if m != nil { - return m.Terrain - } - return nil -} - -func (m *Message) GetProto2Field() *testdata.SubDefaults { - if m != nil { - return m.Proto2Field - } - return nil -} - -func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults { - if m != nil { - return m.Proto2Value - } - return nil -} - -type Nested struct { - Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"` -} - -func (m *Nested) Reset() { *m = Nested{} } -func (m *Nested) String() string { return proto.CompactTextString(m) } -func (*Nested) ProtoMessage() {} - -type MessageWithMap struct { - ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } -func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } -func (*MessageWithMap) ProtoMessage() {} - -func (m *MessageWithMap) GetByteMapping() map[bool][]byte { - if m != nil { - return m.ByteMapping - } - return nil -} - -func init() { - proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto b/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto deleted file mode 100644 index e2311d929..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_proto/proto3.proto +++ /dev/null @@ -1,68 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -syntax = "proto3"; - -import "testdata/test.proto"; - -package proto3_proto; - -message Message { - enum Humour { - UNKNOWN = 0; - PUNS = 1; - SLAPSTICK = 2; - BILL_BAILEY = 3; - } - - string name = 1; - Humour hilarity = 2; - uint32 height_in_cm = 3; - bytes data = 4; - int64 result_count = 7; - bool true_scotsman = 8; - float score = 9; - - repeated uint64 key = 5; - Nested nested = 6; - - map terrain = 10; - testdata.SubDefaults proto2_field = 11; - map proto2_value = 13; -} - -message Nested { - string bunny = 1; -} - -message MessageWithMap { - map byte_mapping = 1; -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go deleted file mode 100644 index 462f8055c..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/proto3_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2014 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "testing" - - "github.com/golang/protobuf/proto" - pb "github.com/golang/protobuf/proto/proto3_proto" - tpb "github.com/golang/protobuf/proto/testdata" -) - -func TestProto3ZeroValues(t *testing.T) { - tests := []struct { - desc string - m proto.Message - }{ - {"zero message", &pb.Message{}}, - {"empty bytes field", &pb.Message{Data: []byte{}}}, - } - for _, test := range tests { - b, err := proto.Marshal(test.m) - if err != nil { - t.Errorf("%s: proto.Marshal: %v", test.desc, err) - continue - } - if len(b) > 0 { - t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) - } - } -} - -func TestRoundTripProto3(t *testing.T) { - m := &pb.Message{ - Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" - Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 - HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 - Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" - ResultCount: 47, // (0 | 7<<3): 0x38 0x2f - TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 - Score: 8.1, // (5 | 9<<3): 0x4d <8.1> - - Key: []uint64{1, 0xdeadbeef}, - Nested: &pb.Nested{ - Bunny: "Monty", - }, - } - t.Logf(" m: %v", m) - - b, err := proto.Marshal(m) - if err != nil { - t.Fatalf("proto.Marshal: %v", err) - } - t.Logf(" b: %q", b) - - m2 := new(pb.Message) - if err := proto.Unmarshal(b, m2); err != nil { - t.Fatalf("proto.Unmarshal: %v", err) - } - t.Logf("m2: %v", m2) - - if !proto.Equal(m, m2) { - t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) - } -} - -func TestProto3SetDefaults(t *testing.T) { - in := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: new(tpb.SubDefaults), - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": new(tpb.SubDefaults), - }, - } - - got := proto.Clone(in).(*pb.Message) - proto.SetDefaults(got) - - // There are no defaults in proto3. Everything should be the zero value, but - // we need to remember to set defaults for nested proto2 messages. - want := &pb.Message{ - Terrain: map[string]*pb.Nested{ - "meadow": new(pb.Nested), - }, - Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, - Proto2Value: map[string]*tpb.SubDefaults{ - "badlands": &tpb.SubDefaults{N: proto.Int64(7)}, - }, - } - - if !proto.Equal(got, want) { - t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size2_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/size2_test.go deleted file mode 100644 index a2729c39a..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size2_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto - -import ( - "testing" -) - -// This is a separate file and package from size_test.go because that one uses -// generated messages and thus may not be in package proto without having a circular -// dependency, whereas this file tests unexported details of size.go. - -func TestVarintSize(t *testing.T) { - // Check the edge cases carefully. - testCases := []struct { - n uint64 - size int - }{ - {0, 1}, - {1, 1}, - {127, 1}, - {128, 2}, - {16383, 2}, - {16384, 3}, - {1<<63 - 1, 9}, - {1 << 63, 10}, - } - for _, tc := range testCases { - size := sizeVarint(tc.n) - if size != tc.size { - t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go deleted file mode 100644 index af1034dc7..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/size_test.go +++ /dev/null @@ -1,164 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "log" - "strings" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)} - -// messageWithExtension2 is in equal_test.go. -var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)} - -func init() { - if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil { - log.Panicf("SetExtension: %v", err) - } - - // Force messageWithExtension3 to have the extension encoded. - Marshal(messageWithExtension3) - -} - -var SizeTests = []struct { - desc string - pb Message -}{ - {"empty", &pb.OtherMessage{}}, - // Basic types. - {"bool", &pb.Defaults{F_Bool: Bool(true)}}, - {"int32", &pb.Defaults{F_Int32: Int32(12)}}, - {"negative int32", &pb.Defaults{F_Int32: Int32(-1)}}, - {"small int64", &pb.Defaults{F_Int64: Int64(1)}}, - {"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}}, - {"negative int64", &pb.Defaults{F_Int64: Int64(-1)}}, - {"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}}, - {"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}}, - {"uint32", &pb.Defaults{F_Uint32: Uint32(123)}}, - {"uint64", &pb.Defaults{F_Uint64: Uint64(124)}}, - {"float", &pb.Defaults{F_Float: Float32(12.6)}}, - {"double", &pb.Defaults{F_Double: Float64(13.9)}}, - {"string", &pb.Defaults{F_String: String("niles")}}, - {"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}}, - {"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}}, - {"sint32", &pb.Defaults{F_Sint32: Int32(65)}}, - {"sint64", &pb.Defaults{F_Sint64: Int64(67)}}, - {"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}}, - // Repeated. - {"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}}, - {"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}}, - {"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}}, - {"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}}, - {"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}}, - {"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{ - // Need enough large numbers to verify that the header is counting the number of bytes - // for the field, not the number of elements. - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, - }}}, - {"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}}, - {"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}}, - // Nested. - {"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}}, - {"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}}, - // Other things. - {"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}}, - {"extension (unencoded)", messageWithExtension1}, - {"extension (encoded)", messageWithExtension3}, - // proto3 message - {"proto3 empty", &proto3pb.Message{}}, - {"proto3 bool", &proto3pb.Message{TrueScotsman: true}}, - {"proto3 int64", &proto3pb.Message{ResultCount: 1}}, - {"proto3 uint32", &proto3pb.Message{HeightInCm: 123}}, - {"proto3 float", &proto3pb.Message{Score: 12.6}}, - {"proto3 string", &proto3pb.Message{Name: "Snezana"}}, - {"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}}, - {"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}}, - {"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, - {"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}}, - - {"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}}, - {"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}}, - {"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}}, - {"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}}, - - {"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}}, - {"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}}, - {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, - - {"oneof not set", &pb.Oneof{}}, - {"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}}, - {"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}}, - {"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}}, - {"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}}, - {"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}}, - {"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}}, - {"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}}, - {"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}}, - {"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}}, - {"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}}, - {"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}}, - {"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}}, - {"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}}, - {"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}}, - {"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}}, - {"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}}, - {"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}}, - {"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}}, - {"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}}, - {"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}}, -} - -func TestSize(t *testing.T) { - for _, tc := range SizeTests { - size := Size(tc.pb) - b, err := Marshal(tc.pb) - if err != nil { - t.Errorf("%v: Marshal failed: %v", tc.desc, err) - continue - } - if size != len(b) { - t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b)) - t.Logf("%v: bytes: %#v", tc.desc, b) - } - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/Makefile b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/Makefile deleted file mode 100644 index fc288628a..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# Go support for Protocol Buffers - Google's data interchange format -# -# Copyright 2010 The Go Authors. All rights reserved. -# https://github.com/golang/protobuf -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -include ../../Make.protobuf - -all: regenerate - -regenerate: - rm -f test.pb.go - make test.pb.go - -# The following rules are just aids to development. Not needed for typical testing. - -diff: regenerate - git diff test.pb.go - -restore: - cp test.pb.go.golden test.pb.go - -preserve: - cp test.pb.go test.pb.go.golden diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go deleted file mode 100644 index 7172d0e96..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/golden_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2012 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Verify that the compiler output for test.proto is unchanged. - -package testdata - -import ( - "crypto/sha1" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "testing" -) - -// sum returns in string form (for easy comparison) the SHA-1 hash of the named file. -func sum(t *testing.T, name string) string { - data, err := ioutil.ReadFile(name) - if err != nil { - t.Fatal(err) - } - t.Logf("sum(%q): length is %d", name, len(data)) - hash := sha1.New() - _, err = hash.Write(data) - if err != nil { - t.Fatal(err) - } - return fmt.Sprintf("% x", hash.Sum(nil)) -} - -func run(t *testing.T, name string, args ...string) { - cmd := exec.Command(name, args...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Run() - if err != nil { - t.Fatal(err) - } -} - -func TestGolden(t *testing.T) { - // Compute the original checksum. - goldenSum := sum(t, "test.pb.go") - // Run the proto compiler. - run(t, "protoc", "--go_out="+os.TempDir(), "test.proto") - newFile := filepath.Join(os.TempDir(), "test.pb.go") - defer os.Remove(newFile) - // Compute the new checksum. - newSum := sum(t, newFile) - // Verify - if newSum != goldenSum { - run(t, "diff", "-u", "test.pb.go", newFile) - t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go") - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go deleted file mode 100644 index e3c83fc1a..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.pb.go +++ /dev/null @@ -1,3926 +0,0 @@ -// Code generated by protoc-gen-go. -// source: test.proto -// DO NOT EDIT! - -/* -Package testdata is a generated protocol buffer package. - -It is generated from these files: - test.proto - -It has these top-level messages: - GoEnum - GoTestField - GoTest - GoSkipTest - NonPackedTest - PackedTest - MaxTag - OldMessage - NewMessage - InnerMessage - OtherMessage - MyMessage - Ext - ComplexExtension - DefaultsMessage - MyMessageSet - Empty - MessageList - Strings - Defaults - SubDefaults - RepeatedEnum - MoreRepeated - GroupOld - GroupNew - FloatingPoint - MessageWithMap - Oneof - Communique -*/ -package testdata - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -const _ = proto.ProtoPackageIsVersion1 - -type FOO int32 - -const ( - FOO_FOO1 FOO = 1 -) - -var FOO_name = map[int32]string{ - 1: "FOO1", -} -var FOO_value = map[string]int32{ - "FOO1": 1, -} - -func (x FOO) Enum() *FOO { - p := new(FOO) - *p = x - return p -} -func (x FOO) String() string { - return proto.EnumName(FOO_name, int32(x)) -} -func (x *FOO) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO") - if err != nil { - return err - } - *x = FOO(value) - return nil -} -func (FOO) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -// An enum, for completeness. -type GoTest_KIND int32 - -const ( - GoTest_VOID GoTest_KIND = 0 - // Basic types - GoTest_BOOL GoTest_KIND = 1 - GoTest_BYTES GoTest_KIND = 2 - GoTest_FINGERPRINT GoTest_KIND = 3 - GoTest_FLOAT GoTest_KIND = 4 - GoTest_INT GoTest_KIND = 5 - GoTest_STRING GoTest_KIND = 6 - GoTest_TIME GoTest_KIND = 7 - // Groupings - GoTest_TUPLE GoTest_KIND = 8 - GoTest_ARRAY GoTest_KIND = 9 - GoTest_MAP GoTest_KIND = 10 - // Table types - GoTest_TABLE GoTest_KIND = 11 - // Functions - GoTest_FUNCTION GoTest_KIND = 12 -) - -var GoTest_KIND_name = map[int32]string{ - 0: "VOID", - 1: "BOOL", - 2: "BYTES", - 3: "FINGERPRINT", - 4: "FLOAT", - 5: "INT", - 6: "STRING", - 7: "TIME", - 8: "TUPLE", - 9: "ARRAY", - 10: "MAP", - 11: "TABLE", - 12: "FUNCTION", -} -var GoTest_KIND_value = map[string]int32{ - "VOID": 0, - "BOOL": 1, - "BYTES": 2, - "FINGERPRINT": 3, - "FLOAT": 4, - "INT": 5, - "STRING": 6, - "TIME": 7, - "TUPLE": 8, - "ARRAY": 9, - "MAP": 10, - "TABLE": 11, - "FUNCTION": 12, -} - -func (x GoTest_KIND) Enum() *GoTest_KIND { - p := new(GoTest_KIND) - *p = x - return p -} -func (x GoTest_KIND) String() string { - return proto.EnumName(GoTest_KIND_name, int32(x)) -} -func (x *GoTest_KIND) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(GoTest_KIND_value, data, "GoTest_KIND") - if err != nil { - return err - } - *x = GoTest_KIND(value) - return nil -} -func (GoTest_KIND) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } - -type MyMessage_Color int32 - -const ( - MyMessage_RED MyMessage_Color = 0 - MyMessage_GREEN MyMessage_Color = 1 - MyMessage_BLUE MyMessage_Color = 2 -) - -var MyMessage_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var MyMessage_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x MyMessage_Color) Enum() *MyMessage_Color { - p := new(MyMessage_Color) - *p = x - return p -} -func (x MyMessage_Color) String() string { - return proto.EnumName(MyMessage_Color_name, int32(x)) -} -func (x *MyMessage_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MyMessage_Color_value, data, "MyMessage_Color") - if err != nil { - return err - } - *x = MyMessage_Color(value) - return nil -} -func (MyMessage_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{11, 0} } - -type DefaultsMessage_DefaultsEnum int32 - -const ( - DefaultsMessage_ZERO DefaultsMessage_DefaultsEnum = 0 - DefaultsMessage_ONE DefaultsMessage_DefaultsEnum = 1 - DefaultsMessage_TWO DefaultsMessage_DefaultsEnum = 2 -) - -var DefaultsMessage_DefaultsEnum_name = map[int32]string{ - 0: "ZERO", - 1: "ONE", - 2: "TWO", -} -var DefaultsMessage_DefaultsEnum_value = map[string]int32{ - "ZERO": 0, - "ONE": 1, - "TWO": 2, -} - -func (x DefaultsMessage_DefaultsEnum) Enum() *DefaultsMessage_DefaultsEnum { - p := new(DefaultsMessage_DefaultsEnum) - *p = x - return p -} -func (x DefaultsMessage_DefaultsEnum) String() string { - return proto.EnumName(DefaultsMessage_DefaultsEnum_name, int32(x)) -} -func (x *DefaultsMessage_DefaultsEnum) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(DefaultsMessage_DefaultsEnum_value, data, "DefaultsMessage_DefaultsEnum") - if err != nil { - return err - } - *x = DefaultsMessage_DefaultsEnum(value) - return nil -} -func (DefaultsMessage_DefaultsEnum) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{14, 0} -} - -type Defaults_Color int32 - -const ( - Defaults_RED Defaults_Color = 0 - Defaults_GREEN Defaults_Color = 1 - Defaults_BLUE Defaults_Color = 2 -) - -var Defaults_Color_name = map[int32]string{ - 0: "RED", - 1: "GREEN", - 2: "BLUE", -} -var Defaults_Color_value = map[string]int32{ - "RED": 0, - "GREEN": 1, - "BLUE": 2, -} - -func (x Defaults_Color) Enum() *Defaults_Color { - p := new(Defaults_Color) - *p = x - return p -} -func (x Defaults_Color) String() string { - return proto.EnumName(Defaults_Color_name, int32(x)) -} -func (x *Defaults_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Defaults_Color_value, data, "Defaults_Color") - if err != nil { - return err - } - *x = Defaults_Color(value) - return nil -} -func (Defaults_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} } - -type RepeatedEnum_Color int32 - -const ( - RepeatedEnum_RED RepeatedEnum_Color = 1 -) - -var RepeatedEnum_Color_name = map[int32]string{ - 1: "RED", -} -var RepeatedEnum_Color_value = map[string]int32{ - "RED": 1, -} - -func (x RepeatedEnum_Color) Enum() *RepeatedEnum_Color { - p := new(RepeatedEnum_Color) - *p = x - return p -} -func (x RepeatedEnum_Color) String() string { - return proto.EnumName(RepeatedEnum_Color_name, int32(x)) -} -func (x *RepeatedEnum_Color) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RepeatedEnum_Color_value, data, "RepeatedEnum_Color") - if err != nil { - return err - } - *x = RepeatedEnum_Color(value) - return nil -} -func (RepeatedEnum_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{21, 0} } - -type GoEnum struct { - Foo *FOO `protobuf:"varint,1,req,name=foo,enum=testdata.FOO" json:"foo,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoEnum) Reset() { *m = GoEnum{} } -func (m *GoEnum) String() string { return proto.CompactTextString(m) } -func (*GoEnum) ProtoMessage() {} -func (*GoEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func (m *GoEnum) GetFoo() FOO { - if m != nil && m.Foo != nil { - return *m.Foo - } - return FOO_FOO1 -} - -type GoTestField struct { - Label *string `protobuf:"bytes,1,req,name=Label" json:"Label,omitempty"` - Type *string `protobuf:"bytes,2,req,name=Type" json:"Type,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTestField) Reset() { *m = GoTestField{} } -func (m *GoTestField) String() string { return proto.CompactTextString(m) } -func (*GoTestField) ProtoMessage() {} -func (*GoTestField) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -func (m *GoTestField) GetLabel() string { - if m != nil && m.Label != nil { - return *m.Label - } - return "" -} - -func (m *GoTestField) GetType() string { - if m != nil && m.Type != nil { - return *m.Type - } - return "" -} - -type GoTest struct { - // Some typical parameters - Kind *GoTest_KIND `protobuf:"varint,1,req,name=Kind,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` - Table *string `protobuf:"bytes,2,opt,name=Table" json:"Table,omitempty"` - Param *int32 `protobuf:"varint,3,opt,name=Param" json:"Param,omitempty"` - // Required, repeated and optional foreign fields. - RequiredField *GoTestField `protobuf:"bytes,4,req,name=RequiredField" json:"RequiredField,omitempty"` - RepeatedField []*GoTestField `protobuf:"bytes,5,rep,name=RepeatedField" json:"RepeatedField,omitempty"` - OptionalField *GoTestField `protobuf:"bytes,6,opt,name=OptionalField" json:"OptionalField,omitempty"` - // Required fields of all basic types - F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required" json:"F_Bool_required,omitempty"` - F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required" json:"F_Int32_required,omitempty"` - F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required" json:"F_Int64_required,omitempty"` - F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required" json:"F_Fixed32_required,omitempty"` - F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required" json:"F_Fixed64_required,omitempty"` - F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required" json:"F_Uint32_required,omitempty"` - F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required" json:"F_Uint64_required,omitempty"` - F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required" json:"F_Float_required,omitempty"` - F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required" json:"F_Double_required,omitempty"` - F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required" json:"F_String_required,omitempty"` - F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required" json:"F_Bytes_required,omitempty"` - F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required" json:"F_Sint32_required,omitempty"` - F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required" json:"F_Sint64_required,omitempty"` - // Repeated fields of all basic types - F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated" json:"F_Bool_repeated,omitempty"` - F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated" json:"F_Int32_repeated,omitempty"` - F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated" json:"F_Int64_repeated,omitempty"` - F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated" json:"F_Fixed32_repeated,omitempty"` - F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated" json:"F_Fixed64_repeated,omitempty"` - F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated" json:"F_Uint32_repeated,omitempty"` - F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated" json:"F_Uint64_repeated,omitempty"` - F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated" json:"F_Float_repeated,omitempty"` - F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated" json:"F_Double_repeated,omitempty"` - F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated" json:"F_String_repeated,omitempty"` - F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated" json:"F_Bytes_repeated,omitempty"` - F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated" json:"F_Sint32_repeated,omitempty"` - F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated" json:"F_Sint64_repeated,omitempty"` - // Optional fields of all basic types - F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional" json:"F_Bool_optional,omitempty"` - F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional" json:"F_Int32_optional,omitempty"` - F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional" json:"F_Int64_optional,omitempty"` - F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional" json:"F_Fixed32_optional,omitempty"` - F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional" json:"F_Fixed64_optional,omitempty"` - F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional" json:"F_Uint32_optional,omitempty"` - F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional" json:"F_Uint64_optional,omitempty"` - F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional" json:"F_Float_optional,omitempty"` - F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional" json:"F_Double_optional,omitempty"` - F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional" json:"F_String_optional,omitempty"` - F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional" json:"F_Bytes_optional,omitempty"` - F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional" json:"F_Sint32_optional,omitempty"` - F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional" json:"F_Sint64_optional,omitempty"` - // Default-valued fields of all basic types - F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,def=1" json:"F_Bool_defaulted,omitempty"` - F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,def=32" json:"F_Int32_defaulted,omitempty"` - F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,def=64" json:"F_Int64_defaulted,omitempty"` - F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,def=320" json:"F_Fixed32_defaulted,omitempty"` - F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,def=640" json:"F_Fixed64_defaulted,omitempty"` - F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,def=3200" json:"F_Uint32_defaulted,omitempty"` - F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,def=6400" json:"F_Uint64_defaulted,omitempty"` - F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,def=314159" json:"F_Float_defaulted,omitempty"` - F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,def=271828" json:"F_Double_defaulted,omitempty"` - F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,def=hello, \"world!\"\n" json:"F_String_defaulted,omitempty"` - F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,def=Bignose" json:"F_Bytes_defaulted,omitempty"` - F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,def=-32" json:"F_Sint32_defaulted,omitempty"` - F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,def=-64" json:"F_Sint64_defaulted,omitempty"` - // Packed repeated fields (no string or bytes). - F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed" json:"F_Bool_repeated_packed,omitempty"` - F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed" json:"F_Int32_repeated_packed,omitempty"` - F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed" json:"F_Int64_repeated_packed,omitempty"` - F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed" json:"F_Fixed32_repeated_packed,omitempty"` - F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed" json:"F_Fixed64_repeated_packed,omitempty"` - F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed" json:"F_Uint32_repeated_packed,omitempty"` - F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed" json:"F_Uint64_repeated_packed,omitempty"` - F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed" json:"F_Float_repeated_packed,omitempty"` - F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed" json:"F_Double_repeated_packed,omitempty"` - F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed" json:"F_Sint32_repeated_packed,omitempty"` - F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed" json:"F_Sint64_repeated_packed,omitempty"` - Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup" json:"requiredgroup,omitempty"` - Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup" json:"repeatedgroup,omitempty"` - Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest) Reset() { *m = GoTest{} } -func (m *GoTest) String() string { return proto.CompactTextString(m) } -func (*GoTest) ProtoMessage() {} -func (*GoTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -const Default_GoTest_F_BoolDefaulted bool = true -const Default_GoTest_F_Int32Defaulted int32 = 32 -const Default_GoTest_F_Int64Defaulted int64 = 64 -const Default_GoTest_F_Fixed32Defaulted uint32 = 320 -const Default_GoTest_F_Fixed64Defaulted uint64 = 640 -const Default_GoTest_F_Uint32Defaulted uint32 = 3200 -const Default_GoTest_F_Uint64Defaulted uint64 = 6400 -const Default_GoTest_F_FloatDefaulted float32 = 314159 -const Default_GoTest_F_DoubleDefaulted float64 = 271828 -const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n" - -var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose") - -const Default_GoTest_F_Sint32Defaulted int32 = -32 -const Default_GoTest_F_Sint64Defaulted int64 = -64 - -func (m *GoTest) GetKind() GoTest_KIND { - if m != nil && m.Kind != nil { - return *m.Kind - } - return GoTest_VOID -} - -func (m *GoTest) GetTable() string { - if m != nil && m.Table != nil { - return *m.Table - } - return "" -} - -func (m *GoTest) GetParam() int32 { - if m != nil && m.Param != nil { - return *m.Param - } - return 0 -} - -func (m *GoTest) GetRequiredField() *GoTestField { - if m != nil { - return m.RequiredField - } - return nil -} - -func (m *GoTest) GetRepeatedField() []*GoTestField { - if m != nil { - return m.RepeatedField - } - return nil -} - -func (m *GoTest) GetOptionalField() *GoTestField { - if m != nil { - return m.OptionalField - } - return nil -} - -func (m *GoTest) GetF_BoolRequired() bool { - if m != nil && m.F_BoolRequired != nil { - return *m.F_BoolRequired - } - return false -} - -func (m *GoTest) GetF_Int32Required() int32 { - if m != nil && m.F_Int32Required != nil { - return *m.F_Int32Required - } - return 0 -} - -func (m *GoTest) GetF_Int64Required() int64 { - if m != nil && m.F_Int64Required != nil { - return *m.F_Int64Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Required() uint32 { - if m != nil && m.F_Fixed32Required != nil { - return *m.F_Fixed32Required - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Required() uint64 { - if m != nil && m.F_Fixed64Required != nil { - return *m.F_Fixed64Required - } - return 0 -} - -func (m *GoTest) GetF_Uint32Required() uint32 { - if m != nil && m.F_Uint32Required != nil { - return *m.F_Uint32Required - } - return 0 -} - -func (m *GoTest) GetF_Uint64Required() uint64 { - if m != nil && m.F_Uint64Required != nil { - return *m.F_Uint64Required - } - return 0 -} - -func (m *GoTest) GetF_FloatRequired() float32 { - if m != nil && m.F_FloatRequired != nil { - return *m.F_FloatRequired - } - return 0 -} - -func (m *GoTest) GetF_DoubleRequired() float64 { - if m != nil && m.F_DoubleRequired != nil { - return *m.F_DoubleRequired - } - return 0 -} - -func (m *GoTest) GetF_StringRequired() string { - if m != nil && m.F_StringRequired != nil { - return *m.F_StringRequired - } - return "" -} - -func (m *GoTest) GetF_BytesRequired() []byte { - if m != nil { - return m.F_BytesRequired - } - return nil -} - -func (m *GoTest) GetF_Sint32Required() int32 { - if m != nil && m.F_Sint32Required != nil { - return *m.F_Sint32Required - } - return 0 -} - -func (m *GoTest) GetF_Sint64Required() int64 { - if m != nil && m.F_Sint64Required != nil { - return *m.F_Sint64Required - } - return 0 -} - -func (m *GoTest) GetF_BoolRepeated() []bool { - if m != nil { - return m.F_BoolRepeated - } - return nil -} - -func (m *GoTest) GetF_Int32Repeated() []int32 { - if m != nil { - return m.F_Int32Repeated - } - return nil -} - -func (m *GoTest) GetF_Int64Repeated() []int64 { - if m != nil { - return m.F_Int64Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed32Repeated() []uint32 { - if m != nil { - return m.F_Fixed32Repeated - } - return nil -} - -func (m *GoTest) GetF_Fixed64Repeated() []uint64 { - if m != nil { - return m.F_Fixed64Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint32Repeated() []uint32 { - if m != nil { - return m.F_Uint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Uint64Repeated() []uint64 { - if m != nil { - return m.F_Uint64Repeated - } - return nil -} - -func (m *GoTest) GetF_FloatRepeated() []float32 { - if m != nil { - return m.F_FloatRepeated - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeated() []float64 { - if m != nil { - return m.F_DoubleRepeated - } - return nil -} - -func (m *GoTest) GetF_StringRepeated() []string { - if m != nil { - return m.F_StringRepeated - } - return nil -} - -func (m *GoTest) GetF_BytesRepeated() [][]byte { - if m != nil { - return m.F_BytesRepeated - } - return nil -} - -func (m *GoTest) GetF_Sint32Repeated() []int32 { - if m != nil { - return m.F_Sint32Repeated - } - return nil -} - -func (m *GoTest) GetF_Sint64Repeated() []int64 { - if m != nil { - return m.F_Sint64Repeated - } - return nil -} - -func (m *GoTest) GetF_BoolOptional() bool { - if m != nil && m.F_BoolOptional != nil { - return *m.F_BoolOptional - } - return false -} - -func (m *GoTest) GetF_Int32Optional() int32 { - if m != nil && m.F_Int32Optional != nil { - return *m.F_Int32Optional - } - return 0 -} - -func (m *GoTest) GetF_Int64Optional() int64 { - if m != nil && m.F_Int64Optional != nil { - return *m.F_Int64Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed32Optional() uint32 { - if m != nil && m.F_Fixed32Optional != nil { - return *m.F_Fixed32Optional - } - return 0 -} - -func (m *GoTest) GetF_Fixed64Optional() uint64 { - if m != nil && m.F_Fixed64Optional != nil { - return *m.F_Fixed64Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint32Optional() uint32 { - if m != nil && m.F_Uint32Optional != nil { - return *m.F_Uint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Uint64Optional() uint64 { - if m != nil && m.F_Uint64Optional != nil { - return *m.F_Uint64Optional - } - return 0 -} - -func (m *GoTest) GetF_FloatOptional() float32 { - if m != nil && m.F_FloatOptional != nil { - return *m.F_FloatOptional - } - return 0 -} - -func (m *GoTest) GetF_DoubleOptional() float64 { - if m != nil && m.F_DoubleOptional != nil { - return *m.F_DoubleOptional - } - return 0 -} - -func (m *GoTest) GetF_StringOptional() string { - if m != nil && m.F_StringOptional != nil { - return *m.F_StringOptional - } - return "" -} - -func (m *GoTest) GetF_BytesOptional() []byte { - if m != nil { - return m.F_BytesOptional - } - return nil -} - -func (m *GoTest) GetF_Sint32Optional() int32 { - if m != nil && m.F_Sint32Optional != nil { - return *m.F_Sint32Optional - } - return 0 -} - -func (m *GoTest) GetF_Sint64Optional() int64 { - if m != nil && m.F_Sint64Optional != nil { - return *m.F_Sint64Optional - } - return 0 -} - -func (m *GoTest) GetF_BoolDefaulted() bool { - if m != nil && m.F_BoolDefaulted != nil { - return *m.F_BoolDefaulted - } - return Default_GoTest_F_BoolDefaulted -} - -func (m *GoTest) GetF_Int32Defaulted() int32 { - if m != nil && m.F_Int32Defaulted != nil { - return *m.F_Int32Defaulted - } - return Default_GoTest_F_Int32Defaulted -} - -func (m *GoTest) GetF_Int64Defaulted() int64 { - if m != nil && m.F_Int64Defaulted != nil { - return *m.F_Int64Defaulted - } - return Default_GoTest_F_Int64Defaulted -} - -func (m *GoTest) GetF_Fixed32Defaulted() uint32 { - if m != nil && m.F_Fixed32Defaulted != nil { - return *m.F_Fixed32Defaulted - } - return Default_GoTest_F_Fixed32Defaulted -} - -func (m *GoTest) GetF_Fixed64Defaulted() uint64 { - if m != nil && m.F_Fixed64Defaulted != nil { - return *m.F_Fixed64Defaulted - } - return Default_GoTest_F_Fixed64Defaulted -} - -func (m *GoTest) GetF_Uint32Defaulted() uint32 { - if m != nil && m.F_Uint32Defaulted != nil { - return *m.F_Uint32Defaulted - } - return Default_GoTest_F_Uint32Defaulted -} - -func (m *GoTest) GetF_Uint64Defaulted() uint64 { - if m != nil && m.F_Uint64Defaulted != nil { - return *m.F_Uint64Defaulted - } - return Default_GoTest_F_Uint64Defaulted -} - -func (m *GoTest) GetF_FloatDefaulted() float32 { - if m != nil && m.F_FloatDefaulted != nil { - return *m.F_FloatDefaulted - } - return Default_GoTest_F_FloatDefaulted -} - -func (m *GoTest) GetF_DoubleDefaulted() float64 { - if m != nil && m.F_DoubleDefaulted != nil { - return *m.F_DoubleDefaulted - } - return Default_GoTest_F_DoubleDefaulted -} - -func (m *GoTest) GetF_StringDefaulted() string { - if m != nil && m.F_StringDefaulted != nil { - return *m.F_StringDefaulted - } - return Default_GoTest_F_StringDefaulted -} - -func (m *GoTest) GetF_BytesDefaulted() []byte { - if m != nil && m.F_BytesDefaulted != nil { - return m.F_BytesDefaulted - } - return append([]byte(nil), Default_GoTest_F_BytesDefaulted...) -} - -func (m *GoTest) GetF_Sint32Defaulted() int32 { - if m != nil && m.F_Sint32Defaulted != nil { - return *m.F_Sint32Defaulted - } - return Default_GoTest_F_Sint32Defaulted -} - -func (m *GoTest) GetF_Sint64Defaulted() int64 { - if m != nil && m.F_Sint64Defaulted != nil { - return *m.F_Sint64Defaulted - } - return Default_GoTest_F_Sint64Defaulted -} - -func (m *GoTest) GetF_BoolRepeatedPacked() []bool { - if m != nil { - return m.F_BoolRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int32RepeatedPacked() []int32 { - if m != nil { - return m.F_Int32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Int64RepeatedPacked() []int64 { - if m != nil { - return m.F_Int64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Fixed32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Fixed64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Fixed64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint32RepeatedPacked() []uint32 { - if m != nil { - return m.F_Uint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Uint64RepeatedPacked() []uint64 { - if m != nil { - return m.F_Uint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_FloatRepeatedPacked() []float32 { - if m != nil { - return m.F_FloatRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_DoubleRepeatedPacked() []float64 { - if m != nil { - return m.F_DoubleRepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint32RepeatedPacked() []int32 { - if m != nil { - return m.F_Sint32RepeatedPacked - } - return nil -} - -func (m *GoTest) GetF_Sint64RepeatedPacked() []int64 { - if m != nil { - return m.F_Sint64RepeatedPacked - } - return nil -} - -func (m *GoTest) GetRequiredgroup() *GoTest_RequiredGroup { - if m != nil { - return m.Requiredgroup - } - return nil -} - -func (m *GoTest) GetRepeatedgroup() []*GoTest_RepeatedGroup { - if m != nil { - return m.Repeatedgroup - } - return nil -} - -func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup { - if m != nil { - return m.Optionalgroup - } - return nil -} - -// Required, repeated, and optional groups. -type GoTest_RequiredGroup struct { - RequiredField *string `protobuf:"bytes,71,req,name=RequiredField" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RequiredGroup) Reset() { *m = GoTest_RequiredGroup{} } -func (m *GoTest_RequiredGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_RequiredGroup) ProtoMessage() {} - -func (m *GoTest_RequiredGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_RepeatedGroup struct { - RequiredField *string `protobuf:"bytes,81,req,name=RequiredField" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_RepeatedGroup) Reset() { *m = GoTest_RepeatedGroup{} } -func (m *GoTest_RepeatedGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_RepeatedGroup) ProtoMessage() {} - -func (m *GoTest_RepeatedGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -type GoTest_OptionalGroup struct { - RequiredField *string `protobuf:"bytes,91,req,name=RequiredField" json:"RequiredField,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoTest_OptionalGroup) Reset() { *m = GoTest_OptionalGroup{} } -func (m *GoTest_OptionalGroup) String() string { return proto.CompactTextString(m) } -func (*GoTest_OptionalGroup) ProtoMessage() {} - -func (m *GoTest_OptionalGroup) GetRequiredField() string { - if m != nil && m.RequiredField != nil { - return *m.RequiredField - } - return "" -} - -// For testing skipping of unrecognized fields. -// Numbers are all big, larger than tag numbers in GoTestField, -// the message used in the corresponding test. -type GoSkipTest struct { - SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32" json:"skip_int32,omitempty"` - SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32" json:"skip_fixed32,omitempty"` - SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64" json:"skip_fixed64,omitempty"` - SkipString *string `protobuf:"bytes,14,req,name=skip_string" json:"skip_string,omitempty"` - Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup" json:"skipgroup,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest) Reset() { *m = GoSkipTest{} } -func (m *GoSkipTest) String() string { return proto.CompactTextString(m) } -func (*GoSkipTest) ProtoMessage() {} -func (*GoSkipTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -func (m *GoSkipTest) GetSkipInt32() int32 { - if m != nil && m.SkipInt32 != nil { - return *m.SkipInt32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed32() uint32 { - if m != nil && m.SkipFixed32 != nil { - return *m.SkipFixed32 - } - return 0 -} - -func (m *GoSkipTest) GetSkipFixed64() uint64 { - if m != nil && m.SkipFixed64 != nil { - return *m.SkipFixed64 - } - return 0 -} - -func (m *GoSkipTest) GetSkipString() string { - if m != nil && m.SkipString != nil { - return *m.SkipString - } - return "" -} - -func (m *GoSkipTest) GetSkipgroup() *GoSkipTest_SkipGroup { - if m != nil { - return m.Skipgroup - } - return nil -} - -type GoSkipTest_SkipGroup struct { - GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32" json:"group_int32,omitempty"` - GroupString *string `protobuf:"bytes,17,req,name=group_string" json:"group_string,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GoSkipTest_SkipGroup) Reset() { *m = GoSkipTest_SkipGroup{} } -func (m *GoSkipTest_SkipGroup) String() string { return proto.CompactTextString(m) } -func (*GoSkipTest_SkipGroup) ProtoMessage() {} - -func (m *GoSkipTest_SkipGroup) GetGroupInt32() int32 { - if m != nil && m.GroupInt32 != nil { - return *m.GroupInt32 - } - return 0 -} - -func (m *GoSkipTest_SkipGroup) GetGroupString() string { - if m != nil && m.GroupString != nil { - return *m.GroupString - } - return "" -} - -// For testing packed/non-packed decoder switching. -// A serialized instance of one should be deserializable as the other. -type NonPackedTest struct { - A []int32 `protobuf:"varint,1,rep,name=a" json:"a,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NonPackedTest) Reset() { *m = NonPackedTest{} } -func (m *NonPackedTest) String() string { return proto.CompactTextString(m) } -func (*NonPackedTest) ProtoMessage() {} -func (*NonPackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } - -func (m *NonPackedTest) GetA() []int32 { - if m != nil { - return m.A - } - return nil -} - -type PackedTest struct { - B []int32 `protobuf:"varint,1,rep,packed,name=b" json:"b,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PackedTest) Reset() { *m = PackedTest{} } -func (m *PackedTest) String() string { return proto.CompactTextString(m) } -func (*PackedTest) ProtoMessage() {} -func (*PackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } - -func (m *PackedTest) GetB() []int32 { - if m != nil { - return m.B - } - return nil -} - -type MaxTag struct { - // Maximum possible tag number. - LastField *string `protobuf:"bytes,536870911,opt,name=last_field" json:"last_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MaxTag) Reset() { *m = MaxTag{} } -func (m *MaxTag) String() string { return proto.CompactTextString(m) } -func (*MaxTag) ProtoMessage() {} -func (*MaxTag) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } - -func (m *MaxTag) GetLastField() string { - if m != nil && m.LastField != nil { - return *m.LastField - } - return "" -} - -type OldMessage struct { - Nested *OldMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - Num *int32 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage) Reset() { *m = OldMessage{} } -func (m *OldMessage) String() string { return proto.CompactTextString(m) } -func (*OldMessage) ProtoMessage() {} -func (*OldMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } - -func (m *OldMessage) GetNested() *OldMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *OldMessage) GetNum() int32 { - if m != nil && m.Num != nil { - return *m.Num - } - return 0 -} - -type OldMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OldMessage_Nested) Reset() { *m = OldMessage_Nested{} } -func (m *OldMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*OldMessage_Nested) ProtoMessage() {} -func (*OldMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7, 0} } - -func (m *OldMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// NewMessage is wire compatible with OldMessage; -// imagine it as a future version. -type NewMessage struct { - Nested *NewMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` - // This is an int32 in OldMessage. - Num *int64 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage) Reset() { *m = NewMessage{} } -func (m *NewMessage) String() string { return proto.CompactTextString(m) } -func (*NewMessage) ProtoMessage() {} -func (*NewMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } - -func (m *NewMessage) GetNested() *NewMessage_Nested { - if m != nil { - return m.Nested - } - return nil -} - -func (m *NewMessage) GetNum() int64 { - if m != nil && m.Num != nil { - return *m.Num - } - return 0 -} - -type NewMessage_Nested struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - FoodGroup *string `protobuf:"bytes,2,opt,name=food_group" json:"food_group,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *NewMessage_Nested) Reset() { *m = NewMessage_Nested{} } -func (m *NewMessage_Nested) String() string { return proto.CompactTextString(m) } -func (*NewMessage_Nested) ProtoMessage() {} -func (*NewMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8, 0} } - -func (m *NewMessage_Nested) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *NewMessage_Nested) GetFoodGroup() string { - if m != nil && m.FoodGroup != nil { - return *m.FoodGroup - } - return "" -} - -type InnerMessage struct { - Host *string `protobuf:"bytes,1,req,name=host" json:"host,omitempty"` - Port *int32 `protobuf:"varint,2,opt,name=port,def=4000" json:"port,omitempty"` - Connected *bool `protobuf:"varint,3,opt,name=connected" json:"connected,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *InnerMessage) Reset() { *m = InnerMessage{} } -func (m *InnerMessage) String() string { return proto.CompactTextString(m) } -func (*InnerMessage) ProtoMessage() {} -func (*InnerMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } - -const Default_InnerMessage_Port int32 = 4000 - -func (m *InnerMessage) GetHost() string { - if m != nil && m.Host != nil { - return *m.Host - } - return "" -} - -func (m *InnerMessage) GetPort() int32 { - if m != nil && m.Port != nil { - return *m.Port - } - return Default_InnerMessage_Port -} - -func (m *InnerMessage) GetConnected() bool { - if m != nil && m.Connected != nil { - return *m.Connected - } - return false -} - -type OtherMessage struct { - Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` - Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"` - Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *OtherMessage) Reset() { *m = OtherMessage{} } -func (m *OtherMessage) String() string { return proto.CompactTextString(m) } -func (*OtherMessage) ProtoMessage() {} -func (*OtherMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } - -var extRange_OtherMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*OtherMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_OtherMessage -} -func (m *OtherMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -func (m *OtherMessage) GetKey() int64 { - if m != nil && m.Key != nil { - return *m.Key - } - return 0 -} - -func (m *OtherMessage) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -func (m *OtherMessage) GetWeight() float32 { - if m != nil && m.Weight != nil { - return *m.Weight - } - return 0 -} - -func (m *OtherMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -type MyMessage struct { - Count *int32 `protobuf:"varint,1,req,name=count" json:"count,omitempty"` - Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` - Quote *string `protobuf:"bytes,3,opt,name=quote" json:"quote,omitempty"` - Pet []string `protobuf:"bytes,4,rep,name=pet" json:"pet,omitempty"` - Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner" json:"inner,omitempty"` - Others []*OtherMessage `protobuf:"bytes,6,rep,name=others" json:"others,omitempty"` - RepInner []*InnerMessage `protobuf:"bytes,12,rep,name=rep_inner" json:"rep_inner,omitempty"` - Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"` - Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup" json:"somegroup,omitempty"` - // This field becomes [][]byte in the generated code. - RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes" json:"rep_bytes,omitempty"` - Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"` - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage) Reset() { *m = MyMessage{} } -func (m *MyMessage) String() string { return proto.CompactTextString(m) } -func (*MyMessage) ProtoMessage() {} -func (*MyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } - -var extRange_MyMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_MyMessage -} -func (m *MyMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -func (m *MyMessage) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *MyMessage) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MyMessage) GetQuote() string { - if m != nil && m.Quote != nil { - return *m.Quote - } - return "" -} - -func (m *MyMessage) GetPet() []string { - if m != nil { - return m.Pet - } - return nil -} - -func (m *MyMessage) GetInner() *InnerMessage { - if m != nil { - return m.Inner - } - return nil -} - -func (m *MyMessage) GetOthers() []*OtherMessage { - if m != nil { - return m.Others - } - return nil -} - -func (m *MyMessage) GetRepInner() []*InnerMessage { - if m != nil { - return m.RepInner - } - return nil -} - -func (m *MyMessage) GetBikeshed() MyMessage_Color { - if m != nil && m.Bikeshed != nil { - return *m.Bikeshed - } - return MyMessage_RED -} - -func (m *MyMessage) GetSomegroup() *MyMessage_SomeGroup { - if m != nil { - return m.Somegroup - } - return nil -} - -func (m *MyMessage) GetRepBytes() [][]byte { - if m != nil { - return m.RepBytes - } - return nil -} - -func (m *MyMessage) GetBigfloat() float64 { - if m != nil && m.Bigfloat != nil { - return *m.Bigfloat - } - return 0 -} - -type MyMessage_SomeGroup struct { - GroupField *int32 `protobuf:"varint,9,opt,name=group_field" json:"group_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessage_SomeGroup) Reset() { *m = MyMessage_SomeGroup{} } -func (m *MyMessage_SomeGroup) String() string { return proto.CompactTextString(m) } -func (*MyMessage_SomeGroup) ProtoMessage() {} - -func (m *MyMessage_SomeGroup) GetGroupField() int32 { - if m != nil && m.GroupField != nil { - return *m.GroupField - } - return 0 -} - -type Ext struct { - Data *string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Ext) Reset() { *m = Ext{} } -func (m *Ext) String() string { return proto.CompactTextString(m) } -func (*Ext) ProtoMessage() {} -func (*Ext) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } - -func (m *Ext) GetData() string { - if m != nil && m.Data != nil { - return *m.Data - } - return "" -} - -var E_Ext_More = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*Ext)(nil), - Field: 103, - Name: "testdata.Ext.more", - Tag: "bytes,103,opt,name=more", -} - -var E_Ext_Text = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*string)(nil), - Field: 104, - Name: "testdata.Ext.text", - Tag: "bytes,104,opt,name=text", -} - -var E_Ext_Number = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 105, - Name: "testdata.Ext.number", - Tag: "varint,105,opt,name=number", -} - -type ComplexExtension struct { - First *int32 `protobuf:"varint,1,opt,name=first" json:"first,omitempty"` - Second *int32 `protobuf:"varint,2,opt,name=second" json:"second,omitempty"` - Third []int32 `protobuf:"varint,3,rep,name=third" json:"third,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ComplexExtension) Reset() { *m = ComplexExtension{} } -func (m *ComplexExtension) String() string { return proto.CompactTextString(m) } -func (*ComplexExtension) ProtoMessage() {} -func (*ComplexExtension) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } - -func (m *ComplexExtension) GetFirst() int32 { - if m != nil && m.First != nil { - return *m.First - } - return 0 -} - -func (m *ComplexExtension) GetSecond() int32 { - if m != nil && m.Second != nil { - return *m.Second - } - return 0 -} - -func (m *ComplexExtension) GetThird() []int32 { - if m != nil { - return m.Third - } - return nil -} - -type DefaultsMessage struct { - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *DefaultsMessage) Reset() { *m = DefaultsMessage{} } -func (m *DefaultsMessage) String() string { return proto.CompactTextString(m) } -func (*DefaultsMessage) ProtoMessage() {} -func (*DefaultsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } - -var extRange_DefaultsMessage = []proto.ExtensionRange{ - {100, 536870911}, -} - -func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_DefaultsMessage -} -func (m *DefaultsMessage) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -type MyMessageSet struct { - XXX_extensions map[int32]proto.Extension `json:"-"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MyMessageSet) Reset() { *m = MyMessageSet{} } -func (m *MyMessageSet) String() string { return proto.CompactTextString(m) } -func (*MyMessageSet) ProtoMessage() {} -func (*MyMessageSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } - -func (m *MyMessageSet) Marshal() ([]byte, error) { - return proto.MarshalMessageSet(m.ExtensionMap()) -} -func (m *MyMessageSet) Unmarshal(buf []byte) error { - return proto.UnmarshalMessageSet(buf, m.ExtensionMap()) -} -func (m *MyMessageSet) MarshalJSON() ([]byte, error) { - return proto.MarshalMessageSetJSON(m.XXX_extensions) -} -func (m *MyMessageSet) UnmarshalJSON(buf []byte) error { - return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions) -} - -// ensure MyMessageSet satisfies proto.Marshaler and proto.Unmarshaler -var _ proto.Marshaler = (*MyMessageSet)(nil) -var _ proto.Unmarshaler = (*MyMessageSet)(nil) - -var extRange_MyMessageSet = []proto.ExtensionRange{ - {100, 2147483646}, -} - -func (*MyMessageSet) ExtensionRangeArray() []proto.ExtensionRange { - return extRange_MyMessageSet -} -func (m *MyMessageSet) ExtensionMap() map[int32]proto.Extension { - if m.XXX_extensions == nil { - m.XXX_extensions = make(map[int32]proto.Extension) - } - return m.XXX_extensions -} - -type Empty struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *Empty) Reset() { *m = Empty{} } -func (m *Empty) String() string { return proto.CompactTextString(m) } -func (*Empty) ProtoMessage() {} -func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } - -type MessageList struct { - Message []*MessageList_Message `protobuf:"group,1,rep,name=Message" json:"message,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList) Reset() { *m = MessageList{} } -func (m *MessageList) String() string { return proto.CompactTextString(m) } -func (*MessageList) ProtoMessage() {} -func (*MessageList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } - -func (m *MessageList) GetMessage() []*MessageList_Message { - if m != nil { - return m.Message - } - return nil -} - -type MessageList_Message struct { - Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` - Count *int32 `protobuf:"varint,3,req,name=count" json:"count,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageList_Message) Reset() { *m = MessageList_Message{} } -func (m *MessageList_Message) String() string { return proto.CompactTextString(m) } -func (*MessageList_Message) ProtoMessage() {} - -func (m *MessageList_Message) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *MessageList_Message) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -type Strings struct { - StringField *string `protobuf:"bytes,1,opt,name=string_field" json:"string_field,omitempty"` - BytesField []byte `protobuf:"bytes,2,opt,name=bytes_field" json:"bytes_field,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Strings) Reset() { *m = Strings{} } -func (m *Strings) String() string { return proto.CompactTextString(m) } -func (*Strings) ProtoMessage() {} -func (*Strings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } - -func (m *Strings) GetStringField() string { - if m != nil && m.StringField != nil { - return *m.StringField - } - return "" -} - -func (m *Strings) GetBytesField() []byte { - if m != nil { - return m.BytesField - } - return nil -} - -type Defaults struct { - // Default-valued fields of all basic types. - // Same as GoTest, but copied here to make testing easier. - F_Bool *bool `protobuf:"varint,1,opt,name=F_Bool,def=1" json:"F_Bool,omitempty"` - F_Int32 *int32 `protobuf:"varint,2,opt,name=F_Int32,def=32" json:"F_Int32,omitempty"` - F_Int64 *int64 `protobuf:"varint,3,opt,name=F_Int64,def=64" json:"F_Int64,omitempty"` - F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,def=320" json:"F_Fixed32,omitempty"` - F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,def=640" json:"F_Fixed64,omitempty"` - F_Uint32 *uint32 `protobuf:"varint,6,opt,name=F_Uint32,def=3200" json:"F_Uint32,omitempty"` - F_Uint64 *uint64 `protobuf:"varint,7,opt,name=F_Uint64,def=6400" json:"F_Uint64,omitempty"` - F_Float *float32 `protobuf:"fixed32,8,opt,name=F_Float,def=314159" json:"F_Float,omitempty"` - F_Double *float64 `protobuf:"fixed64,9,opt,name=F_Double,def=271828" json:"F_Double,omitempty"` - F_String *string `protobuf:"bytes,10,opt,name=F_String,def=hello, \"world!\"\n" json:"F_String,omitempty"` - F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,def=Bignose" json:"F_Bytes,omitempty"` - F_Sint32 *int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,def=-32" json:"F_Sint32,omitempty"` - F_Sint64 *int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,def=-64" json:"F_Sint64,omitempty"` - F_Enum *Defaults_Color `protobuf:"varint,14,opt,name=F_Enum,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` - // More fields with crazy defaults. - F_Pinf *float32 `protobuf:"fixed32,15,opt,name=F_Pinf,def=inf" json:"F_Pinf,omitempty"` - F_Ninf *float32 `protobuf:"fixed32,16,opt,name=F_Ninf,def=-inf" json:"F_Ninf,omitempty"` - F_Nan *float32 `protobuf:"fixed32,17,opt,name=F_Nan,def=nan" json:"F_Nan,omitempty"` - // Sub-message. - Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"` - // Redundant but explicit defaults. - StrZero *string `protobuf:"bytes,19,opt,name=str_zero,def=" json:"str_zero,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Defaults) Reset() { *m = Defaults{} } -func (m *Defaults) String() string { return proto.CompactTextString(m) } -func (*Defaults) ProtoMessage() {} -func (*Defaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } - -const Default_Defaults_F_Bool bool = true -const Default_Defaults_F_Int32 int32 = 32 -const Default_Defaults_F_Int64 int64 = 64 -const Default_Defaults_F_Fixed32 uint32 = 320 -const Default_Defaults_F_Fixed64 uint64 = 640 -const Default_Defaults_F_Uint32 uint32 = 3200 -const Default_Defaults_F_Uint64 uint64 = 6400 -const Default_Defaults_F_Float float32 = 314159 -const Default_Defaults_F_Double float64 = 271828 -const Default_Defaults_F_String string = "hello, \"world!\"\n" - -var Default_Defaults_F_Bytes []byte = []byte("Bignose") - -const Default_Defaults_F_Sint32 int32 = -32 -const Default_Defaults_F_Sint64 int64 = -64 -const Default_Defaults_F_Enum Defaults_Color = Defaults_GREEN - -var Default_Defaults_F_Pinf float32 = float32(math.Inf(1)) -var Default_Defaults_F_Ninf float32 = float32(math.Inf(-1)) -var Default_Defaults_F_Nan float32 = float32(math.NaN()) - -func (m *Defaults) GetF_Bool() bool { - if m != nil && m.F_Bool != nil { - return *m.F_Bool - } - return Default_Defaults_F_Bool -} - -func (m *Defaults) GetF_Int32() int32 { - if m != nil && m.F_Int32 != nil { - return *m.F_Int32 - } - return Default_Defaults_F_Int32 -} - -func (m *Defaults) GetF_Int64() int64 { - if m != nil && m.F_Int64 != nil { - return *m.F_Int64 - } - return Default_Defaults_F_Int64 -} - -func (m *Defaults) GetF_Fixed32() uint32 { - if m != nil && m.F_Fixed32 != nil { - return *m.F_Fixed32 - } - return Default_Defaults_F_Fixed32 -} - -func (m *Defaults) GetF_Fixed64() uint64 { - if m != nil && m.F_Fixed64 != nil { - return *m.F_Fixed64 - } - return Default_Defaults_F_Fixed64 -} - -func (m *Defaults) GetF_Uint32() uint32 { - if m != nil && m.F_Uint32 != nil { - return *m.F_Uint32 - } - return Default_Defaults_F_Uint32 -} - -func (m *Defaults) GetF_Uint64() uint64 { - if m != nil && m.F_Uint64 != nil { - return *m.F_Uint64 - } - return Default_Defaults_F_Uint64 -} - -func (m *Defaults) GetF_Float() float32 { - if m != nil && m.F_Float != nil { - return *m.F_Float - } - return Default_Defaults_F_Float -} - -func (m *Defaults) GetF_Double() float64 { - if m != nil && m.F_Double != nil { - return *m.F_Double - } - return Default_Defaults_F_Double -} - -func (m *Defaults) GetF_String() string { - if m != nil && m.F_String != nil { - return *m.F_String - } - return Default_Defaults_F_String -} - -func (m *Defaults) GetF_Bytes() []byte { - if m != nil && m.F_Bytes != nil { - return m.F_Bytes - } - return append([]byte(nil), Default_Defaults_F_Bytes...) -} - -func (m *Defaults) GetF_Sint32() int32 { - if m != nil && m.F_Sint32 != nil { - return *m.F_Sint32 - } - return Default_Defaults_F_Sint32 -} - -func (m *Defaults) GetF_Sint64() int64 { - if m != nil && m.F_Sint64 != nil { - return *m.F_Sint64 - } - return Default_Defaults_F_Sint64 -} - -func (m *Defaults) GetF_Enum() Defaults_Color { - if m != nil && m.F_Enum != nil { - return *m.F_Enum - } - return Default_Defaults_F_Enum -} - -func (m *Defaults) GetF_Pinf() float32 { - if m != nil && m.F_Pinf != nil { - return *m.F_Pinf - } - return Default_Defaults_F_Pinf -} - -func (m *Defaults) GetF_Ninf() float32 { - if m != nil && m.F_Ninf != nil { - return *m.F_Ninf - } - return Default_Defaults_F_Ninf -} - -func (m *Defaults) GetF_Nan() float32 { - if m != nil && m.F_Nan != nil { - return *m.F_Nan - } - return Default_Defaults_F_Nan -} - -func (m *Defaults) GetSub() *SubDefaults { - if m != nil { - return m.Sub - } - return nil -} - -func (m *Defaults) GetStrZero() string { - if m != nil && m.StrZero != nil { - return *m.StrZero - } - return "" -} - -type SubDefaults struct { - N *int64 `protobuf:"varint,1,opt,name=n,def=7" json:"n,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *SubDefaults) Reset() { *m = SubDefaults{} } -func (m *SubDefaults) String() string { return proto.CompactTextString(m) } -func (*SubDefaults) ProtoMessage() {} -func (*SubDefaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } - -const Default_SubDefaults_N int64 = 7 - -func (m *SubDefaults) GetN() int64 { - if m != nil && m.N != nil { - return *m.N - } - return Default_SubDefaults_N -} - -type RepeatedEnum struct { - Color []RepeatedEnum_Color `protobuf:"varint,1,rep,name=color,enum=testdata.RepeatedEnum_Color" json:"color,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RepeatedEnum) Reset() { *m = RepeatedEnum{} } -func (m *RepeatedEnum) String() string { return proto.CompactTextString(m) } -func (*RepeatedEnum) ProtoMessage() {} -func (*RepeatedEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } - -func (m *RepeatedEnum) GetColor() []RepeatedEnum_Color { - if m != nil { - return m.Color - } - return nil -} - -type MoreRepeated struct { - Bools []bool `protobuf:"varint,1,rep,name=bools" json:"bools,omitempty"` - BoolsPacked []bool `protobuf:"varint,2,rep,packed,name=bools_packed" json:"bools_packed,omitempty"` - Ints []int32 `protobuf:"varint,3,rep,name=ints" json:"ints,omitempty"` - IntsPacked []int32 `protobuf:"varint,4,rep,packed,name=ints_packed" json:"ints_packed,omitempty"` - Int64SPacked []int64 `protobuf:"varint,7,rep,packed,name=int64s_packed" json:"int64s_packed,omitempty"` - Strings []string `protobuf:"bytes,5,rep,name=strings" json:"strings,omitempty"` - Fixeds []uint32 `protobuf:"fixed32,6,rep,name=fixeds" json:"fixeds,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MoreRepeated) Reset() { *m = MoreRepeated{} } -func (m *MoreRepeated) String() string { return proto.CompactTextString(m) } -func (*MoreRepeated) ProtoMessage() {} -func (*MoreRepeated) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } - -func (m *MoreRepeated) GetBools() []bool { - if m != nil { - return m.Bools - } - return nil -} - -func (m *MoreRepeated) GetBoolsPacked() []bool { - if m != nil { - return m.BoolsPacked - } - return nil -} - -func (m *MoreRepeated) GetInts() []int32 { - if m != nil { - return m.Ints - } - return nil -} - -func (m *MoreRepeated) GetIntsPacked() []int32 { - if m != nil { - return m.IntsPacked - } - return nil -} - -func (m *MoreRepeated) GetInt64SPacked() []int64 { - if m != nil { - return m.Int64SPacked - } - return nil -} - -func (m *MoreRepeated) GetStrings() []string { - if m != nil { - return m.Strings - } - return nil -} - -func (m *MoreRepeated) GetFixeds() []uint32 { - if m != nil { - return m.Fixeds - } - return nil -} - -type GroupOld struct { - G *GroupOld_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld) Reset() { *m = GroupOld{} } -func (m *GroupOld) String() string { return proto.CompactTextString(m) } -func (*GroupOld) ProtoMessage() {} -func (*GroupOld) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } - -func (m *GroupOld) GetG() *GroupOld_G { - if m != nil { - return m.G - } - return nil -} - -type GroupOld_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupOld_G) Reset() { *m = GroupOld_G{} } -func (m *GroupOld_G) String() string { return proto.CompactTextString(m) } -func (*GroupOld_G) ProtoMessage() {} - -func (m *GroupOld_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -type GroupNew struct { - G *GroupNew_G `protobuf:"group,101,opt,name=G" json:"g,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew) Reset() { *m = GroupNew{} } -func (m *GroupNew) String() string { return proto.CompactTextString(m) } -func (*GroupNew) ProtoMessage() {} -func (*GroupNew) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } - -func (m *GroupNew) GetG() *GroupNew_G { - if m != nil { - return m.G - } - return nil -} - -type GroupNew_G struct { - X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` - Y *int32 `protobuf:"varint,3,opt,name=y" json:"y,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GroupNew_G) Reset() { *m = GroupNew_G{} } -func (m *GroupNew_G) String() string { return proto.CompactTextString(m) } -func (*GroupNew_G) ProtoMessage() {} - -func (m *GroupNew_G) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -func (m *GroupNew_G) GetY() int32 { - if m != nil && m.Y != nil { - return *m.Y - } - return 0 -} - -type FloatingPoint struct { - F *float64 `protobuf:"fixed64,1,req,name=f" json:"f,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *FloatingPoint) Reset() { *m = FloatingPoint{} } -func (m *FloatingPoint) String() string { return proto.CompactTextString(m) } -func (*FloatingPoint) ProtoMessage() {} -func (*FloatingPoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } - -func (m *FloatingPoint) GetF() float64 { - if m != nil && m.F != nil { - return *m.F - } - return 0 -} - -type MessageWithMap struct { - NameMapping map[int32]string `protobuf:"bytes,1,rep,name=name_mapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - MsgMapping map[int64]*FloatingPoint `protobuf:"bytes,2,rep,name=msg_mapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - ByteMapping map[bool][]byte `protobuf:"bytes,3,rep,name=byte_mapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - StrToStr map[string]string `protobuf:"bytes,4,rep,name=str_to_str" json:"str_to_str,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } -func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } -func (*MessageWithMap) ProtoMessage() {} -func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } - -func (m *MessageWithMap) GetNameMapping() map[int32]string { - if m != nil { - return m.NameMapping - } - return nil -} - -func (m *MessageWithMap) GetMsgMapping() map[int64]*FloatingPoint { - if m != nil { - return m.MsgMapping - } - return nil -} - -func (m *MessageWithMap) GetByteMapping() map[bool][]byte { - if m != nil { - return m.ByteMapping - } - return nil -} - -func (m *MessageWithMap) GetStrToStr() map[string]string { - if m != nil { - return m.StrToStr - } - return nil -} - -type Oneof struct { - // Types that are valid to be assigned to Union: - // *Oneof_F_Bool - // *Oneof_F_Int32 - // *Oneof_F_Int64 - // *Oneof_F_Fixed32 - // *Oneof_F_Fixed64 - // *Oneof_F_Uint32 - // *Oneof_F_Uint64 - // *Oneof_F_Float - // *Oneof_F_Double - // *Oneof_F_String - // *Oneof_F_Bytes - // *Oneof_F_Sint32 - // *Oneof_F_Sint64 - // *Oneof_F_Enum - // *Oneof_F_Message - // *Oneof_FGroup - // *Oneof_F_Largest_Tag - Union isOneof_Union `protobuf_oneof:"union"` - // Types that are valid to be assigned to Tormato: - // *Oneof_Value - Tormato isOneof_Tormato `protobuf_oneof:"tormato"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Oneof) Reset() { *m = Oneof{} } -func (m *Oneof) String() string { return proto.CompactTextString(m) } -func (*Oneof) ProtoMessage() {} -func (*Oneof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } - -type isOneof_Union interface { - isOneof_Union() -} -type isOneof_Tormato interface { - isOneof_Tormato() -} - -type Oneof_F_Bool struct { - F_Bool bool `protobuf:"varint,1,opt,name=F_Bool,oneof"` -} -type Oneof_F_Int32 struct { - F_Int32 int32 `protobuf:"varint,2,opt,name=F_Int32,oneof"` -} -type Oneof_F_Int64 struct { - F_Int64 int64 `protobuf:"varint,3,opt,name=F_Int64,oneof"` -} -type Oneof_F_Fixed32 struct { - F_Fixed32 uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,oneof"` -} -type Oneof_F_Fixed64 struct { - F_Fixed64 uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,oneof"` -} -type Oneof_F_Uint32 struct { - F_Uint32 uint32 `protobuf:"varint,6,opt,name=F_Uint32,oneof"` -} -type Oneof_F_Uint64 struct { - F_Uint64 uint64 `protobuf:"varint,7,opt,name=F_Uint64,oneof"` -} -type Oneof_F_Float struct { - F_Float float32 `protobuf:"fixed32,8,opt,name=F_Float,oneof"` -} -type Oneof_F_Double struct { - F_Double float64 `protobuf:"fixed64,9,opt,name=F_Double,oneof"` -} -type Oneof_F_String struct { - F_String string `protobuf:"bytes,10,opt,name=F_String,oneof"` -} -type Oneof_F_Bytes struct { - F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,oneof"` -} -type Oneof_F_Sint32 struct { - F_Sint32 int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,oneof"` -} -type Oneof_F_Sint64 struct { - F_Sint64 int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,oneof"` -} -type Oneof_F_Enum struct { - F_Enum MyMessage_Color `protobuf:"varint,14,opt,name=F_Enum,enum=testdata.MyMessage_Color,oneof"` -} -type Oneof_F_Message struct { - F_Message *GoTestField `protobuf:"bytes,15,opt,name=F_Message,oneof"` -} -type Oneof_FGroup struct { - FGroup *Oneof_F_Group `protobuf:"group,16,opt,name=F_Group,oneof"` -} -type Oneof_F_Largest_Tag struct { - F_Largest_Tag int32 `protobuf:"varint,536870911,opt,name=F_Largest_Tag,oneof"` -} -type Oneof_Value struct { - Value int32 `protobuf:"varint,100,opt,name=value,oneof"` -} - -func (*Oneof_F_Bool) isOneof_Union() {} -func (*Oneof_F_Int32) isOneof_Union() {} -func (*Oneof_F_Int64) isOneof_Union() {} -func (*Oneof_F_Fixed32) isOneof_Union() {} -func (*Oneof_F_Fixed64) isOneof_Union() {} -func (*Oneof_F_Uint32) isOneof_Union() {} -func (*Oneof_F_Uint64) isOneof_Union() {} -func (*Oneof_F_Float) isOneof_Union() {} -func (*Oneof_F_Double) isOneof_Union() {} -func (*Oneof_F_String) isOneof_Union() {} -func (*Oneof_F_Bytes) isOneof_Union() {} -func (*Oneof_F_Sint32) isOneof_Union() {} -func (*Oneof_F_Sint64) isOneof_Union() {} -func (*Oneof_F_Enum) isOneof_Union() {} -func (*Oneof_F_Message) isOneof_Union() {} -func (*Oneof_FGroup) isOneof_Union() {} -func (*Oneof_F_Largest_Tag) isOneof_Union() {} -func (*Oneof_Value) isOneof_Tormato() {} - -func (m *Oneof) GetUnion() isOneof_Union { - if m != nil { - return m.Union - } - return nil -} -func (m *Oneof) GetTormato() isOneof_Tormato { - if m != nil { - return m.Tormato - } - return nil -} - -func (m *Oneof) GetF_Bool() bool { - if x, ok := m.GetUnion().(*Oneof_F_Bool); ok { - return x.F_Bool - } - return false -} - -func (m *Oneof) GetF_Int32() int32 { - if x, ok := m.GetUnion().(*Oneof_F_Int32); ok { - return x.F_Int32 - } - return 0 -} - -func (m *Oneof) GetF_Int64() int64 { - if x, ok := m.GetUnion().(*Oneof_F_Int64); ok { - return x.F_Int64 - } - return 0 -} - -func (m *Oneof) GetF_Fixed32() uint32 { - if x, ok := m.GetUnion().(*Oneof_F_Fixed32); ok { - return x.F_Fixed32 - } - return 0 -} - -func (m *Oneof) GetF_Fixed64() uint64 { - if x, ok := m.GetUnion().(*Oneof_F_Fixed64); ok { - return x.F_Fixed64 - } - return 0 -} - -func (m *Oneof) GetF_Uint32() uint32 { - if x, ok := m.GetUnion().(*Oneof_F_Uint32); ok { - return x.F_Uint32 - } - return 0 -} - -func (m *Oneof) GetF_Uint64() uint64 { - if x, ok := m.GetUnion().(*Oneof_F_Uint64); ok { - return x.F_Uint64 - } - return 0 -} - -func (m *Oneof) GetF_Float() float32 { - if x, ok := m.GetUnion().(*Oneof_F_Float); ok { - return x.F_Float - } - return 0 -} - -func (m *Oneof) GetF_Double() float64 { - if x, ok := m.GetUnion().(*Oneof_F_Double); ok { - return x.F_Double - } - return 0 -} - -func (m *Oneof) GetF_String() string { - if x, ok := m.GetUnion().(*Oneof_F_String); ok { - return x.F_String - } - return "" -} - -func (m *Oneof) GetF_Bytes() []byte { - if x, ok := m.GetUnion().(*Oneof_F_Bytes); ok { - return x.F_Bytes - } - return nil -} - -func (m *Oneof) GetF_Sint32() int32 { - if x, ok := m.GetUnion().(*Oneof_F_Sint32); ok { - return x.F_Sint32 - } - return 0 -} - -func (m *Oneof) GetF_Sint64() int64 { - if x, ok := m.GetUnion().(*Oneof_F_Sint64); ok { - return x.F_Sint64 - } - return 0 -} - -func (m *Oneof) GetF_Enum() MyMessage_Color { - if x, ok := m.GetUnion().(*Oneof_F_Enum); ok { - return x.F_Enum - } - return MyMessage_RED -} - -func (m *Oneof) GetF_Message() *GoTestField { - if x, ok := m.GetUnion().(*Oneof_F_Message); ok { - return x.F_Message - } - return nil -} - -func (m *Oneof) GetFGroup() *Oneof_F_Group { - if x, ok := m.GetUnion().(*Oneof_FGroup); ok { - return x.FGroup - } - return nil -} - -func (m *Oneof) GetF_Largest_Tag() int32 { - if x, ok := m.GetUnion().(*Oneof_F_Largest_Tag); ok { - return x.F_Largest_Tag - } - return 0 -} - -func (m *Oneof) GetValue() int32 { - if x, ok := m.GetTormato().(*Oneof_Value); ok { - return x.Value - } - return 0 -} - -// XXX_OneofFuncs is for the internal use of the proto package. -func (*Oneof) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { - return _Oneof_OneofMarshaler, _Oneof_OneofUnmarshaler, _Oneof_OneofSizer, []interface{}{ - (*Oneof_F_Bool)(nil), - (*Oneof_F_Int32)(nil), - (*Oneof_F_Int64)(nil), - (*Oneof_F_Fixed32)(nil), - (*Oneof_F_Fixed64)(nil), - (*Oneof_F_Uint32)(nil), - (*Oneof_F_Uint64)(nil), - (*Oneof_F_Float)(nil), - (*Oneof_F_Double)(nil), - (*Oneof_F_String)(nil), - (*Oneof_F_Bytes)(nil), - (*Oneof_F_Sint32)(nil), - (*Oneof_F_Sint64)(nil), - (*Oneof_F_Enum)(nil), - (*Oneof_F_Message)(nil), - (*Oneof_FGroup)(nil), - (*Oneof_F_Largest_Tag)(nil), - (*Oneof_Value)(nil), - } -} - -func _Oneof_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { - m := msg.(*Oneof) - // union - switch x := m.Union.(type) { - case *Oneof_F_Bool: - t := uint64(0) - if x.F_Bool { - t = 1 - } - b.EncodeVarint(1<<3 | proto.WireVarint) - b.EncodeVarint(t) - case *Oneof_F_Int32: - b.EncodeVarint(2<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.F_Int32)) - case *Oneof_F_Int64: - b.EncodeVarint(3<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.F_Int64)) - case *Oneof_F_Fixed32: - b.EncodeVarint(4<<3 | proto.WireFixed32) - b.EncodeFixed32(uint64(x.F_Fixed32)) - case *Oneof_F_Fixed64: - b.EncodeVarint(5<<3 | proto.WireFixed64) - b.EncodeFixed64(uint64(x.F_Fixed64)) - case *Oneof_F_Uint32: - b.EncodeVarint(6<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.F_Uint32)) - case *Oneof_F_Uint64: - b.EncodeVarint(7<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.F_Uint64)) - case *Oneof_F_Float: - b.EncodeVarint(8<<3 | proto.WireFixed32) - b.EncodeFixed32(uint64(math.Float32bits(x.F_Float))) - case *Oneof_F_Double: - b.EncodeVarint(9<<3 | proto.WireFixed64) - b.EncodeFixed64(math.Float64bits(x.F_Double)) - case *Oneof_F_String: - b.EncodeVarint(10<<3 | proto.WireBytes) - b.EncodeStringBytes(x.F_String) - case *Oneof_F_Bytes: - b.EncodeVarint(11<<3 | proto.WireBytes) - b.EncodeRawBytes(x.F_Bytes) - case *Oneof_F_Sint32: - b.EncodeVarint(12<<3 | proto.WireVarint) - b.EncodeZigzag32(uint64(x.F_Sint32)) - case *Oneof_F_Sint64: - b.EncodeVarint(13<<3 | proto.WireVarint) - b.EncodeZigzag64(uint64(x.F_Sint64)) - case *Oneof_F_Enum: - b.EncodeVarint(14<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.F_Enum)) - case *Oneof_F_Message: - b.EncodeVarint(15<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.F_Message); err != nil { - return err - } - case *Oneof_FGroup: - b.EncodeVarint(16<<3 | proto.WireStartGroup) - if err := b.Marshal(x.FGroup); err != nil { - return err - } - b.EncodeVarint(16<<3 | proto.WireEndGroup) - case *Oneof_F_Largest_Tag: - b.EncodeVarint(536870911<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.F_Largest_Tag)) - case nil: - default: - return fmt.Errorf("Oneof.Union has unexpected type %T", x) - } - // tormato - switch x := m.Tormato.(type) { - case *Oneof_Value: - b.EncodeVarint(100<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.Value)) - case nil: - default: - return fmt.Errorf("Oneof.Tormato has unexpected type %T", x) - } - return nil -} - -func _Oneof_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { - m := msg.(*Oneof) - switch tag { - case 1: // union.F_Bool - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Oneof_F_Bool{x != 0} - return true, err - case 2: // union.F_Int32 - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Oneof_F_Int32{int32(x)} - return true, err - case 3: // union.F_Int64 - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Oneof_F_Int64{int64(x)} - return true, err - case 4: // union.F_Fixed32 - if wire != proto.WireFixed32 { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeFixed32() - m.Union = &Oneof_F_Fixed32{uint32(x)} - return true, err - case 5: // union.F_Fixed64 - if wire != proto.WireFixed64 { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeFixed64() - m.Union = &Oneof_F_Fixed64{x} - return true, err - case 6: // union.F_Uint32 - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Oneof_F_Uint32{uint32(x)} - return true, err - case 7: // union.F_Uint64 - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Oneof_F_Uint64{x} - return true, err - case 8: // union.F_Float - if wire != proto.WireFixed32 { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeFixed32() - m.Union = &Oneof_F_Float{math.Float32frombits(uint32(x))} - return true, err - case 9: // union.F_Double - if wire != proto.WireFixed64 { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeFixed64() - m.Union = &Oneof_F_Double{math.Float64frombits(x)} - return true, err - case 10: // union.F_String - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeStringBytes() - m.Union = &Oneof_F_String{x} - return true, err - case 11: // union.F_Bytes - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeRawBytes(true) - m.Union = &Oneof_F_Bytes{x} - return true, err - case 12: // union.F_Sint32 - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeZigzag32() - m.Union = &Oneof_F_Sint32{int32(x)} - return true, err - case 13: // union.F_Sint64 - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeZigzag64() - m.Union = &Oneof_F_Sint64{int64(x)} - return true, err - case 14: // union.F_Enum - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Oneof_F_Enum{MyMessage_Color(x)} - return true, err - case 15: // union.F_Message - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(GoTestField) - err := b.DecodeMessage(msg) - m.Union = &Oneof_F_Message{msg} - return true, err - case 16: // union.f_group - if wire != proto.WireStartGroup { - return true, proto.ErrInternalBadWireType - } - msg := new(Oneof_F_Group) - err := b.DecodeGroup(msg) - m.Union = &Oneof_FGroup{msg} - return true, err - case 536870911: // union.F_Largest_Tag - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Oneof_F_Largest_Tag{int32(x)} - return true, err - case 100: // tormato.value - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Tormato = &Oneof_Value{int32(x)} - return true, err - default: - return false, nil - } -} - -func _Oneof_OneofSizer(msg proto.Message) (n int) { - m := msg.(*Oneof) - // union - switch x := m.Union.(type) { - case *Oneof_F_Bool: - n += proto.SizeVarint(1<<3 | proto.WireVarint) - n += 1 - case *Oneof_F_Int32: - n += proto.SizeVarint(2<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.F_Int32)) - case *Oneof_F_Int64: - n += proto.SizeVarint(3<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.F_Int64)) - case *Oneof_F_Fixed32: - n += proto.SizeVarint(4<<3 | proto.WireFixed32) - n += 4 - case *Oneof_F_Fixed64: - n += proto.SizeVarint(5<<3 | proto.WireFixed64) - n += 8 - case *Oneof_F_Uint32: - n += proto.SizeVarint(6<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.F_Uint32)) - case *Oneof_F_Uint64: - n += proto.SizeVarint(7<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.F_Uint64)) - case *Oneof_F_Float: - n += proto.SizeVarint(8<<3 | proto.WireFixed32) - n += 4 - case *Oneof_F_Double: - n += proto.SizeVarint(9<<3 | proto.WireFixed64) - n += 8 - case *Oneof_F_String: - n += proto.SizeVarint(10<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(len(x.F_String))) - n += len(x.F_String) - case *Oneof_F_Bytes: - n += proto.SizeVarint(11<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(len(x.F_Bytes))) - n += len(x.F_Bytes) - case *Oneof_F_Sint32: - n += proto.SizeVarint(12<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64((uint32(x.F_Sint32) << 1) ^ uint32((int32(x.F_Sint32) >> 31)))) - case *Oneof_F_Sint64: - n += proto.SizeVarint(13<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(uint64(x.F_Sint64<<1) ^ uint64((int64(x.F_Sint64) >> 63)))) - case *Oneof_F_Enum: - n += proto.SizeVarint(14<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.F_Enum)) - case *Oneof_F_Message: - s := proto.Size(x.F_Message) - n += proto.SizeVarint(15<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case *Oneof_FGroup: - n += proto.SizeVarint(16<<3 | proto.WireStartGroup) - n += proto.Size(x.FGroup) - n += proto.SizeVarint(16<<3 | proto.WireEndGroup) - case *Oneof_F_Largest_Tag: - n += proto.SizeVarint(536870911<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.F_Largest_Tag)) - case nil: - default: - panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) - } - // tormato - switch x := m.Tormato.(type) { - case *Oneof_Value: - n += proto.SizeVarint(100<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.Value)) - case nil: - default: - panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) - } - return n -} - -type Oneof_F_Group struct { - X *int32 `protobuf:"varint,17,opt,name=x" json:"x,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Oneof_F_Group) Reset() { *m = Oneof_F_Group{} } -func (m *Oneof_F_Group) String() string { return proto.CompactTextString(m) } -func (*Oneof_F_Group) ProtoMessage() {} - -func (m *Oneof_F_Group) GetX() int32 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -type Communique struct { - MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry" json:"make_me_cry,omitempty"` - // This is a oneof, called "union". - // - // Types that are valid to be assigned to Union: - // *Communique_Number - // *Communique_Name - // *Communique_Data - // *Communique_TempC - // *Communique_Col - // *Communique_Msg - Union isCommunique_Union `protobuf_oneof:"union"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Communique) Reset() { *m = Communique{} } -func (m *Communique) String() string { return proto.CompactTextString(m) } -func (*Communique) ProtoMessage() {} -func (*Communique) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } - -type isCommunique_Union interface { - isCommunique_Union() -} - -type Communique_Number struct { - Number int32 `protobuf:"varint,5,opt,name=number,oneof"` -} -type Communique_Name struct { - Name string `protobuf:"bytes,6,opt,name=name,oneof"` -} -type Communique_Data struct { - Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` -} -type Communique_TempC struct { - TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,oneof"` -} -type Communique_Col struct { - Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color,oneof"` -} -type Communique_Msg struct { - Msg *Strings `protobuf:"bytes,10,opt,name=msg,oneof"` -} - -func (*Communique_Number) isCommunique_Union() {} -func (*Communique_Name) isCommunique_Union() {} -func (*Communique_Data) isCommunique_Union() {} -func (*Communique_TempC) isCommunique_Union() {} -func (*Communique_Col) isCommunique_Union() {} -func (*Communique_Msg) isCommunique_Union() {} - -func (m *Communique) GetUnion() isCommunique_Union { - if m != nil { - return m.Union - } - return nil -} - -func (m *Communique) GetMakeMeCry() bool { - if m != nil && m.MakeMeCry != nil { - return *m.MakeMeCry - } - return false -} - -func (m *Communique) GetNumber() int32 { - if x, ok := m.GetUnion().(*Communique_Number); ok { - return x.Number - } - return 0 -} - -func (m *Communique) GetName() string { - if x, ok := m.GetUnion().(*Communique_Name); ok { - return x.Name - } - return "" -} - -func (m *Communique) GetData() []byte { - if x, ok := m.GetUnion().(*Communique_Data); ok { - return x.Data - } - return nil -} - -func (m *Communique) GetTempC() float64 { - if x, ok := m.GetUnion().(*Communique_TempC); ok { - return x.TempC - } - return 0 -} - -func (m *Communique) GetCol() MyMessage_Color { - if x, ok := m.GetUnion().(*Communique_Col); ok { - return x.Col - } - return MyMessage_RED -} - -func (m *Communique) GetMsg() *Strings { - if x, ok := m.GetUnion().(*Communique_Msg); ok { - return x.Msg - } - return nil -} - -// XXX_OneofFuncs is for the internal use of the proto package. -func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { - return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{ - (*Communique_Number)(nil), - (*Communique_Name)(nil), - (*Communique_Data)(nil), - (*Communique_TempC)(nil), - (*Communique_Col)(nil), - (*Communique_Msg)(nil), - } -} - -func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { - m := msg.(*Communique) - // union - switch x := m.Union.(type) { - case *Communique_Number: - b.EncodeVarint(5<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.Number)) - case *Communique_Name: - b.EncodeVarint(6<<3 | proto.WireBytes) - b.EncodeStringBytes(x.Name) - case *Communique_Data: - b.EncodeVarint(7<<3 | proto.WireBytes) - b.EncodeRawBytes(x.Data) - case *Communique_TempC: - b.EncodeVarint(8<<3 | proto.WireFixed64) - b.EncodeFixed64(math.Float64bits(x.TempC)) - case *Communique_Col: - b.EncodeVarint(9<<3 | proto.WireVarint) - b.EncodeVarint(uint64(x.Col)) - case *Communique_Msg: - b.EncodeVarint(10<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.Msg); err != nil { - return err - } - case nil: - default: - return fmt.Errorf("Communique.Union has unexpected type %T", x) - } - return nil -} - -func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { - m := msg.(*Communique) - switch tag { - case 5: // union.number - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Communique_Number{int32(x)} - return true, err - case 6: // union.name - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeStringBytes() - m.Union = &Communique_Name{x} - return true, err - case 7: // union.data - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeRawBytes(true) - m.Union = &Communique_Data{x} - return true, err - case 8: // union.temp_c - if wire != proto.WireFixed64 { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeFixed64() - m.Union = &Communique_TempC{math.Float64frombits(x)} - return true, err - case 9: // union.col - if wire != proto.WireVarint { - return true, proto.ErrInternalBadWireType - } - x, err := b.DecodeVarint() - m.Union = &Communique_Col{MyMessage_Color(x)} - return true, err - case 10: // union.msg - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(Strings) - err := b.DecodeMessage(msg) - m.Union = &Communique_Msg{msg} - return true, err - default: - return false, nil - } -} - -func _Communique_OneofSizer(msg proto.Message) (n int) { - m := msg.(*Communique) - // union - switch x := m.Union.(type) { - case *Communique_Number: - n += proto.SizeVarint(5<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.Number)) - case *Communique_Name: - n += proto.SizeVarint(6<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(len(x.Name))) - n += len(x.Name) - case *Communique_Data: - n += proto.SizeVarint(7<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(len(x.Data))) - n += len(x.Data) - case *Communique_TempC: - n += proto.SizeVarint(8<<3 | proto.WireFixed64) - n += 8 - case *Communique_Col: - n += proto.SizeVarint(9<<3 | proto.WireVarint) - n += proto.SizeVarint(uint64(x.Col)) - case *Communique_Msg: - s := proto.Size(x.Msg) - n += proto.SizeVarint(10<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case nil: - default: - panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) - } - return n -} - -var E_Greeting = &proto.ExtensionDesc{ - ExtendedType: (*MyMessage)(nil), - ExtensionType: ([]string)(nil), - Field: 106, - Name: "testdata.greeting", - Tag: "bytes,106,rep,name=greeting", -} - -var E_Complex = &proto.ExtensionDesc{ - ExtendedType: (*OtherMessage)(nil), - ExtensionType: (*ComplexExtension)(nil), - Field: 200, - Name: "testdata.complex", - Tag: "bytes,200,opt,name=complex", -} - -var E_RComplex = &proto.ExtensionDesc{ - ExtendedType: (*OtherMessage)(nil), - ExtensionType: ([]*ComplexExtension)(nil), - Field: 201, - Name: "testdata.r_complex", - Tag: "bytes,201,rep,name=r_complex", -} - -var E_NoDefaultDouble = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float64)(nil), - Field: 101, - Name: "testdata.no_default_double", - Tag: "fixed64,101,opt,name=no_default_double", -} - -var E_NoDefaultFloat = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float32)(nil), - Field: 102, - Name: "testdata.no_default_float", - Tag: "fixed32,102,opt,name=no_default_float", -} - -var E_NoDefaultInt32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 103, - Name: "testdata.no_default_int32", - Tag: "varint,103,opt,name=no_default_int32", -} - -var E_NoDefaultInt64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 104, - Name: "testdata.no_default_int64", - Tag: "varint,104,opt,name=no_default_int64", -} - -var E_NoDefaultUint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 105, - Name: "testdata.no_default_uint32", - Tag: "varint,105,opt,name=no_default_uint32", -} - -var E_NoDefaultUint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 106, - Name: "testdata.no_default_uint64", - Tag: "varint,106,opt,name=no_default_uint64", -} - -var E_NoDefaultSint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 107, - Name: "testdata.no_default_sint32", - Tag: "zigzag32,107,opt,name=no_default_sint32", -} - -var E_NoDefaultSint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 108, - Name: "testdata.no_default_sint64", - Tag: "zigzag64,108,opt,name=no_default_sint64", -} - -var E_NoDefaultFixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 109, - Name: "testdata.no_default_fixed32", - Tag: "fixed32,109,opt,name=no_default_fixed32", -} - -var E_NoDefaultFixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 110, - Name: "testdata.no_default_fixed64", - Tag: "fixed64,110,opt,name=no_default_fixed64", -} - -var E_NoDefaultSfixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 111, - Name: "testdata.no_default_sfixed32", - Tag: "fixed32,111,opt,name=no_default_sfixed32", -} - -var E_NoDefaultSfixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 112, - Name: "testdata.no_default_sfixed64", - Tag: "fixed64,112,opt,name=no_default_sfixed64", -} - -var E_NoDefaultBool = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 113, - Name: "testdata.no_default_bool", - Tag: "varint,113,opt,name=no_default_bool", -} - -var E_NoDefaultString = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*string)(nil), - Field: 114, - Name: "testdata.no_default_string", - Tag: "bytes,114,opt,name=no_default_string", -} - -var E_NoDefaultBytes = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: ([]byte)(nil), - Field: 115, - Name: "testdata.no_default_bytes", - Tag: "bytes,115,opt,name=no_default_bytes", -} - -var E_NoDefaultEnum = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), - Field: 116, - Name: "testdata.no_default_enum", - Tag: "varint,116,opt,name=no_default_enum,enum=testdata.DefaultsMessage_DefaultsEnum", -} - -var E_DefaultDouble = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float64)(nil), - Field: 201, - Name: "testdata.default_double", - Tag: "fixed64,201,opt,name=default_double,def=3.1415", -} - -var E_DefaultFloat = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*float32)(nil), - Field: 202, - Name: "testdata.default_float", - Tag: "fixed32,202,opt,name=default_float,def=3.14", -} - -var E_DefaultInt32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 203, - Name: "testdata.default_int32", - Tag: "varint,203,opt,name=default_int32,def=42", -} - -var E_DefaultInt64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 204, - Name: "testdata.default_int64", - Tag: "varint,204,opt,name=default_int64,def=43", -} - -var E_DefaultUint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 205, - Name: "testdata.default_uint32", - Tag: "varint,205,opt,name=default_uint32,def=44", -} - -var E_DefaultUint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 206, - Name: "testdata.default_uint64", - Tag: "varint,206,opt,name=default_uint64,def=45", -} - -var E_DefaultSint32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 207, - Name: "testdata.default_sint32", - Tag: "zigzag32,207,opt,name=default_sint32,def=46", -} - -var E_DefaultSint64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 208, - Name: "testdata.default_sint64", - Tag: "zigzag64,208,opt,name=default_sint64,def=47", -} - -var E_DefaultFixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint32)(nil), - Field: 209, - Name: "testdata.default_fixed32", - Tag: "fixed32,209,opt,name=default_fixed32,def=48", -} - -var E_DefaultFixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*uint64)(nil), - Field: 210, - Name: "testdata.default_fixed64", - Tag: "fixed64,210,opt,name=default_fixed64,def=49", -} - -var E_DefaultSfixed32 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int32)(nil), - Field: 211, - Name: "testdata.default_sfixed32", - Tag: "fixed32,211,opt,name=default_sfixed32,def=50", -} - -var E_DefaultSfixed64 = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*int64)(nil), - Field: 212, - Name: "testdata.default_sfixed64", - Tag: "fixed64,212,opt,name=default_sfixed64,def=51", -} - -var E_DefaultBool = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*bool)(nil), - Field: 213, - Name: "testdata.default_bool", - Tag: "varint,213,opt,name=default_bool,def=1", -} - -var E_DefaultString = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*string)(nil), - Field: 214, - Name: "testdata.default_string", - Tag: "bytes,214,opt,name=default_string,def=Hello, string", -} - -var E_DefaultBytes = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: ([]byte)(nil), - Field: 215, - Name: "testdata.default_bytes", - Tag: "bytes,215,opt,name=default_bytes,def=Hello, bytes", -} - -var E_DefaultEnum = &proto.ExtensionDesc{ - ExtendedType: (*DefaultsMessage)(nil), - ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), - Field: 216, - Name: "testdata.default_enum", - Tag: "varint,216,opt,name=default_enum,enum=testdata.DefaultsMessage_DefaultsEnum,def=1", -} - -var E_X201 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 201, - Name: "testdata.x201", - Tag: "bytes,201,opt,name=x201", -} - -var E_X202 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 202, - Name: "testdata.x202", - Tag: "bytes,202,opt,name=x202", -} - -var E_X203 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 203, - Name: "testdata.x203", - Tag: "bytes,203,opt,name=x203", -} - -var E_X204 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 204, - Name: "testdata.x204", - Tag: "bytes,204,opt,name=x204", -} - -var E_X205 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 205, - Name: "testdata.x205", - Tag: "bytes,205,opt,name=x205", -} - -var E_X206 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 206, - Name: "testdata.x206", - Tag: "bytes,206,opt,name=x206", -} - -var E_X207 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 207, - Name: "testdata.x207", - Tag: "bytes,207,opt,name=x207", -} - -var E_X208 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 208, - Name: "testdata.x208", - Tag: "bytes,208,opt,name=x208", -} - -var E_X209 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 209, - Name: "testdata.x209", - Tag: "bytes,209,opt,name=x209", -} - -var E_X210 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 210, - Name: "testdata.x210", - Tag: "bytes,210,opt,name=x210", -} - -var E_X211 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 211, - Name: "testdata.x211", - Tag: "bytes,211,opt,name=x211", -} - -var E_X212 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 212, - Name: "testdata.x212", - Tag: "bytes,212,opt,name=x212", -} - -var E_X213 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 213, - Name: "testdata.x213", - Tag: "bytes,213,opt,name=x213", -} - -var E_X214 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 214, - Name: "testdata.x214", - Tag: "bytes,214,opt,name=x214", -} - -var E_X215 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 215, - Name: "testdata.x215", - Tag: "bytes,215,opt,name=x215", -} - -var E_X216 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 216, - Name: "testdata.x216", - Tag: "bytes,216,opt,name=x216", -} - -var E_X217 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 217, - Name: "testdata.x217", - Tag: "bytes,217,opt,name=x217", -} - -var E_X218 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 218, - Name: "testdata.x218", - Tag: "bytes,218,opt,name=x218", -} - -var E_X219 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 219, - Name: "testdata.x219", - Tag: "bytes,219,opt,name=x219", -} - -var E_X220 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 220, - Name: "testdata.x220", - Tag: "bytes,220,opt,name=x220", -} - -var E_X221 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 221, - Name: "testdata.x221", - Tag: "bytes,221,opt,name=x221", -} - -var E_X222 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 222, - Name: "testdata.x222", - Tag: "bytes,222,opt,name=x222", -} - -var E_X223 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 223, - Name: "testdata.x223", - Tag: "bytes,223,opt,name=x223", -} - -var E_X224 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 224, - Name: "testdata.x224", - Tag: "bytes,224,opt,name=x224", -} - -var E_X225 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 225, - Name: "testdata.x225", - Tag: "bytes,225,opt,name=x225", -} - -var E_X226 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 226, - Name: "testdata.x226", - Tag: "bytes,226,opt,name=x226", -} - -var E_X227 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 227, - Name: "testdata.x227", - Tag: "bytes,227,opt,name=x227", -} - -var E_X228 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 228, - Name: "testdata.x228", - Tag: "bytes,228,opt,name=x228", -} - -var E_X229 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 229, - Name: "testdata.x229", - Tag: "bytes,229,opt,name=x229", -} - -var E_X230 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 230, - Name: "testdata.x230", - Tag: "bytes,230,opt,name=x230", -} - -var E_X231 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 231, - Name: "testdata.x231", - Tag: "bytes,231,opt,name=x231", -} - -var E_X232 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 232, - Name: "testdata.x232", - Tag: "bytes,232,opt,name=x232", -} - -var E_X233 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 233, - Name: "testdata.x233", - Tag: "bytes,233,opt,name=x233", -} - -var E_X234 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 234, - Name: "testdata.x234", - Tag: "bytes,234,opt,name=x234", -} - -var E_X235 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 235, - Name: "testdata.x235", - Tag: "bytes,235,opt,name=x235", -} - -var E_X236 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 236, - Name: "testdata.x236", - Tag: "bytes,236,opt,name=x236", -} - -var E_X237 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 237, - Name: "testdata.x237", - Tag: "bytes,237,opt,name=x237", -} - -var E_X238 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 238, - Name: "testdata.x238", - Tag: "bytes,238,opt,name=x238", -} - -var E_X239 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 239, - Name: "testdata.x239", - Tag: "bytes,239,opt,name=x239", -} - -var E_X240 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 240, - Name: "testdata.x240", - Tag: "bytes,240,opt,name=x240", -} - -var E_X241 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 241, - Name: "testdata.x241", - Tag: "bytes,241,opt,name=x241", -} - -var E_X242 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 242, - Name: "testdata.x242", - Tag: "bytes,242,opt,name=x242", -} - -var E_X243 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 243, - Name: "testdata.x243", - Tag: "bytes,243,opt,name=x243", -} - -var E_X244 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 244, - Name: "testdata.x244", - Tag: "bytes,244,opt,name=x244", -} - -var E_X245 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 245, - Name: "testdata.x245", - Tag: "bytes,245,opt,name=x245", -} - -var E_X246 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 246, - Name: "testdata.x246", - Tag: "bytes,246,opt,name=x246", -} - -var E_X247 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 247, - Name: "testdata.x247", - Tag: "bytes,247,opt,name=x247", -} - -var E_X248 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 248, - Name: "testdata.x248", - Tag: "bytes,248,opt,name=x248", -} - -var E_X249 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 249, - Name: "testdata.x249", - Tag: "bytes,249,opt,name=x249", -} - -var E_X250 = &proto.ExtensionDesc{ - ExtendedType: (*MyMessageSet)(nil), - ExtensionType: (*Empty)(nil), - Field: 250, - Name: "testdata.x250", - Tag: "bytes,250,opt,name=x250", -} - -func init() { - proto.RegisterType((*GoEnum)(nil), "testdata.GoEnum") - proto.RegisterType((*GoTestField)(nil), "testdata.GoTestField") - proto.RegisterType((*GoTest)(nil), "testdata.GoTest") - proto.RegisterType((*GoTest_RequiredGroup)(nil), "testdata.GoTest.RequiredGroup") - proto.RegisterType((*GoTest_RepeatedGroup)(nil), "testdata.GoTest.RepeatedGroup") - proto.RegisterType((*GoTest_OptionalGroup)(nil), "testdata.GoTest.OptionalGroup") - proto.RegisterType((*GoSkipTest)(nil), "testdata.GoSkipTest") - proto.RegisterType((*GoSkipTest_SkipGroup)(nil), "testdata.GoSkipTest.SkipGroup") - proto.RegisterType((*NonPackedTest)(nil), "testdata.NonPackedTest") - proto.RegisterType((*PackedTest)(nil), "testdata.PackedTest") - proto.RegisterType((*MaxTag)(nil), "testdata.MaxTag") - proto.RegisterType((*OldMessage)(nil), "testdata.OldMessage") - proto.RegisterType((*OldMessage_Nested)(nil), "testdata.OldMessage.Nested") - proto.RegisterType((*NewMessage)(nil), "testdata.NewMessage") - proto.RegisterType((*NewMessage_Nested)(nil), "testdata.NewMessage.Nested") - proto.RegisterType((*InnerMessage)(nil), "testdata.InnerMessage") - proto.RegisterType((*OtherMessage)(nil), "testdata.OtherMessage") - proto.RegisterType((*MyMessage)(nil), "testdata.MyMessage") - proto.RegisterType((*MyMessage_SomeGroup)(nil), "testdata.MyMessage.SomeGroup") - proto.RegisterType((*Ext)(nil), "testdata.Ext") - proto.RegisterType((*ComplexExtension)(nil), "testdata.ComplexExtension") - proto.RegisterType((*DefaultsMessage)(nil), "testdata.DefaultsMessage") - proto.RegisterType((*MyMessageSet)(nil), "testdata.MyMessageSet") - proto.RegisterType((*Empty)(nil), "testdata.Empty") - proto.RegisterType((*MessageList)(nil), "testdata.MessageList") - proto.RegisterType((*MessageList_Message)(nil), "testdata.MessageList.Message") - proto.RegisterType((*Strings)(nil), "testdata.Strings") - proto.RegisterType((*Defaults)(nil), "testdata.Defaults") - proto.RegisterType((*SubDefaults)(nil), "testdata.SubDefaults") - proto.RegisterType((*RepeatedEnum)(nil), "testdata.RepeatedEnum") - proto.RegisterType((*MoreRepeated)(nil), "testdata.MoreRepeated") - proto.RegisterType((*GroupOld)(nil), "testdata.GroupOld") - proto.RegisterType((*GroupOld_G)(nil), "testdata.GroupOld.G") - proto.RegisterType((*GroupNew)(nil), "testdata.GroupNew") - proto.RegisterType((*GroupNew_G)(nil), "testdata.GroupNew.G") - proto.RegisterType((*FloatingPoint)(nil), "testdata.FloatingPoint") - proto.RegisterType((*MessageWithMap)(nil), "testdata.MessageWithMap") - proto.RegisterType((*Oneof)(nil), "testdata.Oneof") - proto.RegisterType((*Oneof_F_Group)(nil), "testdata.Oneof.F_Group") - proto.RegisterType((*Communique)(nil), "testdata.Communique") - proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value) - proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value) - proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value) - proto.RegisterEnum("testdata.DefaultsMessage_DefaultsEnum", DefaultsMessage_DefaultsEnum_name, DefaultsMessage_DefaultsEnum_value) - proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value) - proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value) - proto.RegisterExtension(E_Ext_More) - proto.RegisterExtension(E_Ext_Text) - proto.RegisterExtension(E_Ext_Number) - proto.RegisterExtension(E_Greeting) - proto.RegisterExtension(E_Complex) - proto.RegisterExtension(E_RComplex) - proto.RegisterExtension(E_NoDefaultDouble) - proto.RegisterExtension(E_NoDefaultFloat) - proto.RegisterExtension(E_NoDefaultInt32) - proto.RegisterExtension(E_NoDefaultInt64) - proto.RegisterExtension(E_NoDefaultUint32) - proto.RegisterExtension(E_NoDefaultUint64) - proto.RegisterExtension(E_NoDefaultSint32) - proto.RegisterExtension(E_NoDefaultSint64) - proto.RegisterExtension(E_NoDefaultFixed32) - proto.RegisterExtension(E_NoDefaultFixed64) - proto.RegisterExtension(E_NoDefaultSfixed32) - proto.RegisterExtension(E_NoDefaultSfixed64) - proto.RegisterExtension(E_NoDefaultBool) - proto.RegisterExtension(E_NoDefaultString) - proto.RegisterExtension(E_NoDefaultBytes) - proto.RegisterExtension(E_NoDefaultEnum) - proto.RegisterExtension(E_DefaultDouble) - proto.RegisterExtension(E_DefaultFloat) - proto.RegisterExtension(E_DefaultInt32) - proto.RegisterExtension(E_DefaultInt64) - proto.RegisterExtension(E_DefaultUint32) - proto.RegisterExtension(E_DefaultUint64) - proto.RegisterExtension(E_DefaultSint32) - proto.RegisterExtension(E_DefaultSint64) - proto.RegisterExtension(E_DefaultFixed32) - proto.RegisterExtension(E_DefaultFixed64) - proto.RegisterExtension(E_DefaultSfixed32) - proto.RegisterExtension(E_DefaultSfixed64) - proto.RegisterExtension(E_DefaultBool) - proto.RegisterExtension(E_DefaultString) - proto.RegisterExtension(E_DefaultBytes) - proto.RegisterExtension(E_DefaultEnum) - proto.RegisterExtension(E_X201) - proto.RegisterExtension(E_X202) - proto.RegisterExtension(E_X203) - proto.RegisterExtension(E_X204) - proto.RegisterExtension(E_X205) - proto.RegisterExtension(E_X206) - proto.RegisterExtension(E_X207) - proto.RegisterExtension(E_X208) - proto.RegisterExtension(E_X209) - proto.RegisterExtension(E_X210) - proto.RegisterExtension(E_X211) - proto.RegisterExtension(E_X212) - proto.RegisterExtension(E_X213) - proto.RegisterExtension(E_X214) - proto.RegisterExtension(E_X215) - proto.RegisterExtension(E_X216) - proto.RegisterExtension(E_X217) - proto.RegisterExtension(E_X218) - proto.RegisterExtension(E_X219) - proto.RegisterExtension(E_X220) - proto.RegisterExtension(E_X221) - proto.RegisterExtension(E_X222) - proto.RegisterExtension(E_X223) - proto.RegisterExtension(E_X224) - proto.RegisterExtension(E_X225) - proto.RegisterExtension(E_X226) - proto.RegisterExtension(E_X227) - proto.RegisterExtension(E_X228) - proto.RegisterExtension(E_X229) - proto.RegisterExtension(E_X230) - proto.RegisterExtension(E_X231) - proto.RegisterExtension(E_X232) - proto.RegisterExtension(E_X233) - proto.RegisterExtension(E_X234) - proto.RegisterExtension(E_X235) - proto.RegisterExtension(E_X236) - proto.RegisterExtension(E_X237) - proto.RegisterExtension(E_X238) - proto.RegisterExtension(E_X239) - proto.RegisterExtension(E_X240) - proto.RegisterExtension(E_X241) - proto.RegisterExtension(E_X242) - proto.RegisterExtension(E_X243) - proto.RegisterExtension(E_X244) - proto.RegisterExtension(E_X245) - proto.RegisterExtension(E_X246) - proto.RegisterExtension(E_X247) - proto.RegisterExtension(E_X248) - proto.RegisterExtension(E_X249) - proto.RegisterExtension(E_X250) -} - -var fileDescriptor0 = []byte{ - // 3329 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x58, 0xd9, 0x73, 0x1b, 0xc7, - 0xf1, 0xd6, 0xe2, 0xc6, 0x00, 0x24, 0x96, 0x4b, 0x1d, 0x10, 0xe5, 0x83, 0x5a, 0xd9, 0xfa, 0xc9, - 0x92, 0x0d, 0x93, 0x20, 0x48, 0x49, 0xfb, 0xab, 0x94, 0x23, 0x4a, 0x00, 0xcd, 0x98, 0x24, 0x18, - 0x92, 0x8a, 0xcb, 0x4e, 0x25, 0x28, 0x90, 0x5c, 0x82, 0x30, 0x01, 0x2c, 0x04, 0x2c, 0x62, 0x31, - 0x4f, 0x79, 0xcd, 0x43, 0x1e, 0x92, 0x54, 0xaa, 0x5c, 0xf9, 0x1f, 0x92, 0xbc, 0xe7, 0x2f, 0x88, - 0xef, 0xfb, 0xc8, 0x7d, 0x39, 0xf7, 0xed, 0x24, 0x76, 0x92, 0x97, 0xa4, 0xbb, 0x67, 0x6f, 0x60, - 0x87, 0xb4, 0x1e, 0x6c, 0x70, 0xbe, 0xfe, 0x7a, 0x66, 0x7a, 0xba, 0x7b, 0xbe, 0x59, 0xc6, 0x4c, - 0xbd, 0x6f, 0x16, 0xba, 0x3d, 0xc3, 0x34, 0x94, 0x14, 0xfe, 0xde, 0xad, 0x9b, 0x75, 0xf5, 0x01, - 0x96, 0x58, 0x32, 0xca, 0x9d, 0x41, 0x5b, 0x99, 0x62, 0xd1, 0x3d, 0xc3, 0xc8, 0x4b, 0xd3, 0x91, - 0x4b, 0xe3, 0xc5, 0xb1, 0x82, 0x6d, 0x51, 0xa8, 0x54, 0xab, 0xea, 0x65, 0x96, 0x59, 0x32, 0xb6, - 0x60, 0xa4, 0xd2, 0xd4, 0x5b, 0xbb, 0xca, 0x18, 0x8b, 0xaf, 0xd4, 0xb7, 0xf5, 0x16, 0x19, 0xa7, - 0x95, 0x2c, 0x8b, 0x6d, 0x1d, 0x76, 0xf5, 0x7c, 0x04, 0xff, 0x52, 0xbf, 0x7c, 0x12, 0x5d, 0xa2, - 0xb1, 0x72, 0x81, 0xc5, 0x9e, 0x68, 0x76, 0x76, 0x2d, 0x9f, 0xa7, 0x5c, 0x9f, 0x1c, 0x2f, 0x3c, - 0xb1, 0xbc, 0x76, 0x0b, 0x9d, 0x6d, 0xd5, 0xb7, 0x5b, 0x48, 0x97, 0xc0, 0x19, 0xfc, 0xb9, 0x5e, - 0xef, 0xd5, 0xdb, 0xf9, 0x28, 0xfc, 0x19, 0x57, 0x1e, 0x66, 0x63, 0x1b, 0xfa, 0x9d, 0x41, 0xb3, - 0xa7, 0xef, 0xd2, 0xdc, 0xf9, 0x18, 0xf8, 0xca, 0x0c, 0xfb, 0xe2, 0x0b, 0x23, 0xeb, 0xae, 0x5e, - 0x37, 0x6d, 0xeb, 0xf8, 0x74, 0x54, 0x68, 0x5d, 0xed, 0x9a, 0x4d, 0xa3, 0x53, 0x6f, 0x71, 0xeb, - 0x04, 0x4c, 0x19, 0x6a, 0x7d, 0x86, 0xe5, 0x2a, 0xb5, 0x45, 0xc3, 0x68, 0xd5, 0x7a, 0xd6, 0x82, - 0xf2, 0x0c, 0xd6, 0x92, 0x52, 0xf2, 0x4c, 0xae, 0xd4, 0x96, 0x3b, 0xe6, 0x5c, 0xd1, 0x45, 0x32, - 0x80, 0xc4, 0x1d, 0x64, 0xa1, 0xe4, 0x22, 0x59, 0x40, 0xa2, 0x10, 0x6c, 0xa5, 0x52, 0xab, 0x34, - 0xef, 0xea, 0xbb, 0x5e, 0xd6, 0x18, 0x60, 0x49, 0x0f, 0xe6, 0xe5, 0x8d, 0x03, 0x96, 0x50, 0xce, - 0xb2, 0x89, 0x4a, 0xed, 0x76, 0xd3, 0x3f, 0x59, 0x0e, 0xa0, 0x31, 0x17, 0xf2, 0xb2, 0x64, 0x80, - 0x62, 0x7c, 0x1d, 0x95, 0x96, 0x51, 0x37, 0x5d, 0x64, 0x02, 0x90, 0x08, 0x27, 0xdd, 0x32, 0x06, - 0x10, 0x7f, 0x17, 0x52, 0x00, 0x92, 0x38, 0xb4, 0x69, 0xf6, 0x9a, 0x9d, 0x86, 0x0b, 0x4d, 0xd2, - 0x81, 0x93, 0xbf, 0xc5, 0x43, 0x08, 0x93, 0x8b, 0xe8, 0x80, 0x64, 0x2d, 0x52, 0x60, 0x7d, 0x7b, - 0x00, 0x4d, 0xb8, 0x90, 0x77, 0x7d, 0x0d, 0x80, 0x14, 0x5f, 0x68, 0xf9, 0xe9, 0xe5, 0x4f, 0xc2, - 0xc1, 0x05, 0x42, 0x6b, 0x21, 0xa7, 0x00, 0x09, 0x84, 0xd6, 0x42, 0x4e, 0x03, 0x32, 0x14, 0x5a, - 0x0b, 0x3b, 0x03, 0xd8, 0x50, 0x68, 0x2d, 0x2c, 0x0f, 0x58, 0x30, 0xb4, 0x16, 0x74, 0x16, 0xa0, - 0x60, 0x68, 0x2d, 0x68, 0x0a, 0xa0, 0x40, 0x68, 0x2d, 0xe4, 0x1c, 0x20, 0xc1, 0xd0, 0x5a, 0xd0, - 0x3d, 0x00, 0x05, 0x43, 0x6b, 0x41, 0xf7, 0x02, 0x94, 0x06, 0xc8, 0x13, 0x5a, 0x0b, 0x79, 0x5e, - 0x02, 0x28, 0x0b, 0x8b, 0xf7, 0xc6, 0xd6, 0xc2, 0x5e, 0x40, 0x6c, 0xc2, 0xc5, 0xbc, 0x2b, 0x7c, - 0x11, 0x31, 0x6f, 0x74, 0x0d, 0x2b, 0xdb, 0xf3, 0xf7, 0x41, 0xa2, 0xfb, 0xa2, 0xeb, 0x20, 0xf7, - 0x53, 0xd5, 0x79, 0xa2, 0xeb, 0x20, 0xd3, 0x80, 0x04, 0xa2, 0xeb, 0x60, 0xe7, 0x01, 0x0b, 0x44, - 0xd7, 0xc1, 0x54, 0xc0, 0xfc, 0xd1, 0x75, 0xa0, 0x0b, 0x00, 0xf9, 0xa3, 0xeb, 0x40, 0x0f, 0x00, - 0xe4, 0x8b, 0xae, 0x83, 0x3c, 0x08, 0x88, 0x3f, 0xba, 0x0e, 0x74, 0x11, 0x20, 0x7f, 0x74, 0x1d, - 0xe8, 0xff, 0xa8, 0xb9, 0x78, 0xa2, 0xeb, 0x20, 0xdf, 0xc2, 0xbe, 0xe3, 0x8f, 0xae, 0x83, 0x7d, - 0x1b, 0x31, 0x7f, 0x74, 0x1d, 0xec, 0x3b, 0x88, 0x29, 0xca, 0x7d, 0xe4, 0x12, 0xa3, 0xbb, 0xab, - 0xef, 0xd5, 0x07, 0x2d, 0x0c, 0xfc, 0x25, 0x0c, 0xaf, 0x16, 0x33, 0x7b, 0x03, 0x5d, 0xb9, 0x17, - 0xb9, 0x3c, 0xc8, 0xae, 0xc1, 0x43, 0x18, 0x65, 0x2d, 0x32, 0x57, 0x74, 0x60, 0xf0, 0xec, 0xc2, - 0x97, 0x31, 0xd4, 0x5a, 0x64, 0xa1, 0xa4, 0x4c, 0xb3, 0x49, 0x37, 0xdc, 0xae, 0xc1, 0x15, 0x8c, - 0xb7, 0x16, 0x9d, 0x2b, 0xce, 0x78, 0x2c, 0x7c, 0x2e, 0x1e, 0xc6, 0xa8, 0x6b, 0xd1, 0x85, 0x12, - 0x5a, 0x28, 0x4e, 0xe8, 0x5d, 0x83, 0x47, 0x30, 0xf6, 0x5a, 0x0c, 0x5c, 0x78, 0x2c, 0x7c, 0x2e, - 0x0a, 0x78, 0x04, 0x5a, 0x0c, 0x5c, 0xcc, 0x28, 0xe7, 0x71, 0x99, 0xfc, 0x20, 0x5c, 0x83, 0x47, - 0xf1, 0x24, 0xb4, 0xc4, 0xdc, 0x6c, 0x69, 0x76, 0xfe, 0xba, 0xa2, 0xa2, 0x13, 0xeb, 0x44, 0x5c, - 0x9b, 0x19, 0x3c, 0x12, 0x2d, 0x51, 0xbc, 0x3a, 0x7b, 0xad, 0x78, 0x0d, 0x3a, 0xae, 0xe2, 0x1c, - 0x8d, 0x6b, 0x33, 0x8b, 0x67, 0xa3, 0xc9, 0xfb, 0x7a, 0xab, 0x65, 0x3c, 0x3c, 0xad, 0x3e, 0x6b, - 0xf4, 0x5a, 0xbb, 0xe7, 0xc1, 0xdd, 0x05, 0x9c, 0x94, 0x9f, 0x96, 0x6b, 0xfc, 0x55, 0xbc, 0x17, - 0xb2, 0x5a, 0x72, 0xb1, 0xd9, 0xe8, 0x18, 0x7d, 0x9d, 0xaf, 0x7d, 0x33, 0xb8, 0xbb, 0xaf, 0xa1, - 0xd5, 0x84, 0x16, 0x7d, 0x04, 0x42, 0xec, 0x58, 0xf8, 0x76, 0xf7, 0x75, 0xb4, 0x50, 0xc0, 0x02, - 0xa2, 0xac, 0xb2, 0xd3, 0x81, 0xfe, 0x53, 0xeb, 0xd6, 0x77, 0x0e, 0xc0, 0xaa, 0x88, 0x6d, 0x68, - 0x31, 0x22, 0x4b, 0xb0, 0x98, 0x33, 0xc1, 0x56, 0x64, 0x1b, 0xcd, 0x61, 0x47, 0xf2, 0x19, 0x79, - 0xaa, 0xd0, 0x36, 0x2a, 0x61, 0x73, 0x22, 0xa3, 0x07, 0xd9, 0xd9, 0xe1, 0x06, 0x65, 0x9b, 0xcd, - 0x63, 0x9f, 0x0a, 0x98, 0x8d, 0xf0, 0xb6, 0x80, 0x2d, 0x8b, 0xcc, 0x1e, 0x60, 0xf9, 0xa1, 0xb6, - 0x65, 0x5b, 0x5d, 0xc5, 0xee, 0xe5, 0xb7, 0x1a, 0xe1, 0xeb, 0x1a, 0x36, 0x32, 0x77, 0xf9, 0xfe, - 0x66, 0x66, 0x1b, 0x5d, 0xc7, 0x9e, 0xe6, 0xba, 0x0a, 0xf4, 0x35, 0xdb, 0x4a, 0xc3, 0xf6, 0x66, - 0xad, 0x3e, 0x3f, 0xd4, 0xac, 0x6c, 0xab, 0x0f, 0xa3, 0xd8, 0xb3, 0xfc, 0x66, 0x23, 0xd6, 0xf5, - 0x11, 0x9a, 0x29, 0x64, 0x36, 0xcf, 0xc6, 0xec, 0x2b, 0xa3, 0xd1, 0x33, 0x06, 0xdd, 0x7c, 0x05, - 0xee, 0x0d, 0x56, 0xbc, 0x6f, 0x48, 0x51, 0xd8, 0x5a, 0x61, 0x09, 0xad, 0x38, 0x8d, 0x3b, 0xe5, - 0xb4, 0x75, 0xf0, 0x38, 0x9a, 0xc6, 0xad, 0x1c, 0x9a, 0x5d, 0xe5, 0x9c, 0xf6, 0x34, 0xa4, 0xca, - 0x28, 0x9a, 0xad, 0x1e, 0x88, 0x36, 0x75, 0xd1, 0x95, 0x2a, 0xdc, 0xcf, 0xa9, 0xa0, 0x76, 0x59, - 0xc2, 0xdb, 0x93, 0xdb, 0x79, 0xe7, 0x1b, 0xb2, 0xfb, 0xb4, 0x6d, 0xe7, 0x9b, 0x60, 0xd8, 0xee, - 0xb3, 0x24, 0xb8, 0x9e, 0x93, 0x40, 0x66, 0xa1, 0x92, 0x4a, 0xb1, 0xd8, 0x67, 0xaa, 0xcb, 0xb7, - 0xe4, 0x13, 0xf8, 0x6b, 0xb1, 0x5a, 0x5d, 0x81, 0xc8, 0xa5, 0x59, 0x7c, 0xf1, 0xa9, 0xad, 0xf2, - 0xa6, 0x1c, 0x51, 0x72, 0x2c, 0x53, 0x59, 0x5e, 0x5b, 0x2a, 0x6f, 0xac, 0x6f, 0x2c, 0xaf, 0x6d, - 0xc9, 0x51, 0xc4, 0x2a, 0x2b, 0xd5, 0x1b, 0x5b, 0x72, 0x4c, 0x49, 0xb2, 0x28, 0x8e, 0xc5, 0x15, - 0xc6, 0x12, 0x9b, 0x5b, 0x80, 0x2f, 0xc9, 0x09, 0xf4, 0xb2, 0xb5, 0xbc, 0x5a, 0x96, 0x93, 0x68, - 0xb9, 0x75, 0x7b, 0x7d, 0xa5, 0x2c, 0xa7, 0xf0, 0xe7, 0x8d, 0x8d, 0x8d, 0x1b, 0x4f, 0xc9, 0x69, - 0x24, 0xad, 0xde, 0x58, 0x97, 0x19, 0xc1, 0x37, 0x16, 0x01, 0xce, 0x80, 0x16, 0x4c, 0x55, 0x6e, - 0xaf, 0xdd, 0xdc, 0x5a, 0xae, 0xae, 0xc9, 0x59, 0xf5, 0x25, 0x89, 0xb1, 0x25, 0x63, 0xf3, 0xa0, - 0xd9, 0x25, 0x3d, 0x08, 0xde, 0xfb, 0xf0, 0xbb, 0x46, 0x69, 0x61, 0x69, 0xa4, 0x93, 0x2c, 0x4b, - 0x63, 0x7b, 0xbc, 0x20, 0x48, 0x1f, 0x25, 0xfd, 0xa3, 0x0b, 0x25, 0x52, 0x46, 0x09, 0x65, 0x92, - 0x65, 0x68, 0xb4, 0x4f, 0x1d, 0x84, 0x24, 0x51, 0x5a, 0x99, 0x65, 0x69, 0x1c, 0xe4, 0x27, 0x95, - 0x1b, 0xce, 0x0b, 0x7b, 0xf6, 0x02, 0xfe, 0xe0, 0x27, 0xb5, 0xc0, 0xd2, 0xce, 0x1f, 0xe8, 0x94, - 0xb8, 0xd6, 0xaa, 0x64, 0x7b, 0x55, 0x7c, 0xd0, 0x9a, 0x6a, 0x82, 0x22, 0x3d, 0xc5, 0xc6, 0xd6, - 0x8c, 0xce, 0x3a, 0xa5, 0x27, 0x6d, 0x28, 0xcd, 0xa4, 0x7a, 0x1e, 0x6f, 0xd9, 0xb8, 0x7a, 0x8e, - 0x31, 0x0f, 0x30, 0xc6, 0xa4, 0x6d, 0x0e, 0x60, 0xfe, 0xaa, 0xd3, 0x2c, 0xb1, 0x5a, 0xbf, 0xbb, - 0x55, 0x6f, 0x28, 0xa7, 0x19, 0x6b, 0xd5, 0xfb, 0x26, 0x6c, 0x0c, 0x0f, 0xf0, 0xbf, 0xf0, 0x4f, - 0xc2, 0xee, 0xa7, 0x7e, 0x9e, 0xb1, 0x6a, 0x6b, 0x77, 0x55, 0xef, 0xf7, 0xeb, 0x0d, 0x5d, 0xb9, - 0xc2, 0x12, 0x1d, 0x70, 0xa3, 0xa3, 0x74, 0x46, 0x49, 0x7a, 0xce, 0xdd, 0x90, 0x6b, 0x55, 0x58, - 0x23, 0x13, 0x25, 0xc3, 0xa2, 0xa0, 0xdf, 0x49, 0x3e, 0xc7, 0xa7, 0x4e, 0xb3, 0x84, 0x35, 0x0c, - 0xaa, 0xbc, 0x53, 0x6f, 0xeb, 0x79, 0xee, 0xbf, 0xc7, 0xd8, 0x9a, 0xfe, 0xec, 0x31, 0xfc, 0xbb, - 0x56, 0x23, 0xfc, 0x47, 0xa7, 0x2e, 0x8f, 0xf6, 0x8f, 0x47, 0x0b, 0xaf, 0x87, 0xdd, 0x1a, 0x3f, - 0x06, 0x92, 0xf2, 0xea, 0x4d, 0x96, 0x5d, 0xee, 0x74, 0xf4, 0x9e, 0x3d, 0x2b, 0x30, 0xf6, 0x8d, - 0xbe, 0x69, 0xbd, 0x1a, 0x14, 0x16, 0xeb, 0x1a, 0x3d, 0x93, 0xaf, 0x5b, 0x8b, 0xc1, 0x2d, 0x33, - 0xa3, 0x4c, 0xb0, 0xf4, 0x8e, 0x01, 0x94, 0x1d, 0x5c, 0x1a, 0x36, 0xe8, 0x94, 0x7a, 0xc0, 0xb2, - 0x55, 0x73, 0xdf, 0x75, 0x02, 0xab, 0x39, 0xd0, 0x0f, 0x69, 0xd6, 0x28, 0x3e, 0x16, 0xbe, 0x50, - 0x6f, 0x0d, 0xf8, 0xdb, 0x21, 0xab, 0x8c, 0xb3, 0xc4, 0xb3, 0x7a, 0xb3, 0xb1, 0x6f, 0x12, 0x37, - 0x02, 0xdd, 0x25, 0xde, 0xc4, 0x05, 0xc0, 0xa3, 0x01, 0x77, 0x79, 0xda, 0xdd, 0xa5, 0x77, 0x5d, - 0x97, 0x53, 0xa9, 0x5d, 0xf9, 0x4b, 0xf0, 0x2f, 0xa2, 0x7e, 0x23, 0xca, 0xd2, 0xab, 0x87, 0xf6, - 0x54, 0xe0, 0x7d, 0xc7, 0x18, 0x74, 0xf8, 0x82, 0xe3, 0xce, 0x86, 0x9d, 0x77, 0xca, 0x9d, 0x81, - 0x61, 0xea, 0x34, 0x55, 0x1a, 0x97, 0xd5, 0xd5, 0x4d, 0x98, 0x08, 0x45, 0x9c, 0x33, 0x6f, 0x5c, - 0x34, 0xaf, 0x72, 0x91, 0x25, 0x0c, 0xdc, 0x5a, 0x1f, 0x1e, 0x1e, 0x51, 0xbf, 0x9d, 0x6f, 0xcb, - 0x0f, 0xb1, 0x34, 0xb4, 0xb1, 0x1a, 0x77, 0x99, 0x0d, 0x9a, 0xfa, 0x5c, 0x5e, 0x61, 0xa9, 0xed, - 0xe6, 0x81, 0xde, 0xdf, 0x87, 0xf8, 0x25, 0x61, 0xf2, 0xf1, 0xe2, 0x59, 0xd7, 0xd2, 0xd9, 0x59, - 0xe1, 0xa6, 0xd1, 0x32, 0x7a, 0xca, 0x0c, 0x54, 0x8e, 0xd1, 0xd6, 0xf9, 0x91, 0xa5, 0xa8, 0xc7, - 0xdd, 0x3b, 0xca, 0x7a, 0x13, 0x8c, 0x78, 0xad, 0x4c, 0xf0, 0x95, 0x6c, 0xe3, 0x9d, 0x0c, 0xaf, - 0x1f, 0x54, 0xa5, 0x32, 0xce, 0xd8, 0xd8, 0xc3, 0x4b, 0x03, 0x2a, 0x1a, 0x2e, 0xfb, 0xa9, 0x69, - 0xa8, 0x2e, 0x87, 0xe1, 0x54, 0x17, 0x4f, 0xf8, 0x34, 0x1e, 0xb6, 0x0a, 0xf1, 0xe1, 0x2b, 0x80, - 0x0e, 0xb2, 0x51, 0xc6, 0x86, 0x05, 0x1d, 0x64, 0x69, 0xa3, 0x5c, 0x5e, 0x83, 0x8e, 0x85, 0xbd, - 0x6b, 0xe5, 0x76, 0x59, 0x8e, 0x78, 0xce, 0xe5, 0x2b, 0x12, 0x8b, 0x96, 0xef, 0x9a, 0x78, 0x04, - 0xb8, 0x36, 0x9e, 0x73, 0xc5, 0x19, 0x16, 0x6b, 0x1b, 0x3d, 0x5d, 0x99, 0x1c, 0xb1, 0x68, 0x78, - 0x59, 0x60, 0xe8, 0x3d, 0xef, 0x58, 0xe0, 0x17, 0xcf, 0xb3, 0x98, 0xa9, 0x83, 0x9f, 0x91, 0x8c, - 0x7d, 0x72, 0x7a, 0x01, 0x4a, 0x63, 0xd0, 0xde, 0xd6, 0x7b, 0xa3, 0x8d, 0x9a, 0xb4, 0x81, 0x4f, - 0x32, 0xf9, 0xa6, 0xd1, 0xee, 0xb6, 0xf4, 0xbb, 0xe0, 0x55, 0xef, 0xf4, 0xa1, 0x49, 0x63, 0x42, - 0xec, 0x35, 0x7b, 0x94, 0xde, 0x28, 0xa1, 0x21, 0x17, 0xfb, 0x3a, 0x24, 0xf3, 0x2e, 0x4f, 0x70, - 0x84, 0xcd, 0xfd, 0x66, 0x0f, 0xd3, 0x1a, 0xdb, 0xc5, 0x12, 0xcb, 0xdd, 0xe2, 0x5a, 0xa4, 0x6f, - 0xb9, 0x86, 0x47, 0x76, 0xd6, 0x1e, 0xa2, 0x07, 0x39, 0x04, 0xe2, 0xe9, 0xf2, 0x46, 0x15, 0xa2, - 0x03, 0x61, 0xaa, 0xae, 0x95, 0x21, 0x36, 0xf0, 0x63, 0xeb, 0xc9, 0xaa, 0x2f, 0x34, 0xf7, 0xb0, - 0xac, 0xb3, 0xba, 0x4d, 0xdd, 0x24, 0x04, 0xdb, 0x4a, 0x52, 0x8b, 0xa4, 0x24, 0x35, 0xc9, 0xe2, - 0xe5, 0x76, 0xd7, 0x3c, 0x54, 0x75, 0x96, 0xb1, 0x8c, 0x56, 0x9a, 0xd0, 0x9f, 0x0a, 0x2c, 0xd9, - 0xb6, 0x76, 0x24, 0xd1, 0x9d, 0xe8, 0x3d, 0x78, 0xd7, 0xce, 0xfe, 0x0d, 0x77, 0x51, 0xd2, 0x53, - 0xc5, 0x56, 0x19, 0x44, 0x78, 0x19, 0xf0, 0x1a, 0x89, 0x62, 0x8d, 0xa8, 0x25, 0x96, 0xe4, 0xf2, - 0xae, 0x4f, 0x2d, 0x9c, 0x2b, 0x3d, 0x7e, 0xf4, 0xbc, 0x4f, 0x40, 0x3e, 0x50, 0xf6, 0x58, 0x83, - 0x54, 0xb7, 0xea, 0x73, 0x31, 0x96, 0xb2, 0xb7, 0x0e, 0xbc, 0x04, 0x17, 0x63, 0xc4, 0xb0, 0x65, - 0xf4, 0x24, 0x4b, 0x5a, 0xf2, 0xcb, 0x6a, 0x18, 0x28, 0x9e, 0xed, 0x41, 0xb8, 0x20, 0xa2, 0x8e, - 0x64, 0x3e, 0xcd, 0xd2, 0x8e, 0xbc, 0xa2, 0xc2, 0xb7, 0x84, 0xb2, 0x3b, 0x0e, 0xe6, 0x71, 0x57, - 0x1e, 0x9f, 0x86, 0x1b, 0xcb, 0x12, 0x50, 0xf4, 0x01, 0xc0, 0x16, 0xc5, 0xce, 0x38, 0x98, 0x27, - 0x3d, 0x52, 0xf8, 0x0c, 0x4e, 0x4a, 0x22, 0x89, 0x6a, 0xc6, 0x15, 0xc0, 0x79, 0x24, 0x70, 0x61, - 0x44, 0x79, 0xee, 0xca, 0x5e, 0x15, 0x11, 0x1e, 0x17, 0xa8, 0x9a, 0xd1, 0x62, 0x37, 0x8f, 0x6e, - 0x49, 0xec, 0x52, 0x19, 0x79, 0x14, 0xee, 0x29, 0x62, 0xf3, 0x05, 0x66, 0x5d, 0x59, 0xeb, 0x0c, - 0xd3, 0xf5, 0xe8, 0x68, 0xd9, 0x47, 0x31, 0x7c, 0x98, 0x3f, 0x70, 0x3d, 0x62, 0xfd, 0xe7, 0xdd, - 0x83, 0xb5, 0x43, 0xcc, 0xcb, 0x5f, 0xe3, 0x15, 0x07, 0x41, 0x04, 0xc2, 0x7a, 0xb3, 0xb3, 0x07, - 0x97, 0x27, 0x6e, 0x27, 0x0a, 0x3f, 0xf9, 0x21, 0xac, 0xe1, 0xa0, 0x4c, 0x83, 0xb1, 0x47, 0x70, - 0x54, 0x01, 0xc1, 0x50, 0x5b, 0xab, 0x77, 0xe0, 0x3a, 0x24, 0xcb, 0x4e, 0xbd, 0x03, 0x7b, 0x8b, - 0xf6, 0x07, 0xdb, 0x79, 0x25, 0xf8, 0xe9, 0x64, 0x73, 0xb0, 0xed, 0x1c, 0xa9, 0xc2, 0x52, 0x90, - 0x0a, 0xb5, 0x2f, 0xea, 0x3d, 0x23, 0x3f, 0x49, 0xfb, 0x3f, 0x71, 0xcc, 0x1e, 0x00, 0xd7, 0x6a, - 0xc6, 0xeb, 0x29, 0xcb, 0xa4, 0x0e, 0xef, 0xfd, 0x9a, 0x74, 0x55, 0x5d, 0x65, 0x59, 0x5b, 0x49, - 0x51, 0xc5, 0x5c, 0xc1, 0x64, 0x04, 0x9f, 0x94, 0xd3, 0xe3, 0xc5, 0x7b, 0xdc, 0xd5, 0x78, 0xcd, - 0xf8, 0xf6, 0x55, 0x39, 0xb0, 0x00, 0x49, 0xfd, 0xa6, 0x04, 0xb5, 0x04, 0x0d, 0xc5, 0x36, 0xc6, - 0xe4, 0xde, 0x86, 0x44, 0xec, 0x93, 0x3f, 0x7c, 0x2f, 0x67, 0xe9, 0x4f, 0x5b, 0xa0, 0x46, 0x9c, - 0xc7, 0x01, 0xd4, 0x04, 0x1c, 0x44, 0x9f, 0xd7, 0x36, 0x64, 0x48, 0x06, 0xff, 0xb2, 0xcd, 0x62, - 0xce, 0xf3, 0xe0, 0x2c, 0x1b, 0xa3, 0xf3, 0x72, 0xa0, 0xa4, 0xf3, 0x28, 0xc8, 0xb1, 0x24, 0xaf, - 0x96, 0x3e, 0x7d, 0xb3, 0x4a, 0x63, 0xff, 0x20, 0xf1, 0xc3, 0x2f, 0x87, 0xa4, 0xfa, 0xff, 0x2c, - 0x45, 0x1d, 0x15, 0xee, 0x7f, 0xe5, 0x7e, 0x26, 0x35, 0xf2, 0x3a, 0x35, 0xec, 0x93, 0x1e, 0xa9, - 0x63, 0xc1, 0x85, 0xa5, 0xa9, 0x71, 0x26, 0x2d, 0xa1, 0x38, 0xb9, 0xcb, 0x8b, 0x45, 0xad, 0x58, - 0x64, 0xb8, 0xdc, 0x45, 0x64, 0x80, 0x81, 0x7c, 0xd6, 0x4f, 0xc6, 0x9f, 0x87, 0xfc, 0x6b, 0x1c, - 0x0a, 0x20, 0xca, 0x7c, 0x58, 0xe7, 0xba, 0x01, 0x5b, 0x41, 0x6c, 0x8f, 0xae, 0x47, 0x49, 0xfd, - 0x20, 0xca, 0xc6, 0xad, 0x1e, 0xf1, 0x64, 0xd3, 0xdc, 0x5f, 0xad, 0x77, 0x95, 0xc7, 0x58, 0x16, - 0x5b, 0x45, 0xad, 0x5d, 0xef, 0x76, 0x31, 0xf7, 0x25, 0xba, 0xbb, 0x1e, 0x1a, 0x6a, 0x35, 0x96, - 0x7d, 0x61, 0x0d, 0x8c, 0x57, 0xb9, 0x6d, 0xb9, 0x63, 0xf6, 0x0e, 0x95, 0x4f, 0xb0, 0x4c, 0xbb, - 0xdf, 0x70, 0xf8, 0x11, 0xe2, 0x5f, 0x0a, 0xe5, 0xaf, 0xf6, 0x1b, 0x3e, 0x3a, 0xcc, 0x8f, 0xcd, - 0xc6, 0xe1, 0x47, 0x8f, 0x98, 0x1f, 0xcb, 0xcf, 0xe7, 0x40, 0x03, 0xc1, 0x0a, 0x89, 0x6b, 0x1a, - 0xa8, 0x03, 0xe9, 0x20, 0x33, 0xc5, 0x8b, 0xa1, 0x74, 0xa8, 0xf0, 0x2d, 0x03, 0xfe, 0x43, 0xdc, - 0xa9, 0x22, 0x93, 0x87, 0xf6, 0xe3, 0x11, 0x2f, 0x71, 0xbf, 0x78, 0x49, 0x6b, 0x91, 0x6b, 0xd2, - 0xd4, 0xa7, 0x58, 0x2e, 0xb8, 0x07, 0x0f, 0x45, 0x01, 0xc5, 0xe0, 0xa1, 0x64, 0x8a, 0x67, 0x3c, - 0x5f, 0x69, 0xbd, 0xc7, 0x42, 0xbe, 0x60, 0xfe, 0xa1, 0xfd, 0x78, 0x9c, 0xa5, 0x02, 0xe2, 0x89, - 0x38, 0x8f, 0xb2, 0x31, 0xdf, 0x26, 0xbc, 0x84, 0xf4, 0x88, 0x05, 0xab, 0xef, 0x47, 0x59, 0xbc, - 0xda, 0xd1, 0x8d, 0x3d, 0xd0, 0x01, 0xbe, 0xb6, 0xfd, 0xf8, 0x09, 0x10, 0x0b, 0xfe, 0x96, 0xed, - 0x19, 0xb2, 0x1b, 0x36, 0x0c, 0x4d, 0x0e, 0xb5, 0x6b, 0xdf, 0xa0, 0xdd, 0xab, 0x61, 0x50, 0x09, - 0x36, 0x6a, 0xef, 0x98, 0xdd, 0xa4, 0xed, 0x49, 0x3c, 0x0d, 0xda, 0x36, 0xf3, 0xb6, 0x66, 0x7b, - 0xcc, 0xdb, 0x94, 0x6d, 0xaa, 0xa7, 0x09, 0x3b, 0x66, 0x9e, 0xee, 0xeb, 0x1d, 0xb3, 0x5b, 0x2f, - 0x8c, 0x5d, 0x09, 0xf4, 0xdd, 0x70, 0xdd, 0x05, 0xc6, 0x97, 0x71, 0x7f, 0xb6, 0xa4, 0xc8, 0x09, - 0xbe, 0x3a, 0x93, 0x6d, 0x72, 0xcf, 0x92, 0xd5, 0x32, 0x55, 0xad, 0xe7, 0xd4, 0x29, 0xf4, 0x85, - 0x4a, 0x8d, 0xaa, 0x17, 0x6c, 0xcf, 0x41, 0x7d, 0xd6, 0x56, 0xea, 0xbd, 0x06, 0x18, 0xd4, 0xe0, - 0xb9, 0xe1, 0x3c, 0x30, 0x30, 0xf8, 0x39, 0xfb, 0xf8, 0x76, 0x69, 0x40, 0x9a, 0x3a, 0x89, 0xbb, - 0xe5, 0x32, 0x8d, 0xca, 0x1d, 0xbb, 0x7a, 0x7c, 0x11, 0x24, 0xc3, 0xa0, 0x03, 0x82, 0x66, 0x31, - 0xcd, 0x92, 0xa6, 0xd1, 0x6b, 0xd7, 0x4d, 0x43, 0xfd, 0x2e, 0xbc, 0xe3, 0x40, 0xf0, 0xb4, 0x01, - 0xb8, 0x43, 0x97, 0x71, 0xa6, 0x5d, 0x3f, 0x80, 0xba, 0xd2, 0x6b, 0x3b, 0x3d, 0x3b, 0x9d, 0x64, - 0x5b, 0x38, 0xd1, 0x81, 0xe1, 0x84, 0xe3, 0x96, 0x52, 0x48, 0x58, 0xd1, 0x1d, 0xb7, 0xd4, 0x5b, - 0xd2, 0x0a, 0x2d, 0x30, 0x4c, 0xbd, 0xdd, 0xad, 0xed, 0xd0, 0x39, 0xe1, 0x99, 0x5c, 0x62, 0x51, - 0x68, 0xe0, 0x74, 0x44, 0x47, 0x44, 0x70, 0x9a, 0x45, 0xa1, 0x33, 0xd0, 0xc1, 0x65, 0x8a, 0x13, - 0x9e, 0x6b, 0x87, 0x37, 0xd1, 0xc7, 0x4f, 0x38, 0xfb, 0xb8, 0x9c, 0x63, 0xd1, 0x4a, 0xb5, 0x8a, - 0x77, 0x0a, 0xfc, 0x6f, 0x56, 0x96, 0xb4, 0x07, 0x59, 0xaa, 0xd1, 0xd3, 0x75, 0x2c, 0x97, 0xd1, - 0x22, 0xef, 0x19, 0xec, 0xc0, 0xda, 0x2d, 0x96, 0xdc, 0xe1, 0x22, 0x4f, 0x09, 0x51, 0xe6, 0xf9, - 0xef, 0xf1, 0xe7, 0xd3, 0x94, 0x0b, 0x07, 0x65, 0xa1, 0x56, 0x01, 0xc9, 0x5c, 0x3b, 0xca, 0xcf, - 0xf3, 0xbc, 0x33, 0x8a, 0xfc, 0x94, 0xd8, 0x44, 0xc7, 0xb0, 0xbf, 0x5f, 0xd5, 0x76, 0x29, 0x97, - 0x95, 0xb3, 0xc3, 0x97, 0xbb, 0xed, 0x52, 0x27, 0x05, 0x32, 0xc7, 0x64, 0x0f, 0x8b, 0x54, 0xba, - 0x88, 0xb4, 0x47, 0xf7, 0xba, 0x9f, 0x44, 0xa9, 0x2f, 0x22, 0x35, 0x48, 0x8f, 0x0d, 0x91, 0x40, - 0x8b, 0x08, 0x48, 0xfb, 0x74, 0x87, 0xfb, 0x37, 0x35, 0x38, 0x72, 0xaa, 0x26, 0xe9, 0xb3, 0x61, - 0x96, 0x78, 0xae, 0x67, 0x48, 0xbd, 0xf9, 0x59, 0xfd, 0x23, 0xe7, 0x3a, 0x20, 0xa9, 0x35, 0xcc, - 0x12, 0xcf, 0xd5, 0x22, 0x25, 0x36, 0xcf, 0x14, 0x6f, 0xd8, 0x79, 0x77, 0x13, 0xd1, 0xda, 0xa4, - 0x53, 0x47, 0xd0, 0xc4, 0xb3, 0x75, 0x48, 0xc6, 0x2e, 0xb0, 0x49, 0xef, 0x1a, 0x8f, 0x31, 0x9d, - 0x01, 0xbc, 0xdc, 0x48, 0x9e, 0x78, 0xbe, 0x2e, 0xf0, 0x64, 0xad, 0xc8, 0x72, 0x1e, 0x1e, 0x4a, - 0x22, 0x11, 0xe7, 0x0e, 0xa9, 0xf8, 0x40, 0x1c, 0xa9, 0x4a, 0x45, 0xac, 0x1e, 0x5d, 0x31, 0xfe, - 0xa4, 0xa2, 0x87, 0x83, 0x88, 0xd4, 0xa7, 0x8b, 0xec, 0x69, 0xdf, 0xf2, 0x74, 0x14, 0x86, 0x02, - 0x8e, 0x49, 0xbd, 0xe6, 0x62, 0xa8, 0x41, 0xc1, 0xfb, 0x26, 0xd3, 0x34, 0x36, 0x7e, 0xfc, 0x12, - 0x7c, 0x5e, 0xe2, 0xaf, 0x80, 0xb9, 0x02, 0x3e, 0x10, 0xb4, 0xab, 0x6c, 0xec, 0xd8, 0x85, 0xf8, - 0x82, 0xc4, 0x65, 0x37, 0x52, 0x21, 0x2d, 0xc6, 0x8e, 0x5d, 0x8c, 0x2f, 0x4a, 0xfc, 0x75, 0x54, - 0x2a, 0x06, 0x68, 0xe2, 0x83, 0x7d, 0x89, 0x6b, 0xea, 0x48, 0x69, 0x0e, 0xb2, 0x62, 0xfc, 0xf8, - 0x05, 0xf9, 0xb2, 0x44, 0x15, 0x19, 0x29, 0x95, 0x82, 0x3c, 0xf1, 0x7c, 0xaf, 0x48, 0x54, 0x93, - 0x91, 0xd2, 0xbc, 0x97, 0x77, 0x74, 0x51, 0xbe, 0x2a, 0x51, 0x55, 0x46, 0x4a, 0x0b, 0x41, 0x9e, - 0x78, 0xbe, 0xd7, 0x48, 0x3f, 0x01, 0xef, 0x2a, 0x1c, 0x43, 0xee, 0x63, 0x14, 0xe6, 0xeb, 0x12, - 0x55, 0x66, 0xa4, 0x74, 0x6d, 0x88, 0x28, 0x9e, 0xf1, 0x0d, 0x89, 0x6a, 0x33, 0x52, 0xba, 0xae, - 0x5d, 0x63, 0xf2, 0xc7, 0x29, 0xce, 0x37, 0x25, 0xaa, 0xce, 0xc8, 0xfc, 0xcc, 0x30, 0x53, 0x3c, - 0xe7, 0x5b, 0x12, 0xd5, 0x67, 0x64, 0x7e, 0x16, 0xa2, 0x93, 0x3d, 0x6e, 0x81, 0xbe, 0xed, 0x79, - 0x67, 0x6b, 0x37, 0x3c, 0x51, 0x3d, 0xb2, 0x48, 0xdf, 0x21, 0x5d, 0xa8, 0x8d, 0x3d, 0xce, 0x1f, - 0xb3, 0x9c, 0xa0, 0x3d, 0xe6, 0xe6, 0xdd, 0x91, 0x15, 0xfb, 0xae, 0x44, 0x25, 0x9b, 0xb5, 0x3c, - 0x90, 0xbd, 0xf6, 0x39, 0x77, 0xed, 0x47, 0x55, 0xef, 0x7b, 0xd2, 0xc7, 0x2a, 0x5f, 0xfc, 0x8c, - 0x02, 0xa1, 0x89, 0xdd, 0x2d, 0xce, 0xcc, 0x7a, 0x2f, 0x63, 0xef, 0x17, 0x14, 0x5e, 0xb6, 0x99, - 0x62, 0xce, 0xf3, 0xe9, 0x08, 0x3f, 0xa1, 0x58, 0xbc, 0x62, 0x28, 0xef, 0x05, 0x21, 0x6f, 0x2e, - 0x94, 0xf7, 0xa2, 0x90, 0x57, 0x0a, 0xe5, 0xbd, 0x24, 0xe4, 0xcd, 0x87, 0xf2, 0x5e, 0x16, 0xf2, - 0x16, 0x42, 0x79, 0xaf, 0x08, 0x79, 0x57, 0x43, 0x79, 0xaf, 0x0a, 0x79, 0xd7, 0x42, 0x79, 0xaf, - 0x09, 0x79, 0xd7, 0x43, 0x79, 0xaf, 0x8b, 0x78, 0xb3, 0x33, 0xa1, 0xbc, 0x37, 0x84, 0xbc, 0xf0, - 0x7c, 0x79, 0x53, 0xc8, 0x0b, 0xcf, 0x97, 0xb7, 0x84, 0xbc, 0xf0, 0x7c, 0x79, 0x5b, 0xc8, 0x0b, - 0xcf, 0x97, 0x77, 0x84, 0xbc, 0xf0, 0x7c, 0x79, 0x57, 0xc8, 0x0b, 0xcf, 0x97, 0xf7, 0x84, 0xbc, - 0xf0, 0x7c, 0xf9, 0xbe, 0x90, 0x17, 0x9e, 0x2f, 0x3f, 0x10, 0xf2, 0xc2, 0xf3, 0xe5, 0x87, 0x22, - 0x5e, 0x31, 0x3c, 0x5f, 0x7e, 0x24, 0xe4, 0x85, 0xe7, 0xcb, 0x8f, 0x85, 0xbc, 0xf0, 0x7c, 0xf9, - 0x89, 0x90, 0x17, 0x9e, 0x2f, 0x3f, 0x15, 0xf2, 0xc2, 0xf3, 0xe5, 0x67, 0x42, 0x5e, 0x78, 0xbe, - 0xfc, 0x5c, 0xc8, 0x0b, 0xcf, 0x97, 0x5f, 0x08, 0x79, 0xe1, 0xf9, 0xf2, 0x4b, 0x21, 0x2f, 0x3c, - 0x5f, 0xde, 0x17, 0xf2, 0xc2, 0xf3, 0xe5, 0x57, 0x22, 0xde, 0x5c, 0x78, 0xbe, 0xfc, 0x5a, 0xc8, - 0x0b, 0xcf, 0x97, 0xdf, 0x08, 0x79, 0xe1, 0xf9, 0xf2, 0x5b, 0x21, 0x2f, 0x3c, 0x5f, 0x7e, 0x27, - 0xe4, 0x85, 0xe7, 0xcb, 0xef, 0x85, 0xbc, 0xf0, 0x7c, 0xf9, 0x83, 0x90, 0x17, 0x9e, 0x2f, 0x7f, - 0x14, 0xf2, 0xc2, 0xf3, 0xe5, 0x4f, 0x42, 0x5e, 0x78, 0xbe, 0xfc, 0x59, 0xc8, 0x0b, 0xcf, 0x97, - 0xbf, 0x88, 0x78, 0xa5, 0xf0, 0x7c, 0xf9, 0xab, 0x90, 0x17, 0x9e, 0x2f, 0x7f, 0x13, 0xf2, 0xc2, - 0xf3, 0xe5, 0x03, 0x21, 0x2f, 0x3c, 0x5f, 0xfe, 0x2e, 0xe4, 0x85, 0xe7, 0xcb, 0x3f, 0x84, 0xbc, - 0xf0, 0x7c, 0xf9, 0xa7, 0x90, 0x17, 0x9e, 0x2f, 0x1f, 0x0a, 0x79, 0xe1, 0xf9, 0xf2, 0x91, 0x90, - 0x17, 0x9e, 0x2f, 0xff, 0x12, 0xf2, 0xc2, 0xf3, 0xe5, 0xdf, 0x22, 0xde, 0x7c, 0x78, 0xbe, 0xfc, - 0x67, 0x34, 0xef, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x8e, 0xa4, 0xcf, 0x8d, 0xf9, 0x2b, 0x00, - 0x00, -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto b/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto deleted file mode 100644 index 698c8ce24..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/testdata/test.proto +++ /dev/null @@ -1,535 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// A feature-rich test file for the protocol compiler and libraries. - -syntax = "proto2"; - -package testdata; - -enum FOO { FOO1 = 1; }; - -message GoEnum { - required FOO foo = 1; -} - -message GoTestField { - required string Label = 1; - required string Type = 2; -} - -message GoTest { - // An enum, for completeness. - enum KIND { - VOID = 0; - - // Basic types - BOOL = 1; - BYTES = 2; - FINGERPRINT = 3; - FLOAT = 4; - INT = 5; - STRING = 6; - TIME = 7; - - // Groupings - TUPLE = 8; - ARRAY = 9; - MAP = 10; - - // Table types - TABLE = 11; - - // Functions - FUNCTION = 12; // last tag - }; - - // Some typical parameters - required KIND Kind = 1; - optional string Table = 2; - optional int32 Param = 3; - - // Required, repeated and optional foreign fields. - required GoTestField RequiredField = 4; - repeated GoTestField RepeatedField = 5; - optional GoTestField OptionalField = 6; - - // Required fields of all basic types - required bool F_Bool_required = 10; - required int32 F_Int32_required = 11; - required int64 F_Int64_required = 12; - required fixed32 F_Fixed32_required = 13; - required fixed64 F_Fixed64_required = 14; - required uint32 F_Uint32_required = 15; - required uint64 F_Uint64_required = 16; - required float F_Float_required = 17; - required double F_Double_required = 18; - required string F_String_required = 19; - required bytes F_Bytes_required = 101; - required sint32 F_Sint32_required = 102; - required sint64 F_Sint64_required = 103; - - // Repeated fields of all basic types - repeated bool F_Bool_repeated = 20; - repeated int32 F_Int32_repeated = 21; - repeated int64 F_Int64_repeated = 22; - repeated fixed32 F_Fixed32_repeated = 23; - repeated fixed64 F_Fixed64_repeated = 24; - repeated uint32 F_Uint32_repeated = 25; - repeated uint64 F_Uint64_repeated = 26; - repeated float F_Float_repeated = 27; - repeated double F_Double_repeated = 28; - repeated string F_String_repeated = 29; - repeated bytes F_Bytes_repeated = 201; - repeated sint32 F_Sint32_repeated = 202; - repeated sint64 F_Sint64_repeated = 203; - - // Optional fields of all basic types - optional bool F_Bool_optional = 30; - optional int32 F_Int32_optional = 31; - optional int64 F_Int64_optional = 32; - optional fixed32 F_Fixed32_optional = 33; - optional fixed64 F_Fixed64_optional = 34; - optional uint32 F_Uint32_optional = 35; - optional uint64 F_Uint64_optional = 36; - optional float F_Float_optional = 37; - optional double F_Double_optional = 38; - optional string F_String_optional = 39; - optional bytes F_Bytes_optional = 301; - optional sint32 F_Sint32_optional = 302; - optional sint64 F_Sint64_optional = 303; - - // Default-valued fields of all basic types - optional bool F_Bool_defaulted = 40 [default=true]; - optional int32 F_Int32_defaulted = 41 [default=32]; - optional int64 F_Int64_defaulted = 42 [default=64]; - optional fixed32 F_Fixed32_defaulted = 43 [default=320]; - optional fixed64 F_Fixed64_defaulted = 44 [default=640]; - optional uint32 F_Uint32_defaulted = 45 [default=3200]; - optional uint64 F_Uint64_defaulted = 46 [default=6400]; - optional float F_Float_defaulted = 47 [default=314159.]; - optional double F_Double_defaulted = 48 [default=271828.]; - optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"]; - optional bytes F_Bytes_defaulted = 401 [default="Bignose"]; - optional sint32 F_Sint32_defaulted = 402 [default = -32]; - optional sint64 F_Sint64_defaulted = 403 [default = -64]; - - // Packed repeated fields (no string or bytes). - repeated bool F_Bool_repeated_packed = 50 [packed=true]; - repeated int32 F_Int32_repeated_packed = 51 [packed=true]; - repeated int64 F_Int64_repeated_packed = 52 [packed=true]; - repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true]; - repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true]; - repeated uint32 F_Uint32_repeated_packed = 55 [packed=true]; - repeated uint64 F_Uint64_repeated_packed = 56 [packed=true]; - repeated float F_Float_repeated_packed = 57 [packed=true]; - repeated double F_Double_repeated_packed = 58 [packed=true]; - repeated sint32 F_Sint32_repeated_packed = 502 [packed=true]; - repeated sint64 F_Sint64_repeated_packed = 503 [packed=true]; - - // Required, repeated, and optional groups. - required group RequiredGroup = 70 { - required string RequiredField = 71; - }; - - repeated group RepeatedGroup = 80 { - required string RequiredField = 81; - }; - - optional group OptionalGroup = 90 { - required string RequiredField = 91; - }; -} - -// For testing skipping of unrecognized fields. -// Numbers are all big, larger than tag numbers in GoTestField, -// the message used in the corresponding test. -message GoSkipTest { - required int32 skip_int32 = 11; - required fixed32 skip_fixed32 = 12; - required fixed64 skip_fixed64 = 13; - required string skip_string = 14; - required group SkipGroup = 15 { - required int32 group_int32 = 16; - required string group_string = 17; - } -} - -// For testing packed/non-packed decoder switching. -// A serialized instance of one should be deserializable as the other. -message NonPackedTest { - repeated int32 a = 1; -} - -message PackedTest { - repeated int32 b = 1 [packed=true]; -} - -message MaxTag { - // Maximum possible tag number. - optional string last_field = 536870911; -} - -message OldMessage { - message Nested { - optional string name = 1; - } - optional Nested nested = 1; - - optional int32 num = 2; -} - -// NewMessage is wire compatible with OldMessage; -// imagine it as a future version. -message NewMessage { - message Nested { - optional string name = 1; - optional string food_group = 2; - } - optional Nested nested = 1; - - // This is an int32 in OldMessage. - optional int64 num = 2; -} - -// Smaller tests for ASCII formatting. - -message InnerMessage { - required string host = 1; - optional int32 port = 2 [default=4000]; - optional bool connected = 3; -} - -message OtherMessage { - optional int64 key = 1; - optional bytes value = 2; - optional float weight = 3; - optional InnerMessage inner = 4; - - extensions 100 to max; -} - -message MyMessage { - required int32 count = 1; - optional string name = 2; - optional string quote = 3; - repeated string pet = 4; - optional InnerMessage inner = 5; - repeated OtherMessage others = 6; - repeated InnerMessage rep_inner = 12; - - enum Color { - RED = 0; - GREEN = 1; - BLUE = 2; - }; - optional Color bikeshed = 7; - - optional group SomeGroup = 8 { - optional int32 group_field = 9; - } - - // This field becomes [][]byte in the generated code. - repeated bytes rep_bytes = 10; - - optional double bigfloat = 11; - - extensions 100 to max; -} - -message Ext { - extend MyMessage { - optional Ext more = 103; - optional string text = 104; - optional int32 number = 105; - } - - optional string data = 1; -} - -extend MyMessage { - repeated string greeting = 106; -} - -message ComplexExtension { - optional int32 first = 1; - optional int32 second = 2; - repeated int32 third = 3; -} - -extend OtherMessage { - optional ComplexExtension complex = 200; - repeated ComplexExtension r_complex = 201; -} - -message DefaultsMessage { - enum DefaultsEnum { - ZERO = 0; - ONE = 1; - TWO = 2; - }; - extensions 100 to max; -} - -extend DefaultsMessage { - optional double no_default_double = 101; - optional float no_default_float = 102; - optional int32 no_default_int32 = 103; - optional int64 no_default_int64 = 104; - optional uint32 no_default_uint32 = 105; - optional uint64 no_default_uint64 = 106; - optional sint32 no_default_sint32 = 107; - optional sint64 no_default_sint64 = 108; - optional fixed32 no_default_fixed32 = 109; - optional fixed64 no_default_fixed64 = 110; - optional sfixed32 no_default_sfixed32 = 111; - optional sfixed64 no_default_sfixed64 = 112; - optional bool no_default_bool = 113; - optional string no_default_string = 114; - optional bytes no_default_bytes = 115; - optional DefaultsMessage.DefaultsEnum no_default_enum = 116; - - optional double default_double = 201 [default = 3.1415]; - optional float default_float = 202 [default = 3.14]; - optional int32 default_int32 = 203 [default = 42]; - optional int64 default_int64 = 204 [default = 43]; - optional uint32 default_uint32 = 205 [default = 44]; - optional uint64 default_uint64 = 206 [default = 45]; - optional sint32 default_sint32 = 207 [default = 46]; - optional sint64 default_sint64 = 208 [default = 47]; - optional fixed32 default_fixed32 = 209 [default = 48]; - optional fixed64 default_fixed64 = 210 [default = 49]; - optional sfixed32 default_sfixed32 = 211 [default = 50]; - optional sfixed64 default_sfixed64 = 212 [default = 51]; - optional bool default_bool = 213 [default = true]; - optional string default_string = 214 [default = "Hello, string"]; - optional bytes default_bytes = 215 [default = "Hello, bytes"]; - optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE]; -} - -message MyMessageSet { - option message_set_wire_format = true; - extensions 100 to max; -} - -message Empty { -} - -extend MyMessageSet { - optional Empty x201 = 201; - optional Empty x202 = 202; - optional Empty x203 = 203; - optional Empty x204 = 204; - optional Empty x205 = 205; - optional Empty x206 = 206; - optional Empty x207 = 207; - optional Empty x208 = 208; - optional Empty x209 = 209; - optional Empty x210 = 210; - optional Empty x211 = 211; - optional Empty x212 = 212; - optional Empty x213 = 213; - optional Empty x214 = 214; - optional Empty x215 = 215; - optional Empty x216 = 216; - optional Empty x217 = 217; - optional Empty x218 = 218; - optional Empty x219 = 219; - optional Empty x220 = 220; - optional Empty x221 = 221; - optional Empty x222 = 222; - optional Empty x223 = 223; - optional Empty x224 = 224; - optional Empty x225 = 225; - optional Empty x226 = 226; - optional Empty x227 = 227; - optional Empty x228 = 228; - optional Empty x229 = 229; - optional Empty x230 = 230; - optional Empty x231 = 231; - optional Empty x232 = 232; - optional Empty x233 = 233; - optional Empty x234 = 234; - optional Empty x235 = 235; - optional Empty x236 = 236; - optional Empty x237 = 237; - optional Empty x238 = 238; - optional Empty x239 = 239; - optional Empty x240 = 240; - optional Empty x241 = 241; - optional Empty x242 = 242; - optional Empty x243 = 243; - optional Empty x244 = 244; - optional Empty x245 = 245; - optional Empty x246 = 246; - optional Empty x247 = 247; - optional Empty x248 = 248; - optional Empty x249 = 249; - optional Empty x250 = 250; -} - -message MessageList { - repeated group Message = 1 { - required string name = 2; - required int32 count = 3; - } -} - -message Strings { - optional string string_field = 1; - optional bytes bytes_field = 2; -} - -message Defaults { - enum Color { - RED = 0; - GREEN = 1; - BLUE = 2; - } - - // Default-valued fields of all basic types. - // Same as GoTest, but copied here to make testing easier. - optional bool F_Bool = 1 [default=true]; - optional int32 F_Int32 = 2 [default=32]; - optional int64 F_Int64 = 3 [default=64]; - optional fixed32 F_Fixed32 = 4 [default=320]; - optional fixed64 F_Fixed64 = 5 [default=640]; - optional uint32 F_Uint32 = 6 [default=3200]; - optional uint64 F_Uint64 = 7 [default=6400]; - optional float F_Float = 8 [default=314159.]; - optional double F_Double = 9 [default=271828.]; - optional string F_String = 10 [default="hello, \"world!\"\n"]; - optional bytes F_Bytes = 11 [default="Bignose"]; - optional sint32 F_Sint32 = 12 [default=-32]; - optional sint64 F_Sint64 = 13 [default=-64]; - optional Color F_Enum = 14 [default=GREEN]; - - // More fields with crazy defaults. - optional float F_Pinf = 15 [default=inf]; - optional float F_Ninf = 16 [default=-inf]; - optional float F_Nan = 17 [default=nan]; - - // Sub-message. - optional SubDefaults sub = 18; - - // Redundant but explicit defaults. - optional string str_zero = 19 [default=""]; -} - -message SubDefaults { - optional int64 n = 1 [default=7]; -} - -message RepeatedEnum { - enum Color { - RED = 1; - } - repeated Color color = 1; -} - -message MoreRepeated { - repeated bool bools = 1; - repeated bool bools_packed = 2 [packed=true]; - repeated int32 ints = 3; - repeated int32 ints_packed = 4 [packed=true]; - repeated int64 int64s_packed = 7 [packed=true]; - repeated string strings = 5; - repeated fixed32 fixeds = 6; -} - -// GroupOld and GroupNew have the same wire format. -// GroupNew has a new field inside a group. - -message GroupOld { - optional group G = 101 { - optional int32 x = 2; - } -} - -message GroupNew { - optional group G = 101 { - optional int32 x = 2; - optional int32 y = 3; - } -} - -message FloatingPoint { - required double f = 1; -} - -message MessageWithMap { - map name_mapping = 1; - map msg_mapping = 2; - map byte_mapping = 3; - map str_to_str = 4; -} - -message Oneof { - oneof union { - bool F_Bool = 1; - int32 F_Int32 = 2; - int64 F_Int64 = 3; - fixed32 F_Fixed32 = 4; - fixed64 F_Fixed64 = 5; - uint32 F_Uint32 = 6; - uint64 F_Uint64 = 7; - float F_Float = 8; - double F_Double = 9; - string F_String = 10; - bytes F_Bytes = 11; - sint32 F_Sint32 = 12; - sint64 F_Sint64 = 13; - MyMessage.Color F_Enum = 14; - GoTestField F_Message = 15; - group F_Group = 16 { - optional int32 x = 17; - } - int32 F_Largest_Tag = 536870911; - } - - oneof tormato { - int32 value = 100; - } -} - -message Communique { - optional bool make_me_cry = 1; - - // This is a oneof, called "union". - oneof union { - int32 number = 5; - string name = 6; - bytes data = 7; - double temp_c = 8; - MyMessage.Color col = 9; - Strings msg = 10; - } -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go deleted file mode 100644 index d2e4cca0c..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_parser_test.go +++ /dev/null @@ -1,557 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "math" - "reflect" - "testing" - - . "github.com/golang/protobuf/proto" - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - . "github.com/golang/protobuf/proto/testdata" -) - -type UnmarshalTextTest struct { - in string - err string // if "", no error expected - out *MyMessage -} - -func buildExtStructTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_More, &Ext{ - Data: String("Hello, world!"), - }) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtDataTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - SetExtension(msg, E_Ext_Text, String("Hello, world!")) - SetExtension(msg, E_Ext_Number, Int32(1729)) - return UnmarshalTextTest{in: text, out: msg} -} - -func buildExtRepStringTest(text string) UnmarshalTextTest { - msg := &MyMessage{ - Count: Int32(42), - } - if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil { - panic(err) - } - return UnmarshalTextTest{in: text, out: msg} -} - -var unMarshalTextTests = []UnmarshalTextTest{ - // Basic - { - in: " count:42\n name:\"Dave\" ", - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - }, - }, - - // Empty quoted string - { - in: `count:42 name:""`, - out: &MyMessage{ - Count: Int32(42), - Name: String(""), - }, - }, - - // Quoted string concatenation with double quotes - { - in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string concatenation with single quotes - { - in: "count:42 name: 'My name is '\n'elsewhere'", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string concatenations with mixed quotes - { - in: "count:42 name: 'My name is '\n\"elsewhere\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - { - in: "count:42 name: \"My name is \"\n'elsewhere'", - out: &MyMessage{ - Count: Int32(42), - Name: String("My name is elsewhere"), - }, - }, - - // Quoted string with escaped apostrophe - { - in: `count:42 name: "HOLIDAY - New Year\'s Day"`, - out: &MyMessage{ - Count: Int32(42), - Name: String("HOLIDAY - New Year's Day"), - }, - }, - - // Quoted string with single quote - { - in: `count:42 name: 'Roger "The Ramster" Ramjet'`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`Roger "The Ramster" Ramjet`), - }, - }, - - // Quoted string with all the accepted special characters from the C++ test - { - in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"", - out: &MyMessage{ - Count: Int32(42), - Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"), - }, - }, - - // Quoted string with quoted backslash - { - in: `count:42 name: "\\'xyz"`, - out: &MyMessage{ - Count: Int32(42), - Name: String(`\'xyz`), - }, - }, - - // Quoted string with UTF-8 bytes. - { - in: "count:42 name: '\303\277\302\201\xAB'", - out: &MyMessage{ - Count: Int32(42), - Name: String("\303\277\302\201\xAB"), - }, - }, - - // Bad quoted string - { - in: `inner: < host: "\0" >` + "\n", - err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`, - }, - - // Number too large for int64 - { - in: "count: 1 others { key: 123456789012345678901 }", - err: "line 1.23: invalid int64: 123456789012345678901", - }, - - // Number too large for int32 - { - in: "count: 1234567890123", - err: "line 1.7: invalid int32: 1234567890123", - }, - - // Number in hexadecimal - { - in: "count: 0x2beef", - out: &MyMessage{ - Count: Int32(0x2beef), - }, - }, - - // Number in octal - { - in: "count: 024601", - out: &MyMessage{ - Count: Int32(024601), - }, - }, - - // Floating point number with "f" suffix - { - in: "count: 4 others:< weight: 17.0f >", - out: &MyMessage{ - Count: Int32(4), - Others: []*OtherMessage{ - { - Weight: Float32(17), - }, - }, - }, - }, - - // Floating point positive infinity - { - in: "count: 4 bigfloat: inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(1)), - }, - }, - - // Floating point negative infinity - { - in: "count: 4 bigfloat: -inf", - out: &MyMessage{ - Count: Int32(4), - Bigfloat: Float64(math.Inf(-1)), - }, - }, - - // Number too large for float32 - { - in: "others:< weight: 12345678901234567890123456789012345678901234567890 >", - err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890", - }, - - // Number posing as a quoted string - { - in: `inner: < host: 12 >` + "\n", - err: `line 1.15: invalid string: 12`, - }, - - // Quoted string posing as int32 - { - in: `count: "12"`, - err: `line 1.7: invalid int32: "12"`, - }, - - // Quoted string posing a float32 - { - in: `others:< weight: "17.4" >`, - err: `line 1.17: invalid float32: "17.4"`, - }, - - // Enum - { - in: `count:42 bikeshed: BLUE`, - out: &MyMessage{ - Count: Int32(42), - Bikeshed: MyMessage_BLUE.Enum(), - }, - }, - - // Repeated field - { - in: `count:42 pet: "horsey" pet:"bunny"`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated field with list notation - { - in: `count:42 pet: ["horsey", "bunny"]`, - out: &MyMessage{ - Count: Int32(42), - Pet: []string{"horsey", "bunny"}, - }, - }, - - // Repeated message with/without colon and <>/{} - { - in: `count:42 others:{} others{} others:<> others:{}`, - out: &MyMessage{ - Count: Int32(42), - Others: []*OtherMessage{ - {}, - {}, - {}, - {}, - }, - }, - }, - - // Missing colon for inner message - { - in: `count:42 inner < host: "cauchy.syd" >`, - out: &MyMessage{ - Count: Int32(42), - Inner: &InnerMessage{ - Host: String("cauchy.syd"), - }, - }, - }, - - // Missing colon for string field - { - in: `name "Dave"`, - err: `line 1.5: expected ':', found "\"Dave\""`, - }, - - // Missing colon for int32 field - { - in: `count 42`, - err: `line 1.6: expected ':', found "42"`, - }, - - // Missing required field - { - in: `name: "Pawel"`, - err: `proto: required field "testdata.MyMessage.count" not set`, - out: &MyMessage{ - Name: String("Pawel"), - }, - }, - - // Repeated non-repeated field - { - in: `name: "Rob" name: "Russ"`, - err: `line 1.12: non-repeated field "name" was repeated`, - }, - - // Group - { - in: `count: 17 SomeGroup { group_field: 12 }`, - out: &MyMessage{ - Count: Int32(17), - Somegroup: &MyMessage_SomeGroup{ - GroupField: Int32(12), - }, - }, - }, - - // Semicolon between fields - { - in: `count:3;name:"Calvin"`, - out: &MyMessage{ - Count: Int32(3), - Name: String("Calvin"), - }, - }, - // Comma between fields - { - in: `count:4,name:"Ezekiel"`, - out: &MyMessage{ - Count: Int32(4), - Name: String("Ezekiel"), - }, - }, - - // Extension - buildExtStructTest(`count: 42 [testdata.Ext.more]:`), - buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`), - buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`), - buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`), - - // Big all-in-one - { - in: "count:42 # Meaning\n" + - `name:"Dave" ` + - `quote:"\"I didn't want to go.\"" ` + - `pet:"bunny" ` + - `pet:"kitty" ` + - `pet:"horsey" ` + - `inner:<` + - ` host:"footrest.syd" ` + - ` port:7001 ` + - ` connected:true ` + - `> ` + - `others:<` + - ` key:3735928559 ` + - ` value:"\x01A\a\f" ` + - `> ` + - `others:<` + - " weight:58.9 # Atomic weight of Co\n" + - ` inner:<` + - ` host:"lesha.mtv" ` + - ` port:8002 ` + - ` >` + - `>`, - out: &MyMessage{ - Count: Int32(42), - Name: String("Dave"), - Quote: String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &InnerMessage{ - Host: String("footrest.syd"), - Port: Int32(7001), - Connected: Bool(true), - }, - Others: []*OtherMessage{ - { - Key: Int64(3735928559), - Value: []byte{0x1, 'A', '\a', '\f'}, - }, - { - Weight: Float32(58.9), - Inner: &InnerMessage{ - Host: String("lesha.mtv"), - Port: Int32(8002), - }, - }, - }, - }, - }, -} - -func TestUnmarshalText(t *testing.T) { - for i, test := range unMarshalTextTests { - pb := new(MyMessage) - err := UnmarshalText(test.in, pb) - if test.err == "" { - // We don't expect failure. - if err != nil { - t.Errorf("Test %d: Unexpected error: %v", i, err) - } else if !reflect.DeepEqual(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } else { - // We do expect failure. - if err == nil { - t.Errorf("Test %d: Didn't get expected error: %v", i, test.err) - } else if err.Error() != test.err { - t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v", - i, err.Error(), test.err) - } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) { - t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", - i, pb, test.out) - } - } - } -} - -func TestUnmarshalTextCustomMessage(t *testing.T) { - msg := &textMessage{} - if err := UnmarshalText("custom", msg); err != nil { - t.Errorf("Unexpected error from custom unmarshal: %v", err) - } - if UnmarshalText("not custom", msg) == nil { - t.Errorf("Didn't get expected error from custom unmarshal") - } -} - -// Regression test; this caused a panic. -func TestRepeatedEnum(t *testing.T) { - pb := new(RepeatedEnum) - if err := UnmarshalText("color: RED", pb); err != nil { - t.Fatal(err) - } - exp := &RepeatedEnum{ - Color: []RepeatedEnum_Color{RepeatedEnum_RED}, - } - if !Equal(pb, exp) { - t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp) - } -} - -func TestProto3TextParsing(t *testing.T) { - m := new(proto3pb.Message) - const in = `name: "Wallace" true_scotsman: true` - want := &proto3pb.Message{ - Name: "Wallace", - TrueScotsman: true, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestMapParsing(t *testing.T) { - m := new(MessageWithMap) - const in = `name_mapping: name_mapping:` + - `msg_mapping:,>` + // separating commas are okay - `msg_mapping>` + // no colon after "value" - `byte_mapping:` - want := &MessageWithMap{ - NameMapping: map[int32]string{ - 1: "Beatles", - 1234: "Feist", - }, - MsgMapping: map[int64]*FloatingPoint{ - -4: {F: Float64(2.0)}, - -2: {F: Float64(4.0)}, - }, - ByteMapping: map[bool][]byte{ - true: []byte("so be it"), - }, - } - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -func TestOneofParsing(t *testing.T) { - const in = `name:"Shrek"` - m := new(Communique) - want := &Communique{Union: &Communique_Name{"Shrek"}} - if err := UnmarshalText(in, m); err != nil { - t.Fatal(err) - } - if !Equal(m, want) { - t.Errorf("\n got %v\nwant %v", m, want) - } -} - -var benchInput string - -func init() { - benchInput = "count: 4\n" - for i := 0; i < 1000; i++ { - benchInput += "pet: \"fido\"\n" - } - - // Check it is valid input. - pb := new(MyMessage) - err := UnmarshalText(benchInput, pb) - if err != nil { - panic("Bad benchmark input: " + err.Error()) - } -} - -func BenchmarkUnmarshalText(b *testing.B) { - pb := new(MyMessage) - for i := 0; i < b.N; i++ { - UnmarshalText(benchInput, pb) - } - b.SetBytes(int64(len(benchInput))) -} diff --git a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go b/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go deleted file mode 100644 index 3eabacac8..000000000 --- a/Godeps/_workspace/src/github.com/golang/protobuf/proto/text_test.go +++ /dev/null @@ -1,474 +0,0 @@ -// Go support for Protocol Buffers - Google's data interchange format -// -// Copyright 2010 The Go Authors. All rights reserved. -// https://github.com/golang/protobuf -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package proto_test - -import ( - "bytes" - "errors" - "io/ioutil" - "math" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - - proto3pb "github.com/golang/protobuf/proto/proto3_proto" - pb "github.com/golang/protobuf/proto/testdata" -) - -// textMessage implements the methods that allow it to marshal and unmarshal -// itself as text. -type textMessage struct { -} - -func (*textMessage) MarshalText() ([]byte, error) { - return []byte("custom"), nil -} - -func (*textMessage) UnmarshalText(bytes []byte) error { - if string(bytes) != "custom" { - return errors.New("expected 'custom'") - } - return nil -} - -func (*textMessage) Reset() {} -func (*textMessage) String() string { return "" } -func (*textMessage) ProtoMessage() {} - -func newTestMessage() *pb.MyMessage { - msg := &pb.MyMessage{ - Count: proto.Int32(42), - Name: proto.String("Dave"), - Quote: proto.String(`"I didn't want to go."`), - Pet: []string{"bunny", "kitty", "horsey"}, - Inner: &pb.InnerMessage{ - Host: proto.String("footrest.syd"), - Port: proto.Int32(7001), - Connected: proto.Bool(true), - }, - Others: []*pb.OtherMessage{ - { - Key: proto.Int64(0xdeadbeef), - Value: []byte{1, 65, 7, 12}, - }, - { - Weight: proto.Float32(6.022), - Inner: &pb.InnerMessage{ - Host: proto.String("lesha.mtv"), - Port: proto.Int32(8002), - }, - }, - }, - Bikeshed: pb.MyMessage_BLUE.Enum(), - Somegroup: &pb.MyMessage_SomeGroup{ - GroupField: proto.Int32(8), - }, - // One normally wouldn't do this. - // This is an undeclared tag 13, as a varint (wire type 0) with value 4. - XXX_unrecognized: []byte{13<<3 | 0, 4}, - } - ext := &pb.Ext{ - Data: proto.String("Big gobs for big rats"), - } - if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { - panic(err) - } - greetings := []string{"adg", "easy", "cow"} - if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { - panic(err) - } - - // Add an unknown extension. We marshal a pb.Ext, and fake the ID. - b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) - if err != nil { - panic(err) - } - b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) - proto.SetRawExtension(msg, 201, b) - - // Extensions can be plain fields, too, so let's test that. - b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) - proto.SetRawExtension(msg, 202, b) - - return msg -} - -const text = `count: 42 -name: "Dave" -quote: "\"I didn't want to go.\"" -pet: "bunny" -pet: "kitty" -pet: "horsey" -inner: < - host: "footrest.syd" - port: 7001 - connected: true -> -others: < - key: 3735928559 - value: "\001A\007\014" -> -others: < - weight: 6.022 - inner: < - host: "lesha.mtv" - port: 8002 - > -> -bikeshed: BLUE -SomeGroup { - group_field: 8 -} -/* 2 unknown bytes */ -13: 4 -[testdata.Ext.more]: < - data: "Big gobs for big rats" -> -[testdata.greeting]: "adg" -[testdata.greeting]: "easy" -[testdata.greeting]: "cow" -/* 13 unknown bytes */ -201: "\t3G skiing" -/* 3 unknown bytes */ -202: 19 -` - -func TestMarshalText(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, newTestMessage()); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != text { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text) - } -} - -func TestMarshalTextCustomMessage(t *testing.T) { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, &textMessage{}); err != nil { - t.Fatalf("proto.MarshalText: %v", err) - } - s := buf.String() - if s != "custom" { - t.Errorf("Got %q, expected %q", s, "custom") - } -} -func TestMarshalTextNil(t *testing.T) { - want := "" - tests := []proto.Message{nil, (*pb.MyMessage)(nil)} - for i, test := range tests { - buf := new(bytes.Buffer) - if err := proto.MarshalText(buf, test); err != nil { - t.Fatal(err) - } - if got := buf.String(); got != want { - t.Errorf("%d: got %q want %q", i, got, want) - } - } -} - -func TestMarshalTextUnknownEnum(t *testing.T) { - // The Color enum only specifies values 0-2. - m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()} - got := m.String() - const want = `bikeshed:3 ` - if got != want { - t.Errorf("\n got %q\nwant %q", got, want) - } -} - -func TestTextOneof(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&pb.Communique{}, ``}, - // scalar field - {&pb.Communique{Union: &pb.Communique_Number{4}}, `number:4`}, - // message field - {&pb.Communique{Union: &pb.Communique_Msg{ - &pb.Strings{StringField: proto.String("why hello!")}, - }}, `msg:`}, - // bad oneof (should not panic) - {&pb.Communique{Union: &pb.Communique_Msg{nil}}, `msg:/* nil */`}, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} - -func BenchmarkMarshalTextBuffered(b *testing.B) { - buf := new(bytes.Buffer) - m := newTestMessage() - for i := 0; i < b.N; i++ { - buf.Reset() - proto.MarshalText(buf, m) - } -} - -func BenchmarkMarshalTextUnbuffered(b *testing.B) { - w := ioutil.Discard - m := newTestMessage() - for i := 0; i < b.N; i++ { - proto.MarshalText(w, m) - } -} - -func compact(src string) string { - // s/[ \n]+/ /g; s/ $//; - dst := make([]byte, len(src)) - space, comment := false, false - j := 0 - for i := 0; i < len(src); i++ { - if strings.HasPrefix(src[i:], "/*") { - comment = true - i++ - continue - } - if comment && strings.HasPrefix(src[i:], "*/") { - comment = false - i++ - continue - } - if comment { - continue - } - c := src[i] - if c == ' ' || c == '\n' { - space = true - continue - } - if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') { - space = false - } - if c == '{' { - space = false - } - if space { - dst[j] = ' ' - j++ - space = false - } - dst[j] = c - j++ - } - if space { - dst[j] = ' ' - j++ - } - return string(dst[0:j]) -} - -var compactText = compact(text) - -func TestCompactText(t *testing.T) { - s := proto.CompactTextString(newTestMessage()) - if s != compactText { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText) - } -} - -func TestStringEscaping(t *testing.T) { - testCases := []struct { - in *pb.Strings - out string - }{ - { - // Test data from C++ test (TextFormatTest.StringEscape). - // Single divergence: we don't escape apostrophes. - &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, - "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", - }, - { - // Test data from the same C++ test. - &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, - "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", - }, - { - // Some UTF-8. - &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, - `string_field: "\000\001\377\201"` + "\n", - }, - } - - for i, tc := range testCases { - var buf bytes.Buffer - if err := proto.MarshalText(&buf, tc.in); err != nil { - t.Errorf("proto.MarsalText: %v", err) - continue - } - s := buf.String() - if s != tc.out { - t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) - continue - } - - // Check round-trip. - pb := new(pb.Strings) - if err := proto.UnmarshalText(s, pb); err != nil { - t.Errorf("#%d: UnmarshalText: %v", i, err) - continue - } - if !proto.Equal(pb, tc.in) { - t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) - } - } -} - -// A limitedWriter accepts some output before it fails. -// This is a proxy for something like a nearly-full or imminently-failing disk, -// or a network connection that is about to die. -type limitedWriter struct { - b bytes.Buffer - limit int -} - -var outOfSpace = errors.New("proto: insufficient space") - -func (w *limitedWriter) Write(p []byte) (n int, err error) { - var avail = w.limit - w.b.Len() - if avail <= 0 { - return 0, outOfSpace - } - if len(p) <= avail { - return w.b.Write(p) - } - n, _ = w.b.Write(p[:avail]) - return n, outOfSpace -} - -func TestMarshalTextFailing(t *testing.T) { - // Try lots of different sizes to exercise more error code-paths. - for lim := 0; lim < len(text); lim++ { - buf := new(limitedWriter) - buf.limit = lim - err := proto.MarshalText(buf, newTestMessage()) - // We expect a certain error, but also some partial results in the buffer. - if err != outOfSpace { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace) - } - s := buf.b.String() - x := text[:buf.limit] - if s != x { - t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x) - } - } -} - -func TestFloats(t *testing.T) { - tests := []struct { - f float64 - want string - }{ - {0, "0"}, - {4.7, "4.7"}, - {math.Inf(1), "inf"}, - {math.Inf(-1), "-inf"}, - {math.NaN(), "nan"}, - } - for _, test := range tests { - msg := &pb.FloatingPoint{F: &test.f} - got := strings.TrimSpace(msg.String()) - want := `f:` + test.want - if got != want { - t.Errorf("f=%f: got %q, want %q", test.f, got, want) - } - } -} - -func TestRepeatedNilText(t *testing.T) { - m := &pb.MessageList{ - Message: []*pb.MessageList_Message{ - nil, - &pb.MessageList_Message{ - Name: proto.String("Horse"), - }, - nil, - }, - } - want := `Message -Message { - name: "Horse" -} -Message -` - if s := proto.MarshalTextString(m); s != want { - t.Errorf(" got: %s\nwant: %s", s, want) - } -} - -func TestProto3Text(t *testing.T) { - tests := []struct { - m proto.Message - want string - }{ - // zero message - {&proto3pb.Message{}, ``}, - // zero message except for an empty byte slice - {&proto3pb.Message{Data: []byte{}}, ``}, - // trivial case - {&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`}, - // empty map - {&pb.MessageWithMap{}, ``}, - // non-empty map; map format is the same as a repeated struct, - // and they are sorted by key (numerically for numeric keys). - { - &pb.MessageWithMap{NameMapping: map[int32]string{ - -1: "Negatory", - 7: "Lucky", - 1234: "Feist", - 6345789: "Otis", - }}, - `name_mapping: ` + - `name_mapping: ` + - `name_mapping: ` + - `name_mapping:`, - }, - // map with nil value; not well-defined, but we shouldn't crash - { - &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}}, - `msg_mapping:`, - }, - } - for _, test := range tests { - got := strings.TrimSpace(test.m.String()) - if got != test.want { - t.Errorf("\n got %s\nwant %s", got, test.want) - } - } -} diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container_test.go b/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container_test.go deleted file mode 100644 index 58dc79e39..000000000 --- a/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2014 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 v1 - -import ( - "testing" - "time" -) - -func TestStatsStartTime(t *testing.T) { - N := 10 - stats := make([]*ContainerStats, 0, N) - ct := time.Now() - for i := 0; i < N; i++ { - s := &ContainerStats{ - Timestamp: ct.Add(time.Duration(i) * time.Second), - } - stats = append(stats, s) - } - cinfo := &ContainerInfo{ - ContainerReference: ContainerReference{ - Name: "/some/container", - }, - Stats: stats, - } - ref := ct.Add(time.Duration(N-1) * time.Second) - end := cinfo.StatsEndTime() - - if !ref.Equal(end) { - t.Errorf("end time is %v; should be %v", end, ref) - } -} - -func TestStatsEndTime(t *testing.T) { - N := 10 - stats := make([]*ContainerStats, 0, N) - ct := time.Now() - for i := 0; i < N; i++ { - s := &ContainerStats{ - Timestamp: ct.Add(time.Duration(i) * time.Second), - } - stats = append(stats, s) - } - cinfo := &ContainerInfo{ - ContainerReference: ContainerReference{ - Name: "/some/container", - }, - Stats: stats, - } - ref := ct - start := cinfo.StatsStartTime() - - if !ref.Equal(start) { - t.Errorf("start time is %v; should be %v", start, ref) - } -} - -func createStats(cpuUsage, memUsage uint64, timestamp time.Time) *ContainerStats { - stats := &ContainerStats{} - stats.Cpu.Usage.PerCpu = []uint64{cpuUsage} - stats.Cpu.Usage.Total = cpuUsage - stats.Cpu.Usage.System = 0 - stats.Cpu.Usage.User = cpuUsage - stats.Memory.Usage = memUsage - stats.Timestamp = timestamp - return stats -} diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/test/datagen.go b/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/test/datagen.go deleted file mode 100644 index 42a0526d4..000000000 --- a/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/test/datagen.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2014 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 test - -import ( - "fmt" - "math/rand" - "time" - - info "github.com/google/cadvisor/info/v1" -) - -func GenerateRandomStats(numStats, numCores int, duration time.Duration) []*info.ContainerStats { - ret := make([]*info.ContainerStats, numStats) - perCoreUsages := make([]uint64, numCores) - currentTime := time.Now() - for i := range perCoreUsages { - perCoreUsages[i] = uint64(rand.Int63n(1000)) - } - for i := 0; i < numStats; i++ { - stats := new(info.ContainerStats) - stats.Timestamp = currentTime - currentTime = currentTime.Add(duration) - - percore := make([]uint64, numCores) - for i := range perCoreUsages { - perCoreUsages[i] += uint64(rand.Int63n(1000)) - percore[i] = perCoreUsages[i] - stats.Cpu.Usage.Total += percore[i] - } - stats.Cpu.Usage.PerCpu = percore - stats.Cpu.Usage.User = stats.Cpu.Usage.Total - stats.Cpu.Usage.System = 0 - stats.Memory.Usage = uint64(rand.Int63n(4096)) - stats.Memory.Cache = uint64(rand.Int63n(4096)) - stats.Memory.RSS = uint64(rand.Int63n(4096)) - ret[i] = stats - } - return ret -} - -func GenerateRandomContainerSpec(numCores int) info.ContainerSpec { - ret := info.ContainerSpec{ - CreationTime: time.Now(), - HasCpu: true, - Cpu: info.CpuSpec{}, - HasMemory: true, - Memory: info.MemorySpec{}, - } - ret.Cpu.Limit = uint64(1000 + rand.Int63n(2000)) - ret.Cpu.MaxLimit = uint64(1000 + rand.Int63n(2000)) - ret.Cpu.Mask = fmt.Sprintf("0-%d", numCores-1) - ret.Memory.Limit = uint64(4096 + rand.Int63n(4096)) - return ret -} - -func GenerateRandomContainerInfo(containerName string, numCores int, query *info.ContainerInfoRequest, duration time.Duration) *info.ContainerInfo { - stats := GenerateRandomStats(query.NumStats, numCores, duration) - spec := GenerateRandomContainerSpec(numCores) - - ret := &info.ContainerInfo{ - ContainerReference: info.ContainerReference{ - Name: containerName, - }, - Spec: spec, - Stats: stats, - } - return ret -} diff --git a/Godeps/_workspace/src/github.com/google/gofuzz/example_test.go b/Godeps/_workspace/src/github.com/google/gofuzz/example_test.go deleted file mode 100644 index 792707a3a..000000000 --- a/Godeps/_workspace/src/github.com/google/gofuzz/example_test.go +++ /dev/null @@ -1,225 +0,0 @@ -/* -Copyright 2014 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 fuzz_test - -import ( - "encoding/json" - "fmt" - "math/rand" - - "github.com/google/gofuzz" -) - -func ExampleSimple() { - type MyType struct { - A string - B string - C int - D struct { - E float64 - } - } - - f := fuzz.New() - object := MyType{} - - uniqueObjects := map[MyType]int{} - - for i := 0; i < 1000; i++ { - f.Fuzz(&object) - uniqueObjects[object]++ - } - fmt.Printf("Got %v unique objects.\n", len(uniqueObjects)) - // Output: - // Got 1000 unique objects. -} - -func ExampleCustom() { - type MyType struct { - A int - B string - } - - counter := 0 - f := fuzz.New().Funcs( - func(i *int, c fuzz.Continue) { - *i = counter - counter++ - }, - ) - object := MyType{} - - uniqueObjects := map[MyType]int{} - - for i := 0; i < 100; i++ { - f.Fuzz(&object) - if object.A != i { - fmt.Printf("Unexpected value: %#v\n", object) - } - uniqueObjects[object]++ - } - fmt.Printf("Got %v unique objects.\n", len(uniqueObjects)) - // Output: - // Got 100 unique objects. -} - -func ExampleComplex() { - type OtherType struct { - A string - B string - } - type MyType struct { - Pointer *OtherType - Map map[string]OtherType - PointerMap *map[string]OtherType - Slice []OtherType - SlicePointer []*OtherType - PointerSlicePointer *[]*OtherType - } - - f := fuzz.New().RandSource(rand.NewSource(0)).NilChance(0).NumElements(1, 1).Funcs( - func(o *OtherType, c fuzz.Continue) { - o.A = "Foo" - o.B = "Bar" - }, - func(op **OtherType, c fuzz.Continue) { - *op = &OtherType{"A", "B"} - }, - func(m map[string]OtherType, c fuzz.Continue) { - m["Works Because"] = OtherType{ - "Fuzzer", - "Preallocated", - } - }, - ) - object := MyType{} - f.Fuzz(&object) - bytes, err := json.MarshalIndent(&object, "", " ") - if err != nil { - fmt.Printf("error: %v\n", err) - } - fmt.Printf("%s\n", string(bytes)) - // Output: - // { - // "Pointer": { - // "A": "A", - // "B": "B" - // }, - // "Map": { - // "Works Because": { - // "A": "Fuzzer", - // "B": "Preallocated" - // } - // }, - // "PointerMap": { - // "Works Because": { - // "A": "Fuzzer", - // "B": "Preallocated" - // } - // }, - // "Slice": [ - // { - // "A": "Foo", - // "B": "Bar" - // } - // ], - // "SlicePointer": [ - // { - // "A": "A", - // "B": "B" - // } - // ], - // "PointerSlicePointer": [ - // { - // "A": "A", - // "B": "B" - // } - // ] - // } -} - -func ExampleMap() { - f := fuzz.New().NilChance(0).NumElements(1, 1) - var myMap map[struct{ A, B, C int }]string - f.Fuzz(&myMap) - fmt.Printf("myMap has %v element(s).\n", len(myMap)) - // Output: - // myMap has 1 element(s). -} - -func ExampleSingle() { - f := fuzz.New() - var i int - f.Fuzz(&i) - - // Technically, we'd expect this to fail one out of 2 billion attempts... - fmt.Printf("(i == 0) == %v", i == 0) - // Output: - // (i == 0) == false -} - -func ExampleEnum() { - type MyEnum string - const ( - A MyEnum = "A" - B MyEnum = "B" - ) - type MyInfo struct { - Type MyEnum - AInfo *string - BInfo *string - } - - f := fuzz.New().NilChance(0).Funcs( - func(e *MyInfo, c fuzz.Continue) { - // Note c's embedded Rand allows for direct use. - // We could also use c.RandBool() here. - switch c.Intn(2) { - case 0: - e.Type = A - c.Fuzz(&e.AInfo) - case 1: - e.Type = B - c.Fuzz(&e.BInfo) - } - }, - ) - - for i := 0; i < 100; i++ { - var myObject MyInfo - f.Fuzz(&myObject) - switch myObject.Type { - case A: - if myObject.AInfo == nil { - fmt.Println("AInfo should have been set!") - } - if myObject.BInfo != nil { - fmt.Println("BInfo should NOT have been set!") - } - case B: - if myObject.BInfo == nil { - fmt.Println("BInfo should have been set!") - } - if myObject.AInfo != nil { - fmt.Println("AInfo should NOT have been set!") - } - default: - fmt.Println("Invalid enum value!") - } - } - // Output: -} diff --git a/Godeps/_workspace/src/github.com/google/gofuzz/fuzz_test.go b/Godeps/_workspace/src/github.com/google/gofuzz/fuzz_test.go deleted file mode 100644 index 12abc8f65..000000000 --- a/Godeps/_workspace/src/github.com/google/gofuzz/fuzz_test.go +++ /dev/null @@ -1,384 +0,0 @@ -/* -Copyright 2014 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 fuzz - -import ( - "reflect" - "testing" - "time" -) - -func TestFuzz_basic(t *testing.T) { - obj := &struct { - I int - I8 int8 - I16 int16 - I32 int32 - I64 int64 - U uint - U8 uint8 - U16 uint16 - U32 uint32 - U64 uint64 - Uptr uintptr - S string - B bool - T time.Time - }{} - - failed := map[string]int{} - for i := 0; i < 10; i++ { - New().Fuzz(obj) - - if n, v := "i", obj.I; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "i8", obj.I8; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "i16", obj.I16; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "i32", obj.I32; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "i64", obj.I64; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "u", obj.U; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "u8", obj.U8; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "u16", obj.U16; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "u32", obj.U32; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "u64", obj.U64; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "uptr", obj.Uptr; v == 0 { - failed[n] = failed[n] + 1 - } - if n, v := "s", obj.S; v == "" { - failed[n] = failed[n] + 1 - } - if n, v := "b", obj.B; v == false { - failed[n] = failed[n] + 1 - } - if n, v := "t", obj.T; v.IsZero() { - failed[n] = failed[n] + 1 - } - } - checkFailed(t, failed) -} - -func checkFailed(t *testing.T, failed map[string]int) { - for k, v := range failed { - if v > 8 { - t.Errorf("%v seems to not be getting set, was zero value %v times", k, v) - } - } -} - -func TestFuzz_structptr(t *testing.T) { - obj := &struct { - A *struct { - S string - } - }{} - - f := New().NilChance(.5) - failed := map[string]int{} - for i := 0; i < 10; i++ { - f.Fuzz(obj) - - if n, v := "a not nil", obj.A; v == nil { - failed[n] = failed[n] + 1 - } - if n, v := "a nil", obj.A; v != nil { - failed[n] = failed[n] + 1 - } - if n, v := "as", obj.A; v == nil || v.S == "" { - failed[n] = failed[n] + 1 - } - } - checkFailed(t, failed) -} - -// tryFuzz tries fuzzing up to 20 times. Fail if check() never passes, report the highest -// stage it ever got to. -func tryFuzz(t *testing.T, f *Fuzzer, obj interface{}, check func() (stage int, passed bool)) { - maxStage := 0 - for i := 0; i < 20; i++ { - f.Fuzz(obj) - stage, passed := check() - if stage > maxStage { - maxStage = stage - } - if passed { - return - } - } - t.Errorf("Only ever got to stage %v", maxStage) -} - -func TestFuzz_structmap(t *testing.T) { - obj := &struct { - A map[struct { - S string - }]struct { - S2 string - } - B map[string]string - }{} - - tryFuzz(t, New(), obj, func() (int, bool) { - if obj.A == nil { - return 1, false - } - if len(obj.A) == 0 { - return 2, false - } - for k, v := range obj.A { - if k.S == "" { - return 3, false - } - if v.S2 == "" { - return 4, false - } - } - - if obj.B == nil { - return 5, false - } - if len(obj.B) == 0 { - return 6, false - } - for k, v := range obj.B { - if k == "" { - return 7, false - } - if v == "" { - return 8, false - } - } - return 9, true - }) -} - -func TestFuzz_structslice(t *testing.T) { - obj := &struct { - A []struct { - S string - } - B []string - }{} - - tryFuzz(t, New(), obj, func() (int, bool) { - if obj.A == nil { - return 1, false - } - if len(obj.A) == 0 { - return 2, false - } - for _, v := range obj.A { - if v.S == "" { - return 3, false - } - } - - if obj.B == nil { - return 4, false - } - if len(obj.B) == 0 { - return 5, false - } - for _, v := range obj.B { - if v == "" { - return 6, false - } - } - return 7, true - }) -} - -func TestFuzz_custom(t *testing.T) { - obj := &struct { - A string - B *string - C map[string]string - D *map[string]string - }{} - - testPhrase := "gotcalled" - testMap := map[string]string{"C": "D"} - f := New().Funcs( - func(s *string, c Continue) { - *s = testPhrase - }, - func(m map[string]string, c Continue) { - m["C"] = "D" - }, - ) - - tryFuzz(t, f, obj, func() (int, bool) { - if obj.A != testPhrase { - return 1, false - } - if obj.B == nil { - return 2, false - } - if *obj.B != testPhrase { - return 3, false - } - if e, a := testMap, obj.C; !reflect.DeepEqual(e, a) { - return 4, false - } - if obj.D == nil { - return 5, false - } - if e, a := testMap, *obj.D; !reflect.DeepEqual(e, a) { - return 6, false - } - return 7, true - }) -} - -type SelfFuzzer string - -// Implement fuzz.Interface. -func (sf *SelfFuzzer) Fuzz(c Continue) { - *sf = selfFuzzerTestPhrase -} - -const selfFuzzerTestPhrase = "was fuzzed" - -func TestFuzz_interface(t *testing.T) { - f := New() - - var obj1 SelfFuzzer - tryFuzz(t, f, &obj1, func() (int, bool) { - if obj1 != selfFuzzerTestPhrase { - return 1, false - } - return 1, true - }) - - var obj2 map[int]SelfFuzzer - tryFuzz(t, f, &obj2, func() (int, bool) { - for _, v := range obj2 { - if v != selfFuzzerTestPhrase { - return 1, false - } - } - return 1, true - }) -} - -func TestFuzz_interfaceAndFunc(t *testing.T) { - const privateTestPhrase = "private phrase" - f := New().Funcs( - // This should take precedence over SelfFuzzer.Fuzz(). - func(s *SelfFuzzer, c Continue) { - *s = privateTestPhrase - }, - ) - - var obj1 SelfFuzzer - tryFuzz(t, f, &obj1, func() (int, bool) { - if obj1 != privateTestPhrase { - return 1, false - } - return 1, true - }) - - var obj2 map[int]SelfFuzzer - tryFuzz(t, f, &obj2, func() (int, bool) { - for _, v := range obj2 { - if v != privateTestPhrase { - return 1, false - } - } - return 1, true - }) -} - -func TestFuzz_noCustom(t *testing.T) { - type Inner struct { - Str string - } - type Outer struct { - Str string - In Inner - } - - testPhrase := "gotcalled" - f := New().Funcs( - func(outer *Outer, c Continue) { - outer.Str = testPhrase - c.Fuzz(&outer.In) - }, - func(inner *Inner, c Continue) { - inner.Str = testPhrase - }, - ) - c := Continue{f: f, Rand: f.r} - - // Fuzzer.Fuzz() - obj1 := Outer{} - f.Fuzz(&obj1) - if obj1.Str != testPhrase { - t.Errorf("expected Outer custom function to have been called") - } - if obj1.In.Str != testPhrase { - t.Errorf("expected Inner custom function to have been called") - } - - // Continue.Fuzz() - obj2 := Outer{} - c.Fuzz(&obj2) - if obj2.Str != testPhrase { - t.Errorf("expected Outer custom function to have been called") - } - if obj2.In.Str != testPhrase { - t.Errorf("expected Inner custom function to have been called") - } - - // Fuzzer.FuzzNoCustom() - obj3 := Outer{} - f.FuzzNoCustom(&obj3) - if obj3.Str == testPhrase { - t.Errorf("expected Outer custom function to not have been called") - } - if obj3.In.Str != testPhrase { - t.Errorf("expected Inner custom function to have been called") - } - - // Continue.FuzzNoCustom() - obj4 := Outer{} - c.FuzzNoCustom(&obj4) - if obj4.Str == testPhrase { - t.Errorf("expected Outer custom function to not have been called") - } - if obj4.In.Str != testPhrase { - t.Errorf("expected Inner custom function to have been called") - } -} diff --git a/Godeps/_workspace/src/github.com/imdario/mergo/mergo_test.go b/Godeps/_workspace/src/github.com/imdario/mergo/mergo_test.go deleted file mode 100644 index 072bddb79..000000000 --- a/Godeps/_workspace/src/github.com/imdario/mergo/mergo_test.go +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright 2013 Dario Castañé. All rights reserved. -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mergo - -import ( - "gopkg.in/yaml.v1" - "io/ioutil" - "reflect" - "testing" -) - -type simpleTest struct { - Value int -} - -type complexTest struct { - St simpleTest - sz int - Id string -} - -type moreComplextText struct { - Ct complexTest - St simpleTest - Nt simpleTest -} - -type pointerTest struct { - C *simpleTest -} - -type sliceTest struct { - S []int -} - -func TestNil(t *testing.T) { - if err := Merge(nil, nil); err != ErrNilArguments { - t.Fail() - } -} - -func TestDifferentTypes(t *testing.T) { - a := simpleTest{42} - b := 42 - if err := Merge(&a, b); err != ErrDifferentArgumentsTypes { - t.Fail() - } -} - -func TestSimpleStruct(t *testing.T) { - a := simpleTest{} - b := simpleTest{42} - if err := Merge(&a, b); err != nil { - t.FailNow() - } - if a.Value != 42 { - t.Fatalf("b not merged in a properly: a.Value(%d) != b.Value(%d)", a.Value, b.Value) - } - if !reflect.DeepEqual(a, b) { - t.FailNow() - } -} - -func TestComplexStruct(t *testing.T) { - a := complexTest{} - a.Id = "athing" - b := complexTest{simpleTest{42}, 1, "bthing"} - if err := Merge(&a, b); err != nil { - t.FailNow() - } - if a.St.Value != 42 { - t.Fatalf("b not merged in a properly: a.St.Value(%d) != b.St.Value(%d)", a.St.Value, b.St.Value) - } - if a.sz == 1 { - t.Fatalf("a's private field sz not preserved from merge: a.sz(%d) == b.sz(%d)", a.sz, b.sz) - } - if a.Id != b.Id { - t.Fatalf("a's field Id not merged properly: a.Id(%s) != b.Id(%s)", a.Id, b.Id) - } -} - -func TestPointerStruct(t *testing.T) { - s1 := simpleTest{} - s2 := simpleTest{19} - a := pointerTest{&s1} - b := pointerTest{&s2} - if err := Merge(&a, b); err != nil { - t.FailNow() - } - if a.C.Value != b.C.Value { - //t.Fatalf("b not merged in a properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value) - } -} - -func TestPointerStructNil(t *testing.T) { - a := pointerTest{nil} - b := pointerTest{&simpleTest{19}} - if err := Merge(&a, b); err != nil { - t.FailNow() - } - if a.C.Value != b.C.Value { - t.Fatalf("b not merged in a properly: a.C.Value(%d) != b.C.Value(%d)", a.C.Value, b.C.Value) - } -} - -func TestSliceStruct(t *testing.T) { - a := sliceTest{} - b := sliceTest{[]int{1, 2, 3}} - if err := Merge(&a, b); err != nil { - t.FailNow() - } - if len(b.S) != 3 { - t.FailNow() - } - if len(a.S) != len(b.S) { - t.Fatalf("b not merged in a properly %d != %d", len(a.S), len(b.S)) - } - - a = sliceTest{[]int{1}} - b = sliceTest{[]int{1, 2, 3}} - if err := Merge(&a, b); err != nil { - t.FailNow() - } - if len(b.S) != 3 { - t.FailNow() - } - if len(a.S) != len(b.S) { - t.Fatalf("b not merged in a properly %d != %d", len(a.S), len(b.S)) - } -} - -func TestMaps(t *testing.T) { - m := map[string]simpleTest{ - "a": simpleTest{}, - "b": simpleTest{42}, - } - n := map[string]simpleTest{ - "a": simpleTest{16}, - "b": simpleTest{}, - "c": simpleTest{12}, - } - if err := Merge(&m, n); err != nil { - t.Fatalf(err.Error()) - } - if len(m) != 3 { - t.Fatalf(`n not merged in m properly, m must have 3 elements instead of %d`, len(m)) - } - if m["a"].Value != 0 { - t.Fatalf(`n merged in m because I solved non-addressable map values TODO: m["a"].Value(%d) != n["a"].Value(%d)`, m["a"].Value, n["a"].Value) - } - if m["b"].Value != 42 { - t.Fatalf(`n wrongly merged in m: m["b"].Value(%d) != n["b"].Value(%d)`, m["b"].Value, n["b"].Value) - } - if m["c"].Value != 12 { - t.Fatalf(`n not merged in m: m["c"].Value(%d) != n["c"].Value(%d)`, m["c"].Value, n["c"].Value) - } -} - -func TestYAMLMaps(t *testing.T) { - thing := loadYAML("testdata/thing.yml") - license := loadYAML("testdata/license.yml") - ft := thing["fields"].(map[interface{}]interface{}) - fl := license["fields"].(map[interface{}]interface{}) - expectedLength := len(ft) + len(fl) - if err := Merge(&license, thing); err != nil { - t.Fatal(err.Error()) - } - currentLength := len(license["fields"].(map[interface{}]interface{})) - if currentLength != expectedLength { - t.Fatalf(`thing not merged in license properly, license must have %d elements instead of %d`, expectedLength, currentLength) - } - fields := license["fields"].(map[interface{}]interface{}) - if _, ok := fields["id"]; !ok { - t.Fatalf(`thing not merged in license properly, license must have a new id field from thing`) - } -} - -func TestTwoPointerValues(t *testing.T) { - a := &simpleTest{} - b := &simpleTest{42} - if err := Merge(a, b); err != nil { - t.Fatalf(`Boom. You crossed the streams: %s`, err) - } -} - -func TestMap(t *testing.T) { - a := complexTest{} - a.Id = "athing" - c := moreComplextText{a, simpleTest{}, simpleTest{}} - b := map[string]interface{}{ - "ct": map[string]interface{}{ - "st": map[string]interface{}{ - "value": 42, - }, - "sz": 1, - "id": "bthing", - }, - "st": &simpleTest{144}, // Mapping a reference - "zt": simpleTest{299}, // Mapping a missing field (zt doesn't exist) - "nt": simpleTest{3}, - } - if err := Map(&c, b); err != nil { - t.FailNow() - } - m := b["ct"].(map[string]interface{}) - n := m["st"].(map[string]interface{}) - o := b["st"].(*simpleTest) - p := b["nt"].(simpleTest) - if c.Ct.St.Value != 42 { - t.Fatalf("b not merged in a properly: c.Ct.St.Value(%d) != b.Ct.St.Value(%d)", c.Ct.St.Value, n["value"]) - } - if c.St.Value != 144 { - t.Fatalf("b not merged in a properly: c.St.Value(%d) != b.St.Value(%d)", c.St.Value, o.Value) - } - if c.Nt.Value != 3 { - t.Fatalf("b not merged in a properly: c.Nt.Value(%d) != b.Nt.Value(%d)", c.St.Value, p.Value) - } - if c.Ct.sz == 1 { - t.Fatalf("a's private field sz not preserved from merge: c.Ct.sz(%d) == b.Ct.sz(%d)", c.Ct.sz, m["sz"]) - } - if c.Ct.Id != m["id"] { - t.Fatalf("a's field Id not merged properly: c.Ct.Id(%s) != b.Ct.Id(%s)", c.Ct.Id, m["id"]) - } -} - -func TestSimpleMap(t *testing.T) { - a := simpleTest{} - b := map[string]interface{}{ - "value": 42, - } - if err := Map(&a, b); err != nil { - t.FailNow() - } - if a.Value != 42 { - t.Fatalf("b not merged in a properly: a.Value(%d) != b.Value(%v)", a.Value, b["value"]) - } -} - -type pointerMapTest struct { - A int - hidden int - B *simpleTest -} - -func TestBackAndForth(t *testing.T) { - pt := pointerMapTest{42, 1, &simpleTest{66}} - m := make(map[string]interface{}) - if err := Map(&m, pt); err != nil { - t.FailNow() - } - var ( - v interface{} - ok bool - ) - if v, ok = m["a"]; v.(int) != pt.A || !ok { - t.Fatalf("pt not merged properly: m[`a`](%d) != pt.A(%d)", v, pt.A) - } - if v, ok = m["b"]; !ok { - t.Fatalf("pt not merged properly: B is missing in m") - } - var st *simpleTest - if st = v.(*simpleTest); st.Value != 66 { - t.Fatalf("something went wrong while mapping pt on m, B wasn't copied") - } - bpt := pointerMapTest{} - if err := Map(&bpt, m); err != nil { - t.Fatal(err) - } - if bpt.A != pt.A { - t.Fatalf("pt not merged properly: bpt.A(%d) != pt.A(%d)", bpt.A, pt.A) - } - if bpt.hidden == pt.hidden { - t.Fatalf("pt unexpectedly merged: bpt.hidden(%d) == pt.hidden(%d)", bpt.hidden, pt.hidden) - } - if bpt.B.Value != pt.B.Value { - t.Fatalf("pt not merged properly: bpt.B.Value(%d) != pt.B.Value(%d)", bpt.B.Value, pt.B.Value) - } -} - -func loadYAML(path string) (m map[string]interface{}) { - m = make(map[string]interface{}) - raw, _ := ioutil.ReadFile(path) - _ = yaml.Unmarshal(raw, &m) - return -} diff --git a/Godeps/_workspace/src/github.com/imdario/mergo/testdata/license.yml b/Godeps/_workspace/src/github.com/imdario/mergo/testdata/license.yml deleted file mode 100644 index 62fdb61ec..000000000 --- a/Godeps/_workspace/src/github.com/imdario/mergo/testdata/license.yml +++ /dev/null @@ -1,3 +0,0 @@ -import: ../../../../fossene/db/schema/thing.yml -fields: - site: string diff --git a/Godeps/_workspace/src/github.com/imdario/mergo/testdata/thing.yml b/Godeps/_workspace/src/github.com/imdario/mergo/testdata/thing.yml deleted file mode 100644 index c28eab0d0..000000000 --- a/Godeps/_workspace/src/github.com/imdario/mergo/testdata/thing.yml +++ /dev/null @@ -1,5 +0,0 @@ -fields: - id: int - name: string - parent: ref "datu:thing" - status: enum(draft, public, private) diff --git a/Godeps/_workspace/src/github.com/juju/ratelimit/ratelimit_test.go b/Godeps/_workspace/src/github.com/juju/ratelimit/ratelimit_test.go deleted file mode 100644 index 62d88ded0..000000000 --- a/Godeps/_workspace/src/github.com/juju/ratelimit/ratelimit_test.go +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright 2014 Canonical Ltd. -// Licensed under the LGPLv3 with static-linking exception. -// See LICENCE file for details. - -package ratelimit - -import ( - "math" - "testing" - "time" - - gc "gopkg.in/check.v1" -) - -func TestPackage(t *testing.T) { - gc.TestingT(t) -} - -type rateLimitSuite struct{} - -var _ = gc.Suite(rateLimitSuite{}) - -type takeReq struct { - time time.Duration - count int64 - expectWait time.Duration -} - -var takeTests = []struct { - about string - fillInterval time.Duration - capacity int64 - reqs []takeReq -}{{ - about: "serial requests", - fillInterval: 250 * time.Millisecond, - capacity: 10, - reqs: []takeReq{{ - time: 0, - count: 0, - expectWait: 0, - }, { - time: 0, - count: 10, - expectWait: 0, - }, { - time: 0, - count: 1, - expectWait: 250 * time.Millisecond, - }, { - time: 250 * time.Millisecond, - count: 1, - expectWait: 250 * time.Millisecond, - }}, -}, { - about: "concurrent requests", - fillInterval: 250 * time.Millisecond, - capacity: 10, - reqs: []takeReq{{ - time: 0, - count: 10, - expectWait: 0, - }, { - time: 0, - count: 2, - expectWait: 500 * time.Millisecond, - }, { - time: 0, - count: 2, - expectWait: 1000 * time.Millisecond, - }, { - time: 0, - count: 1, - expectWait: 1250 * time.Millisecond, - }}, -}, { - about: "more than capacity", - fillInterval: 1 * time.Millisecond, - capacity: 10, - reqs: []takeReq{{ - time: 0, - count: 10, - expectWait: 0, - }, { - time: 20 * time.Millisecond, - count: 15, - expectWait: 5 * time.Millisecond, - }}, -}, { - about: "sub-quantum time", - fillInterval: 10 * time.Millisecond, - capacity: 10, - reqs: []takeReq{{ - time: 0, - count: 10, - expectWait: 0, - }, { - time: 7 * time.Millisecond, - count: 1, - expectWait: 3 * time.Millisecond, - }, { - time: 8 * time.Millisecond, - count: 1, - expectWait: 12 * time.Millisecond, - }}, -}, { - about: "within capacity", - fillInterval: 10 * time.Millisecond, - capacity: 5, - reqs: []takeReq{{ - time: 0, - count: 5, - expectWait: 0, - }, { - time: 60 * time.Millisecond, - count: 5, - expectWait: 0, - }, { - time: 60 * time.Millisecond, - count: 1, - expectWait: 10 * time.Millisecond, - }, { - time: 80 * time.Millisecond, - count: 2, - expectWait: 10 * time.Millisecond, - }}, -}} - -var availTests = []struct { - about string - capacity int64 - fillInterval time.Duration - take int64 - sleep time.Duration - - expectCountAfterTake int64 - expectCountAfterSleep int64 -}{{ - about: "should fill tokens after interval", - capacity: 5, - fillInterval: time.Second, - take: 5, - sleep: time.Second, - expectCountAfterTake: 0, - expectCountAfterSleep: 1, -}, { - about: "should fill tokens plus existing count", - capacity: 2, - fillInterval: time.Second, - take: 1, - sleep: time.Second, - expectCountAfterTake: 1, - expectCountAfterSleep: 2, -}, { - about: "shouldn't fill before interval", - capacity: 2, - fillInterval: 2 * time.Second, - take: 1, - sleep: time.Second, - expectCountAfterTake: 1, - expectCountAfterSleep: 1, -}, { - about: "should fill only once after 1*interval before 2*interval", - capacity: 2, - fillInterval: 2 * time.Second, - take: 1, - sleep: 3 * time.Second, - expectCountAfterTake: 1, - expectCountAfterSleep: 2, -}} - -func (rateLimitSuite) TestTake(c *gc.C) { - for i, test := range takeTests { - tb := NewBucket(test.fillInterval, test.capacity) - for j, req := range test.reqs { - d, ok := tb.take(tb.startTime.Add(req.time), req.count, infinityDuration) - c.Assert(ok, gc.Equals, true) - if d != req.expectWait { - c.Fatalf("test %d.%d, %s, got %v want %v", i, j, test.about, d, req.expectWait) - } - } - } -} - -func (rateLimitSuite) TestTakeMaxDuration(c *gc.C) { - for i, test := range takeTests { - tb := NewBucket(test.fillInterval, test.capacity) - for j, req := range test.reqs { - if req.expectWait > 0 { - d, ok := tb.take(tb.startTime.Add(req.time), req.count, req.expectWait-1) - c.Assert(ok, gc.Equals, false) - c.Assert(d, gc.Equals, time.Duration(0)) - } - d, ok := tb.take(tb.startTime.Add(req.time), req.count, req.expectWait) - c.Assert(ok, gc.Equals, true) - if d != req.expectWait { - c.Fatalf("test %d.%d, %s, got %v want %v", i, j, test.about, d, req.expectWait) - } - } - } -} - -type takeAvailableReq struct { - time time.Duration - count int64 - expect int64 -} - -var takeAvailableTests = []struct { - about string - fillInterval time.Duration - capacity int64 - reqs []takeAvailableReq -}{{ - about: "serial requests", - fillInterval: 250 * time.Millisecond, - capacity: 10, - reqs: []takeAvailableReq{{ - time: 0, - count: 0, - expect: 0, - }, { - time: 0, - count: 10, - expect: 10, - }, { - time: 0, - count: 1, - expect: 0, - }, { - time: 250 * time.Millisecond, - count: 1, - expect: 1, - }}, -}, { - about: "concurrent requests", - fillInterval: 250 * time.Millisecond, - capacity: 10, - reqs: []takeAvailableReq{{ - time: 0, - count: 5, - expect: 5, - }, { - time: 0, - count: 2, - expect: 2, - }, { - time: 0, - count: 5, - expect: 3, - }, { - time: 0, - count: 1, - expect: 0, - }}, -}, { - about: "more than capacity", - fillInterval: 1 * time.Millisecond, - capacity: 10, - reqs: []takeAvailableReq{{ - time: 0, - count: 10, - expect: 10, - }, { - time: 20 * time.Millisecond, - count: 15, - expect: 10, - }}, -}, { - about: "within capacity", - fillInterval: 10 * time.Millisecond, - capacity: 5, - reqs: []takeAvailableReq{{ - time: 0, - count: 5, - expect: 5, - }, { - time: 60 * time.Millisecond, - count: 5, - expect: 5, - }, { - time: 70 * time.Millisecond, - count: 1, - expect: 1, - }}, -}} - -func (rateLimitSuite) TestTakeAvailable(c *gc.C) { - for i, test := range takeAvailableTests { - tb := NewBucket(test.fillInterval, test.capacity) - for j, req := range test.reqs { - d := tb.takeAvailable(tb.startTime.Add(req.time), req.count) - if d != req.expect { - c.Fatalf("test %d.%d, %s, got %v want %v", i, j, test.about, d, req.expect) - } - } - } -} - -func (rateLimitSuite) TestPanics(c *gc.C) { - c.Assert(func() { NewBucket(0, 1) }, gc.PanicMatches, "token bucket fill interval is not > 0") - c.Assert(func() { NewBucket(-2, 1) }, gc.PanicMatches, "token bucket fill interval is not > 0") - c.Assert(func() { NewBucket(1, 0) }, gc.PanicMatches, "token bucket capacity is not > 0") - c.Assert(func() { NewBucket(1, -2) }, gc.PanicMatches, "token bucket capacity is not > 0") -} - -func isCloseTo(x, y, tolerance float64) bool { - return math.Abs(x-y)/y < tolerance -} - -func (rateLimitSuite) TestRate(c *gc.C) { - tb := NewBucket(1, 1) - if !isCloseTo(tb.Rate(), 1e9, 0.00001) { - c.Fatalf("got %v want 1e9", tb.Rate()) - } - tb = NewBucket(2*time.Second, 1) - if !isCloseTo(tb.Rate(), 0.5, 0.00001) { - c.Fatalf("got %v want 0.5", tb.Rate()) - } - tb = NewBucketWithQuantum(100*time.Millisecond, 1, 5) - if !isCloseTo(tb.Rate(), 50, 0.00001) { - c.Fatalf("got %v want 50", tb.Rate()) - } -} - -func checkRate(c *gc.C, rate float64) { - tb := NewBucketWithRate(rate, 1<<62) - if !isCloseTo(tb.Rate(), rate, rateMargin) { - c.Fatalf("got %g want %v", tb.Rate(), rate) - } - d, ok := tb.take(tb.startTime, 1<<62, infinityDuration) - c.Assert(ok, gc.Equals, true) - c.Assert(d, gc.Equals, time.Duration(0)) - - // Check that the actual rate is as expected by - // asking for a not-quite multiple of the bucket's - // quantum and checking that the wait time - // correct. - d, ok = tb.take(tb.startTime, tb.quantum*2-tb.quantum/2, infinityDuration) - c.Assert(ok, gc.Equals, true) - expectTime := 1e9 * float64(tb.quantum) * 2 / rate - if !isCloseTo(float64(d), expectTime, rateMargin) { - c.Fatalf("rate %g: got %g want %v", rate, float64(d), expectTime) - } -} - -func (rateLimitSuite) TestNewWithRate(c *gc.C) { - for rate := float64(1); rate < 1e6; rate += 7 { - checkRate(c, rate) - } - for _, rate := range []float64{ - 1024 * 1024 * 1024, - 1e-5, - 0.9e-5, - 0.5, - 0.9, - 0.9e8, - 3e12, - 4e18, - } { - checkRate(c, rate) - checkRate(c, rate/3) - checkRate(c, rate*1.3) - } -} - -func TestAvailable(t *testing.T) { - for i, tt := range availTests { - tb := NewBucket(tt.fillInterval, tt.capacity) - if c := tb.takeAvailable(tb.startTime, tt.take); c != tt.take { - t.Fatalf("#%d: %s, take = %d, want = %d", i, tt.about, c, tt.take) - } - if c := tb.available(tb.startTime); c != tt.expectCountAfterTake { - t.Fatalf("#%d: %s, after take, available = %d, want = %d", i, tt.about, c, tt.expectCountAfterTake) - } - if c := tb.available(tb.startTime.Add(tt.sleep)); c != tt.expectCountAfterSleep { - t.Fatalf("#%d: %s, after some time it should fill in new tokens, available = %d, want = %d", - i, tt.about, c, tt.expectCountAfterSleep) - } - } - -} - -func BenchmarkWait(b *testing.B) { - tb := NewBucket(1, 16*1024) - for i := b.N - 1; i >= 0; i-- { - tb.Wait(1) - } -} diff --git a/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go b/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go deleted file mode 100644 index 094156e66..000000000 --- a/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/all_test.go +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright 2013 Matt T. Proud -// -// 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 pbutil - -import ( - "bytes" - "math/rand" - "reflect" - "testing" - "testing/quick" - - "github.com/matttproud/golang_protobuf_extensions/pbtest" - - . "github.com/golang/protobuf/proto" - . "github.com/golang/protobuf/proto/testdata" -) - -func TestWriteDelimited(t *testing.T) { - for _, test := range []struct { - msg Message - buf []byte - n int - err error - }{ - { - msg: &Empty{}, - n: 1, - buf: []byte{0}, - }, - { - msg: &GoEnum{Foo: FOO_FOO1.Enum()}, - n: 3, - buf: []byte{2, 8, 1}, - }, - { - msg: &Strings{ - StringField: String(`This is my gigantic, unhappy string. It exceeds -the encoding size of a single byte varint. We are using it to fuzz test the -correctness of the header decoding mechanisms, which may prove problematic. -I expect it may. Let's hope you enjoy testing as much as we do.`), - }, - n: 271, - buf: []byte{141, 2, 10, 138, 2, 84, 104, 105, 115, 32, 105, 115, 32, 109, - 121, 32, 103, 105, 103, 97, 110, 116, 105, 99, 44, 32, 117, 110, 104, - 97, 112, 112, 121, 32, 115, 116, 114, 105, 110, 103, 46, 32, 32, 73, - 116, 32, 101, 120, 99, 101, 101, 100, 115, 10, 116, 104, 101, 32, 101, - 110, 99, 111, 100, 105, 110, 103, 32, 115, 105, 122, 101, 32, 111, 102, - 32, 97, 32, 115, 105, 110, 103, 108, 101, 32, 98, 121, 116, 101, 32, - 118, 97, 114, 105, 110, 116, 46, 32, 32, 87, 101, 32, 97, 114, 101, 32, - 117, 115, 105, 110, 103, 32, 105, 116, 32, 116, 111, 32, 102, 117, 122, - 122, 32, 116, 101, 115, 116, 32, 116, 104, 101, 10, 99, 111, 114, 114, - 101, 99, 116, 110, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, - 104, 101, 97, 100, 101, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103, - 32, 109, 101, 99, 104, 97, 110, 105, 115, 109, 115, 44, 32, 119, 104, - 105, 99, 104, 32, 109, 97, 121, 32, 112, 114, 111, 118, 101, 32, 112, - 114, 111, 98, 108, 101, 109, 97, 116, 105, 99, 46, 10, 73, 32, 101, 120, - 112, 101, 99, 116, 32, 105, 116, 32, 109, 97, 121, 46, 32, 32, 76, 101, - 116, 39, 115, 32, 104, 111, 112, 101, 32, 121, 111, 117, 32, 101, 110, - 106, 111, 121, 32, 116, 101, 115, 116, 105, 110, 103, 32, 97, 115, 32, - 109, 117, 99, 104, 32, 97, 115, 32, 119, 101, 32, 100, 111, 46}, - }, - } { - var buf bytes.Buffer - if n, err := WriteDelimited(&buf, test.msg); n != test.n || err != test.err { - t.Fatalf("WriteDelimited(buf, %#v) = %v, %v; want %v, %v", test.msg, n, err, test.n, test.err) - } - if out := buf.Bytes(); !bytes.Equal(out, test.buf) { - t.Fatalf("WriteDelimited(buf, %#v); buf = %v; want %v", test.msg, out, test.buf) - } - } -} - -func TestReadDelimited(t *testing.T) { - for _, test := range []struct { - buf []byte - msg Message - n int - err error - }{ - { - buf: []byte{0}, - msg: &Empty{}, - n: 1, - }, - { - n: 3, - buf: []byte{2, 8, 1}, - msg: &GoEnum{Foo: FOO_FOO1.Enum()}, - }, - { - buf: []byte{141, 2, 10, 138, 2, 84, 104, 105, 115, 32, 105, 115, 32, 109, - 121, 32, 103, 105, 103, 97, 110, 116, 105, 99, 44, 32, 117, 110, 104, - 97, 112, 112, 121, 32, 115, 116, 114, 105, 110, 103, 46, 32, 32, 73, - 116, 32, 101, 120, 99, 101, 101, 100, 115, 10, 116, 104, 101, 32, 101, - 110, 99, 111, 100, 105, 110, 103, 32, 115, 105, 122, 101, 32, 111, 102, - 32, 97, 32, 115, 105, 110, 103, 108, 101, 32, 98, 121, 116, 101, 32, - 118, 97, 114, 105, 110, 116, 46, 32, 32, 87, 101, 32, 97, 114, 101, 32, - 117, 115, 105, 110, 103, 32, 105, 116, 32, 116, 111, 32, 102, 117, 122, - 122, 32, 116, 101, 115, 116, 32, 116, 104, 101, 10, 99, 111, 114, 114, - 101, 99, 116, 110, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, - 104, 101, 97, 100, 101, 114, 32, 100, 101, 99, 111, 100, 105, 110, 103, - 32, 109, 101, 99, 104, 97, 110, 105, 115, 109, 115, 44, 32, 119, 104, - 105, 99, 104, 32, 109, 97, 121, 32, 112, 114, 111, 118, 101, 32, 112, - 114, 111, 98, 108, 101, 109, 97, 116, 105, 99, 46, 10, 73, 32, 101, 120, - 112, 101, 99, 116, 32, 105, 116, 32, 109, 97, 121, 46, 32, 32, 76, 101, - 116, 39, 115, 32, 104, 111, 112, 101, 32, 121, 111, 117, 32, 101, 110, - 106, 111, 121, 32, 116, 101, 115, 116, 105, 110, 103, 32, 97, 115, 32, - 109, 117, 99, 104, 32, 97, 115, 32, 119, 101, 32, 100, 111, 46}, - msg: &Strings{ - StringField: String(`This is my gigantic, unhappy string. It exceeds -the encoding size of a single byte varint. We are using it to fuzz test the -correctness of the header decoding mechanisms, which may prove problematic. -I expect it may. Let's hope you enjoy testing as much as we do.`), - }, - n: 271, - }, - } { - msg := Clone(test.msg) - msg.Reset() - if n, err := ReadDelimited(bytes.NewBuffer(test.buf), msg); n != test.n || err != test.err { - t.Fatalf("ReadDelimited(%v, msg) = %v, %v; want %v, %v", test.buf, n, err, test.n, test.err) - } - if !Equal(msg, test.msg) { - t.Fatalf("ReadDelimited(%v, msg); msg = %v; want %v", test.buf, msg, test.msg) - } - } -} - -func TestEndToEndValid(t *testing.T) { - for _, test := range [][]Message{ - {&Empty{}}, - {&GoEnum{Foo: FOO_FOO1.Enum()}, &Empty{}, &GoEnum{Foo: FOO_FOO1.Enum()}}, - {&GoEnum{Foo: FOO_FOO1.Enum()}}, - {&Strings{ - StringField: String(`This is my gigantic, unhappy string. It exceeds -the encoding size of a single byte varint. We are using it to fuzz test the -correctness of the header decoding mechanisms, which may prove problematic. -I expect it may. Let's hope you enjoy testing as much as we do.`), - }}, - } { - var buf bytes.Buffer - var written int - for i, msg := range test { - n, err := WriteDelimited(&buf, msg) - if err != nil { - // Assumption: TestReadDelimited and TestWriteDelimited are sufficient - // and inputs for this test are explicitly exercised there. - t.Fatalf("WriteDelimited(buf, %v[%d]) = ?, %v; wanted ?, nil", test, i, err) - } - written += n - } - var read int - for i, msg := range test { - out := Clone(msg) - out.Reset() - n, _ := ReadDelimited(&buf, out) - // Decide to do EOF checking? - read += n - if !Equal(out, msg) { - t.Fatalf("out = %v; want %v[%d] = %#v", out, test, i, msg) - } - } - if read != written { - t.Fatalf("%v read = %d; want %d", test, read, written) - } - } -} - -// rndMessage generates a random valid Protocol Buffer message. -func rndMessage(r *rand.Rand) Message { - var t reflect.Type - switch v := rand.Intn(23); v { - // TODO(br): Uncomment the elements below once fix is incorporated, except - // for the elements marked as patently incompatible. - // case 0: - // t = reflect.TypeOf(&GoEnum{}) - // break - // case 1: - // t = reflect.TypeOf(&GoTestField{}) - // break - case 2: - t = reflect.TypeOf(&GoTest{}) - break - // case 3: - // t = reflect.TypeOf(&GoSkipTest{}) - // break - // case 4: - // t = reflect.TypeOf(&NonPackedTest{}) - // break - // case 5: - // t = reflect.TypeOf(&PackedTest{}) - // break - case 6: - t = reflect.TypeOf(&MaxTag{}) - break - case 7: - t = reflect.TypeOf(&OldMessage{}) - break - case 8: - t = reflect.TypeOf(&NewMessage{}) - break - case 9: - t = reflect.TypeOf(&InnerMessage{}) - break - case 10: - t = reflect.TypeOf(&OtherMessage{}) - break - case 11: - // PATENTLY INVALID FOR FUZZ GENERATION - // t = reflect.TypeOf(&MyMessage{}) - break - // case 12: - // t = reflect.TypeOf(&Ext{}) - // break - case 13: - // PATENTLY INVALID FOR FUZZ GENERATION - // t = reflect.TypeOf(&MyMessageSet{}) - break - // case 14: - // t = reflect.TypeOf(&Empty{}) - // break - // case 15: - // t = reflect.TypeOf(&MessageList{}) - // break - // case 16: - // t = reflect.TypeOf(&Strings{}) - // break - // case 17: - // t = reflect.TypeOf(&Defaults{}) - // break - // case 17: - // t = reflect.TypeOf(&SubDefaults{}) - // break - // case 18: - // t = reflect.TypeOf(&RepeatedEnum{}) - // break - case 19: - t = reflect.TypeOf(&MoreRepeated{}) - break - // case 20: - // t = reflect.TypeOf(&GroupOld{}) - // break - // case 21: - // t = reflect.TypeOf(&GroupNew{}) - // break - case 22: - t = reflect.TypeOf(&FloatingPoint{}) - break - default: - // TODO(br): Replace with an unreachable once fixed. - t = reflect.TypeOf(&GoTest{}) - break - } - if t == nil { - t = reflect.TypeOf(&GoTest{}) - } - v, ok := quick.Value(t, r) - if !ok { - panic("attempt to generate illegal item; consult item 11") - } - if err := pbtest.SanitizeGenerated(v.Interface().(Message)); err != nil { - panic(err) - } - return v.Interface().(Message) -} - -// rndMessages generates several random Protocol Buffer messages. -func rndMessages(r *rand.Rand) []Message { - n := r.Intn(128) - out := make([]Message, 0, n) - for i := 0; i < n; i++ { - out = append(out, rndMessage(r)) - } - return out -} - -func TestFuzz(t *testing.T) { - rnd := rand.New(rand.NewSource(42)) - check := func() bool { - messages := rndMessages(rnd) - var buf bytes.Buffer - var written int - for i, msg := range messages { - n, err := WriteDelimited(&buf, msg) - if err != nil { - t.Fatalf("WriteDelimited(buf, %v[%d]) = ?, %v; wanted ?, nil", messages, i, err) - } - written += n - } - var read int - for i, msg := range messages { - out := Clone(msg) - out.Reset() - n, _ := ReadDelimited(&buf, out) - read += n - if !Equal(out, msg) { - t.Fatalf("out = %v; want %v[%d] = %#v", out, messages, i, msg) - } - } - if read != written { - t.Fatalf("%v read = %d; want %d", messages, read, written) - } - return true - } - if err := quick.Check(check, nil); err != nil { - t.Fatal(err) - } -} diff --git a/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/fixtures_test.go b/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/fixtures_test.go deleted file mode 100644 index d6d9b2559..000000000 --- a/Godeps/_workspace/src/github.com/matttproud/golang_protobuf_extensions/pbutil/fixtures_test.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// http://github.com/golang/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package pbutil - -import ( - . "github.com/golang/protobuf/proto" - . "github.com/golang/protobuf/proto/testdata" -) - -// FROM https://github.com/golang/protobuf/blob/master/proto/all_test.go. - -func initGoTestField() *GoTestField { - f := new(GoTestField) - f.Label = String("label") - f.Type = String("type") - return f -} - -// These are all structurally equivalent but the tag numbers differ. -// (It's remarkable that required, optional, and repeated all have -// 8 letters.) -func initGoTest_RequiredGroup() *GoTest_RequiredGroup { - return &GoTest_RequiredGroup{ - RequiredField: String("required"), - } -} - -func initGoTest_OptionalGroup() *GoTest_OptionalGroup { - return &GoTest_OptionalGroup{ - RequiredField: String("optional"), - } -} - -func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { - return &GoTest_RepeatedGroup{ - RequiredField: String("repeated"), - } -} - -func initGoTest(setdefaults bool) *GoTest { - pb := new(GoTest) - if setdefaults { - pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) - pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) - pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) - pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) - pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) - pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) - pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) - pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) - pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) - pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) - pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted - pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) - pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) - } - - pb.Kind = GoTest_TIME.Enum() - pb.RequiredField = initGoTestField() - pb.F_BoolRequired = Bool(true) - pb.F_Int32Required = Int32(3) - pb.F_Int64Required = Int64(6) - pb.F_Fixed32Required = Uint32(32) - pb.F_Fixed64Required = Uint64(64) - pb.F_Uint32Required = Uint32(3232) - pb.F_Uint64Required = Uint64(6464) - pb.F_FloatRequired = Float32(3232) - pb.F_DoubleRequired = Float64(6464) - pb.F_StringRequired = String("string") - pb.F_BytesRequired = []byte("bytes") - pb.F_Sint32Required = Int32(-32) - pb.F_Sint64Required = Int64(-64) - pb.Requiredgroup = initGoTest_RequiredGroup() - - return pb -} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks_test.go deleted file mode 100644 index b417deeb6..000000000 --- a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/decode_hooks_test.go +++ /dev/null @@ -1,191 +0,0 @@ -package mapstructure - -import ( - "errors" - "reflect" - "testing" -) - -func TestComposeDecodeHookFunc(t *testing.T) { - f1 := func( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - return data.(string) + "foo", nil - } - - f2 := func( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - return data.(string) + "bar", nil - } - - f := ComposeDecodeHookFunc(f1, f2) - - result, err := f(reflect.String, reflect.Slice, "") - if err != nil { - t.Fatalf("bad: %s", err) - } - if result.(string) != "foobar" { - t.Fatalf("bad: %#v", result) - } -} - -func TestComposeDecodeHookFunc_err(t *testing.T) { - f1 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) { - return nil, errors.New("foo") - } - - f2 := func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) { - panic("NOPE") - } - - f := ComposeDecodeHookFunc(f1, f2) - - _, err := f(reflect.String, reflect.Slice, 42) - if err.Error() != "foo" { - t.Fatalf("bad: %s", err) - } -} - -func TestComposeDecodeHookFunc_kinds(t *testing.T) { - var f2From reflect.Kind - - f1 := func( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - return int(42), nil - } - - f2 := func( - f reflect.Kind, - t reflect.Kind, - data interface{}) (interface{}, error) { - f2From = f - return data, nil - } - - f := ComposeDecodeHookFunc(f1, f2) - - _, err := f(reflect.String, reflect.Slice, "") - if err != nil { - t.Fatalf("bad: %s", err) - } - if f2From != reflect.Int { - t.Fatalf("bad: %#v", f2From) - } -} - -func TestStringToSliceHookFunc(t *testing.T) { - f := StringToSliceHookFunc(",") - - cases := []struct { - f, t reflect.Kind - data interface{} - result interface{} - err bool - }{ - {reflect.Slice, reflect.Slice, 42, 42, false}, - {reflect.String, reflect.String, 42, 42, false}, - { - reflect.String, - reflect.Slice, - "foo,bar,baz", - []string{"foo", "bar", "baz"}, - false, - }, - { - reflect.String, - reflect.Slice, - "", - []string{}, - false, - }, - } - - for i, tc := range cases { - actual, err := f(tc.f, tc.t, tc.data) - if tc.err != (err != nil) { - t.Fatalf("case %d: expected err %#v", i, tc.err) - } - if !reflect.DeepEqual(actual, tc.result) { - t.Fatalf( - "case %d: expected %#v, got %#v", - i, tc.result, actual) - } - } -} - -func TestWeaklyTypedHook(t *testing.T) { - var f DecodeHookFunc = WeaklyTypedHook - - cases := []struct { - f, t reflect.Kind - data interface{} - result interface{} - err bool - }{ - // TO STRING - { - reflect.Bool, - reflect.String, - false, - "0", - false, - }, - - { - reflect.Bool, - reflect.String, - true, - "1", - false, - }, - - { - reflect.Float32, - reflect.String, - float32(7), - "7", - false, - }, - - { - reflect.Int, - reflect.String, - int(7), - "7", - false, - }, - - { - reflect.Slice, - reflect.String, - []uint8("foo"), - "foo", - false, - }, - - { - reflect.Uint, - reflect.String, - uint(7), - "7", - false, - }, - } - - for i, tc := range cases { - actual, err := f(tc.f, tc.t, tc.data) - if tc.err != (err != nil) { - t.Fatalf("case %d: expected err %#v", i, tc.err) - } - if !reflect.DeepEqual(actual, tc.result) { - t.Fatalf( - "case %d: expected %#v, got %#v", - i, tc.result, actual) - } - } -} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go deleted file mode 100644 index b50ac36e5..000000000 --- a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_benchmark_test.go +++ /dev/null @@ -1,243 +0,0 @@ -package mapstructure - -import ( - "testing" -) - -func Benchmark_Decode(b *testing.B) { - type Person struct { - Name string - Age int - Emails []string - Extra map[string]string - } - - input := map[string]interface{}{ - "name": "Mitchell", - "age": 91, - "emails": []string{"one", "two", "three"}, - "extra": map[string]string{ - "twitter": "mitchellh", - }, - } - - var result Person - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} - -func Benchmark_DecodeBasic(b *testing.B) { - input := map[string]interface{}{ - "vstring": "foo", - "vint": 42, - "Vuint": 42, - "vbool": true, - "Vfloat": 42.42, - "vsilent": true, - "vdata": 42, - } - - var result Basic - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} - -func Benchmark_DecodeEmbedded(b *testing.B) { - input := map[string]interface{}{ - "vstring": "foo", - "Basic": map[string]interface{}{ - "vstring": "innerfoo", - }, - "vunique": "bar", - } - - var result Embedded - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} - -func Benchmark_DecodeTypeConversion(b *testing.B) { - input := map[string]interface{}{ - "IntToFloat": 42, - "IntToUint": 42, - "IntToBool": 1, - "IntToString": 42, - "UintToInt": 42, - "UintToFloat": 42, - "UintToBool": 42, - "UintToString": 42, - "BoolToInt": true, - "BoolToUint": true, - "BoolToFloat": true, - "BoolToString": true, - "FloatToInt": 42.42, - "FloatToUint": 42.42, - "FloatToBool": 42.42, - "FloatToString": 42.42, - "StringToInt": "42", - "StringToUint": "42", - "StringToBool": "1", - "StringToFloat": "42.42", - "SliceToMap": []interface{}{}, - "MapToSlice": map[string]interface{}{}, - } - - var resultStrict TypeConversionResult - for i := 0; i < b.N; i++ { - Decode(input, &resultStrict) - } -} - -func Benchmark_DecodeMap(b *testing.B) { - input := map[string]interface{}{ - "vfoo": "foo", - "vother": map[interface{}]interface{}{ - "foo": "foo", - "bar": "bar", - }, - } - - var result Map - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} - -func Benchmark_DecodeMapOfStruct(b *testing.B) { - input := map[string]interface{}{ - "value": map[string]interface{}{ - "foo": map[string]string{"vstring": "one"}, - "bar": map[string]string{"vstring": "two"}, - }, - } - - var result MapOfStruct - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} - -func Benchmark_DecodeSlice(b *testing.B) { - input := map[string]interface{}{ - "vfoo": "foo", - "vbar": []string{"foo", "bar", "baz"}, - } - - var result Slice - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} - -func Benchmark_DecodeSliceOfStruct(b *testing.B) { - input := map[string]interface{}{ - "value": []map[string]interface{}{ - {"vstring": "one"}, - {"vstring": "two"}, - }, - } - - var result SliceOfStruct - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} - -func Benchmark_DecodeWeaklyTypedInput(b *testing.B) { - type Person struct { - Name string - Age int - Emails []string - } - - // This input can come from anywhere, but typically comes from - // something like decoding JSON, generated by a weakly typed language - // such as PHP. - input := map[string]interface{}{ - "name": 123, // number => string - "age": "42", // string => number - "emails": map[string]interface{}{}, // empty map => empty array - } - - var result Person - config := &DecoderConfig{ - WeaklyTypedInput: true, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - panic(err) - } - - for i := 0; i < b.N; i++ { - decoder.Decode(input) - } -} - -func Benchmark_DecodeMetadata(b *testing.B) { - type Person struct { - Name string - Age int - } - - input := map[string]interface{}{ - "name": "Mitchell", - "age": 91, - "email": "foo@bar.com", - } - - var md Metadata - var result Person - config := &DecoderConfig{ - Metadata: &md, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - panic(err) - } - - for i := 0; i < b.N; i++ { - decoder.Decode(input) - } -} - -func Benchmark_DecodeMetadataEmbedded(b *testing.B) { - input := map[string]interface{}{ - "vstring": "foo", - "vunique": "bar", - } - - var md Metadata - var result EmbeddedSquash - config := &DecoderConfig{ - Metadata: &md, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - b.Fatalf("err: %s", err) - } - - for i := 0; i < b.N; i++ { - decoder.Decode(input) - } -} - -func Benchmark_DecodeTagged(b *testing.B) { - input := map[string]interface{}{ - "foo": "bar", - "bar": "value", - } - - var result Tagged - for i := 0; i < b.N; i++ { - Decode(input, &result) - } -} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go deleted file mode 100644 index 7054f1ac9..000000000 --- a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_bugs_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package mapstructure - -import "testing" - -// GH-1 -func TestDecode_NilValue(t *testing.T) { - input := map[string]interface{}{ - "vfoo": nil, - "vother": nil, - } - - var result Map - err := Decode(input, &result) - if err != nil { - t.Fatalf("should not error: %s", err) - } - - if result.Vfoo != "" { - t.Fatalf("value should be default: %s", result.Vfoo) - } - - if result.Vother != nil { - t.Fatalf("Vother should be nil: %s", result.Vother) - } -} - -// GH-10 -func TestDecode_mapInterfaceInterface(t *testing.T) { - input := map[interface{}]interface{}{ - "vfoo": nil, - "vother": nil, - } - - var result Map - err := Decode(input, &result) - if err != nil { - t.Fatalf("should not error: %s", err) - } - - if result.Vfoo != "" { - t.Fatalf("value should be default: %s", result.Vfoo) - } - - if result.Vother != nil { - t.Fatalf("Vother should be nil: %s", result.Vother) - } -} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_examples_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_examples_test.go deleted file mode 100644 index aa393cc57..000000000 --- a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_examples_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package mapstructure - -import ( - "fmt" -) - -func ExampleDecode() { - type Person struct { - Name string - Age int - Emails []string - Extra map[string]string - } - - // This input can come from anywhere, but typically comes from - // something like decoding JSON where we're not quite sure of the - // struct initially. - input := map[string]interface{}{ - "name": "Mitchell", - "age": 91, - "emails": []string{"one", "two", "three"}, - "extra": map[string]string{ - "twitter": "mitchellh", - }, - } - - var result Person - err := Decode(input, &result) - if err != nil { - panic(err) - } - - fmt.Printf("%#v", result) - // Output: - // mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}} -} - -func ExampleDecode_errors() { - type Person struct { - Name string - Age int - Emails []string - Extra map[string]string - } - - // This input can come from anywhere, but typically comes from - // something like decoding JSON where we're not quite sure of the - // struct initially. - input := map[string]interface{}{ - "name": 123, - "age": "bad value", - "emails": []int{1, 2, 3}, - } - - var result Person - err := Decode(input, &result) - if err == nil { - panic("should have an error") - } - - fmt.Println(err.Error()) - // Output: - // 5 error(s) decoding: - // - // * 'Name' expected type 'string', got unconvertible type 'int' - // * 'Age' expected type 'int', got unconvertible type 'string' - // * 'Emails[0]' expected type 'string', got unconvertible type 'int' - // * 'Emails[1]' expected type 'string', got unconvertible type 'int' - // * 'Emails[2]' expected type 'string', got unconvertible type 'int' -} - -func ExampleDecode_metadata() { - type Person struct { - Name string - Age int - } - - // This input can come from anywhere, but typically comes from - // something like decoding JSON where we're not quite sure of the - // struct initially. - input := map[string]interface{}{ - "name": "Mitchell", - "age": 91, - "email": "foo@bar.com", - } - - // For metadata, we make a more advanced DecoderConfig so we can - // more finely configure the decoder that is used. In this case, we - // just tell the decoder we want to track metadata. - var md Metadata - var result Person - config := &DecoderConfig{ - Metadata: &md, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - panic(err) - } - - if err := decoder.Decode(input); err != nil { - panic(err) - } - - fmt.Printf("Unused keys: %#v", md.Unused) - // Output: - // Unused keys: []string{"email"} -} - -func ExampleDecode_weaklyTypedInput() { - type Person struct { - Name string - Age int - Emails []string - } - - // This input can come from anywhere, but typically comes from - // something like decoding JSON, generated by a weakly typed language - // such as PHP. - input := map[string]interface{}{ - "name": 123, // number => string - "age": "42", // string => number - "emails": map[string]interface{}{}, // empty map => empty array - } - - var result Person - config := &DecoderConfig{ - WeaklyTypedInput: true, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - panic(err) - } - - err = decoder.Decode(input) - if err != nil { - panic(err) - } - - fmt.Printf("%#v", result) - // Output: mapstructure.Person{Name:"123", Age:42, Emails:[]string{}} -} - -func ExampleDecode_tags() { - // Note that the mapstructure tags defined in the struct type - // can indicate which fields the values are mapped to. - type Person struct { - Name string `mapstructure:"person_name"` - Age int `mapstructure:"person_age"` - } - - input := map[string]interface{}{ - "person_name": "Mitchell", - "person_age": 91, - } - - var result Person - err := Decode(input, &result) - if err != nil { - panic(err) - } - - fmt.Printf("%#v", result) - // Output: - // mapstructure.Person{Name:"Mitchell", Age:91} -} diff --git a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_test.go b/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_test.go deleted file mode 100644 index 23029c7c4..000000000 --- a/Godeps/_workspace/src/github.com/mitchellh/mapstructure/mapstructure_test.go +++ /dev/null @@ -1,828 +0,0 @@ -package mapstructure - -import ( - "reflect" - "sort" - "testing" -) - -type Basic struct { - Vstring string - Vint int - Vuint uint - Vbool bool - Vfloat float64 - Vextra string - vsilent bool - Vdata interface{} -} - -type Embedded struct { - Basic - Vunique string -} - -type EmbeddedPointer struct { - *Basic - Vunique string -} - -type EmbeddedSquash struct { - Basic `mapstructure:",squash"` - Vunique string -} - -type Map struct { - Vfoo string - Vother map[string]string -} - -type MapOfStruct struct { - Value map[string]Basic -} - -type Nested struct { - Vfoo string - Vbar Basic -} - -type NestedPointer struct { - Vfoo string - Vbar *Basic -} - -type Slice struct { - Vfoo string - Vbar []string -} - -type SliceOfStruct struct { - Value []Basic -} - -type Tagged struct { - Extra string `mapstructure:"bar,what,what"` - Value string `mapstructure:"foo"` -} - -type TypeConversionResult struct { - IntToFloat float32 - IntToUint uint - IntToBool bool - IntToString string - UintToInt int - UintToFloat float32 - UintToBool bool - UintToString string - BoolToInt int - BoolToUint uint - BoolToFloat float32 - BoolToString string - FloatToInt int - FloatToUint uint - FloatToBool bool - FloatToString string - SliceUint8ToString string - StringToInt int - StringToUint uint - StringToBool bool - StringToFloat float32 - SliceToMap map[string]interface{} - MapToSlice []interface{} -} - -func TestBasicTypes(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vstring": "foo", - "vint": 42, - "Vuint": 42, - "vbool": true, - "Vfloat": 42.42, - "vsilent": true, - "vdata": 42, - } - - var result Basic - err := Decode(input, &result) - if err != nil { - t.Errorf("got an err: %s", err.Error()) - t.FailNow() - } - - if result.Vstring != "foo" { - t.Errorf("vstring value should be 'foo': %#v", result.Vstring) - } - - if result.Vint != 42 { - t.Errorf("vint value should be 42: %#v", result.Vint) - } - - if result.Vuint != 42 { - t.Errorf("vuint value should be 42: %#v", result.Vuint) - } - - if result.Vbool != true { - t.Errorf("vbool value should be true: %#v", result.Vbool) - } - - if result.Vfloat != 42.42 { - t.Errorf("vfloat value should be 42.42: %#v", result.Vfloat) - } - - if result.Vextra != "" { - t.Errorf("vextra value should be empty: %#v", result.Vextra) - } - - if result.vsilent != false { - t.Error("vsilent should not be set, it is unexported") - } - - if result.Vdata != 42 { - t.Error("vdata should be valid") - } -} - -func TestBasic_IntWithFloat(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vint": float64(42), - } - - var result Basic - err := Decode(input, &result) - if err != nil { - t.Fatalf("got an err: %s", err) - } -} - -func TestDecode_Embedded(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vstring": "foo", - "Basic": map[string]interface{}{ - "vstring": "innerfoo", - }, - "vunique": "bar", - } - - var result Embedded - err := Decode(input, &result) - if err != nil { - t.Fatalf("got an err: %s", err.Error()) - } - - if result.Vstring != "innerfoo" { - t.Errorf("vstring value should be 'innerfoo': %#v", result.Vstring) - } - - if result.Vunique != "bar" { - t.Errorf("vunique value should be 'bar': %#v", result.Vunique) - } -} - -func TestDecode_EmbeddedPointer(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vstring": "foo", - "Basic": map[string]interface{}{ - "vstring": "innerfoo", - }, - "vunique": "bar", - } - - var result EmbeddedPointer - err := Decode(input, &result) - if err == nil { - t.Fatal("should get error") - } -} - -func TestDecode_EmbeddedSquash(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vstring": "foo", - "vunique": "bar", - } - - var result EmbeddedSquash - err := Decode(input, &result) - if err != nil { - t.Fatalf("got an err: %s", err.Error()) - } - - if result.Vstring != "foo" { - t.Errorf("vstring value should be 'foo': %#v", result.Vstring) - } - - if result.Vunique != "bar" { - t.Errorf("vunique value should be 'bar': %#v", result.Vunique) - } -} - -func TestDecode_DecodeHook(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vint": "WHAT", - } - - decodeHook := func(from reflect.Kind, to reflect.Kind, v interface{}) (interface{}, error) { - if from == reflect.String && to != reflect.String { - return 5, nil - } - - return v, nil - } - - var result Basic - config := &DecoderConfig{ - DecodeHook: decodeHook, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - err = decoder.Decode(input) - if err != nil { - t.Fatalf("got an err: %s", err) - } - - if result.Vint != 5 { - t.Errorf("vint should be 5: %#v", result.Vint) - } -} - -func TestDecode_Nil(t *testing.T) { - t.Parallel() - - var input interface{} = nil - result := Basic{ - Vstring: "foo", - } - - err := Decode(input, &result) - if err != nil { - t.Fatalf("err: %s", err) - } - - if result.Vstring != "foo" { - t.Fatalf("bad: %#v", result.Vstring) - } -} - -func TestDecode_NonStruct(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "foo": "bar", - "bar": "baz", - } - - var result map[string]string - err := Decode(input, &result) - if err != nil { - t.Fatalf("err: %s", err) - } - - if result["foo"] != "bar" { - t.Fatal("foo is not bar") - } -} - -func TestDecode_TypeConversion(t *testing.T) { - input := map[string]interface{}{ - "IntToFloat": 42, - "IntToUint": 42, - "IntToBool": 1, - "IntToString": 42, - "UintToInt": 42, - "UintToFloat": 42, - "UintToBool": 42, - "UintToString": 42, - "BoolToInt": true, - "BoolToUint": true, - "BoolToFloat": true, - "BoolToString": true, - "FloatToInt": 42.42, - "FloatToUint": 42.42, - "FloatToBool": 42.42, - "FloatToString": 42.42, - "SliceUint8ToString": []uint8("foo"), - "StringToInt": "42", - "StringToUint": "42", - "StringToBool": "1", - "StringToFloat": "42.42", - "SliceToMap": []interface{}{}, - "MapToSlice": map[string]interface{}{}, - } - - expectedResultStrict := TypeConversionResult{ - IntToFloat: 42.0, - IntToUint: 42, - UintToInt: 42, - UintToFloat: 42, - BoolToInt: 0, - BoolToUint: 0, - BoolToFloat: 0, - FloatToInt: 42, - FloatToUint: 42, - } - - expectedResultWeak := TypeConversionResult{ - IntToFloat: 42.0, - IntToUint: 42, - IntToBool: true, - IntToString: "42", - UintToInt: 42, - UintToFloat: 42, - UintToBool: true, - UintToString: "42", - BoolToInt: 1, - BoolToUint: 1, - BoolToFloat: 1, - BoolToString: "1", - FloatToInt: 42, - FloatToUint: 42, - FloatToBool: true, - FloatToString: "42.42", - SliceUint8ToString: "foo", - StringToInt: 42, - StringToUint: 42, - StringToBool: true, - StringToFloat: 42.42, - SliceToMap: map[string]interface{}{}, - MapToSlice: []interface{}{}, - } - - // Test strict type conversion - var resultStrict TypeConversionResult - err := Decode(input, &resultStrict) - if err == nil { - t.Errorf("should return an error") - } - if !reflect.DeepEqual(resultStrict, expectedResultStrict) { - t.Errorf("expected %v, got: %v", expectedResultStrict, resultStrict) - } - - // Test weak type conversion - var decoder *Decoder - var resultWeak TypeConversionResult - - config := &DecoderConfig{ - WeaklyTypedInput: true, - Result: &resultWeak, - } - - decoder, err = NewDecoder(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - err = decoder.Decode(input) - if err != nil { - t.Fatalf("got an err: %s", err) - } - - if !reflect.DeepEqual(resultWeak, expectedResultWeak) { - t.Errorf("expected \n%#v, got: \n%#v", expectedResultWeak, resultWeak) - } -} - -func TestDecoder_ErrorUnused(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vstring": "hello", - "foo": "bar", - } - - var result Basic - config := &DecoderConfig{ - ErrorUnused: true, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - err = decoder.Decode(input) - if err == nil { - t.Fatal("expected error") - } -} - -func TestMap(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vfoo": "foo", - "vother": map[interface{}]interface{}{ - "foo": "foo", - "bar": "bar", - }, - } - - var result Map - err := Decode(input, &result) - if err != nil { - t.Fatalf("got an error: %s", err) - } - - if result.Vfoo != "foo" { - t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) - } - - if result.Vother == nil { - t.Fatal("vother should not be nil") - } - - if len(result.Vother) != 2 { - t.Error("vother should have two items") - } - - if result.Vother["foo"] != "foo" { - t.Errorf("'foo' key should be foo, got: %#v", result.Vother["foo"]) - } - - if result.Vother["bar"] != "bar" { - t.Errorf("'bar' key should be bar, got: %#v", result.Vother["bar"]) - } -} - -func TestMapOfStruct(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "value": map[string]interface{}{ - "foo": map[string]string{"vstring": "one"}, - "bar": map[string]string{"vstring": "two"}, - }, - } - - var result MapOfStruct - err := Decode(input, &result) - if err != nil { - t.Fatalf("got an err: %s", err) - } - - if result.Value == nil { - t.Fatal("value should not be nil") - } - - if len(result.Value) != 2 { - t.Error("value should have two items") - } - - if result.Value["foo"].Vstring != "one" { - t.Errorf("foo value should be 'one', got: %s", result.Value["foo"].Vstring) - } - - if result.Value["bar"].Vstring != "two" { - t.Errorf("bar value should be 'two', got: %s", result.Value["bar"].Vstring) - } -} - -func TestNestedType(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vfoo": "foo", - "vbar": map[string]interface{}{ - "vstring": "foo", - "vint": 42, - "vbool": true, - }, - } - - var result Nested - err := Decode(input, &result) - if err != nil { - t.Fatalf("got an err: %s", err.Error()) - } - - if result.Vfoo != "foo" { - t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) - } - - if result.Vbar.Vstring != "foo" { - t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring) - } - - if result.Vbar.Vint != 42 { - t.Errorf("vint value should be 42: %#v", result.Vbar.Vint) - } - - if result.Vbar.Vbool != true { - t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool) - } - - if result.Vbar.Vextra != "" { - t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra) - } -} - -func TestNestedTypePointer(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vfoo": "foo", - "vbar": &map[string]interface{}{ - "vstring": "foo", - "vint": 42, - "vbool": true, - }, - } - - var result NestedPointer - err := Decode(input, &result) - if err != nil { - t.Fatalf("got an err: %s", err.Error()) - } - - if result.Vfoo != "foo" { - t.Errorf("vfoo value should be 'foo': %#v", result.Vfoo) - } - - if result.Vbar.Vstring != "foo" { - t.Errorf("vstring value should be 'foo': %#v", result.Vbar.Vstring) - } - - if result.Vbar.Vint != 42 { - t.Errorf("vint value should be 42: %#v", result.Vbar.Vint) - } - - if result.Vbar.Vbool != true { - t.Errorf("vbool value should be true: %#v", result.Vbar.Vbool) - } - - if result.Vbar.Vextra != "" { - t.Errorf("vextra value should be empty: %#v", result.Vbar.Vextra) - } -} - -func TestSlice(t *testing.T) { - t.Parallel() - - inputStringSlice := map[string]interface{}{ - "vfoo": "foo", - "vbar": []string{"foo", "bar", "baz"}, - } - - inputStringSlicePointer := map[string]interface{}{ - "vfoo": "foo", - "vbar": &[]string{"foo", "bar", "baz"}, - } - - outputStringSlice := &Slice{ - "foo", - []string{"foo", "bar", "baz"}, - } - - testSliceInput(t, inputStringSlice, outputStringSlice) - testSliceInput(t, inputStringSlicePointer, outputStringSlice) -} - -func TestInvalidSlice(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vfoo": "foo", - "vbar": 42, - } - - result := Slice{} - err := Decode(input, &result) - if err == nil { - t.Errorf("expected failure") - } -} - -func TestSliceOfStruct(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "value": []map[string]interface{}{ - {"vstring": "one"}, - {"vstring": "two"}, - }, - } - - var result SliceOfStruct - err := Decode(input, &result) - if err != nil { - t.Fatalf("got unexpected error: %s", err) - } - - if len(result.Value) != 2 { - t.Fatalf("expected two values, got %d", len(result.Value)) - } - - if result.Value[0].Vstring != "one" { - t.Errorf("first value should be 'one', got: %s", result.Value[0].Vstring) - } - - if result.Value[1].Vstring != "two" { - t.Errorf("second value should be 'two', got: %s", result.Value[1].Vstring) - } -} - -func TestInvalidType(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vstring": 42, - } - - var result Basic - err := Decode(input, &result) - if err == nil { - t.Fatal("error should exist") - } - - derr, ok := err.(*Error) - if !ok { - t.Fatalf("error should be kind of Error, instead: %#v", err) - } - - if derr.Errors[0] != "'Vstring' expected type 'string', got unconvertible type 'int'" { - t.Errorf("got unexpected error: %s", err) - } -} - -func TestMetadata(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vfoo": "foo", - "vbar": map[string]interface{}{ - "vstring": "foo", - "Vuint": 42, - "foo": "bar", - }, - "bar": "nil", - } - - var md Metadata - var result Nested - config := &DecoderConfig{ - Metadata: &md, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - err = decoder.Decode(input) - if err != nil { - t.Fatalf("err: %s", err.Error()) - } - - expectedKeys := []string{"Vfoo", "Vbar.Vstring", "Vbar.Vuint", "Vbar"} - if !reflect.DeepEqual(md.Keys, expectedKeys) { - t.Fatalf("bad keys: %#v", md.Keys) - } - - expectedUnused := []string{"Vbar.foo", "bar"} - if !reflect.DeepEqual(md.Unused, expectedUnused) { - t.Fatalf("bad unused: %#v", md.Unused) - } -} - -func TestMetadata_Embedded(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "vstring": "foo", - "vunique": "bar", - } - - var md Metadata - var result EmbeddedSquash - config := &DecoderConfig{ - Metadata: &md, - Result: &result, - } - - decoder, err := NewDecoder(config) - if err != nil { - t.Fatalf("err: %s", err) - } - - err = decoder.Decode(input) - if err != nil { - t.Fatalf("err: %s", err.Error()) - } - - expectedKeys := []string{"Vstring", "Vunique"} - - sort.Strings(md.Keys) - if !reflect.DeepEqual(md.Keys, expectedKeys) { - t.Fatalf("bad keys: %#v", md.Keys) - } - - expectedUnused := []string{} - if !reflect.DeepEqual(md.Unused, expectedUnused) { - t.Fatalf("bad unused: %#v", md.Unused) - } -} - -func TestNonPtrValue(t *testing.T) { - t.Parallel() - - err := Decode(map[string]interface{}{}, Basic{}) - if err == nil { - t.Fatal("error should exist") - } - - if err.Error() != "result must be a pointer" { - t.Errorf("got unexpected error: %s", err) - } -} - -func TestTagged(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "foo": "bar", - "bar": "value", - } - - var result Tagged - err := Decode(input, &result) - if err != nil { - t.Fatalf("unexpected error: %s", err) - } - - if result.Value != "bar" { - t.Errorf("value should be 'bar', got: %#v", result.Value) - } - - if result.Extra != "value" { - t.Errorf("extra should be 'value', got: %#v", result.Extra) - } -} - -func TestWeakDecode(t *testing.T) { - t.Parallel() - - input := map[string]interface{}{ - "foo": "4", - "bar": "value", - } - - var result struct { - Foo int - Bar string - } - - if err := WeakDecode(input, &result); err != nil { - t.Fatalf("err: %s", err) - } - if result.Foo != 4 { - t.Fatalf("bad: %#v", result) - } - if result.Bar != "value" { - t.Fatalf("bad: %#v", result) - } -} - -func testSliceInput(t *testing.T, input map[string]interface{}, expected *Slice) { - var result Slice - err := Decode(input, &result) - if err != nil { - t.Fatalf("got error: %s", err) - } - - if result.Vfoo != expected.Vfoo { - t.Errorf("Vfoo expected '%s', got '%s'", expected.Vfoo, result.Vfoo) - } - - if result.Vbar == nil { - t.Fatalf("Vbar a slice, got '%#v'", result.Vbar) - } - - if len(result.Vbar) != len(expected.Vbar) { - t.Errorf("Vbar length should be %d, got %d", len(expected.Vbar), len(result.Vbar)) - } - - for i, v := range result.Vbar { - if v != expected.Vbar[i] { - t.Errorf( - "Vbar[%d] should be '%#v', got '%#v'", - i, expected.Vbar[i], v) - } - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_test.go deleted file mode 100644 index 2f702bc2e..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build linux - -package cgroups - -import ( - "testing" -) - -func TestParseCgroups(t *testing.T) { - cgroups, err := ParseCgroupFile("/proc/self/cgroup") - if err != nil { - t.Fatal(err) - } - - if _, ok := cgroups["cpu"]; !ok { - t.Fail() - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio_test.go deleted file mode 100644 index 695739204..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/blkio_test.go +++ /dev/null @@ -1,636 +0,0 @@ -// +build linux - -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -const ( - sectorsRecursiveContents = `8:0 1024` - serviceBytesRecursiveContents = `8:0 Read 100 -8:0 Write 200 -8:0 Sync 300 -8:0 Async 500 -8:0 Total 500 -Total 500` - servicedRecursiveContents = `8:0 Read 10 -8:0 Write 40 -8:0 Sync 20 -8:0 Async 30 -8:0 Total 50 -Total 50` - queuedRecursiveContents = `8:0 Read 1 -8:0 Write 4 -8:0 Sync 2 -8:0 Async 3 -8:0 Total 5 -Total 5` - serviceTimeRecursiveContents = `8:0 Read 173959 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 173959 -8:0 Total 17395 -Total 17395` - waitTimeRecursiveContents = `8:0 Read 15571 -8:0 Write 0 -8:0 Sync 0 -8:0 Async 15571 -8:0 Total 15571` - mergedRecursiveContents = `8:0 Read 5 -8:0 Write 10 -8:0 Sync 0 -8:0 Async 0 -8:0 Total 15 -Total 15` - timeRecursiveContents = `8:0 8` - throttleServiceBytes = `8:0 Read 11030528 -8:0 Write 23 -8:0 Sync 42 -8:0 Async 11030528 -8:0 Total 11030528 -252:0 Read 11030528 -252:0 Write 23 -252:0 Sync 42 -252:0 Async 11030528 -252:0 Total 11030528 -Total 22061056` - throttleServiced = `8:0 Read 164 -8:0 Write 23 -8:0 Sync 42 -8:0 Async 164 -8:0 Total 164 -252:0 Read 164 -252:0 Write 23 -252:0 Sync 42 -252:0 Async 164 -252:0 Total 164 -Total 328` -) - -func appendBlkioStatEntry(blkioStatEntries *[]cgroups.BlkioStatEntry, major, minor, value uint64, op string) { - *blkioStatEntries = append(*blkioStatEntries, cgroups.BlkioStatEntry{Major: major, Minor: minor, Value: value, Op: op}) -} - -func TestBlkioSetWeight(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - weightBefore = 100 - weightAfter = 200 - ) - - helper.writeFileContents(map[string]string{ - "blkio.weight": strconv.Itoa(weightBefore), - }) - - helper.CgroupData.config.Resources.BlkioWeight = weightAfter - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "blkio.weight") - if err != nil { - t.Fatalf("Failed to parse blkio.weight - %s", err) - } - - if value != weightAfter { - t.Fatal("Got the wrong value, set blkio.weight failed.") - } -} - -func TestBlkioSetWeightDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - weightDeviceBefore = "8:0 400" - ) - - wd := configs.NewWeightDevice(8, 0, 500, 0) - weightDeviceAfter := wd.WeightString() - - helper.writeFileContents(map[string]string{ - "blkio.weight_device": weightDeviceBefore, - }) - - helper.CgroupData.config.Resources.BlkioWeightDevice = []*configs.WeightDevice{wd} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.weight_device") - if err != nil { - t.Fatalf("Failed to parse blkio.weight_device - %s", err) - } - - if value != weightDeviceAfter { - t.Fatal("Got the wrong value, set blkio.weight_device failed.") - } -} - -// regression #274 -func TestBlkioSetMultipleWeightDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - weightDeviceBefore = "8:0 400" - ) - - wd1 := configs.NewWeightDevice(8, 0, 500, 0) - wd2 := configs.NewWeightDevice(8, 16, 500, 0) - // we cannot actually set and check both because normal ioutil.WriteFile - // when writing to cgroup file will overwrite the whole file content instead - // of updating it as the kernel is doing. Just check the second device - // is present will suffice for the test to ensure multiple writes are done. - weightDeviceAfter := wd2.WeightString() - - helper.writeFileContents(map[string]string{ - "blkio.weight_device": weightDeviceBefore, - }) - - helper.CgroupData.config.Resources.BlkioWeightDevice = []*configs.WeightDevice{wd1, wd2} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.weight_device") - if err != nil { - t.Fatalf("Failed to parse blkio.weight_device - %s", err) - } - - if value != weightDeviceAfter { - t.Fatal("Got the wrong value, set blkio.weight_device failed.") - } -} - -func TestBlkioStats(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - - // Verify expected stats. - expectedStats := cgroups.BlkioStats{} - appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 1024, "") - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 100, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 200, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 300, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 10, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 40, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 20, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 30, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 50, "Total") - - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 1, "Read") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Write") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Sync") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Async") - appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Total") - - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 17395, "Total") - - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Read") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Async") - appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Total") - - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 5, "Read") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 10, "Write") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async") - appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 15, "Total") - - appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 8, "") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioStatsNoSectorsFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoServiceBytesFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoServicedFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoQueuedFile(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoServiceTimeFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoWaitTimeFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoMergedFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsNoTimeFile(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatalf("Failed unexpectedly: %s", err) - } -} - -func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": "8:0 Read 100 100", - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected to fail, but did not") - } -} - -func TestBlkioStatsUnexpectedFieldType(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": "8:0 Read Write", - "blkio.io_serviced_recursive": servicedRecursiveContents, - "blkio.io_queued_recursive": queuedRecursiveContents, - "blkio.sectors_recursive": sectorsRecursiveContents, - "blkio.io_service_time_recursive": serviceTimeRecursiveContents, - "blkio.io_wait_time_recursive": waitTimeRecursiveContents, - "blkio.io_merged_recursive": mergedRecursiveContents, - "blkio.time_recursive": timeRecursiveContents, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected to fail, but did not") - } -} - -func TestNonCFQBlkioStats(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "blkio.io_service_bytes_recursive": "", - "blkio.io_serviced_recursive": "", - "blkio.io_queued_recursive": "", - "blkio.sectors_recursive": "", - "blkio.io_service_time_recursive": "", - "blkio.io_wait_time_recursive": "", - "blkio.io_merged_recursive": "", - "blkio.time_recursive": "", - "blkio.throttle.io_service_bytes": throttleServiceBytes, - "blkio.throttle.io_serviced": throttleServiced, - }) - - blkio := &BlkioGroup{} - actualStats := *cgroups.NewStats() - err := blkio.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - - // Verify expected stats. - expectedStats := cgroups.BlkioStats{} - - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Total") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Read") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Async") - appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Total") - - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Total") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Read") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 23, "Write") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 42, "Sync") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Async") - appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Total") - - expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats) -} - -func TestBlkioSetThrottleReadBpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.read_bps_device": throttleBefore, - }) - - helper.CgroupData.config.Resources.BlkioThrottleReadBpsDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.read_bps_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.read_bps_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.read_bps_device failed.") - } -} -func TestBlkioSetThrottleWriteBpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.write_bps_device": throttleBefore, - }) - - helper.CgroupData.config.Resources.BlkioThrottleWriteBpsDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.write_bps_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.write_bps_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.write_bps_device failed.") - } -} -func TestBlkioSetThrottleReadIOpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.read_iops_device": throttleBefore, - }) - - helper.CgroupData.config.Resources.BlkioThrottleReadIOPSDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.read_iops_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.read_iops_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.read_iops_device failed.") - } -} -func TestBlkioSetThrottleWriteIOpsDevice(t *testing.T) { - helper := NewCgroupTestUtil("blkio", t) - defer helper.cleanup() - - const ( - throttleBefore = `8:0 1024` - ) - - td := configs.NewThrottleDevice(8, 0, 2048) - throttleAfter := td.String() - - helper.writeFileContents(map[string]string{ - "blkio.throttle.write_iops_device": throttleBefore, - }) - - helper.CgroupData.config.Resources.BlkioThrottleWriteIOPSDevice = []*configs.ThrottleDevice{td} - blkio := &BlkioGroup{} - if err := blkio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.write_iops_device") - if err != nil { - t.Fatalf("Failed to parse blkio.throttle.write_iops_device - %s", err) - } - - if value != throttleAfter { - t.Fatal("Got the wrong value, set blkio.throttle.write_iops_device failed.") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_test.go deleted file mode 100644 index 554fd5e85..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_test.go +++ /dev/null @@ -1,163 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func TestCpuSetShares(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - const ( - sharesBefore = 1024 - sharesAfter = 512 - ) - - helper.writeFileContents(map[string]string{ - "cpu.shares": strconv.Itoa(sharesBefore), - }) - - helper.CgroupData.config.Resources.CpuShares = sharesAfter - cpu := &CpuGroup{} - if err := cpu.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "cpu.shares") - if err != nil { - t.Fatalf("Failed to parse cpu.shares - %s", err) - } - - if value != sharesAfter { - t.Fatal("Got the wrong value, set cpu.shares failed.") - } -} - -func TestCpuSetBandWidth(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - const ( - quotaBefore = 8000 - quotaAfter = 5000 - periodBefore = 10000 - periodAfter = 7000 - rtRuntimeBefore = 8000 - rtRuntimeAfter = 5000 - rtPeriodBefore = 10000 - rtPeriodAfter = 7000 - ) - - helper.writeFileContents(map[string]string{ - "cpu.cfs_quota_us": strconv.Itoa(quotaBefore), - "cpu.cfs_period_us": strconv.Itoa(periodBefore), - "cpu.rt_runtime_us": strconv.Itoa(rtRuntimeBefore), - "cpu.rt_period_us": strconv.Itoa(rtPeriodBefore), - }) - - helper.CgroupData.config.Resources.CpuQuota = quotaAfter - helper.CgroupData.config.Resources.CpuPeriod = periodAfter - helper.CgroupData.config.Resources.CpuRtRuntime = rtRuntimeAfter - helper.CgroupData.config.Resources.CpuRtPeriod = rtPeriodAfter - cpu := &CpuGroup{} - if err := cpu.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - quota, err := getCgroupParamUint(helper.CgroupPath, "cpu.cfs_quota_us") - if err != nil { - t.Fatalf("Failed to parse cpu.cfs_quota_us - %s", err) - } - if quota != quotaAfter { - t.Fatal("Got the wrong value, set cpu.cfs_quota_us failed.") - } - - period, err := getCgroupParamUint(helper.CgroupPath, "cpu.cfs_period_us") - if err != nil { - t.Fatalf("Failed to parse cpu.cfs_period_us - %s", err) - } - if period != periodAfter { - t.Fatal("Got the wrong value, set cpu.cfs_period_us failed.") - } - rtRuntime, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_runtime_us") - if err != nil { - t.Fatalf("Failed to parse cpu.rt_runtime_us - %s", err) - } - if rtRuntime != rtRuntimeAfter { - t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") - } - rtPeriod, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_period_us") - if err != nil { - t.Fatalf("Failed to parse cpu.rt_period_us - %s", err) - } - if rtPeriod != rtPeriodAfter { - t.Fatal("Got the wrong value, set cpu.rt_period_us failed.") - } -} - -func TestCpuStats(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - const ( - kNrPeriods = 2000 - kNrThrottled = 200 - kThrottledTime = uint64(18446744073709551615) - ) - - cpuStatContent := fmt.Sprintf("nr_periods %d\n nr_throttled %d\n throttled_time %d\n", - kNrPeriods, kNrThrottled, kThrottledTime) - helper.writeFileContents(map[string]string{ - "cpu.stat": cpuStatContent, - }) - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - - expectedStats := cgroups.ThrottlingData{ - Periods: kNrPeriods, - ThrottledPeriods: kNrThrottled, - ThrottledTime: kThrottledTime} - - expectThrottlingDataEquals(t, expectedStats, actualStats.CpuStats.ThrottlingData) -} - -func TestNoCpuStatFile(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal("Expected not to fail, but did") - } -} - -func TestInvalidCpuStat(t *testing.T) { - helper := NewCgroupTestUtil("cpu", t) - defer helper.cleanup() - cpuStatContent := `nr_periods 2000 - nr_throttled 200 - throttled_time fortytwo` - helper.writeFileContents(map[string]string{ - "cpu.stat": cpuStatContent, - }) - - cpu := &CpuGroup{} - actualStats := *cgroups.NewStats() - err := cpu.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failed stat parsing.") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_test.go deleted file mode 100644 index 0f929151f..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// +build linux - -package fs - -import ( - "testing" -) - -func TestCpusetSetCpus(t *testing.T) { - helper := NewCgroupTestUtil("cpuset", t) - defer helper.cleanup() - - const ( - cpusBefore = "0" - cpusAfter = "1-3" - ) - - helper.writeFileContents(map[string]string{ - "cpuset.cpus": cpusBefore, - }) - - helper.CgroupData.config.Resources.CpusetCpus = cpusAfter - cpuset := &CpusetGroup{} - if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "cpuset.cpus") - if err != nil { - t.Fatalf("Failed to parse cpuset.cpus - %s", err) - } - - if value != cpusAfter { - t.Fatal("Got the wrong value, set cpuset.cpus failed.") - } -} - -func TestCpusetSetMems(t *testing.T) { - helper := NewCgroupTestUtil("cpuset", t) - defer helper.cleanup() - - const ( - memsBefore = "0" - memsAfter = "1" - ) - - helper.writeFileContents(map[string]string{ - "cpuset.mems": memsBefore, - }) - - helper.CgroupData.config.Resources.CpusetMems = memsAfter - cpuset := &CpusetGroup{} - if err := cpuset.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "cpuset.mems") - if err != nil { - t.Fatalf("Failed to parse cpuset.mems - %s", err) - } - - if value != memsAfter { - t.Fatal("Got the wrong value, set cpuset.mems failed.") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices_test.go deleted file mode 100644 index ee44084ee..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/devices_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// +build linux - -package fs - -import ( - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -var ( - allowedDevices = []*configs.Device{ - { - Path: "/dev/zero", - Type: 'c', - Major: 1, - Minor: 5, - Permissions: "rwm", - FileMode: 0666, - }, - } - allowedList = "c 1:5 rwm" - deniedDevices = []*configs.Device{ - { - Path: "/dev/null", - Type: 'c', - Major: 1, - Minor: 3, - Permissions: "rwm", - FileMode: 0666, - }, - } - deniedList = "c 1:3 rwm" -) - -func TestDevicesSetAllow(t *testing.T) { - helper := NewCgroupTestUtil("devices", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "devices.deny": "a", - }) - - helper.CgroupData.config.Resources.AllowAllDevices = false - helper.CgroupData.config.Resources.AllowedDevices = allowedDevices - devices := &DevicesGroup{} - if err := devices.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "devices.allow") - if err != nil { - t.Fatalf("Failed to parse devices.allow - %s", err) - } - - if value != allowedList { - t.Fatal("Got the wrong value, set devices.allow failed.") - } -} - -func TestDevicesSetDeny(t *testing.T) { - helper := NewCgroupTestUtil("devices", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "devices.allow": "a", - }) - - helper.CgroupData.config.Resources.AllowAllDevices = true - helper.CgroupData.config.Resources.DeniedDevices = deniedDevices - devices := &DevicesGroup{} - if err := devices.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "devices.deny") - if err != nil { - t.Fatalf("Failed to parse devices.deny - %s", err) - } - - if value != deniedList { - t.Fatal("Got the wrong value, set devices.deny failed.") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_test.go deleted file mode 100644 index 77708db9a..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_test.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build linux - -package fs - -import ( - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -func TestFreezerSetState(t *testing.T) { - helper := NewCgroupTestUtil("freezer", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "freezer.state": string(configs.Frozen), - }) - - helper.CgroupData.config.Resources.Freezer = configs.Thawed - freezer := &FreezerGroup{} - if err := freezer.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "freezer.state") - if err != nil { - t.Fatalf("Failed to parse freezer.state - %s", err) - } - if value != string(configs.Thawed) { - t.Fatal("Got the wrong value, set freezer.state failed.") - } -} - -func TestFreezerSetInvalidState(t *testing.T) { - helper := NewCgroupTestUtil("freezer", t) - defer helper.cleanup() - - const ( - invalidArg configs.FreezerState = "Invalid" - ) - - helper.CgroupData.config.Resources.Freezer = invalidArg - freezer := &FreezerGroup{} - if err := freezer.Set(helper.CgroupPath, helper.CgroupData.config); err == nil { - t.Fatal("Failed to return invalid argument error") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb_test.go deleted file mode 100644 index 2d41c4eb2..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/hugetlb_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -const ( - hugetlbUsageContents = "128\n" - hugetlbMaxUsageContents = "256\n" - hugetlbFailcnt = "100\n" -) - -var ( - usage = "hugetlb.%s.usage_in_bytes" - limit = "hugetlb.%s.limit_in_bytes" - maxUsage = "hugetlb.%s.max_usage_in_bytes" - failcnt = "hugetlb.%s.failcnt" -) - -func TestHugetlbSetHugetlb(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - - const ( - hugetlbBefore = 256 - hugetlbAfter = 512 - ) - - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(limit, pageSize): strconv.Itoa(hugetlbBefore), - }) - } - - for _, pageSize := range HugePageSizes { - helper.CgroupData.config.Resources.HugetlbLimit = []*configs.HugepageLimit{ - { - Pagesize: pageSize, - Limit: hugetlbAfter, - }, - } - hugetlb := &HugetlbGroup{} - if err := hugetlb.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - } - - for _, pageSize := range HugePageSizes { - limit := fmt.Sprintf(limit, pageSize) - value, err := getCgroupParamUint(helper.CgroupPath, limit) - if err != nil { - t.Fatalf("Failed to parse %s - %s", limit, err) - } - if value != hugetlbAfter { - t.Fatalf("Set hugetlb.limit_in_bytes failed. Expected: %v, Got: %v", hugetlbAfter, value) - } - } -} - -func TestHugetlbStats(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(usage, pageSize): hugetlbUsageContents, - fmt.Sprintf(maxUsage, pageSize): hugetlbMaxUsageContents, - fmt.Sprintf(failcnt, pageSize): hugetlbFailcnt, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.HugetlbStats{Usage: 128, MaxUsage: 256, Failcnt: 100} - for _, pageSize := range HugePageSizes { - expectHugetlbStatEquals(t, expectedStats, actualStats.HugetlbStats[pageSize]) - } -} - -func TestHugetlbStatsNoUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - maxUsage: hugetlbMaxUsageContents, - }) - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsNoMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(usage, pageSize): hugetlbUsageContents, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsBadUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - for _, pageSize := range HugePageSizes { - helper.writeFileContents(map[string]string{ - fmt.Sprintf(usage, pageSize): "bad", - maxUsage: hugetlbMaxUsageContents, - }) - } - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestHugetlbStatsBadMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("hugetlb", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - usage: hugetlbUsageContents, - maxUsage: "bad", - }) - - hugetlb := &HugetlbGroup{} - actualStats := *cgroups.NewStats() - err := hugetlb.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_test.go deleted file mode 100644 index 9464599b0..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_test.go +++ /dev/null @@ -1,294 +0,0 @@ -// +build linux - -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const ( - memoryStatContents = `cache 512 -rss 1024` - memoryUsageContents = "2048\n" - memoryMaxUsageContents = "4096\n" - memoryFailcnt = "100\n" -) - -func TestMemorySetMemory(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - memoryBefore = 314572800 // 300M - memoryAfter = 524288000 // 500M - reservationBefore = 209715200 // 200M - reservationAfter = 314572800 // 300M - ) - - helper.writeFileContents(map[string]string{ - "memory.limit_in_bytes": strconv.Itoa(memoryBefore), - "memory.soft_limit_in_bytes": strconv.Itoa(reservationBefore), - }) - - helper.CgroupData.config.Resources.Memory = memoryAfter - helper.CgroupData.config.Resources.MemoryReservation = reservationAfter - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.limit_in_bytes - %s", err) - } - if value != memoryAfter { - t.Fatal("Got the wrong value, set memory.limit_in_bytes failed.") - } - - value, err = getCgroupParamUint(helper.CgroupPath, "memory.soft_limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.soft_limit_in_bytes - %s", err) - } - if value != reservationAfter { - t.Fatal("Got the wrong value, set memory.soft_limit_in_bytes failed.") - } -} - -func TestMemorySetMemoryswap(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - memoryswapBefore = 314572800 // 300M - memoryswapAfter = 524288000 // 500M - ) - - helper.writeFileContents(map[string]string{ - "memory.memsw.limit_in_bytes": strconv.Itoa(memoryswapBefore), - }) - - helper.CgroupData.config.Resources.MemorySwap = memoryswapAfter - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err) - } - if value != memoryswapAfter { - t.Fatal("Got the wrong value, set memory.memsw.limit_in_bytes failed.") - } -} - -func TestMemorySetKernelMemory(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - kernelMemoryBefore = 314572800 // 300M - kernelMemoryAfter = 524288000 // 500M - ) - - helper.writeFileContents(map[string]string{ - "memory.kmem.limit_in_bytes": strconv.Itoa(kernelMemoryBefore), - }) - - helper.CgroupData.config.Resources.KernelMemory = kernelMemoryAfter - memory := &MemoryGroup{} - if err := memory.SetKernelMemory(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.kmem.limit_in_bytes") - if err != nil { - t.Fatalf("Failed to parse memory.kmem.limit_in_bytes - %s", err) - } - if value != kernelMemoryAfter { - t.Fatal("Got the wrong value, set memory.kmem.limit_in_bytes failed.") - } -} - -func TestMemorySetMemorySwappinessDefault(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - swappinessBefore = 60 //deafult is 60 - swappinessAfter = 0 - ) - - helper.writeFileContents(map[string]string{ - "memory.swappiness": strconv.Itoa(swappinessBefore), - }) - - helper.CgroupData.config.Resources.Memory = swappinessAfter - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.swappiness") - if err != nil { - t.Fatalf("Failed to parse memory.swappiness - %s", err) - } - if value != swappinessAfter { - t.Fatal("Got the wrong value, set memory.swappiness failed.") - } -} - -func TestMemoryStats(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - "memory.failcnt": memoryFailcnt, - "memory.memsw.usage_in_bytes": memoryUsageContents, - "memory.memsw.max_usage_in_bytes": memoryMaxUsageContents, - "memory.memsw.failcnt": memoryFailcnt, - "memory.kmem.usage_in_bytes": memoryUsageContents, - "memory.kmem.max_usage_in_bytes": memoryMaxUsageContents, - "memory.kmem.failcnt": memoryFailcnt, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } - expectedStats := cgroups.MemoryStats{Cache: 512, Usage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100}, SwapUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100}, KernelUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100}, Stats: map[string]uint64{"cache": 512, "rss": 1024}} - expectMemoryStatEquals(t, expectedStats, actualStats.MemoryStats) -} - -func TestMemoryStatsNoStatFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err != nil { - t.Fatal(err) - } -} - -func TestMemoryStatsNoUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsNoMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadStatFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": "rss rss", - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": "bad", - "memory.max_usage_in_bytes": memoryMaxUsageContents, - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemoryStatsBadMaxUsageFile(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - helper.writeFileContents(map[string]string{ - "memory.stat": memoryStatContents, - "memory.usage_in_bytes": memoryUsageContents, - "memory.max_usage_in_bytes": "bad", - }) - - memory := &MemoryGroup{} - actualStats := *cgroups.NewStats() - err := memory.GetStats(helper.CgroupPath, &actualStats) - if err == nil { - t.Fatal("Expected failure") - } -} - -func TestMemorySetOomControl(t *testing.T) { - helper := NewCgroupTestUtil("memory", t) - defer helper.cleanup() - - const ( - oom_kill_disable = 1 // disable oom killer, default is 0 - ) - - helper.writeFileContents(map[string]string{ - "memory.oom_control": strconv.Itoa(oom_kill_disable), - }) - - memory := &MemoryGroup{} - if err := memory.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "memory.oom_control") - if err != nil { - t.Fatalf("Failed to parse memory.oom_control - %s", err) - } - - if value != oom_kill_disable { - t.Fatalf("Got the wrong value, set memory.oom_control failed.") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls_test.go deleted file mode 100644 index 974bd9d88..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_cls_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build linux - -package fs - -import ( - "testing" -) - -const ( - classidBefore = "0x100002" - classidAfter = "0x100001" -) - -func TestNetClsSetClassid(t *testing.T) { - helper := NewCgroupTestUtil("net_cls", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "net_cls.classid": classidBefore, - }) - - helper.CgroupData.config.Resources.NetClsClassid = classidAfter - netcls := &NetClsGroup{} - if err := netcls.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - // As we are in mock environment, we can't get correct value of classid from - // net_cls.classid. - // So. we just judge if we successfully write classid into file - value, err := getCgroupParamString(helper.CgroupPath, "net_cls.classid") - if err != nil { - t.Fatalf("Failed to parse net_cls.classid - %s", err) - } - if value != classidAfter { - t.Fatal("Got the wrong value, set net_cls.classid failed.") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio_test.go deleted file mode 100644 index efbf0639a..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/net_prio_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build linux - -package fs - -import ( - "strings" - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -var ( - prioMap = []*configs.IfPrioMap{ - { - Interface: "test", - Priority: 5, - }, - } -) - -func TestNetPrioSetIfPrio(t *testing.T) { - helper := NewCgroupTestUtil("net_prio", t) - defer helper.cleanup() - - helper.CgroupData.config.Resources.NetPrioIfpriomap = prioMap - netPrio := &NetPrioGroup{} - if err := netPrio.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "net_prio.ifpriomap") - if err != nil { - t.Fatalf("Failed to parse net_prio.ifpriomap - %s", err) - } - if !strings.Contains(value, "test 5") { - t.Fatal("Got the wrong value, set net_prio.ifpriomap failed.") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids_test.go deleted file mode 100644 index 06b11927a..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids_test.go +++ /dev/null @@ -1,83 +0,0 @@ -// +build linux - -package fs - -import ( - "strconv" - "testing" - - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -const ( - maxUnlimited = -1 - maxLimited = 1024 -) - -func TestPidsSetMax(t *testing.T) { - helper := NewCgroupTestUtil("pids", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "pids.max": "max", - }) - - helper.CgroupData.config.Resources.PidsLimit = maxLimited - pids := &PidsGroup{} - if err := pids.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamUint(helper.CgroupPath, "pids.max") - if err != nil { - t.Fatalf("Failed to parse pids.max - %s", err) - } - - if value != maxLimited { - t.Fatalf("Expected %d, got %d for setting pids.max - limited", maxLimited, value) - } -} - -func TestPidsSetUnlimited(t *testing.T) { - helper := NewCgroupTestUtil("pids", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "pids.max": strconv.Itoa(maxLimited), - }) - - helper.CgroupData.config.Resources.PidsLimit = maxUnlimited - pids := &PidsGroup{} - if err := pids.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { - t.Fatal(err) - } - - value, err := getCgroupParamString(helper.CgroupPath, "pids.max") - if err != nil { - t.Fatalf("Failed to parse pids.max - %s", err) - } - - if value != "max" { - t.Fatalf("Expected %s, got %s for setting pids.max - unlimited", "max", value) - } -} - -func TestPidsStats(t *testing.T) { - helper := NewCgroupTestUtil("pids", t) - defer helper.cleanup() - - helper.writeFileContents(map[string]string{ - "pids.current": strconv.Itoa(1337), - "pids.max": strconv.Itoa(maxLimited), - }) - - pids := &PidsGroup{} - stats := *cgroups.NewStats() - if err := pids.GetStats(helper.CgroupPath, &stats); err != nil { - t.Fatal(err) - } - - if stats.PidsStats.Current != 1337 { - t.Fatalf("Expected %d, got %d for pids.current", 1337, stats.PidsStats.Current) - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/stats_util_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/stats_util_test.go deleted file mode 100644 index b1777cc0a..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/stats_util_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "testing" - - "github.com/Sirupsen/logrus" - "github.com/opencontainers/runc/libcontainer/cgroups" -) - -func blkioStatEntryEquals(expected, actual []cgroups.BlkioStatEntry) error { - if len(expected) != len(actual) { - return fmt.Errorf("blkioStatEntries length do not match") - } - for i, expValue := range expected { - actValue := actual[i] - if expValue != actValue { - return fmt.Errorf("Expected blkio stat entry %v but found %v", expValue, actValue) - } - } - return nil -} - -func expectBlkioStatsEquals(t *testing.T, expected, actual cgroups.BlkioStats) { - if err := blkioStatEntryEquals(expected.IoServiceBytesRecursive, actual.IoServiceBytesRecursive); err != nil { - logrus.Printf("blkio IoServiceBytesRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoServicedRecursive, actual.IoServicedRecursive); err != nil { - logrus.Printf("blkio IoServicedRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoQueuedRecursive, actual.IoQueuedRecursive); err != nil { - logrus.Printf("blkio IoQueuedRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.SectorsRecursive, actual.SectorsRecursive); err != nil { - logrus.Printf("blkio SectorsRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoServiceTimeRecursive, actual.IoServiceTimeRecursive); err != nil { - logrus.Printf("blkio IoServiceTimeRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoWaitTimeRecursive, actual.IoWaitTimeRecursive); err != nil { - logrus.Printf("blkio IoWaitTimeRecursive do not match - %s\n", err) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoMergedRecursive, actual.IoMergedRecursive); err != nil { - logrus.Printf("blkio IoMergedRecursive do not match - %v vs %v\n", expected.IoMergedRecursive, actual.IoMergedRecursive) - t.Fail() - } - - if err := blkioStatEntryEquals(expected.IoTimeRecursive, actual.IoTimeRecursive); err != nil { - logrus.Printf("blkio IoTimeRecursive do not match - %s\n", err) - t.Fail() - } -} - -func expectThrottlingDataEquals(t *testing.T, expected, actual cgroups.ThrottlingData) { - if expected != actual { - logrus.Printf("Expected throttling data %v but found %v\n", expected, actual) - t.Fail() - } -} - -func expectHugetlbStatEquals(t *testing.T, expected, actual cgroups.HugetlbStats) { - if expected != actual { - logrus.Printf("Expected hugetlb stats %v but found %v\n", expected, actual) - t.Fail() - } -} - -func expectMemoryStatEquals(t *testing.T, expected, actual cgroups.MemoryStats) { - expectMemoryDataEquals(t, expected.Usage, actual.Usage) - expectMemoryDataEquals(t, expected.SwapUsage, actual.SwapUsage) - expectMemoryDataEquals(t, expected.KernelUsage, actual.KernelUsage) - - for key, expValue := range expected.Stats { - actValue, ok := actual.Stats[key] - if !ok { - logrus.Printf("Expected memory stat key %s not found\n", key) - t.Fail() - } - if expValue != actValue { - logrus.Printf("Expected memory stat value %d but found %d\n", expValue, actValue) - t.Fail() - } - } -} - -func expectMemoryDataEquals(t *testing.T, expected, actual cgroups.MemoryData) { - if expected.Usage != actual.Usage { - logrus.Printf("Expected memory usage %d but found %d\n", expected.Usage, actual.Usage) - t.Fail() - } - if expected.MaxUsage != actual.MaxUsage { - logrus.Printf("Expected memory max usage %d but found %d\n", expected.MaxUsage, actual.MaxUsage) - t.Fail() - } - if expected.Failcnt != actual.Failcnt { - logrus.Printf("Expected memory failcnt %d but found %d\n", expected.Failcnt, actual.Failcnt) - t.Fail() - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/util_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/util_test.go deleted file mode 100644 index 7067e799f..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/util_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// +build linux - -/* -Utility for testing cgroup operations. - -Creates a mock of the cgroup filesystem for the duration of the test. -*/ -package fs - -import ( - "io/ioutil" - "os" - "path/filepath" - "testing" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -type cgroupTestUtil struct { - // cgroup data to use in tests. - CgroupData *cgroupData - - // Path to the mock cgroup directory. - CgroupPath string - - // Temporary directory to store mock cgroup filesystem. - tempDir string - t *testing.T -} - -// Creates a new test util for the specified subsystem -func NewCgroupTestUtil(subsystem string, t *testing.T) *cgroupTestUtil { - d := &cgroupData{ - config: &configs.Cgroup{}, - } - d.config.Resources = &configs.Resources{} - tempDir, err := ioutil.TempDir("", "cgroup_test") - if err != nil { - t.Fatal(err) - } - d.root = tempDir - testCgroupPath := filepath.Join(d.root, subsystem) - if err != nil { - t.Fatal(err) - } - - // Ensure the full mock cgroup path exists. - err = os.MkdirAll(testCgroupPath, 0755) - if err != nil { - t.Fatal(err) - } - return &cgroupTestUtil{CgroupData: d, CgroupPath: testCgroupPath, tempDir: tempDir, t: t} -} - -func (c *cgroupTestUtil) cleanup() { - os.RemoveAll(c.tempDir) -} - -// Write the specified contents on the mock of the specified cgroup files. -func (c *cgroupTestUtil) writeFileContents(fileContents map[string]string) { - for file, contents := range fileContents { - err := writeFile(c.CgroupPath, file, contents) - if err != nil { - c.t.Fatal(err) - } - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils_test.go deleted file mode 100644 index 99cdc18e0..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// +build linux - -package fs - -import ( - "io/ioutil" - "math" - "os" - "path/filepath" - "strconv" - "testing" -) - -const ( - cgroupFile = "cgroup.file" - floatValue = 2048.0 - floatString = "2048" -) - -func TestGetCgroupParamsInt(t *testing.T) { - // Setup tempdir. - tempDir, err := ioutil.TempDir("", "cgroup_utils_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - tempFile := filepath.Join(tempDir, cgroupFile) - - // Success. - err = ioutil.WriteFile(tempFile, []byte(floatString), 0755) - if err != nil { - t.Fatal(err) - } - value, err := getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with new line. - err = ioutil.WriteFile(tempFile, []byte(floatString+"\n"), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with negative values - err = ioutil.WriteFile(tempFile, []byte("-12345"), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Success with negative values lesser than min int64 - s := strconv.FormatFloat(math.MinInt64, 'f', -1, 64) - err = ioutil.WriteFile(tempFile, []byte(s), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Not a float. - err = ioutil.WriteFile(tempFile, []byte("not-a-float"), 0755) - if err != nil { - t.Fatal(err) - } - _, err = getCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } - - // Unknown file. - err = os.Remove(tempFile) - if err != nil { - t.Fatal(err) - } - _, err = getCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_nosystemd.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_nosystemd.go deleted file mode 100644 index 7de9ae605..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_nosystemd.go +++ /dev/null @@ -1,55 +0,0 @@ -// +build !linux - -package systemd - -import ( - "fmt" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type Manager struct { - Cgroups *configs.Cgroup - Paths map[string]string -} - -func UseSystemd() bool { - return false -} - -func (m *Manager) Apply(pid int) error { - return fmt.Errorf("Systemd not supported") -} - -func (m *Manager) GetPids() ([]int, error) { - return nil, fmt.Errorf("Systemd not supported") -} - -func (m *Manager) GetAllPids() ([]int, error) { - return nil, fmt.Errorf("Systemd not supported") -} - -func (m *Manager) Destroy() error { - return fmt.Errorf("Systemd not supported") -} - -func (m *Manager) GetPaths() map[string]string { - return nil -} - -func (m *Manager) GetStats() (*cgroups.Stats, error) { - return nil, fmt.Errorf("Systemd not supported") -} - -func (m *Manager) Set(container *configs.Config) error { - return nil, fmt.Errorf("Systemd not supported") -} - -func (m *Manager) Freeze(state configs.FreezerState) error { - return fmt.Errorf("Systemd not supported") -} - -func Freeze(c *configs.Cgroup, state configs.FreezerState) error { - return fmt.Errorf("Systemd not supported") -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go deleted file mode 100644 index db020a971..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go +++ /dev/null @@ -1,596 +0,0 @@ -// +build linux - -package systemd - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - "sync" - "time" - - systemdDbus "github.com/coreos/go-systemd/dbus" - systemdUtil "github.com/coreos/go-systemd/util" - "github.com/godbus/dbus" - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fs" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type Manager struct { - mu sync.Mutex - Cgroups *configs.Cgroup - Paths map[string]string -} - -type subsystem interface { - // Name returns the name of the subsystem. - Name() string - // Returns the stats, as 'stats', corresponding to the cgroup under 'path'. - GetStats(path string, stats *cgroups.Stats) error - // Set the cgroup represented by cgroup. - Set(path string, cgroup *configs.Cgroup) error -} - -var errSubsystemDoesNotExist = errors.New("cgroup: subsystem does not exist") - -type subsystemSet []subsystem - -func (s subsystemSet) Get(name string) (subsystem, error) { - for _, ss := range s { - if ss.Name() == name { - return ss, nil - } - } - return nil, errSubsystemDoesNotExist -} - -var subsystems = subsystemSet{ - &fs.CpusetGroup{}, - &fs.DevicesGroup{}, - &fs.MemoryGroup{}, - &fs.CpuGroup{}, - &fs.CpuacctGroup{}, - &fs.PidsGroup{}, - &fs.BlkioGroup{}, - &fs.HugetlbGroup{}, - &fs.PerfEventGroup{}, - &fs.FreezerGroup{}, - &fs.NetPrioGroup{}, - &fs.NetClsGroup{}, - &fs.NameGroup{GroupName: "name=systemd"}, -} - -const ( - testScopeWait = 4 -) - -var ( - connLock sync.Mutex - theConn *systemdDbus.Conn - hasStartTransientUnit bool - hasTransientDefaultDependencies bool -) - -func newProp(name string, units interface{}) systemdDbus.Property { - return systemdDbus.Property{ - Name: name, - Value: dbus.MakeVariant(units), - } -} - -func UseSystemd() bool { - if !systemdUtil.IsRunningSystemd() { - return false - } - - connLock.Lock() - defer connLock.Unlock() - - if theConn == nil { - var err error - theConn, err = systemdDbus.New() - if err != nil { - return false - } - - // Assume we have StartTransientUnit - hasStartTransientUnit = true - - // But if we get UnknownMethod error we don't - if _, err := theConn.StartTransientUnit("test.scope", "invalid", nil, nil); err != nil { - if dbusError, ok := err.(dbus.Error); ok { - if dbusError.Name == "org.freedesktop.DBus.Error.UnknownMethod" { - hasStartTransientUnit = false - return hasStartTransientUnit - } - } - } - - // Ensure the scope name we use doesn't exist. Use the Pid to - // avoid collisions between multiple libcontainer users on a - // single host. - scope := fmt.Sprintf("libcontainer-%d-systemd-test-default-dependencies.scope", os.Getpid()) - testScopeExists := true - for i := 0; i <= testScopeWait; i++ { - if _, err := theConn.StopUnit(scope, "replace", nil); err != nil { - if dbusError, ok := err.(dbus.Error); ok { - if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") { - testScopeExists = false - break - } - } - } - time.Sleep(time.Millisecond) - } - - // Bail out if we can't kill this scope without testing for DefaultDependencies - if testScopeExists { - return hasStartTransientUnit - } - - // Assume StartTransientUnit on a scope allows DefaultDependencies - hasTransientDefaultDependencies = true - ddf := newProp("DefaultDependencies", false) - if _, err := theConn.StartTransientUnit(scope, "replace", []systemdDbus.Property{ddf}, nil); err != nil { - if dbusError, ok := err.(dbus.Error); ok { - if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") { - hasTransientDefaultDependencies = false - } - } - } - - // Not critical because of the stop unit logic above. - theConn.StopUnit(scope, "replace", nil) - } - return hasStartTransientUnit -} - -func getIfaceForUnit(unitName string) string { - if strings.HasSuffix(unitName, ".scope") { - return "Scope" - } - if strings.HasSuffix(unitName, ".service") { - return "Service" - } - return "Unit" -} - -func (m *Manager) Apply(pid int) error { - var ( - c = m.Cgroups - unitName = getUnitName(c) - slice = "system.slice" - properties []systemdDbus.Property - ) - - if c.Paths != nil { - paths := make(map[string]string) - for name, path := range c.Paths { - _, err := getSubsystemPath(m.Cgroups, name) - if err != nil { - // Don't fail if a cgroup hierarchy was not found, just skip this subsystem - if cgroups.IsNotFound(err) { - continue - } - return err - } - paths[name] = path - } - m.Paths = paths - return cgroups.EnterPid(m.Paths, pid) - } - - if c.Parent != "" { - slice = c.Parent - } - - properties = append(properties, - systemdDbus.PropSlice(slice), - systemdDbus.PropDescription("docker container "+c.Name), - newProp("PIDs", []uint32{uint32(pid)}), - ) - - // Always enable accounting, this gets us the same behaviour as the fs implementation, - // plus the kernel has some problems with joining the memory cgroup at a later time. - properties = append(properties, - newProp("MemoryAccounting", true), - newProp("CPUAccounting", true), - newProp("BlockIOAccounting", true)) - - if hasTransientDefaultDependencies { - properties = append(properties, - newProp("DefaultDependencies", false)) - } - - if c.Resources.Memory != 0 { - properties = append(properties, - newProp("MemoryLimit", uint64(c.Resources.Memory))) - } - - if c.Resources.CpuShares != 0 { - properties = append(properties, - newProp("CPUShares", uint64(c.Resources.CpuShares))) - } - - if c.Resources.BlkioWeight != 0 { - properties = append(properties, - newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight))) - } - - // We need to set kernel memory before processes join cgroup because - // kmem.limit_in_bytes can only be set when the cgroup is empty. - // And swap memory limit needs to be set after memory limit, only - // memory limit is handled by systemd, so it's kind of ugly here. - if c.Resources.KernelMemory > 0 { - if err := setKernelMemory(c); err != nil { - return err - } - } - - if _, err := theConn.StartTransientUnit(unitName, "replace", properties, nil); err != nil { - return err - } - - if err := joinDevices(c, pid); err != nil { - return err - } - - // TODO: CpuQuota and CpuPeriod not available in systemd - // we need to manually join the cpu.cfs_quota_us and cpu.cfs_period_us - if err := joinCpu(c, pid); err != nil { - return err - } - - // TODO: MemoryReservation and MemorySwap not available in systemd - if err := joinMemory(c, pid); err != nil { - return err - } - - // we need to manually join the freezer, net_cls, net_prio, pids and cpuset cgroup in systemd - // because it does not currently support it via the dbus api. - if err := joinFreezer(c, pid); err != nil { - return err - } - - if err := joinNetPrio(c, pid); err != nil { - return err - } - if err := joinNetCls(c, pid); err != nil { - return err - } - - if err := joinPids(c, pid); err != nil { - return err - } - - if err := joinCpuset(c, pid); err != nil { - return err - } - - if err := joinHugetlb(c, pid); err != nil { - return err - } - - if err := joinPerfEvent(c, pid); err != nil { - return err - } - // FIXME: Systemd does have `BlockIODeviceWeight` property, but we got problem - // using that (at least on systemd 208, see https://github.com/opencontainers/runc/libcontainer/pull/354), - // so use fs work around for now. - if err := joinBlkio(c, pid); err != nil { - return err - } - - paths := make(map[string]string) - for _, s := range subsystems { - subsystemPath, err := getSubsystemPath(m.Cgroups, s.Name()) - if err != nil { - // Don't fail if a cgroup hierarchy was not found, just skip this subsystem - if cgroups.IsNotFound(err) { - continue - } - return err - } - paths[s.Name()] = subsystemPath - } - m.Paths = paths - return nil -} - -func (m *Manager) Destroy() error { - if m.Cgroups.Paths != nil { - return nil - } - m.mu.Lock() - defer m.mu.Unlock() - theConn.StopUnit(getUnitName(m.Cgroups), "replace", nil) - if err := cgroups.RemovePaths(m.Paths); err != nil { - return err - } - m.Paths = make(map[string]string) - return nil -} - -func (m *Manager) GetPaths() map[string]string { - m.mu.Lock() - paths := m.Paths - m.mu.Unlock() - return paths -} - -func writeFile(dir, file, data string) error { - // Normally dir should not be empty, one case is that cgroup subsystem - // is not mounted, we will get empty dir, and we want it fail here. - if dir == "" { - return fmt.Errorf("no such directory for %s.", file) - } - return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700) -} - -func join(c *configs.Cgroup, subsystem string, pid int) (string, error) { - path, err := getSubsystemPath(c, subsystem) - if err != nil { - return "", err - } - if err := os.MkdirAll(path, 0755); err != nil { - return "", err - } - if err := writeFile(path, "cgroup.procs", strconv.Itoa(pid)); err != nil { - return "", err - } - - return path, nil -} - -func joinCpu(c *configs.Cgroup, pid int) error { - _, err := join(c, "cpu", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func joinFreezer(c *configs.Cgroup, pid int) error { - _, err := join(c, "freezer", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func joinNetPrio(c *configs.Cgroup, pid int) error { - _, err := join(c, "net_prio", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func joinNetCls(c *configs.Cgroup, pid int) error { - _, err := join(c, "net_cls", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func joinPids(c *configs.Cgroup, pid int) error { - _, err := join(c, "pids", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -// systemd represents slice heirarchy using `-`, so we need to follow suit when -// generating the path of slice. Essentially, test-a-b.slice becomes -// test.slice/test-a.slice/test-a-b.slice. -func expandSlice(slice string) (string, error) { - suffix := ".slice" - sliceName := strings.TrimSuffix(slice, suffix) - - var path, prefix string - for _, component := range strings.Split(sliceName, "-") { - // test--a.slice isn't permitted, nor is -test.slice. - if component == "" { - return "", fmt.Errorf("invalid slice name: %s", slice) - } - - // Append the component to the path and to the prefix. - path += prefix + component + suffix + "/" - prefix += component + "-" - } - - return path, nil -} - -func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) { - mountpoint, err := cgroups.FindCgroupMountpoint(subsystem) - if err != nil { - return "", err - } - - initPath, err := cgroups.GetInitCgroupDir(subsystem) - if err != nil { - return "", err - } - - slice := "system.slice" - if c.Parent != "" { - slice = c.Parent - } - - slice, err = expandSlice(slice) - if err != nil { - return "", err - } - - return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil -} - -func (m *Manager) Freeze(state configs.FreezerState) error { - path, err := getSubsystemPath(m.Cgroups, "freezer") - if err != nil { - return err - } - prevState := m.Cgroups.Resources.Freezer - m.Cgroups.Resources.Freezer = state - freezer, err := subsystems.Get("freezer") - if err != nil { - return err - } - err = freezer.Set(path, m.Cgroups) - if err != nil { - m.Cgroups.Resources.Freezer = prevState - return err - } - return nil -} - -func (m *Manager) GetPids() ([]int, error) { - path, err := getSubsystemPath(m.Cgroups, "devices") - if err != nil { - return nil, err - } - return cgroups.GetPids(path) -} - -func (m *Manager) GetAllPids() ([]int, error) { - path, err := getSubsystemPath(m.Cgroups, "devices") - if err != nil { - return nil, err - } - return cgroups.GetAllPids(path) -} - -func (m *Manager) GetStats() (*cgroups.Stats, error) { - m.mu.Lock() - defer m.mu.Unlock() - stats := cgroups.NewStats() - for name, path := range m.Paths { - sys, err := subsystems.Get(name) - if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) { - continue - } - if err := sys.GetStats(path, stats); err != nil { - return nil, err - } - } - - return stats, nil -} - -func (m *Manager) Set(container *configs.Config) error { - for _, sys := range subsystems { - // Get the subsystem path, but don't error out for not found cgroups. - path, err := getSubsystemPath(container.Cgroups, sys.Name()) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := sys.Set(path, container.Cgroups); err != nil { - return err - } - } - - if m.Paths["cpu"] != "" { - if err := fs.CheckCpushares(m.Paths["cpu"], container.Cgroups.Resources.CpuShares); err != nil { - return err - } - } - return nil -} - -func getUnitName(c *configs.Cgroup) string { - return fmt.Sprintf("%s-%s.scope", c.ScopePrefix, c.Name) -} - -// Atm we can't use the systemd device support because of two missing things: -// * Support for wildcards to allow mknod on any device -// * Support for wildcards to allow /dev/pts support -// -// The second is available in more recent systemd as "char-pts", but not in e.g. v208 which is -// in wide use. When both these are available we will be able to switch, but need to keep the old -// implementation for backwards compat. -// -// Note: we can't use systemd to set up the initial limits, and then change the cgroup -// because systemd will re-write the device settings if it needs to re-apply the cgroup context. -// This happens at least for v208 when any sibling unit is started. -func joinDevices(c *configs.Cgroup, pid int) error { - _, err := join(c, "devices", pid) - // Even if it's `not found` error, we'll return err because devices cgroup - // is hard requirement for container security. - if err != nil { - return err - } - return nil -} - -func setKernelMemory(c *configs.Cgroup) error { - path, err := getSubsystemPath(c, "memory") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := os.MkdirAll(path, 0755); err != nil { - return err - } - - // This doesn't get called by manager.Set, so we need to do it here. - s := &fs.MemoryGroup{} - return s.SetKernelMemory(path, c) -} - -func joinMemory(c *configs.Cgroup, pid int) error { - _, err := join(c, "memory", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -// systemd does not atm set up the cpuset controller, so we must manually -// join it. Additionally that is a very finicky controller where each -// level must have a full setup as the default for a new directory is "no cpus" -func joinCpuset(c *configs.Cgroup, pid int) error { - path, err := getSubsystemPath(c, "cpuset") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - s := &fs.CpusetGroup{} - - return s.ApplyDir(path, c, pid) -} - -// `BlockIODeviceWeight` property of systemd does not work properly, and systemd -// expects device path instead of major minor numbers, which is also confusing -// for users. So we use fs work around for now. -func joinBlkio(c *configs.Cgroup, pid int) error { - _, err := join(c, "blkio", pid) - if err != nil { - return err - } - return nil -} - -func joinHugetlb(c *configs.Cgroup, pid int) error { - _, err := join(c, "hugetlb", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func joinPerfEvent(c *configs.Cgroup, pid int) error { - _, err := join(c, "perf_event", pid) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/config_unix_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/config_unix_test.go deleted file mode 100644 index 27d07d4e8..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/config_unix_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// +build linux freebsd - -package configs - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "testing" -) - -// Checks whether the expected capability is specified in the capabilities. -func contains(expected string, values []string) bool { - for _, v := range values { - if v == expected { - return true - } - } - return false -} - -func containsDevice(expected *Device, values []*Device) bool { - for _, d := range values { - if d.Path == expected.Path && - d.Permissions == expected.Permissions && - d.FileMode == expected.FileMode && - d.Major == expected.Major && - d.Minor == expected.Minor && - d.Type == expected.Type { - return true - } - } - return false -} - -func loadConfig(name string) (*Config, error) { - f, err := os.Open(filepath.Join("../sample_configs", name)) - if err != nil { - return nil, err - } - defer f.Close() - - var container *Config - if err := json.NewDecoder(f).Decode(&container); err != nil { - return nil, err - } - - // Check that a config doesn't contain extra fields - var configMap, abstractMap map[string]interface{} - - if _, err := f.Seek(0, 0); err != nil { - return nil, err - } - - if err := json.NewDecoder(f).Decode(&abstractMap); err != nil { - return nil, err - } - - configData, err := json.Marshal(&container) - if err != nil { - return nil, err - } - - if err := json.Unmarshal(configData, &configMap); err != nil { - return nil, err - } - - for k := range configMap { - delete(abstractMap, k) - } - - if len(abstractMap) != 0 { - return nil, fmt.Errorf("unknown fields: %s", abstractMap) - } - - return container, nil -} - -func TestRemoveNamespace(t *testing.T) { - ns := Namespaces{ - {Type: NEWNET}, - } - if !ns.Remove(NEWNET) { - t.Fatal("NEWNET was not removed") - } - if len(ns) != 0 { - t.Fatalf("namespaces should have 0 items but reports %d", len(ns)) - } -} - -func TestHostUIDNoUSERNS(t *testing.T) { - config := &Config{ - Namespaces: Namespaces{}, - } - uid, err := config.HostUID() - if err != nil { - t.Fatal(err) - } - if uid != 0 { - t.Fatalf("expected uid 0 with no USERNS but received %d", uid) - } -} - -func TestHostUIDWithUSERNS(t *testing.T) { - config := &Config{ - Namespaces: Namespaces{{Type: NEWUSER}}, - UidMappings: []IDMap{ - { - ContainerID: 0, - HostID: 1000, - Size: 1, - }, - }, - } - uid, err := config.HostUID() - if err != nil { - t.Fatal(err) - } - if uid != 1000 { - t.Fatalf("expected uid 1000 with no USERNS but received %d", uid) - } -} - -func TestHostGIDNoUSERNS(t *testing.T) { - config := &Config{ - Namespaces: Namespaces{}, - } - uid, err := config.HostGID() - if err != nil { - t.Fatal(err) - } - if uid != 0 { - t.Fatalf("expected gid 0 with no USERNS but received %d", uid) - } -} - -func TestHostGIDWithUSERNS(t *testing.T) { - config := &Config{ - Namespaces: Namespaces{{Type: NEWUSER}}, - GidMappings: []IDMap{ - { - ContainerID: 0, - HostID: 1000, - Size: 1, - }, - }, - } - uid, err := config.HostGID() - if err != nil { - t.Fatal(err) - } - if uid != 1000 { - t.Fatalf("expected gid 1000 with no USERNS but received %d", uid) - } -} diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/config_windows_test.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/config_windows_test.go deleted file mode 100644 index 1a0c8fa2d..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/config_windows_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package configs - -// All current tests are for Unix-specific functionality diff --git a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/validate/config.go b/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/validate/config.go deleted file mode 100644 index 848a67c34..000000000 --- a/Godeps/_workspace/src/github.com/opencontainers/runc/libcontainer/configs/validate/config.go +++ /dev/null @@ -1,93 +0,0 @@ -package validate - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/opencontainers/runc/libcontainer/configs" -) - -type Validator interface { - Validate(*configs.Config) error -} - -func New() Validator { - return &ConfigValidator{} -} - -type ConfigValidator struct { -} - -func (v *ConfigValidator) Validate(config *configs.Config) error { - if err := v.rootfs(config); err != nil { - return err - } - if err := v.network(config); err != nil { - return err - } - if err := v.hostname(config); err != nil { - return err - } - if err := v.security(config); err != nil { - return err - } - if err := v.usernamespace(config); err != nil { - return err - } - return nil -} - -// rootfs validates the the rootfs is an absolute path and is not a symlink -// to the container's root filesystem. -func (v *ConfigValidator) rootfs(config *configs.Config) error { - cleaned, err := filepath.Abs(config.Rootfs) - if err != nil { - return err - } - if cleaned, err = filepath.EvalSymlinks(cleaned); err != nil { - return err - } - if config.Rootfs != cleaned { - return fmt.Errorf("%s is not an absolute path or is a symlink", config.Rootfs) - } - return nil -} - -func (v *ConfigValidator) network(config *configs.Config) error { - if !config.Namespaces.Contains(configs.NEWNET) { - if len(config.Networks) > 0 || len(config.Routes) > 0 { - return fmt.Errorf("unable to apply network settings without a private NET namespace") - } - } - return nil -} - -func (v *ConfigValidator) hostname(config *configs.Config) error { - if config.Hostname != "" && !config.Namespaces.Contains(configs.NEWUTS) { - return fmt.Errorf("unable to set hostname without a private UTS namespace") - } - return nil -} - -func (v *ConfigValidator) security(config *configs.Config) error { - // restrict sys without mount namespace - if (len(config.MaskPaths) > 0 || len(config.ReadonlyPaths) > 0) && - !config.Namespaces.Contains(configs.NEWNS) { - return fmt.Errorf("unable to restrict sys entries without a private MNT namespace") - } - return nil -} - -func (v *ConfigValidator) usernamespace(config *configs.Config) error { - if config.Namespaces.Contains(configs.NEWUSER) { - if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) { - return fmt.Errorf("USER namespaces aren't enabled in the kernel") - } - } else { - if config.UidMappings != nil || config.GidMappings != nil { - return fmt.Errorf("User namespace mappings specified, but USER namespace isn't enabled in the config") - } - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/pborman/uuid/json_test.go b/Godeps/_workspace/src/github.com/pborman/uuid/json_test.go deleted file mode 100644 index b5eae0924..000000000 --- a/Godeps/_workspace/src/github.com/pborman/uuid/json_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "encoding/json" - "reflect" - "testing" -) - -var testUUID = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479") - -func TestJSON(t *testing.T) { - type S struct { - ID1 UUID - ID2 UUID - } - s1 := S{ID1: testUUID} - data, err := json.Marshal(&s1) - if err != nil { - t.Fatal(err) - } - var s2 S - if err := json.Unmarshal(data, &s2); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(&s1, &s2) { - t.Errorf("got %#v, want %#v", s2, s1) - } -} diff --git a/Godeps/_workspace/src/github.com/pborman/uuid/seq_test.go b/Godeps/_workspace/src/github.com/pborman/uuid/seq_test.go deleted file mode 100644 index 3b3d1430d..000000000 --- a/Godeps/_workspace/src/github.com/pborman/uuid/seq_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "flag" - "runtime" - "testing" - "time" -) - -// This test is only run when --regressions is passed on the go test line. -var regressions = flag.Bool("regressions", false, "run uuid regression tests") - -// TestClockSeqRace tests for a particular race condition of returning two -// identical Version1 UUIDs. The duration of 1 minute was chosen as the race -// condition, before being fixed, nearly always occured in under 30 seconds. -func TestClockSeqRace(t *testing.T) { - if !*regressions { - t.Skip("skipping regression tests") - } - duration := time.Minute - - done := make(chan struct{}) - defer close(done) - - ch := make(chan UUID, 10000) - ncpu := runtime.NumCPU() - switch ncpu { - case 0, 1: - // We can't run the test effectively. - t.Skip("skipping race test, only one CPU detected") - return - default: - runtime.GOMAXPROCS(ncpu) - } - for i := 0; i < ncpu; i++ { - go func() { - for { - select { - case <-done: - return - case ch <- NewUUID(): - } - } - }() - } - - uuids := make(map[string]bool) - cnt := 0 - start := time.Now() - for u := range ch { - s := u.String() - if uuids[s] { - t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s) - return - } - uuids[s] = true - if time.Since(start) > duration { - return - } - cnt++ - } -} diff --git a/Godeps/_workspace/src/github.com/pborman/uuid/uuid_test.go b/Godeps/_workspace/src/github.com/pborman/uuid/uuid_test.go deleted file mode 100644 index 417ebeb26..000000000 --- a/Godeps/_workspace/src/github.com/pborman/uuid/uuid_test.go +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "bytes" - "fmt" - "os" - "strings" - "testing" - "time" -) - -type test struct { - in string - version Version - variant Variant - isuuid bool -} - -var tests = []test{ - {"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true}, - {"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true}, - {"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true}, - {"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true}, - {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true}, - {"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true}, - {"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true}, - {"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true}, - {"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true}, - {"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true}, - {"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true}, - {"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true}, - {"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true}, - {"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true}, - {"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true}, - {"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true}, - - {"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, - {"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true}, - {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true}, - {"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true}, - {"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true}, - {"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true}, - {"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true}, - {"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true}, - {"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true}, - {"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true}, - - {"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false}, - {"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false}, - {"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false}, - {"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false}, - {"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false}, - {"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false}, -} - -var constants = []struct { - c interface{} - name string -}{ - {Person, "Person"}, - {Group, "Group"}, - {Org, "Org"}, - {Invalid, "Invalid"}, - {RFC4122, "RFC4122"}, - {Reserved, "Reserved"}, - {Microsoft, "Microsoft"}, - {Future, "Future"}, - {Domain(17), "Domain17"}, - {Variant(42), "BadVariant42"}, -} - -func testTest(t *testing.T, in string, tt test) { - uuid := Parse(in) - if ok := (uuid != nil); ok != tt.isuuid { - t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid) - } - if uuid == nil { - return - } - - if v := uuid.Variant(); v != tt.variant { - t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant) - } - if v, _ := uuid.Version(); v != tt.version { - t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version) - } -} - -func TestUUID(t *testing.T) { - for _, tt := range tests { - testTest(t, tt.in, tt) - testTest(t, strings.ToUpper(tt.in), tt) - } -} - -func TestConstants(t *testing.T) { - for x, tt := range constants { - v, ok := tt.c.(fmt.Stringer) - if !ok { - t.Errorf("%x: %v: not a stringer", x, v) - } else if s := v.String(); s != tt.name { - v, _ := tt.c.(int) - t.Errorf("%x: Constant %T:%d gives %q, expected %q\n", x, tt.c, v, s, tt.name) - } - } -} - -func TestRandomUUID(t *testing.T) { - m := make(map[string]bool) - for x := 1; x < 32; x++ { - uuid := NewRandom() - s := uuid.String() - if m[s] { - t.Errorf("NewRandom returned duplicated UUID %s\n", s) - } - m[s] = true - if v, _ := uuid.Version(); v != 4 { - t.Errorf("Random UUID of version %s\n", v) - } - if uuid.Variant() != RFC4122 { - t.Errorf("Random UUID is variant %d\n", uuid.Variant()) - } - } -} - -func TestNew(t *testing.T) { - m := make(map[string]bool) - for x := 1; x < 32; x++ { - s := New() - if m[s] { - t.Errorf("New returned duplicated UUID %s\n", s) - } - m[s] = true - uuid := Parse(s) - if uuid == nil { - t.Errorf("New returned %q which does not decode\n", s) - continue - } - if v, _ := uuid.Version(); v != 4 { - t.Errorf("Random UUID of version %s\n", v) - } - if uuid.Variant() != RFC4122 { - t.Errorf("Random UUID is variant %d\n", uuid.Variant()) - } - } -} - -func clockSeq(t *testing.T, uuid UUID) int { - seq, ok := uuid.ClockSequence() - if !ok { - t.Fatalf("%s: invalid clock sequence\n", uuid) - } - return seq -} - -func TestClockSeq(t *testing.T) { - // Fake time.Now for this test to return a monotonically advancing time; restore it at end. - defer func(orig func() time.Time) { timeNow = orig }(timeNow) - monTime := time.Now() - timeNow = func() time.Time { - monTime = monTime.Add(1 * time.Second) - return monTime - } - - SetClockSequence(-1) - uuid1 := NewUUID() - uuid2 := NewUUID() - - if clockSeq(t, uuid1) != clockSeq(t, uuid2) { - t.Errorf("clock sequence %d != %d\n", clockSeq(t, uuid1), clockSeq(t, uuid2)) - } - - SetClockSequence(-1) - uuid2 = NewUUID() - - // Just on the very off chance we generated the same sequence - // two times we try again. - if clockSeq(t, uuid1) == clockSeq(t, uuid2) { - SetClockSequence(-1) - uuid2 = NewUUID() - } - if clockSeq(t, uuid1) == clockSeq(t, uuid2) { - t.Errorf("Duplicate clock sequence %d\n", clockSeq(t, uuid1)) - } - - SetClockSequence(0x1234) - uuid1 = NewUUID() - if seq := clockSeq(t, uuid1); seq != 0x1234 { - t.Errorf("%s: expected seq 0x1234 got 0x%04x\n", uuid1, seq) - } -} - -func TestCoding(t *testing.T) { - text := "7d444840-9dc0-11d1-b245-5ffdce74fad2" - urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2" - data := UUID{ - 0x7d, 0x44, 0x48, 0x40, - 0x9d, 0xc0, - 0x11, 0xd1, - 0xb2, 0x45, - 0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2, - } - if v := data.String(); v != text { - t.Errorf("%x: encoded to %s, expected %s\n", data, v, text) - } - if v := data.URN(); v != urn { - t.Errorf("%x: urn is %s, expected %s\n", data, v, urn) - } - - uuid := Parse(text) - if !Equal(uuid, data) { - t.Errorf("%s: decoded to %s, expected %s\n", text, uuid, data) - } -} - -func TestVersion1(t *testing.T) { - uuid1 := NewUUID() - uuid2 := NewUUID() - - if Equal(uuid1, uuid2) { - t.Errorf("%s:duplicate uuid\n", uuid1) - } - if v, _ := uuid1.Version(); v != 1 { - t.Errorf("%s: version %s expected 1\n", uuid1, v) - } - if v, _ := uuid2.Version(); v != 1 { - t.Errorf("%s: version %s expected 1\n", uuid2, v) - } - n1 := uuid1.NodeID() - n2 := uuid2.NodeID() - if !bytes.Equal(n1, n2) { - t.Errorf("Different nodes %x != %x\n", n1, n2) - } - t1, ok := uuid1.Time() - if !ok { - t.Errorf("%s: invalid time\n", uuid1) - } - t2, ok := uuid2.Time() - if !ok { - t.Errorf("%s: invalid time\n", uuid2) - } - q1, ok := uuid1.ClockSequence() - if !ok { - t.Errorf("%s: invalid clock sequence\n", uuid1) - } - q2, ok := uuid2.ClockSequence() - if !ok { - t.Errorf("%s: invalid clock sequence", uuid2) - } - - switch { - case t1 == t2 && q1 == q2: - t.Errorf("time stopped\n") - case t1 > t2 && q1 == q2: - t.Errorf("time reversed\n") - case t1 < t2 && q1 != q2: - t.Errorf("clock sequence chaned unexpectedly\n") - } -} - -func TestNodeAndTime(t *testing.T) { - // Time is February 5, 1998 12:30:23.136364800 AM GMT - - uuid := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2") - node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2} - - ts, ok := uuid.Time() - if ok { - c := time.Unix(ts.UnixTime()) - want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC) - if !c.Equal(want) { - t.Errorf("Got time %v, want %v", c, want) - } - } else { - t.Errorf("%s: bad time\n", uuid) - } - if !bytes.Equal(node, uuid.NodeID()) { - t.Errorf("Expected node %v got %v\n", node, uuid.NodeID()) - } -} - -func TestMD5(t *testing.T) { - uuid := NewMD5(NameSpace_DNS, []byte("python.org")).String() - want := "6fa459ea-ee8a-3ca4-894e-db77e160355e" - if uuid != want { - t.Errorf("MD5: got %q expected %q\n", uuid, want) - } -} - -func TestSHA1(t *testing.T) { - uuid := NewSHA1(NameSpace_DNS, []byte("python.org")).String() - want := "886313e1-3b8a-5372-9b90-0c9aee199e5d" - if uuid != want { - t.Errorf("SHA1: got %q expected %q\n", uuid, want) - } -} - -func TestNodeID(t *testing.T) { - nid := []byte{1, 2, 3, 4, 5, 6} - SetNodeInterface("") - s := NodeInterface() - if s == "" || s == "user" { - t.Errorf("NodeInterface %q after SetInteface\n", s) - } - node1 := NodeID() - if node1 == nil { - t.Errorf("NodeID nil after SetNodeInterface\n", s) - } - SetNodeID(nid) - s = NodeInterface() - if s != "user" { - t.Errorf("Expected NodeInterface %q got %q\n", "user", s) - } - node2 := NodeID() - if node2 == nil { - t.Errorf("NodeID nil after SetNodeID\n", s) - } - if bytes.Equal(node1, node2) { - t.Errorf("NodeID not changed after SetNodeID\n", s) - } else if !bytes.Equal(nid, node2) { - t.Errorf("NodeID is %x, expected %x\n", node2, nid) - } -} - -func testDCE(t *testing.T, name string, uuid UUID, domain Domain, id uint32) { - if uuid == nil { - t.Errorf("%s failed\n", name) - return - } - if v, _ := uuid.Version(); v != 2 { - t.Errorf("%s: %s: expected version 2, got %s\n", name, uuid, v) - return - } - if v, ok := uuid.Domain(); !ok || v != domain { - if !ok { - t.Errorf("%s: %d: Domain failed\n", name, uuid) - } else { - t.Errorf("%s: %s: expected domain %d, got %d\n", name, uuid, domain, v) - } - } - if v, ok := uuid.Id(); !ok || v != id { - if !ok { - t.Errorf("%s: %d: Id failed\n", name, uuid) - } else { - t.Errorf("%s: %s: expected id %d, got %d\n", name, uuid, id, v) - } - } -} - -func TestDCE(t *testing.T) { - testDCE(t, "NewDCESecurity", NewDCESecurity(42, 12345678), 42, 12345678) - testDCE(t, "NewDCEPerson", NewDCEPerson(), Person, uint32(os.Getuid())) - testDCE(t, "NewDCEGroup", NewDCEGroup(), Group, uint32(os.Getgid())) -} - -type badRand struct{} - -func (r badRand) Read(buf []byte) (int, error) { - for i, _ := range buf { - buf[i] = byte(i) - } - return len(buf), nil -} - -func TestBadRand(t *testing.T) { - SetRand(badRand{}) - uuid1 := New() - uuid2 := New() - if uuid1 != uuid2 { - t.Errorf("execpted duplicates, got %q and %q\n", uuid1, uuid2) - } - SetRand(nil) - uuid1 = New() - uuid2 = New() - if uuid1 == uuid2 { - t.Errorf("unexecpted duplicates, got %q\n", uuid1) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/benchmark_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/benchmark_test.go deleted file mode 100644 index 6ae7333fc..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/benchmark_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus - -import ( - "testing" -) - -func BenchmarkCounterWithLabelValues(b *testing.B) { - m := NewCounterVec( - CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Inc() - } -} - -func BenchmarkCounterWithMappedLabels(b *testing.B) { - m := NewCounterVec( - CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.With(Labels{"two": "zwei", "one": "eins", "three": "drei"}).Inc() - } -} - -func BenchmarkCounterWithPreparedMappedLabels(b *testing.B) { - m := NewCounterVec( - CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - labels := Labels{"two": "zwei", "one": "eins", "three": "drei"} - for i := 0; i < b.N; i++ { - m.With(labels).Inc() - } -} - -func BenchmarkCounterNoLabels(b *testing.B) { - m := NewCounter(CounterOpts{ - Name: "benchmark_counter", - Help: "A counter to benchmark it.", - }) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Inc() - } -} - -func BenchmarkGaugeWithLabelValues(b *testing.B) { - m := NewGaugeVec( - GaugeOpts{ - Name: "benchmark_gauge", - Help: "A gauge to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Set(3.1415) - } -} - -func BenchmarkGaugeNoLabels(b *testing.B) { - m := NewGauge(GaugeOpts{ - Name: "benchmark_gauge", - Help: "A gauge to benchmark it.", - }) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Set(3.1415) - } -} - -func BenchmarkSummaryWithLabelValues(b *testing.B) { - m := NewSummaryVec( - SummaryOpts{ - Name: "benchmark_summary", - Help: "A summary to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Observe(3.1415) - } -} - -func BenchmarkSummaryNoLabels(b *testing.B) { - m := NewSummary(SummaryOpts{ - Name: "benchmark_summary", - Help: "A summary to benchmark it.", - }, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Observe(3.1415) - } -} - -func BenchmarkHistogramWithLabelValues(b *testing.B) { - m := NewHistogramVec( - HistogramOpts{ - Name: "benchmark_histogram", - Help: "A histogram to benchmark it.", - }, - []string{"one", "two", "three"}, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.WithLabelValues("eins", "zwei", "drei").Observe(3.1415) - } -} - -func BenchmarkHistogramNoLabels(b *testing.B) { - m := NewHistogram(HistogramOpts{ - Name: "benchmark_histogram", - Help: "A histogram to benchmark it.", - }, - ) - b.ReportAllocs() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Observe(3.1415) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/counter_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/counter_test.go deleted file mode 100644 index 67391a23a..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/counter_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus - -import ( - "math" - "testing" - - dto "github.com/prometheus/client_model/go" -) - -func TestCounterAdd(t *testing.T) { - counter := NewCounter(CounterOpts{ - Name: "test", - Help: "test help", - ConstLabels: Labels{"a": "1", "b": "2"}, - }).(*counter) - counter.Inc() - if expected, got := 1., math.Float64frombits(counter.valBits); expected != got { - t.Errorf("Expected %f, got %f.", expected, got) - } - counter.Add(42) - if expected, got := 43., math.Float64frombits(counter.valBits); expected != got { - t.Errorf("Expected %f, got %f.", expected, got) - } - - if expected, got := "counter cannot decrease in value", decreaseCounter(counter).Error(); expected != got { - t.Errorf("Expected error %q, got %q.", expected, got) - } - - m := &dto.Metric{} - counter.Write(m) - - if expected, got := `label: label: counter: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } -} - -func decreaseCounter(c *counter) (err error) { - defer func() { - if e := recover(); e != nil { - err = e.(error) - } - }() - c.Add(-1) - return nil -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go deleted file mode 100644 index 6f3e215d4..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_clustermanager_test.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus_test - -import ( - "sync" - - "github.com/prometheus/client_golang/prometheus" -) - -// ClusterManager is an example for a system that might have been built without -// Prometheus in mind. It models a central manager of jobs running in a -// cluster. To turn it into something that collects Prometheus metrics, we -// simply add the two methods required for the Collector interface. -// -// An additional challenge is that multiple instances of the ClusterManager are -// run within the same binary, each in charge of a different zone. We need to -// make use of ConstLabels to be able to register each ClusterManager instance -// with Prometheus. -type ClusterManager struct { - Zone string - OOMCount *prometheus.CounterVec - RAMUsage *prometheus.GaugeVec - mtx sync.Mutex // Protects OOMCount and RAMUsage. - // ... many more fields -} - -// ReallyExpensiveAssessmentOfTheSystemState is a mock for the data gathering a -// real cluster manager would have to do. Since it may actually be really -// expensive, it must only be called once per collection. This implementation, -// obviously, only returns some made-up data. -func (c *ClusterManager) ReallyExpensiveAssessmentOfTheSystemState() ( - oomCountByHost map[string]int, ramUsageByHost map[string]float64, -) { - // Just example fake data. - oomCountByHost = map[string]int{ - "foo.example.org": 42, - "bar.example.org": 2001, - } - ramUsageByHost = map[string]float64{ - "foo.example.org": 6.023e23, - "bar.example.org": 3.14, - } - return -} - -// Describe faces the interesting challenge that the two metric vectors that are -// used in this example are already Collectors themselves. However, thanks to -// the use of channels, it is really easy to "chain" Collectors. Here we simply -// call the Describe methods of the two metric vectors. -func (c *ClusterManager) Describe(ch chan<- *prometheus.Desc) { - c.OOMCount.Describe(ch) - c.RAMUsage.Describe(ch) -} - -// Collect first triggers the ReallyExpensiveAssessmentOfTheSystemState. Then it -// sets the retrieved values in the two metric vectors and then sends all their -// metrics to the channel (again using a chaining technique as in the Describe -// method). Since Collect could be called multiple times concurrently, that part -// is protected by a mutex. -func (c *ClusterManager) Collect(ch chan<- prometheus.Metric) { - oomCountByHost, ramUsageByHost := c.ReallyExpensiveAssessmentOfTheSystemState() - c.mtx.Lock() - defer c.mtx.Unlock() - for host, oomCount := range oomCountByHost { - c.OOMCount.WithLabelValues(host).Set(float64(oomCount)) - } - for host, ramUsage := range ramUsageByHost { - c.RAMUsage.WithLabelValues(host).Set(ramUsage) - } - c.OOMCount.Collect(ch) - c.RAMUsage.Collect(ch) - // All metrics in OOMCount and RAMUsage are sent to the channel now. We - // can safely reset the two metric vectors now, so that we can start - // fresh in the next Collect cycle. (Imagine a host disappears from the - // cluster. If we did not reset here, its Metric would stay in the - // metric vectors forever.) - c.OOMCount.Reset() - c.RAMUsage.Reset() -} - -// NewClusterManager creates the two metric vectors OOMCount and RAMUsage. Note -// that the zone is set as a ConstLabel. (It's different in each instance of the -// ClusterManager, but constant over the lifetime of an instance.) The reported -// values are partitioned by host, which is therefore a variable label. -func NewClusterManager(zone string) *ClusterManager { - return &ClusterManager{ - Zone: zone, - OOMCount: prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: "clustermanager", - Name: "oom_count", - Help: "number of OOM crashes", - ConstLabels: prometheus.Labels{"zone": zone}, - }, - []string{"host"}, - ), - RAMUsage: prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Subsystem: "clustermanager", - Name: "ram_usage_bytes", - Help: "RAM usage as reported to the cluster manager", - ConstLabels: prometheus.Labels{"zone": zone}, - }, - []string{"host"}, - ), - } -} - -func ExampleCollector_clustermanager() { - workerDB := NewClusterManager("db") - workerCA := NewClusterManager("ca") - prometheus.MustRegister(workerDB) - prometheus.MustRegister(workerCA) - - // Since we are dealing with custom Collector implementations, it might - // be a good idea to enable the collect checks in the registry. - prometheus.EnableCollectChecks(true) -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_memstats_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_memstats_test.go deleted file mode 100644 index a84d07250..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_memstats_test.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus_test - -import ( - "runtime" - - "github.com/prometheus/client_golang/prometheus" -) - -var ( - allocDesc = prometheus.NewDesc( - prometheus.BuildFQName("", "memstats", "alloc_bytes"), - "bytes allocated and still in use", - nil, nil, - ) - totalAllocDesc = prometheus.NewDesc( - prometheus.BuildFQName("", "memstats", "total_alloc_bytes"), - "bytes allocated (even if freed)", - nil, nil, - ) - numGCDesc = prometheus.NewDesc( - prometheus.BuildFQName("", "memstats", "num_gc_total"), - "number of GCs run", - nil, nil, - ) -) - -// MemStatsCollector is an example for a custom Collector that solves the -// problem of feeding into multiple metrics at the same time. The -// runtime.ReadMemStats should happen only once, and then the results need to be -// fed into a number of separate Metrics. In this example, only a few of the -// values reported by ReadMemStats are used. For each, there is a Desc provided -// as a var, so the MemStatsCollector itself needs nothing else in the -// struct. Only the methods need to be implemented. -type MemStatsCollector struct{} - -// Describe just sends the three Desc objects for the Metrics we intend to -// collect. -func (_ MemStatsCollector) Describe(ch chan<- *prometheus.Desc) { - ch <- allocDesc - ch <- totalAllocDesc - ch <- numGCDesc -} - -// Collect does the trick by calling ReadMemStats once and then constructing -// three different Metrics on the fly. -func (_ MemStatsCollector) Collect(ch chan<- prometheus.Metric) { - var ms runtime.MemStats - runtime.ReadMemStats(&ms) - ch <- prometheus.MustNewConstMetric( - allocDesc, - prometheus.GaugeValue, - float64(ms.Alloc), - ) - ch <- prometheus.MustNewConstMetric( - totalAllocDesc, - prometheus.GaugeValue, - float64(ms.TotalAlloc), - ) - ch <- prometheus.MustNewConstMetric( - numGCDesc, - prometheus.CounterValue, - float64(ms.NumGC), - ) - // To avoid new allocations on each collection, you could also keep - // metric objects around and return the same objects each time, just - // with new values set. -} - -func ExampleCollector_memstats() { - prometheus.MustRegister(&MemStatsCollector{}) - // Since we are dealing with custom Collector implementations, it might - // be a good idea to enable the collect checks in the registry. - prometheus.EnableCollectChecks(true) -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_selfcollector_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_selfcollector_test.go deleted file mode 100644 index 608deeb02..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/example_selfcollector_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus_test - -import ( - "runtime" - - "github.com/golang/protobuf/proto" - - dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus" -) - -func NewCallbackMetric(desc *prometheus.Desc, callback func() float64) *CallbackMetric { - result := &CallbackMetric{desc: desc, callback: callback} - result.Init(result) // Initialize the SelfCollector. - return result -} - -// TODO: Come up with a better example. - -// CallbackMetric is an example for a user-defined Metric that exports the -// result of a function call as a metric of type "untyped" without any -// labels. It uses SelfCollector to turn the Metric into a Collector so that it -// can be registered with Prometheus. -// -// Note that this example is pretty much academic as the prometheus package -// already provides an UntypedFunc type. -type CallbackMetric struct { - prometheus.SelfCollector - - desc *prometheus.Desc - callback func() float64 -} - -func (cm *CallbackMetric) Desc() *prometheus.Desc { - return cm.desc -} - -func (cm *CallbackMetric) Write(m *dto.Metric) error { - m.Untyped = &dto.Untyped{Value: proto.Float64(cm.callback())} - return nil -} - -func ExampleSelfCollector() { - m := NewCallbackMetric( - prometheus.NewDesc( - "runtime_goroutines_count", - "Total number of goroutines that currently exist.", - nil, nil, // No labels, these must be nil. - ), - func() float64 { - return float64(runtime.NumGoroutine()) - }, - ) - prometheus.MustRegister(m) -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/examples_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/examples_test.go deleted file mode 100644 index 0344e465b..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/examples_test.go +++ /dev/null @@ -1,649 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus_test - -import ( - "flag" - "fmt" - "math" - "net/http" - "os" - "runtime" - "sort" - "time" - - dto "github.com/prometheus/client_model/go" - - "github.com/golang/protobuf/proto" - - "github.com/prometheus/client_golang/prometheus" -) - -func ExampleGauge() { - opsQueued := prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "our_company", - Subsystem: "blob_storage", - Name: "ops_queued", - Help: "Number of blob storage operations waiting to be processed.", - }) - prometheus.MustRegister(opsQueued) - - // 10 operations queued by the goroutine managing incoming requests. - opsQueued.Add(10) - // A worker goroutine has picked up a waiting operation. - opsQueued.Dec() - // And once more... - opsQueued.Dec() -} - -func ExampleGaugeVec() { - binaryVersion := flag.String("binary_version", "debug", "Version of the binary: debug, canary, production.") - flag.Parse() - - opsQueued := prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: "our_company", - Subsystem: "blob_storage", - Name: "ops_queued", - Help: "Number of blob storage operations waiting to be processed, partitioned by user and type.", - ConstLabels: prometheus.Labels{"binary_version": *binaryVersion}, - }, - []string{ - // Which user has requested the operation? - "user", - // Of what type is the operation? - "type", - }, - ) - prometheus.MustRegister(opsQueued) - - // Increase a value using compact (but order-sensitive!) WithLabelValues(). - opsQueued.WithLabelValues("bob", "put").Add(4) - // Increase a value with a map using WithLabels. More verbose, but order - // doesn't matter anymore. - opsQueued.With(prometheus.Labels{"type": "delete", "user": "alice"}).Inc() -} - -func ExampleGaugeFunc() { - if err := prometheus.Register(prometheus.NewGaugeFunc( - prometheus.GaugeOpts{ - Subsystem: "runtime", - Name: "goroutines_count", - Help: "Number of goroutines that currently exist.", - }, - func() float64 { return float64(runtime.NumGoroutine()) }, - )); err == nil { - fmt.Println("GaugeFunc 'goroutines_count' registered.") - } - // Note that the count of goroutines is a gauge (and not a counter) as - // it can go up and down. - - // Output: - // GaugeFunc 'goroutines_count' registered. -} - -func ExampleCounter() { - pushCounter := prometheus.NewCounter(prometheus.CounterOpts{ - Name: "repository_pushes", // Note: No help string... - }) - err := prometheus.Register(pushCounter) // ... so this will return an error. - if err != nil { - fmt.Println("Push counter couldn't be registered, no counting will happen:", err) - return - } - - // Try it once more, this time with a help string. - pushCounter = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "repository_pushes", - Help: "Number of pushes to external repository.", - }) - err = prometheus.Register(pushCounter) - if err != nil { - fmt.Println("Push counter couldn't be registered AGAIN, no counting will happen:", err) - return - } - - pushComplete := make(chan struct{}) - // TODO: Start a goroutine that performs repository pushes and reports - // each completion via the channel. - for _ = range pushComplete { - pushCounter.Inc() - } - // Output: - // Push counter couldn't be registered, no counting will happen: descriptor Desc{fqName: "repository_pushes", help: "", constLabels: {}, variableLabels: []} is invalid: empty help string -} - -func ExampleCounterVec() { - binaryVersion := flag.String("environment", "test", "Execution environment: test, staging, production.") - flag.Parse() - - httpReqs := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "http_requests_total", - Help: "How many HTTP requests processed, partitioned by status code and HTTP method.", - ConstLabels: prometheus.Labels{"env": *binaryVersion}, - }, - []string{"code", "method"}, - ) - prometheus.MustRegister(httpReqs) - - httpReqs.WithLabelValues("404", "POST").Add(42) - - // If you have to access the same set of labels very frequently, it - // might be good to retrieve the metric only once and keep a handle to - // it. But beware of deletion of that metric, see below! - m := httpReqs.WithLabelValues("200", "GET") - for i := 0; i < 1000000; i++ { - m.Inc() - } - // Delete a metric from the vector. If you have previously kept a handle - // to that metric (as above), future updates via that handle will go - // unseen (even if you re-create a metric with the same label set - // later). - httpReqs.DeleteLabelValues("200", "GET") - // Same thing with the more verbose Labels syntax. - httpReqs.Delete(prometheus.Labels{"method": "GET", "code": "200"}) -} - -func ExampleInstrumentHandler() { - // Handle the "/doc" endpoint with the standard http.FileServer handler. - // By wrapping the handler with InstrumentHandler, request count, - // request and response sizes, and request latency are automatically - // exported to Prometheus, partitioned by HTTP status code and method - // and by the handler name (here "fileserver"). - http.Handle("/doc", prometheus.InstrumentHandler( - "fileserver", http.FileServer(http.Dir("/usr/share/doc")), - )) - // The Prometheus handler still has to be registered to handle the - // "/metrics" endpoint. The handler returned by prometheus.Handler() is - // already instrumented - with "prometheus" as the handler name. In this - // example, we want the handler name to be "metrics", so we instrument - // the uninstrumented Prometheus handler ourselves. - http.Handle("/metrics", prometheus.InstrumentHandler( - "metrics", prometheus.UninstrumentedHandler(), - )) -} - -func ExampleLabelPairSorter() { - labelPairs := []*dto.LabelPair{ - &dto.LabelPair{Name: proto.String("status"), Value: proto.String("404")}, - &dto.LabelPair{Name: proto.String("method"), Value: proto.String("get")}, - } - - sort.Sort(prometheus.LabelPairSorter(labelPairs)) - - fmt.Println(labelPairs) - // Output: - // [name:"method" value:"get" name:"status" value:"404" ] -} - -func ExampleRegister() { - // Imagine you have a worker pool and want to count the tasks completed. - taskCounter := prometheus.NewCounter(prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks_total", - Help: "Total number of tasks completed.", - }) - // This will register fine. - if err := prometheus.Register(taskCounter); err != nil { - fmt.Println(err) - } else { - fmt.Println("taskCounter registered.") - } - // Don't forget to tell the HTTP server about the Prometheus handler. - // (In a real program, you still need to start the HTTP server...) - http.Handle("/metrics", prometheus.Handler()) - - // Now you can start workers and give every one of them a pointer to - // taskCounter and let it increment it whenever it completes a task. - taskCounter.Inc() // This has to happen somewhere in the worker code. - - // But wait, you want to see how individual workers perform. So you need - // a vector of counters, with one element for each worker. - taskCounterVec := prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks_total", - Help: "Total number of tasks completed.", - }, - []string{"worker_id"}, - ) - - // Registering will fail because we already have a metric of that name. - if err := prometheus.Register(taskCounterVec); err != nil { - fmt.Println("taskCounterVec not registered:", err) - } else { - fmt.Println("taskCounterVec registered.") - } - - // To fix, first unregister the old taskCounter. - if prometheus.Unregister(taskCounter) { - fmt.Println("taskCounter unregistered.") - } - - // Try registering taskCounterVec again. - if err := prometheus.Register(taskCounterVec); err != nil { - fmt.Println("taskCounterVec not registered:", err) - } else { - fmt.Println("taskCounterVec registered.") - } - // Bummer! Still doesn't work. - - // Prometheus will not allow you to ever export metrics with - // inconsistent help strings or label names. After unregistering, the - // unregistered metrics will cease to show up in the /metrics HTTP - // response, but the registry still remembers that those metrics had - // been exported before. For this example, we will now choose a - // different name. (In a real program, you would obviously not export - // the obsolete metric in the first place.) - taskCounterVec = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks_by_id", - Help: "Total number of tasks completed.", - }, - []string{"worker_id"}, - ) - if err := prometheus.Register(taskCounterVec); err != nil { - fmt.Println("taskCounterVec not registered:", err) - } else { - fmt.Println("taskCounterVec registered.") - } - // Finally it worked! - - // The workers have to tell taskCounterVec their id to increment the - // right element in the metric vector. - taskCounterVec.WithLabelValues("42").Inc() // Code from worker 42. - - // Each worker could also keep a reference to their own counter element - // around. Pick the counter at initialization time of the worker. - myCounter := taskCounterVec.WithLabelValues("42") // From worker 42 initialization code. - myCounter.Inc() // Somewhere in the code of that worker. - - // Note that something like WithLabelValues("42", "spurious arg") would - // panic (because you have provided too many label values). If you want - // to get an error instead, use GetMetricWithLabelValues(...) instead. - notMyCounter, err := taskCounterVec.GetMetricWithLabelValues("42", "spurious arg") - if err != nil { - fmt.Println("Worker initialization failed:", err) - } - if notMyCounter == nil { - fmt.Println("notMyCounter is nil.") - } - - // A different (and somewhat tricky) approach is to use - // ConstLabels. ConstLabels are pairs of label names and label values - // that never change. You might ask what those labels are good for (and - // rightfully so - if they never change, they could as well be part of - // the metric name). There are essentially two use-cases: The first is - // if labels are constant throughout the lifetime of a binary execution, - // but they vary over time or between different instances of a running - // binary. The second is what we have here: Each worker creates and - // registers an own Counter instance where the only difference is in the - // value of the ConstLabels. Those Counters can all be registered - // because the different ConstLabel values guarantee that each worker - // will increment a different Counter metric. - counterOpts := prometheus.CounterOpts{ - Subsystem: "worker_pool", - Name: "completed_tasks", - Help: "Total number of tasks completed.", - ConstLabels: prometheus.Labels{"worker_id": "42"}, - } - taskCounterForWorker42 := prometheus.NewCounter(counterOpts) - if err := prometheus.Register(taskCounterForWorker42); err != nil { - fmt.Println("taskCounterVForWorker42 not registered:", err) - } else { - fmt.Println("taskCounterForWorker42 registered.") - } - // Obviously, in real code, taskCounterForWorker42 would be a member - // variable of a worker struct, and the "42" would be retrieved with a - // GetId() method or something. The Counter would be created and - // registered in the initialization code of the worker. - - // For the creation of the next Counter, we can recycle - // counterOpts. Just change the ConstLabels. - counterOpts.ConstLabels = prometheus.Labels{"worker_id": "2001"} - taskCounterForWorker2001 := prometheus.NewCounter(counterOpts) - if err := prometheus.Register(taskCounterForWorker2001); err != nil { - fmt.Println("taskCounterVForWorker2001 not registered:", err) - } else { - fmt.Println("taskCounterForWorker2001 registered.") - } - - taskCounterForWorker2001.Inc() - taskCounterForWorker42.Inc() - taskCounterForWorker2001.Inc() - - // Yet another approach would be to turn the workers themselves into - // Collectors and register them. See the Collector example for details. - - // Output: - // taskCounter registered. - // taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string - // taskCounter unregistered. - // taskCounterVec not registered: a previously registered descriptor with the same fully-qualified name as Desc{fqName: "worker_pool_completed_tasks_total", help: "Total number of tasks completed.", constLabels: {}, variableLabels: [worker_id]} has different label names or a different help string - // taskCounterVec registered. - // Worker initialization failed: inconsistent label cardinality - // notMyCounter is nil. - // taskCounterForWorker42 registered. - // taskCounterForWorker2001 registered. -} - -func ExampleSummary() { - temps := prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "pond_temperature_celsius", - Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells. - }) - - // Simulate some observations. - for i := 0; i < 1000; i++ { - temps.Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10) - } - - // Just for demonstration, let's check the state of the summary by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - temps.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // summary: < - // sample_count: 1000 - // sample_sum: 29969.50000000001 - // quantile: < - // quantile: 0.5 - // value: 31.1 - // > - // quantile: < - // quantile: 0.9 - // value: 41.3 - // > - // quantile: < - // quantile: 0.99 - // value: 41.9 - // > - // > -} - -func ExampleSummaryVec() { - temps := prometheus.NewSummaryVec( - prometheus.SummaryOpts{ - Name: "pond_temperature_celsius", - Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells. - }, - []string{"species"}, - ) - - // Simulate some observations. - for i := 0; i < 1000; i++ { - temps.WithLabelValues("litoria-caerulea").Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10) - temps.WithLabelValues("lithobates-catesbeianus").Observe(32 + math.Floor(100*math.Cos(float64(i)*0.11))/10) - } - - // Create a Summary without any observations. - temps.WithLabelValues("leiopelma-hochstetteri") - - // Just for demonstration, let's check the state of the summary vector - // by (ab)using its Collect method and the Write method of its elements - // (which is usually only used by Prometheus internally - code like the - // following will never appear in your own code). - metricChan := make(chan prometheus.Metric) - go func() { - defer close(metricChan) - temps.Collect(metricChan) - }() - - metricStrings := []string{} - for metric := range metricChan { - dtoMetric := &dto.Metric{} - metric.Write(dtoMetric) - metricStrings = append(metricStrings, proto.MarshalTextString(dtoMetric)) - } - sort.Strings(metricStrings) // For reproducible print order. - fmt.Println(metricStrings) - - // Output: - // [label: < - // name: "species" - // value: "leiopelma-hochstetteri" - // > - // summary: < - // sample_count: 0 - // sample_sum: 0 - // quantile: < - // quantile: 0.5 - // value: nan - // > - // quantile: < - // quantile: 0.9 - // value: nan - // > - // quantile: < - // quantile: 0.99 - // value: nan - // > - // > - // label: < - // name: "species" - // value: "lithobates-catesbeianus" - // > - // summary: < - // sample_count: 1000 - // sample_sum: 31956.100000000017 - // quantile: < - // quantile: 0.5 - // value: 32.4 - // > - // quantile: < - // quantile: 0.9 - // value: 41.4 - // > - // quantile: < - // quantile: 0.99 - // value: 41.9 - // > - // > - // label: < - // name: "species" - // value: "litoria-caerulea" - // > - // summary: < - // sample_count: 1000 - // sample_sum: 29969.50000000001 - // quantile: < - // quantile: 0.5 - // value: 31.1 - // > - // quantile: < - // quantile: 0.9 - // value: 41.3 - // > - // quantile: < - // quantile: 0.99 - // value: 41.9 - // > - // > - // ] -} - -func ExampleConstSummary() { - desc := prometheus.NewDesc( - "http_request_duration_seconds", - "A summary of the HTTP request durations.", - []string{"code", "method"}, - prometheus.Labels{"owner": "example"}, - ) - - // Create a constant summary from values we got from a 3rd party telemetry system. - s := prometheus.MustNewConstSummary( - desc, - 4711, 403.34, - map[float64]float64{0.5: 42.3, 0.9: 323.3}, - "200", "get", - ) - - // Just for demonstration, let's check the state of the summary by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - s.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // label: < - // name: "code" - // value: "200" - // > - // label: < - // name: "method" - // value: "get" - // > - // label: < - // name: "owner" - // value: "example" - // > - // summary: < - // sample_count: 4711 - // sample_sum: 403.34 - // quantile: < - // quantile: 0.5 - // value: 42.3 - // > - // quantile: < - // quantile: 0.9 - // value: 323.3 - // > - // > -} - -func ExampleHistogram() { - temps := prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "pond_temperature_celsius", - Help: "The temperature of the frog pond.", // Sorry, we can't measure how badly it smells. - Buckets: prometheus.LinearBuckets(20, 5, 5), // 5 buckets, each 5 centigrade wide. - }) - - // Simulate some observations. - for i := 0; i < 1000; i++ { - temps.Observe(30 + math.Floor(120*math.Sin(float64(i)*0.1))/10) - } - - // Just for demonstration, let's check the state of the histogram by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - temps.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // histogram: < - // sample_count: 1000 - // sample_sum: 29969.50000000001 - // bucket: < - // cumulative_count: 192 - // upper_bound: 20 - // > - // bucket: < - // cumulative_count: 366 - // upper_bound: 25 - // > - // bucket: < - // cumulative_count: 501 - // upper_bound: 30 - // > - // bucket: < - // cumulative_count: 638 - // upper_bound: 35 - // > - // bucket: < - // cumulative_count: 816 - // upper_bound: 40 - // > - // > -} - -func ExampleConstHistogram() { - desc := prometheus.NewDesc( - "http_request_duration_seconds", - "A histogram of the HTTP request durations.", - []string{"code", "method"}, - prometheus.Labels{"owner": "example"}, - ) - - // Create a constant histogram from values we got from a 3rd party telemetry system. - h := prometheus.MustNewConstHistogram( - desc, - 4711, 403.34, - map[float64]uint64{25: 121, 50: 2403, 100: 3221, 200: 4233}, - "200", "get", - ) - - // Just for demonstration, let's check the state of the histogram by - // (ab)using its Write method (which is usually only used by Prometheus - // internally). - metric := &dto.Metric{} - h.Write(metric) - fmt.Println(proto.MarshalTextString(metric)) - - // Output: - // label: < - // name: "code" - // value: "200" - // > - // label: < - // name: "method" - // value: "get" - // > - // label: < - // name: "owner" - // value: "example" - // > - // histogram: < - // sample_count: 4711 - // sample_sum: 403.34 - // bucket: < - // cumulative_count: 121 - // upper_bound: 25 - // > - // bucket: < - // cumulative_count: 2403 - // upper_bound: 50 - // > - // bucket: < - // cumulative_count: 3221 - // upper_bound: 100 - // > - // bucket: < - // cumulative_count: 4233 - // upper_bound: 200 - // > - // > -} - -func ExamplePushCollectors() { - hostname, _ := os.Hostname() - completionTime := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "db_backup_last_completion_time", - Help: "The timestamp of the last succesful completion of a DB backup.", - }) - completionTime.Set(float64(time.Now().Unix())) - if err := prometheus.PushCollectors( - "db_backup", hostname, - "http://pushgateway:9091", - completionTime, - ); err != nil { - fmt.Println("Could not push completion time to Pushgateway:", err) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go deleted file mode 100644 index 5d3128fae..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus_test - -import ( - "expvar" - "fmt" - "sort" - "strings" - - dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus" -) - -func ExampleExpvarCollector() { - expvarCollector := prometheus.NewExpvarCollector(map[string]*prometheus.Desc{ - "memstats": prometheus.NewDesc( - "expvar_memstats", - "All numeric memstats as one metric family. Not a good role-model, actually... ;-)", - []string{"type"}, nil, - ), - "lone-int": prometheus.NewDesc( - "expvar_lone_int", - "Just an expvar int as an example.", - nil, nil, - ), - "http-request-map": prometheus.NewDesc( - "expvar_http_request_total", - "How many http requests processed, partitioned by status code and http method.", - []string{"code", "method"}, nil, - ), - }) - prometheus.MustRegister(expvarCollector) - - // The Prometheus part is done here. But to show that this example is - // doing anything, we have to manually export something via expvar. In - // real-life use-cases, some library would already have exported via - // expvar what we want to re-export as Prometheus metrics. - expvar.NewInt("lone-int").Set(42) - expvarMap := expvar.NewMap("http-request-map") - var ( - expvarMap1, expvarMap2 expvar.Map - expvarInt11, expvarInt12, expvarInt21, expvarInt22 expvar.Int - ) - expvarMap1.Init() - expvarMap2.Init() - expvarInt11.Set(3) - expvarInt12.Set(13) - expvarInt21.Set(11) - expvarInt22.Set(212) - expvarMap1.Set("POST", &expvarInt11) - expvarMap1.Set("GET", &expvarInt12) - expvarMap2.Set("POST", &expvarInt21) - expvarMap2.Set("GET", &expvarInt22) - expvarMap.Set("404", &expvarMap1) - expvarMap.Set("200", &expvarMap2) - // Results in the following expvar map: - // "http-request-count": {"200": {"POST": 11, "GET": 212}, "404": {"POST": 3, "GET": 13}} - - // Let's see what the scrape would yield, but exclude the memstats metrics. - metricStrings := []string{} - metric := dto.Metric{} - metricChan := make(chan prometheus.Metric) - go func() { - expvarCollector.Collect(metricChan) - close(metricChan) - }() - for m := range metricChan { - if strings.Index(m.Desc().String(), "expvar_memstats") == -1 { - metric.Reset() - m.Write(&metric) - metricStrings = append(metricStrings, metric.String()) - } - } - sort.Strings(metricStrings) - for _, s := range metricStrings { - fmt.Println(strings.TrimRight(s, " ")) - } - // Output: - // label: label: untyped: - // label: label: untyped: - // label: label: untyped: - // label: label: untyped: - // untyped: -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/gauge_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/gauge_test.go deleted file mode 100644 index 48cab4636..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/gauge_test.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus - -import ( - "math" - "math/rand" - "sync" - "testing" - "testing/quick" - - dto "github.com/prometheus/client_model/go" -) - -func listenGaugeStream(vals, result chan float64, done chan struct{}) { - var sum float64 -outer: - for { - select { - case <-done: - close(vals) - for v := range vals { - sum += v - } - break outer - case v := <-vals: - sum += v - } - } - result <- sum - close(result) -} - -func TestGaugeConcurrency(t *testing.T) { - it := func(n uint32) bool { - mutations := int(n % 10000) - concLevel := int(n%15 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sStream := make(chan float64, mutations*concLevel) - result := make(chan float64) - done := make(chan struct{}) - - go listenGaugeStream(sStream, result, done) - go func() { - end.Wait() - close(done) - }() - - gge := NewGauge(GaugeOpts{ - Name: "test_gauge", - Help: "no help can be found here", - }) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - for j := 0; j < mutations; j++ { - vals[j] = rand.Float64() - 0.5 - } - - go func(vals []float64) { - start.Wait() - for _, v := range vals { - sStream <- v - gge.Add(v) - } - end.Done() - }(vals) - } - start.Done() - - if expected, got := <-result, math.Float64frombits(gge.(*value).valBits); math.Abs(expected-got) > 0.000001 { - t.Fatalf("expected approx. %f, got %f", expected, got) - return false - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Fatal(err) - } -} - -func TestGaugeVecConcurrency(t *testing.T) { - it := func(n uint32) bool { - mutations := int(n % 10000) - concLevel := int(n%15 + 1) - vecLength := int(n%5 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sStreams := make([]chan float64, vecLength) - results := make([]chan float64, vecLength) - done := make(chan struct{}) - - for i := 0; i < vecLength; i++ { - sStreams[i] = make(chan float64, mutations*concLevel) - results[i] = make(chan float64) - go listenGaugeStream(sStreams[i], results[i], done) - } - - go func() { - end.Wait() - close(done) - }() - - gge := NewGaugeVec( - GaugeOpts{ - Name: "test_gauge", - Help: "no help can be found here", - }, - []string{"label"}, - ) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - pick := make([]int, mutations) - for j := 0; j < mutations; j++ { - vals[j] = rand.Float64() - 0.5 - pick[j] = rand.Intn(vecLength) - } - - go func(vals []float64) { - start.Wait() - for i, v := range vals { - sStreams[pick[i]] <- v - gge.WithLabelValues(string('A' + pick[i])).Add(v) - } - end.Done() - }(vals) - } - start.Done() - - for i := range sStreams { - if expected, got := <-results[i], math.Float64frombits(gge.WithLabelValues(string('A'+i)).(*value).valBits); math.Abs(expected-got) > 0.000001 { - t.Fatalf("expected approx. %f, got %f", expected, got) - return false - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Fatal(err) - } -} - -func TestGaugeFunc(t *testing.T) { - gf := NewGaugeFunc( - GaugeOpts{ - Name: "test_name", - Help: "test help", - ConstLabels: Labels{"a": "1", "b": "2"}, - }, - func() float64 { return 3.1415 }, - ) - - if expected, got := `Desc{fqName: "test_name", help: "test help", constLabels: {a="1",b="2"}, variableLabels: []}`, gf.Desc().String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } - - m := &dto.Metric{} - gf.Write(m) - - if expected, got := `label: label: gauge: `, m.String(); expected != got { - t.Errorf("expected %q, got %q", expected, got) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector_test.go deleted file mode 100644 index 9a8858cbd..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/go_collector_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package prometheus - -import ( - "runtime" - "testing" - "time" - - dto "github.com/prometheus/client_model/go" -) - -func TestGoCollector(t *testing.T) { - var ( - c = NewGoCollector() - ch = make(chan Metric) - waitc = make(chan struct{}) - closec = make(chan struct{}) - old = -1 - ) - defer close(closec) - - go func() { - c.Collect(ch) - go func(c <-chan struct{}) { - <-c - }(closec) - <-waitc - c.Collect(ch) - }() - - for { - select { - case metric := <-ch: - switch m := metric.(type) { - // Attention, this also catches Counter... - case Gauge: - pb := &dto.Metric{} - m.Write(pb) - if pb.GetGauge() == nil { - continue - } - - if old == -1 { - old = int(pb.GetGauge().GetValue()) - close(waitc) - continue - } - - if diff := int(pb.GetGauge().GetValue()) - old; diff != 1 { - // TODO: This is flaky in highly concurrent situations. - t.Errorf("want 1 new goroutine, got %d", diff) - } - - // GoCollector performs two sends per call. - // On line 27 we need to receive the second send - // to shut down cleanly. - <-ch - return - } - case <-time.After(1 * time.Second): - t.Fatalf("expected collect timed out") - } - } -} - -func TestGCCollector(t *testing.T) { - var ( - c = NewGoCollector() - ch = make(chan Metric) - waitc = make(chan struct{}) - closec = make(chan struct{}) - oldGC uint64 - oldPause float64 - ) - defer close(closec) - - go func() { - c.Collect(ch) - // force GC - runtime.GC() - <-waitc - c.Collect(ch) - }() - - first := true - for { - select { - case metric := <-ch: - switch m := metric.(type) { - case *constSummary, *value: - pb := &dto.Metric{} - m.Write(pb) - if pb.GetSummary() == nil { - continue - } - - if len(pb.GetSummary().Quantile) != 5 { - t.Errorf("expected 4 buckets, got %d", len(pb.GetSummary().Quantile)) - } - for idx, want := range []float64{0.0, 0.25, 0.5, 0.75, 1.0} { - if *pb.GetSummary().Quantile[idx].Quantile != want { - t.Errorf("bucket #%d is off, got %f, want %f", idx, *pb.GetSummary().Quantile[idx].Quantile, want) - } - } - if first { - first = false - oldGC = *pb.GetSummary().SampleCount - oldPause = *pb.GetSummary().SampleSum - close(waitc) - continue - } - if diff := *pb.GetSummary().SampleCount - oldGC; diff != 1 { - t.Errorf("want 1 new garbage collection run, got %d", diff) - } - if diff := *pb.GetSummary().SampleSum - oldPause; diff <= 0 { - t.Errorf("want moar pause, got %f", diff) - } - return - } - case <-time.After(1 * time.Second): - t.Fatalf("expected collect timed out") - } - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram_test.go deleted file mode 100644 index 11cf66b4f..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram_test.go +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2015 The Prometheus 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 prometheus - -import ( - "math" - "math/rand" - "reflect" - "sort" - "sync" - "testing" - "testing/quick" - - dto "github.com/prometheus/client_model/go" -) - -func benchmarkHistogramObserve(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewHistogram(HistogramOpts{}) - - for i := 0; i < w; i++ { - go func() { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Observe(float64(i)) - } - - wg.Done() - }() - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkHistogramObserve1(b *testing.B) { - benchmarkHistogramObserve(1, b) -} - -func BenchmarkHistogramObserve2(b *testing.B) { - benchmarkHistogramObserve(2, b) -} - -func BenchmarkHistogramObserve4(b *testing.B) { - benchmarkHistogramObserve(4, b) -} - -func BenchmarkHistogramObserve8(b *testing.B) { - benchmarkHistogramObserve(8, b) -} - -func benchmarkHistogramWrite(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewHistogram(HistogramOpts{}) - - for i := 0; i < 1000000; i++ { - s.Observe(float64(i)) - } - - for j := 0; j < w; j++ { - outs := make([]dto.Metric, b.N) - - go func(o []dto.Metric) { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Write(&o[i]) - } - - wg.Done() - }(outs) - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkHistogramWrite1(b *testing.B) { - benchmarkHistogramWrite(1, b) -} - -func BenchmarkHistogramWrite2(b *testing.B) { - benchmarkHistogramWrite(2, b) -} - -func BenchmarkHistogramWrite4(b *testing.B) { - benchmarkHistogramWrite(4, b) -} - -func BenchmarkHistogramWrite8(b *testing.B) { - benchmarkHistogramWrite(8, b) -} - -// Intentionally adding +Inf here to test if that case is handled correctly. -// Also, getCumulativeCounts depends on it. -var testBuckets = []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)} - -func TestHistogramConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%5 + 1) - total := mutations * concLevel - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sum := NewHistogram(HistogramOpts{ - Name: "test_histogram", - Help: "helpless", - Buckets: testBuckets, - }) - - allVars := make([]float64, total) - var sampleSum float64 - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - allVars[i*mutations+j] = v - sampleSum += v - } - - go func(vals []float64) { - start.Wait() - for _, v := range vals { - sum.Observe(v) - } - end.Done() - }(vals) - } - sort.Float64s(allVars) - start.Done() - end.Wait() - - m := &dto.Metric{} - sum.Write(m) - if got, want := int(*m.Histogram.SampleCount), total; got != want { - t.Errorf("got sample count %d, want %d", got, want) - } - if got, want := *m.Histogram.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f, want %f", got, want) - } - - wantCounts := getCumulativeCounts(allVars) - - if got, want := len(m.Histogram.Bucket), len(testBuckets)-1; got != want { - t.Errorf("got %d buckets in protobuf, want %d", got, want) - } - for i, wantBound := range testBuckets { - if i == len(testBuckets)-1 { - break // No +Inf bucket in protobuf. - } - if gotBound := *m.Histogram.Bucket[i].UpperBound; gotBound != wantBound { - t.Errorf("got bound %f, want %f", gotBound, wantBound) - } - if gotCount, wantCount := *m.Histogram.Bucket[i].CumulativeCount, wantCounts[i]; gotCount != wantCount { - t.Errorf("got count %d, want %d", gotCount, wantCount) - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func TestHistogramVecConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - objectives := make([]float64, 0, len(DefObjectives)) - for qu := range DefObjectives { - - objectives = append(objectives, qu) - } - sort.Float64s(objectives) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%7 + 1) - vecLength := int(n%3 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - his := NewHistogramVec( - HistogramOpts{ - Name: "test_histogram", - Help: "helpless", - Buckets: []float64{-2, -1, -0.5, 0, 0.5, 1, 2, math.Inf(+1)}, - }, - []string{"label"}, - ) - - allVars := make([][]float64, vecLength) - sampleSums := make([]float64, vecLength) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - picks := make([]int, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - pick := rand.Intn(vecLength) - picks[j] = pick - allVars[pick] = append(allVars[pick], v) - sampleSums[pick] += v - } - - go func(vals []float64) { - start.Wait() - for i, v := range vals { - his.WithLabelValues(string('A' + picks[i])).Observe(v) - } - end.Done() - }(vals) - } - for _, vars := range allVars { - sort.Float64s(vars) - } - start.Done() - end.Wait() - - for i := 0; i < vecLength; i++ { - m := &dto.Metric{} - s := his.WithLabelValues(string('A' + i)) - s.Write(m) - - if got, want := len(m.Histogram.Bucket), len(testBuckets)-1; got != want { - t.Errorf("got %d buckets in protobuf, want %d", got, want) - } - if got, want := int(*m.Histogram.SampleCount), len(allVars[i]); got != want { - t.Errorf("got sample count %d, want %d", got, want) - } - if got, want := *m.Histogram.SampleSum, sampleSums[i]; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f, want %f", got, want) - } - - wantCounts := getCumulativeCounts(allVars[i]) - - for j, wantBound := range testBuckets { - if j == len(testBuckets)-1 { - break // No +Inf bucket in protobuf. - } - if gotBound := *m.Histogram.Bucket[j].UpperBound; gotBound != wantBound { - t.Errorf("got bound %f, want %f", gotBound, wantBound) - } - if gotCount, wantCount := *m.Histogram.Bucket[j].CumulativeCount, wantCounts[j]; gotCount != wantCount { - t.Errorf("got count %d, want %d", gotCount, wantCount) - } - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func getCumulativeCounts(vars []float64) []uint64 { - counts := make([]uint64, len(testBuckets)) - for _, v := range vars { - for i := len(testBuckets) - 1; i >= 0; i-- { - if v > testBuckets[i] { - break - } - counts[i]++ - } - } - return counts -} - -func TestBuckets(t *testing.T) { - got := LinearBuckets(-15, 5, 6) - want := []float64{-15, -10, -5, 0, 5, 10} - if !reflect.DeepEqual(got, want) { - t.Errorf("linear buckets: got %v, want %v", got, want) - } - - got = ExponentialBuckets(100, 1.2, 3) - want = []float64{100, 120, 144} - if !reflect.DeepEqual(got, want) { - t.Errorf("linear buckets: got %v, want %v", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/http_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/http_test.go deleted file mode 100644 index ffe0418cf..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/http_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - dto "github.com/prometheus/client_model/go" -) - -type respBody string - -func (b respBody) ServeHTTP(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusTeapot) - w.Write([]byte(b)) -} - -func TestInstrumentHandler(t *testing.T) { - defer func(n nower) { - now = n.(nower) - }(now) - - instant := time.Now() - end := instant.Add(30 * time.Second) - now = nowSeries(instant, end) - respBody := respBody("Howdy there!") - - hndlr := InstrumentHandler("test-handler", respBody) - - opts := SummaryOpts{ - Subsystem: "http", - ConstLabels: Labels{"handler": "test-handler"}, - } - - reqCnt := MustRegisterOrGet(NewCounterVec( - CounterOpts{ - Namespace: opts.Namespace, - Subsystem: opts.Subsystem, - Name: "requests_total", - Help: "Total number of HTTP requests made.", - ConstLabels: opts.ConstLabels, - }, - instLabels, - )).(*CounterVec) - - opts.Name = "request_duration_microseconds" - opts.Help = "The HTTP request latencies in microseconds." - reqDur := MustRegisterOrGet(NewSummary(opts)).(Summary) - - opts.Name = "request_size_bytes" - opts.Help = "The HTTP request sizes in bytes." - MustRegisterOrGet(NewSummary(opts)) - - opts.Name = "response_size_bytes" - opts.Help = "The HTTP response sizes in bytes." - MustRegisterOrGet(NewSummary(opts)) - - reqCnt.Reset() - - resp := httptest.NewRecorder() - req := &http.Request{ - Method: "GET", - } - - hndlr.ServeHTTP(resp, req) - - if resp.Code != http.StatusTeapot { - t.Fatalf("expected status %d, got %d", http.StatusTeapot, resp.Code) - } - if string(resp.Body.Bytes()) != "Howdy there!" { - t.Fatalf("expected body %s, got %s", "Howdy there!", string(resp.Body.Bytes())) - } - - out := &dto.Metric{} - reqDur.Write(out) - if want, got := "test-handler", out.Label[0].GetValue(); want != got { - t.Errorf("want label value %q in reqDur, got %q", want, got) - } - if want, got := uint64(1), out.Summary.GetSampleCount(); want != got { - t.Errorf("want sample count %d in reqDur, got %d", want, got) - } - - out.Reset() - if want, got := 1, len(reqCnt.children); want != got { - t.Errorf("want %d children in reqCnt, got %d", want, got) - } - cnt, err := reqCnt.GetMetricWithLabelValues("get", "418") - if err != nil { - t.Fatal(err) - } - cnt.Write(out) - if want, got := "418", out.Label[0].GetValue(); want != got { - t.Errorf("want label value %q in reqCnt, got %q", want, got) - } - if want, got := "test-handler", out.Label[1].GetValue(); want != got { - t.Errorf("want label value %q in reqCnt, got %q", want, got) - } - if want, got := "get", out.Label[2].GetValue(); want != got { - t.Errorf("want label value %q in reqCnt, got %q", want, got) - } - if out.Counter == nil { - t.Fatal("expected non-nil counter in reqCnt") - } - if want, got := 1., out.Counter.GetValue(); want != got { - t.Errorf("want reqCnt of %f, got %f", want, got) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/metric_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/metric_test.go deleted file mode 100644 index 7145f5e53..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/metric_test.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus - -import "testing" - -func TestBuildFQName(t *testing.T) { - scenarios := []struct{ namespace, subsystem, name, result string }{ - {"a", "b", "c", "a_b_c"}, - {"", "b", "c", "b_c"}, - {"a", "", "c", "a_c"}, - {"", "", "c", "c"}, - {"a", "b", "", ""}, - {"a", "", "", ""}, - {"", "b", "", ""}, - {" ", "", "", ""}, - } - - for i, s := range scenarios { - if want, got := s.result, BuildFQName(s.namespace, s.subsystem, s.name); want != got { - t.Errorf("%d. want %s, got %s", i, want, got) - } - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/process_collector_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/process_collector_test.go deleted file mode 100644 index 829715acd..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/process_collector_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package prometheus - -import ( - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "regexp" - "testing" - - "github.com/prometheus/procfs" -) - -func TestProcessCollector(t *testing.T) { - if _, err := procfs.Self(); err != nil { - t.Skipf("skipping TestProcessCollector, procfs not available: %s", err) - } - - registry := newRegistry() - registry.Register(NewProcessCollector(os.Getpid(), "")) - registry.Register(NewProcessCollectorPIDFn( - func() (int, error) { return os.Getpid(), nil }, "foobar")) - - s := httptest.NewServer(InstrumentHandler("prometheus", registry)) - defer s.Close() - r, err := http.Get(s.URL) - if err != nil { - t.Fatal(err) - } - defer r.Body.Close() - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Fatal(err) - } - - for _, re := range []*regexp.Regexp{ - regexp.MustCompile("process_cpu_seconds_total [0-9]"), - regexp.MustCompile("process_max_fds [0-9]{2,}"), - regexp.MustCompile("process_open_fds [1-9]"), - regexp.MustCompile("process_virtual_memory_bytes [1-9]"), - regexp.MustCompile("process_resident_memory_bytes [1-9]"), - regexp.MustCompile("process_start_time_seconds [0-9.]{10,}"), - regexp.MustCompile("foobar_process_cpu_seconds_total [0-9]"), - regexp.MustCompile("foobar_process_max_fds [0-9]{2,}"), - regexp.MustCompile("foobar_process_open_fds [1-9]"), - regexp.MustCompile("foobar_process_virtual_memory_bytes [1-9]"), - regexp.MustCompile("foobar_process_resident_memory_bytes [1-9]"), - regexp.MustCompile("foobar_process_start_time_seconds [0-9.]{10,}"), - } { - if !re.Match(body) { - t.Errorf("want body to match %s\n%s", re, body) - } - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry_test.go deleted file mode 100644 index f30c90c06..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry_test.go +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright 2014 The Prometheus 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. - -// Copyright (c) 2013, The Prometheus Authors -// All rights reserved. -// -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -package prometheus - -import ( - "bytes" - "encoding/binary" - "net/http" - "testing" - - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" -) - -type fakeResponseWriter struct { - header http.Header - body bytes.Buffer -} - -func (r *fakeResponseWriter) Header() http.Header { - return r.header -} - -func (r *fakeResponseWriter) Write(d []byte) (l int, err error) { - return r.body.Write(d) -} - -func (r *fakeResponseWriter) WriteHeader(c int) { -} - -func testHandler(t testing.TB) { - - metricVec := NewCounterVec( - CounterOpts{ - Name: "name", - Help: "docstring", - ConstLabels: Labels{"constname": "constvalue"}, - }, - []string{"labelname"}, - ) - - metricVec.WithLabelValues("val1").Inc() - metricVec.WithLabelValues("val2").Inc() - - varintBuf := make([]byte, binary.MaxVarintLen32) - - externalMetricFamily := &dto.MetricFamily{ - Name: proto.String("externalname"), - Help: proto.String("externaldocstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("externalconstname"), - Value: proto.String("externalconstvalue"), - }, - { - Name: proto.String("externallabelname"), - Value: proto.String("externalval1"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - }, - } - marshaledExternalMetricFamily, err := proto.Marshal(externalMetricFamily) - if err != nil { - t.Fatal(err) - } - var externalBuf bytes.Buffer - l := binary.PutUvarint(varintBuf, uint64(len(marshaledExternalMetricFamily))) - _, err = externalBuf.Write(varintBuf[:l]) - if err != nil { - t.Fatal(err) - } - _, err = externalBuf.Write(marshaledExternalMetricFamily) - if err != nil { - t.Fatal(err) - } - externalMetricFamilyAsBytes := externalBuf.Bytes() - externalMetricFamilyAsText := []byte(`# HELP externalname externaldocstring -# TYPE externalname counter -externalname{externalconstname="externalconstvalue",externallabelname="externalval1"} 1 -`) - externalMetricFamilyAsProtoText := []byte(`name: "externalname" -help: "externaldocstring" -type: COUNTER -metric: < - label: < - name: "externalconstname" - value: "externalconstvalue" - > - label: < - name: "externallabelname" - value: "externalval1" - > - counter: < - value: 1 - > -> - -`) - externalMetricFamilyAsProtoCompactText := []byte(`name:"externalname" help:"externaldocstring" type:COUNTER metric: label: counter: > -`) - - expectedMetricFamily := &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("docstring"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("constname"), - Value: proto.String("constvalue"), - }, - { - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - { - Label: []*dto.LabelPair{ - { - Name: proto.String("constname"), - Value: proto.String("constvalue"), - }, - { - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(1), - }, - }, - }, - } - marshaledExpectedMetricFamily, err := proto.Marshal(expectedMetricFamily) - if err != nil { - t.Fatal(err) - } - var buf bytes.Buffer - l = binary.PutUvarint(varintBuf, uint64(len(marshaledExpectedMetricFamily))) - _, err = buf.Write(varintBuf[:l]) - if err != nil { - t.Fatal(err) - } - _, err = buf.Write(marshaledExpectedMetricFamily) - if err != nil { - t.Fatal(err) - } - expectedMetricFamilyAsBytes := buf.Bytes() - expectedMetricFamilyAsText := []byte(`# HELP name docstring -# TYPE name counter -name{constname="constvalue",labelname="val1"} 1 -name{constname="constvalue",labelname="val2"} 1 -`) - expectedMetricFamilyAsProtoText := []byte(`name: "name" -help: "docstring" -type: COUNTER -metric: < - label: < - name: "constname" - value: "constvalue" - > - label: < - name: "labelname" - value: "val1" - > - counter: < - value: 1 - > -> -metric: < - label: < - name: "constname" - value: "constvalue" - > - label: < - name: "labelname" - value: "val2" - > - counter: < - value: 1 - > -> - -`) - expectedMetricFamilyAsProtoCompactText := []byte(`name:"name" help:"docstring" type:COUNTER metric: label: counter: > metric: label: counter: > -`) - - externalMetricFamilyWithSameName := &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("inconsistent help string does not matter here"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("constname"), - Value: proto.String("constvalue"), - }, - { - Name: proto.String("labelname"), - Value: proto.String("different_val"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(42), - }, - }, - }, - } - - expectedMetricFamilyMergedWithExternalAsProtoCompactText := []byte(`name:"name" help:"docstring" type:COUNTER metric: label: counter: > metric: label: counter: > metric: label: counter: > -`) - - type output struct { - headers map[string]string - body []byte - } - - var scenarios = []struct { - headers map[string]string - out output - collector Collector - externalMF []*dto.MetricFamily - }{ - { // 0 - headers: map[string]string{ - "Accept": "foo/bar;q=0.2, dings/bums;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: []byte{}, - }, - }, - { // 1 - headers: map[string]string{ - "Accept": "foo/bar;q=0.2, application/quark;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: []byte{}, - }, - }, - { // 2 - headers: map[string]string{ - "Accept": "foo/bar;q=0.2, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: []byte{}, - }, - }, - { // 3 - headers: map[string]string{ - "Accept": "text/plain;q=0.2, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.8", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: []byte{}, - }, - }, - { // 4 - headers: map[string]string{ - "Accept": "application/json", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: expectedMetricFamilyAsText, - }, - collector: metricVec, - }, - { // 5 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: expectedMetricFamilyAsBytes, - }, - collector: metricVec, - }, - { // 6 - headers: map[string]string{ - "Accept": "application/json", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: externalMetricFamilyAsText, - }, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 7 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: externalMetricFamilyAsBytes, - }, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 8 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsBytes, - expectedMetricFamilyAsBytes, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 9 - headers: map[string]string{ - "Accept": "text/plain", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: []byte{}, - }, - }, - { // 10 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.2, text/plain;q=0.5", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: expectedMetricFamilyAsText, - }, - collector: metricVec, - }, - { // 11 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=bla;q=0.2, text/plain;q=0.5;version=0.0.4", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `text/plain; version=0.0.4`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsText, - expectedMetricFamilyAsText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 12 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.2, text/plain;q=0.5;version=0.0.2", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsBytes, - expectedMetricFamilyAsBytes, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 13 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=text;q=0.5, application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.4", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=text`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsProtoText, - expectedMetricFamilyAsProtoText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 14 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsProtoCompactText, - expectedMetricFamilyAsProtoCompactText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{externalMetricFamily}, - }, - { // 15 - headers: map[string]string{ - "Accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=compact-text", - }, - out: output{ - headers: map[string]string{ - "Content-Type": `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`, - }, - body: bytes.Join( - [][]byte{ - externalMetricFamilyAsProtoCompactText, - expectedMetricFamilyMergedWithExternalAsProtoCompactText, - }, - []byte{}, - ), - }, - collector: metricVec, - externalMF: []*dto.MetricFamily{ - externalMetricFamily, - externalMetricFamilyWithSameName, - }, - }, - } - for i, scenario := range scenarios { - registry := newRegistry() - registry.collectChecksEnabled = true - - if scenario.collector != nil { - registry.Register(scenario.collector) - } - if scenario.externalMF != nil { - registry.metricFamilyInjectionHook = func() []*dto.MetricFamily { - return scenario.externalMF - } - } - writer := &fakeResponseWriter{ - header: http.Header{}, - } - handler := InstrumentHandler("prometheus", registry) - request, _ := http.NewRequest("GET", "/", nil) - for key, value := range scenario.headers { - request.Header.Add(key, value) - } - handler(writer, request) - - for key, value := range scenario.out.headers { - if writer.Header().Get(key) != value { - t.Errorf( - "%d. expected %q for header %q, got %q", - i, value, key, writer.Header().Get(key), - ) - } - } - - if !bytes.Equal(scenario.out.body, writer.body.Bytes()) { - t.Errorf( - "%d. expected %q for body, got %q", - i, scenario.out.body, writer.body.Bytes(), - ) - } - } -} - -func TestHandler(t *testing.T) { - testHandler(t) -} - -func BenchmarkHandler(b *testing.B) { - for i := 0; i < b.N; i++ { - testHandler(b) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary_test.go deleted file mode 100644 index 0790cdfe7..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary_test.go +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus - -import ( - "math" - "math/rand" - "sort" - "sync" - "testing" - "testing/quick" - "time" - - dto "github.com/prometheus/client_model/go" -) - -func benchmarkSummaryObserve(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewSummary(SummaryOpts{}) - - for i := 0; i < w; i++ { - go func() { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Observe(float64(i)) - } - - wg.Done() - }() - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkSummaryObserve1(b *testing.B) { - benchmarkSummaryObserve(1, b) -} - -func BenchmarkSummaryObserve2(b *testing.B) { - benchmarkSummaryObserve(2, b) -} - -func BenchmarkSummaryObserve4(b *testing.B) { - benchmarkSummaryObserve(4, b) -} - -func BenchmarkSummaryObserve8(b *testing.B) { - benchmarkSummaryObserve(8, b) -} - -func benchmarkSummaryWrite(w int, b *testing.B) { - b.StopTimer() - - wg := new(sync.WaitGroup) - wg.Add(w) - - g := new(sync.WaitGroup) - g.Add(1) - - s := NewSummary(SummaryOpts{}) - - for i := 0; i < 1000000; i++ { - s.Observe(float64(i)) - } - - for j := 0; j < w; j++ { - outs := make([]dto.Metric, b.N) - - go func(o []dto.Metric) { - g.Wait() - - for i := 0; i < b.N; i++ { - s.Write(&o[i]) - } - - wg.Done() - }(outs) - } - - b.StartTimer() - g.Done() - wg.Wait() -} - -func BenchmarkSummaryWrite1(b *testing.B) { - benchmarkSummaryWrite(1, b) -} - -func BenchmarkSummaryWrite2(b *testing.B) { - benchmarkSummaryWrite(2, b) -} - -func BenchmarkSummaryWrite4(b *testing.B) { - benchmarkSummaryWrite(4, b) -} - -func BenchmarkSummaryWrite8(b *testing.B) { - benchmarkSummaryWrite(8, b) -} - -func TestSummaryConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%5 + 1) - total := mutations * concLevel - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sum := NewSummary(SummaryOpts{ - Name: "test_summary", - Help: "helpless", - }) - - allVars := make([]float64, total) - var sampleSum float64 - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - allVars[i*mutations+j] = v - sampleSum += v - } - - go func(vals []float64) { - start.Wait() - for _, v := range vals { - sum.Observe(v) - } - end.Done() - }(vals) - } - sort.Float64s(allVars) - start.Done() - end.Wait() - - m := &dto.Metric{} - sum.Write(m) - if got, want := int(*m.Summary.SampleCount), total; got != want { - t.Errorf("got sample count %d, want %d", got, want) - } - if got, want := *m.Summary.SampleSum, sampleSum; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f, want %f", got, want) - } - - objectives := make([]float64, 0, len(DefObjectives)) - for qu := range DefObjectives { - objectives = append(objectives, qu) - } - sort.Float64s(objectives) - - for i, wantQ := range objectives { - ε := DefObjectives[wantQ] - gotQ := *m.Summary.Quantile[i].Quantile - gotV := *m.Summary.Quantile[i].Value - min, max := getBounds(allVars, wantQ, ε) - if gotQ != wantQ { - t.Errorf("got quantile %f, want %f", gotQ, wantQ) - } - if gotV < min || gotV > max { - t.Errorf("got %f for quantile %f, want [%f,%f]", gotV, gotQ, min, max) - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func TestSummaryVecConcurrency(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - } - - rand.Seed(42) - - objectives := make([]float64, 0, len(DefObjectives)) - for qu := range DefObjectives { - - objectives = append(objectives, qu) - } - sort.Float64s(objectives) - - it := func(n uint32) bool { - mutations := int(n%1e4 + 1e4) - concLevel := int(n%7 + 1) - vecLength := int(n%3 + 1) - - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - sum := NewSummaryVec( - SummaryOpts{ - Name: "test_summary", - Help: "helpless", - }, - []string{"label"}, - ) - - allVars := make([][]float64, vecLength) - sampleSums := make([]float64, vecLength) - for i := 0; i < concLevel; i++ { - vals := make([]float64, mutations) - picks := make([]int, mutations) - for j := 0; j < mutations; j++ { - v := rand.NormFloat64() - vals[j] = v - pick := rand.Intn(vecLength) - picks[j] = pick - allVars[pick] = append(allVars[pick], v) - sampleSums[pick] += v - } - - go func(vals []float64) { - start.Wait() - for i, v := range vals { - sum.WithLabelValues(string('A' + picks[i])).Observe(v) - } - end.Done() - }(vals) - } - for _, vars := range allVars { - sort.Float64s(vars) - } - start.Done() - end.Wait() - - for i := 0; i < vecLength; i++ { - m := &dto.Metric{} - s := sum.WithLabelValues(string('A' + i)) - s.Write(m) - if got, want := int(*m.Summary.SampleCount), len(allVars[i]); got != want { - t.Errorf("got sample count %d for label %c, want %d", got, 'A'+i, want) - } - if got, want := *m.Summary.SampleSum, sampleSums[i]; math.Abs((got-want)/want) > 0.001 { - t.Errorf("got sample sum %f for label %c, want %f", got, 'A'+i, want) - } - for j, wantQ := range objectives { - ε := DefObjectives[wantQ] - gotQ := *m.Summary.Quantile[j].Quantile - gotV := *m.Summary.Quantile[j].Value - min, max := getBounds(allVars[i], wantQ, ε) - if gotQ != wantQ { - t.Errorf("got quantile %f for label %c, want %f", gotQ, 'A'+i, wantQ) - } - if gotV < min || gotV > max { - t.Errorf("got %f for quantile %f for label %c, want [%f,%f]", gotV, gotQ, 'A'+i, min, max) - } - } - } - return true - } - - if err := quick.Check(it, nil); err != nil { - t.Error(err) - } -} - -func TestSummaryDecay(t *testing.T) { - if testing.Short() { - t.Skip("Skipping test in short mode.") - // More because it depends on timing than because it is particularly long... - } - - sum := NewSummary(SummaryOpts{ - Name: "test_summary", - Help: "helpless", - MaxAge: 100 * time.Millisecond, - Objectives: map[float64]float64{0.1: 0.001}, - AgeBuckets: 10, - }) - - m := &dto.Metric{} - i := 0 - tick := time.NewTicker(time.Millisecond) - for _ = range tick.C { - i++ - sum.Observe(float64(i)) - if i%10 == 0 { - sum.Write(m) - if got, want := *m.Summary.Quantile[0].Value, math.Max(float64(i)/10, float64(i-90)); math.Abs(got-want) > 20 { - t.Errorf("%d. got %f, want %f", i, got, want) - } - m.Reset() - } - if i >= 1000 { - break - } - } - tick.Stop() - // Wait for MaxAge without observations and make sure quantiles are NaN. - time.Sleep(100 * time.Millisecond) - sum.Write(m) - if got := *m.Summary.Quantile[0].Value; !math.IsNaN(got) { - t.Errorf("got %f, want NaN after expiration", got) - } -} - -func getBounds(vars []float64, q, ε float64) (min, max float64) { - // TODO: This currently tolerates an error of up to 2*ε. The error must - // be at most ε, but for some reason, it's sometimes slightly - // higher. That's a bug. - n := float64(len(vars)) - lower := int((q - 2*ε) * n) - upper := int(math.Ceil((q + 2*ε) * n)) - min = vars[0] - if lower > 1 { - min = vars[lower-1] - } - max = vars[len(vars)-1] - if upper < len(vars) { - max = vars[upper-1] - } - return -} diff --git a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/vec_test.go b/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/vec_test.go deleted file mode 100644 index 0e9431e65..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/vec_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2014 The Prometheus 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 prometheus - -import ( - "hash/fnv" - "testing" -) - -func TestDelete(t *testing.T) { - desc := NewDesc("test", "helpless", []string{"l1", "l2"}, nil) - vec := MetricVec{ - children: map[uint64]Metric{}, - desc: desc, - hash: fnv.New64a(), - newMetric: func(lvs ...string) Metric { - return newValue(desc, UntypedValue, 0, lvs...) - }, - } - - if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42) - if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), true; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.Delete(Labels{"l1": "v1", "l2": "v2"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42) - if got, want := vec.Delete(Labels{"l2": "v2", "l1": "v1"}), true; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.Delete(Labels{"l2": "v2", "l1": "v1"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42) - if got, want := vec.Delete(Labels{"l2": "v1", "l1": "v2"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.Delete(Labels{"l1": "v1"}), false; got != want { - t.Errorf("got %v, want %v", got, want) - } -} - -func TestDeleteLabelValues(t *testing.T) { - desc := NewDesc("test", "helpless", []string{"l1", "l2"}, nil) - vec := MetricVec{ - children: map[uint64]Metric{}, - desc: desc, - hash: fnv.New64a(), - newMetric: func(lvs ...string) Metric { - return newValue(desc, UntypedValue, 0, lvs...) - }, - } - - if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42) - if got, want := vec.DeleteLabelValues("v1", "v2"), true; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.DeleteLabelValues("v1", "v2"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - - vec.With(Labels{"l1": "v1", "l2": "v2"}).(Untyped).Set(42) - if got, want := vec.DeleteLabelValues("v2", "v1"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } - if got, want := vec.DeleteLabelValues("v1"), false; got != want { - t.Errorf("got %v, want %v", got, want) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/bench_test.go b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/bench_test.go deleted file mode 100644 index 92b16a028..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/bench_test.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2015 The Prometheus 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 expfmt - -import ( - "bytes" - "compress/gzip" - "io" - "io/ioutil" - "testing" - - "github.com/matttproud/golang_protobuf_extensions/pbutil" - - dto "github.com/prometheus/client_model/go" -) - -var parser TextParser - -// Benchmarks to show how much penalty text format parsing actually inflicts. -// -// Example results on Linux 3.13.0, Intel(R) Core(TM) i7-4700MQ CPU @ 2.40GHz, go1.4. -// -// BenchmarkParseText 1000 1188535 ns/op 205085 B/op 6135 allocs/op -// BenchmarkParseTextGzip 1000 1376567 ns/op 246224 B/op 6151 allocs/op -// BenchmarkParseProto 10000 172790 ns/op 52258 B/op 1160 allocs/op -// BenchmarkParseProtoGzip 5000 324021 ns/op 94931 B/op 1211 allocs/op -// BenchmarkParseProtoMap 10000 187946 ns/op 58714 B/op 1203 allocs/op -// -// CONCLUSION: The overhead for the map is negligible. Text format needs ~5x more allocations. -// Without compression, it needs ~7x longer, but with compression (the more relevant scenario), -// the difference becomes less relevant, only ~4x. -// -// The test data contains 248 samples. -// -// BenchmarkProcessor002ParseOnly in the extraction package is not quite -// comparable to the benchmarks here, but it gives an idea: JSON parsing is even -// slower than text parsing and needs a comparable amount of allocs. - -// BenchmarkParseText benchmarks the parsing of a text-format scrape into metric -// family DTOs. -func BenchmarkParseText(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/text") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - if _, err := parser.TextToMetricFamilies(bytes.NewReader(data)); err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkParseTextGzip benchmarks the parsing of a gzipped text-format scrape -// into metric family DTOs. -func BenchmarkParseTextGzip(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/text.gz") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - in, err := gzip.NewReader(bytes.NewReader(data)) - if err != nil { - b.Fatal(err) - } - if _, err := parser.TextToMetricFamilies(in); err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkParseProto benchmarks the parsing of a protobuf-format scrape into -// metric family DTOs. Note that this does not build a map of metric families -// (as the text version does), because it is not required for Prometheus -// ingestion either. (However, it is required for the text-format parsing, as -// the metric family might be sprinkled all over the text, while the -// protobuf-format guarantees bundling at one place.) -func BenchmarkParseProto(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/protobuf") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - family := &dto.MetricFamily{} - in := bytes.NewReader(data) - for { - family.Reset() - if _, err := pbutil.ReadDelimited(in, family); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - } - } -} - -// BenchmarkParseProtoGzip is like BenchmarkParseProto above, but parses gzipped -// protobuf format. -func BenchmarkParseProtoGzip(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/protobuf.gz") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - family := &dto.MetricFamily{} - in, err := gzip.NewReader(bytes.NewReader(data)) - if err != nil { - b.Fatal(err) - } - for { - family.Reset() - if _, err := pbutil.ReadDelimited(in, family); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - } - } -} - -// BenchmarkParseProtoMap is like BenchmarkParseProto but DOES put the parsed -// metric family DTOs into a map. This is not happening during Prometheus -// ingestion. It is just here to measure the overhead of that map creation and -// separate it from the overhead of the text format parsing. -func BenchmarkParseProtoMap(b *testing.B) { - b.StopTimer() - data, err := ioutil.ReadFile("testdata/protobuf") - if err != nil { - b.Fatal(err) - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - families := map[string]*dto.MetricFamily{} - in := bytes.NewReader(data) - for { - family := &dto.MetricFamily{} - if _, err := pbutil.ReadDelimited(in, family); err != nil { - if err == io.EOF { - break - } - b.Fatal(err) - } - families[family.GetName()] = family - } - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/decode_test.go b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/decode_test.go deleted file mode 100644 index 307fcd21f..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/decode_test.go +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2015 The Prometheus 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 expfmt - -import ( - "errors" - "io" - "net/http" - "reflect" - "sort" - "strings" - "testing" - - "github.com/prometheus/common/model" -) - -func TestTextDecoder(t *testing.T) { - var ( - ts = model.Now() - in = ` -# Only a quite simple scenario with two metric families. -# More complicated tests of the parser itself can be found in the text package. -# TYPE mf2 counter -mf2 3 -mf1{label="value1"} -3.14 123456 -mf1{label="value2"} 42 -mf2 4 -` - out = model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf1", - "label": "value1", - }, - Value: -3.14, - Timestamp: 123456, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf1", - "label": "value2", - }, - Value: 42, - Timestamp: ts, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf2", - }, - Value: 3, - Timestamp: ts, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "mf2", - }, - Value: 4, - Timestamp: ts, - }, - } - ) - - dec := &SampleDecoder{ - Dec: &textDecoder{r: strings.NewReader(in)}, - Opts: &DecodeOptions{ - Timestamp: ts, - }, - } - var all model.Vector - for { - var smpls model.Vector - err := dec.Decode(&smpls) - if err == io.EOF { - break - } - if err != nil { - t.Fatal(err) - } - all = append(all, smpls...) - } - sort.Sort(all) - sort.Sort(out) - if !reflect.DeepEqual(all, out) { - t.Fatalf("output does not match") - } -} - -func TestProtoDecoder(t *testing.T) { - - var testTime = model.Now() - - scenarios := []struct { - in string - expected model.Vector - }{ - { - in: "", - }, - { - in: "\x8f\x01\n\rrequest_count\x12\x12Number of requests\x18\x00\"0\n#\n\x0fsome_label_name\x12\x10some_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00E\xc0\"6\n)\n\x12another_label_name\x12\x13another_label_value\x1a\t\t\x00\x00\x00\x00\x00\x00U@", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "some_label_name": "some_label_value", - }, - Value: -42, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "another_label_name": "another_label_value", - }, - Value: 84, - Timestamp: testTime, - }, - }, - }, - { - in: "\xb9\x01\n\rrequest_count\x12\x12Number of requests\x18\x02\"O\n#\n\x0fsome_label_name\x12\x10some_label_value\"(\x1a\x12\t\xaeG\xe1z\x14\xae\xef?\x11\x00\x00\x00\x00\x00\x00E\xc0\x1a\x12\t+\x87\x16\xd9\xce\xf7\xef?\x11\x00\x00\x00\x00\x00\x00U\xc0\"A\n)\n\x12another_label_name\x12\x13another_label_value\"\x14\x1a\x12\t\x00\x00\x00\x00\x00\x00\xe0?\x11\x00\x00\x00\x00\x00\x00$@", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_count", - "some_label_name": "some_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_sum", - "some_label_name": "some_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "some_label_name": "some_label_value", - "quantile": "0.99", - }, - Value: -42, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "some_label_name": "some_label_value", - "quantile": "0.999", - }, - Value: -84, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_count", - "another_label_name": "another_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count_sum", - "another_label_name": "another_label_value", - }, - Value: 0, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - "another_label_name": "another_label_value", - "quantile": "0.5", - }, - Value: 10, - Timestamp: testTime, - }, - }, - }, - { - in: "\x8d\x01\n\x1drequest_duration_microseconds\x12\x15The response latency.\x18\x04\"S:Q\b\x85\x15\x11\xcd\xcc\xccL\x8f\xcb:A\x1a\v\b{\x11\x00\x00\x00\x00\x00\x00Y@\x1a\f\b\x9c\x03\x11\x00\x00\x00\x00\x00\x00^@\x1a\f\b\xd0\x04\x11\x00\x00\x00\x00\x00\x00b@\x1a\f\b\xf4\v\x11\x9a\x99\x99\x99\x99\x99e@\x1a\f\b\x85\x15\x11\x00\x00\x00\x00\x00\x00\xf0\u007f", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "100", - }, - Value: 123, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "120", - }, - Value: 412, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "144", - }, - Value: 592, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "172.8", - }, - Value: 1524, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_bucket", - "le": "+Inf", - }, - Value: 2693, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_sum", - }, - Value: 1756047.3, - Timestamp: testTime, - }, - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_duration_microseconds_count", - }, - Value: 2693, - Timestamp: testTime, - }, - }, - }, - { - // The metric type is unset in this protobuf, which needs to be handled - // correctly by the decoder. - in: "\x1c\n\rrequest_count\"\v\x1a\t\t\x00\x00\x00\x00\x00\x00\xf0?", - expected: model.Vector{ - &model.Sample{ - Metric: model.Metric{ - model.MetricNameLabel: "request_count", - }, - Value: 1, - Timestamp: testTime, - }, - }, - }, - } - - for i, scenario := range scenarios { - dec := &SampleDecoder{ - Dec: &protoDecoder{r: strings.NewReader(scenario.in)}, - Opts: &DecodeOptions{ - Timestamp: testTime, - }, - } - - var all model.Vector - for { - var smpls model.Vector - err := dec.Decode(&smpls) - if err == io.EOF { - break - } - if err != nil { - t.Fatal(err) - } - all = append(all, smpls...) - } - sort.Sort(all) - sort.Sort(scenario.expected) - if !reflect.DeepEqual(all, scenario.expected) { - t.Fatalf("%d. output does not match, want: %#v, got %#v", i, scenario.expected, all) - } - } -} - -func testDiscriminatorHTTPHeader(t testing.TB) { - var scenarios = []struct { - input map[string]string - output Format - err error - }{ - { - input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="delimited"`}, - output: FmtProtoDelim, - err: nil, - }, - { - input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="illegal"; encoding="delimited"`}, - output: "", - err: errors.New("unrecognized protocol message illegal"), - }, - { - input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="illegal"`}, - output: "", - err: errors.New("unsupported encoding illegal"), - }, - { - input: map[string]string{"Content-Type": `text/plain; version=0.0.4`}, - output: FmtText, - err: nil, - }, - { - input: map[string]string{"Content-Type": `text/plain`}, - output: FmtText, - err: nil, - }, - { - input: map[string]string{"Content-Type": `text/plain; version=0.0.3`}, - output: "", - err: errors.New("unrecognized protocol version 0.0.3"), - }, - } - - for i, scenario := range scenarios { - var header http.Header - - if len(scenario.input) > 0 { - header = http.Header{} - } - - for key, value := range scenario.input { - header.Add(key, value) - } - - actual, err := ResponseFormat(header) - - if scenario.err != err { - if scenario.err != nil && err != nil { - if scenario.err.Error() != err.Error() { - t.Errorf("%d. expected %s, got %s", i, scenario.err, err) - } - } else if scenario.err != nil || err != nil { - t.Errorf("%d. expected %s, got %s", i, scenario.err, err) - } - } - - if !reflect.DeepEqual(scenario.output, actual) { - t.Errorf("%d. expected %s, got %s", i, scenario.output, actual) - } - } -} - -func TestDiscriminatorHTTPHeader(t *testing.T) { - testDiscriminatorHTTPHeader(t) -} - -func BenchmarkDiscriminatorHTTPHeader(b *testing.B) { - for i := 0; i < b.N; i++ { - testDiscriminatorHTTPHeader(b) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_0 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_0 deleted file mode 100644 index 139597f9c..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_0 +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_1 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_1 deleted file mode 100644 index 2ae870679..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_1 +++ /dev/null @@ -1,6 +0,0 @@ - -minimal_metric 1.234 -another_metric -3e3 103948 -# Even that: -no_labels{} 3 -# HELP line for non-existing metric will be ignored. diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_2 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_2 deleted file mode 100644 index 5c351db36..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_2 +++ /dev/null @@ -1,12 +0,0 @@ - -# A normal comment. -# -# TYPE name counter -name{labelname="val1",basename="basevalue"} NaN -name {labelname="val2",basename="base\"v\\al\nue"} 0.23 1234567890 -# HELP name two-line\n doc str\\ing - - # HELP name2 doc str"ing 2 - # TYPE name2 gauge -name2{labelname="val2" ,basename = "basevalue2" } +Inf 54321 -name2{ labelname = "val1" , }-Inf diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_3 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_3 deleted file mode 100644 index 0b3c345aa..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_3 +++ /dev/null @@ -1,22 +0,0 @@ - -# TYPE my_summary summary -my_summary{n1="val1",quantile="0.5"} 110 -decoy -1 -2 -my_summary{n1="val1",quantile="0.9"} 140 1 -my_summary_count{n1="val1"} 42 -# Latest timestamp wins in case of a summary. -my_summary_sum{n1="val1"} 4711 2 -fake_sum{n1="val1"} 2001 -# TYPE another_summary summary -another_summary_count{n2="val2",n1="val1"} 20 -my_summary_count{n2="val2",n1="val1"} 5 5 -another_summary{n1="val1",n2="val2",quantile=".3"} -1.2 -my_summary_sum{n1="val2"} 08 15 -my_summary{n1="val3", quantile="0.2"} 4711 - my_summary{n1="val1",n2="val2",quantile="-12.34",} NaN -# some -# funny comments -# HELP -# HELP -# HELP my_summary -# HELP my_summary diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_4 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_4 deleted file mode 100644 index bde0a387a..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_4 +++ /dev/null @@ -1,10 +0,0 @@ - -# HELP request_duration_microseconds The response latency. -# TYPE request_duration_microseconds histogram -request_duration_microseconds_bucket{le="100"} 123 -request_duration_microseconds_bucket{le="120"} 412 -request_duration_microseconds_bucket{le="144"} 592 -request_duration_microseconds_bucket{le="172.8"} 1524 -request_duration_microseconds_bucket{le="+Inf"} 2693 -request_duration_microseconds_sum 1.7560473e+06 -request_duration_microseconds_count 2693 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_0 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_0 deleted file mode 100644 index 4c67f9a19..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_0 +++ /dev/null @@ -1 +0,0 @@ -bla 3.14 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_1 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_1 deleted file mode 100644 index b853478ee..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_1 +++ /dev/null @@ -1 +0,0 @@ -metric{label="\t"} 3.14 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_10 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_10 deleted file mode 100644 index b5fe5f5a6..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_10 +++ /dev/null @@ -1 +0,0 @@ -metric{label="bla"} 3.14 2 3 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_11 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_11 deleted file mode 100644 index 57c7fbc0b..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_11 +++ /dev/null @@ -1 +0,0 @@ -metric{label="bla"} blubb diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_12 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_12 deleted file mode 100644 index 0a9df79a1..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_12 +++ /dev/null @@ -1,3 +0,0 @@ - -# HELP metric one -# HELP metric two diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_13 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_13 deleted file mode 100644 index 5bc742781..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_13 +++ /dev/null @@ -1,3 +0,0 @@ - -# TYPE metric counter -# TYPE metric untyped diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_14 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_14 deleted file mode 100644 index a9a24265b..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_14 +++ /dev/null @@ -1,3 +0,0 @@ - -metric 4.12 -# TYPE metric counter diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_15 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_15 deleted file mode 100644 index 7e95ca8f4..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_15 +++ /dev/null @@ -1,2 +0,0 @@ - -# TYPE metric bla diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_16 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_16 deleted file mode 100644 index 7825f8887..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_16 +++ /dev/null @@ -1,2 +0,0 @@ - -# TYPE met-ric diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_17 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_17 deleted file mode 100644 index 8f35cae0c..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_17 +++ /dev/null @@ -1 +0,0 @@ -@invalidmetric{label="bla"} 3.14 2 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_18 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_18 deleted file mode 100644 index 7ca2cc268..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_18 +++ /dev/null @@ -1 +0,0 @@ -{label="bla"} 3.14 2 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_19 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_19 deleted file mode 100644 index 7a6ccc0dd..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_19 +++ /dev/null @@ -1,3 +0,0 @@ - -# TYPE metric histogram -metric_bucket{le="bla"} 3.14 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_2 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_2 deleted file mode 100644 index 726d0017c..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_2 +++ /dev/null @@ -1,3 +0,0 @@ - -metric{label="new -line"} 3.14 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_3 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_3 deleted file mode 100644 index 6aa9e3081..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_3 +++ /dev/null @@ -1 +0,0 @@ -metric{@="bla"} 3.14 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_4 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_4 deleted file mode 100644 index d112cb902..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_4 +++ /dev/null @@ -1 +0,0 @@ -metric{__name__="bla"} 3.14 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_5 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_5 deleted file mode 100644 index b34554a8d..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_5 +++ /dev/null @@ -1 +0,0 @@ -metric{label+="bla"} 3.14 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_6 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_6 deleted file mode 100644 index c4d7df3d1..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_6 +++ /dev/null @@ -1 +0,0 @@ -metric{label=bla} 3.14 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_7 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_7 deleted file mode 100644 index 97eafc4a6..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_7 +++ /dev/null @@ -1,3 +0,0 @@ - -# TYPE metric summary -metric{quantile="bla"} 3.14 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_8 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_8 deleted file mode 100644 index fc706496b..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_8 +++ /dev/null @@ -1 +0,0 @@ -metric{label="bla"+} 3.14 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_9 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_9 deleted file mode 100644 index 57b4879c0..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/from_test_parse_error_9 +++ /dev/null @@ -1 +0,0 @@ -metric{label="bla"} 3.14 2.72 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/minimal b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/minimal deleted file mode 100644 index be1e6a369..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/fuzz/corpus/minimal +++ /dev/null @@ -1 +0,0 @@ -m{} 0 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/json_decode_test.go b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/json_decode_test.go deleted file mode 100644 index c98ea29e1..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/json_decode_test.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015 The Prometheus 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 expfmt - -import ( - "os" - "reflect" - "testing" - - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" -) - -func TestJSON2Decode(t *testing.T) { - f, err := os.Open("testdata/json2") - if err != nil { - t.Fatal(err) - } - defer f.Close() - - dec := newJSON2Decoder(f) - - var v1 dto.MetricFamily - if err := dec.Decode(&v1); err != nil { - t.Fatal(err) - } - - exp1 := dto.MetricFamily{ - Type: dto.MetricType_UNTYPED.Enum(), - Help: proto.String("RPC calls."), - Name: proto.String("rpc_calls_total"), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("job"), - Value: proto.String("batch_job"), - }, { - Name: proto.String("service"), - Value: proto.String("zed"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(25), - }, - }, - { - Label: []*dto.LabelPair{ - { - Name: proto.String("job"), - Value: proto.String("batch_job"), - }, { - Name: proto.String("service"), - Value: proto.String("bar"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(24), - }, - }, - }, - } - - if !reflect.DeepEqual(v1, exp1) { - t.Fatalf("Expected %v, got %v", exp1, v1) - } - - var v2 dto.MetricFamily - if err := dec.Decode(&v2); err != nil { - t.Fatal(err) - } - - exp2 := dto.MetricFamily{ - Type: dto.MetricType_UNTYPED.Enum(), - Help: proto.String("RPC latency."), - Name: proto.String("rpc_latency_microseconds"), - Metric: []*dto.Metric{ - { - Label: []*dto.LabelPair{ - { - Name: proto.String("percentile"), - Value: proto.String("0.010000"), - }, { - Name: proto.String("service"), - Value: proto.String("foo"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(15), - }, - }, - { - Label: []*dto.LabelPair{ - { - Name: proto.String("percentile"), - Value: proto.String("0.990000"), - }, { - Name: proto.String("service"), - Value: proto.String("foo"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(17), - }, - }, - }, - } - - if !reflect.DeepEqual(v2, exp2) { - t.Fatalf("Expected %v, got %v", exp2, v2) - } - -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/json2 b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/json2 deleted file mode 100644 index b914c9386..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/json2 +++ /dev/null @@ -1,46 +0,0 @@ -[ - { - "baseLabels": { - "__name__": "rpc_calls_total", - "job": "batch_job" - }, - "docstring": "RPC calls.", - "metric": { - "type": "counter", - "value": [ - { - "labels": { - "service": "zed" - }, - "value": 25 - }, - { - "labels": { - "service": "bar" - }, - "value": 24 - } - ] - } - }, - { - "baseLabels": { - "__name__": "rpc_latency_microseconds" - }, - "docstring": "RPC latency.", - "metric": { - "type": "histogram", - "value": [ - { - "labels": { - "service": "foo" - }, - "value": { - "0.010000": 15, - "0.990000": 17 - } - } - ] - } - } -] diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf deleted file mode 100644 index d5aae5091..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf +++ /dev/null @@ -1,516 +0,0 @@ -fc08 0a22 6874 7470 5f72 6571 7565 7374 -5f64 7572 6174 696f 6e5f 6d69 6372 6f73 -6563 6f6e 6473 122b 5468 6520 4854 5450 -2072 6571 7565 7374 206c 6174 656e 6369 -6573 2069 6e20 6d69 6372 6f73 6563 6f6e -6473 2e18 0222 570a 0c0a 0768 616e 646c -6572 1201 2f22 4708 0011 0000 0000 0000 -0000 1a12 0900 0000 0000 00e0 3f11 0000 -0000 0000 0000 1a12 09cd cccc cccc ccec -3f11 0000 0000 0000 0000 1a12 09ae 47e1 -7a14 aeef 3f11 0000 0000 0000 0000 225d -0a12 0a07 6861 6e64 6c65 7212 072f 616c -6572 7473 2247 0800 1100 0000 0000 0000 -001a 1209 0000 0000 0000 e03f 1100 0000 -0000 0000 001a 1209 cdcc cccc cccc ec3f -1100 0000 0000 0000 001a 1209 ae47 e17a -14ae ef3f 1100 0000 0000 0000 0022 620a -170a 0768 616e 646c 6572 120c 2f61 7069 -2f6d 6574 7269 6373 2247 0800 1100 0000 -0000 0000 001a 1209 0000 0000 0000 e03f -1100 0000 0000 0000 001a 1209 cdcc cccc -cccc ec3f 1100 0000 0000 0000 001a 1209 -ae47 e17a 14ae ef3f 1100 0000 0000 0000 -0022 600a 150a 0768 616e 646c 6572 120a -2f61 7069 2f71 7565 7279 2247 0800 1100 -0000 0000 0000 001a 1209 0000 0000 0000 -e03f 1100 0000 0000 0000 001a 1209 cdcc -cccc cccc ec3f 1100 0000 0000 0000 001a -1209 ae47 e17a 14ae ef3f 1100 0000 0000 -0000 0022 660a 1b0a 0768 616e 646c 6572 -1210 2f61 7069 2f71 7565 7279 5f72 616e -6765 2247 0800 1100 0000 0000 0000 001a -1209 0000 0000 0000 e03f 1100 0000 0000 -0000 001a 1209 cdcc cccc cccc ec3f 1100 -0000 0000 0000 001a 1209 ae47 e17a 14ae -ef3f 1100 0000 0000 0000 0022 620a 170a -0768 616e 646c 6572 120c 2f61 7069 2f74 -6172 6765 7473 2247 0800 1100 0000 0000 -0000 001a 1209 0000 0000 0000 e03f 1100 -0000 0000 0000 001a 1209 cdcc cccc cccc -ec3f 1100 0000 0000 0000 001a 1209 ae47 -e17a 14ae ef3f 1100 0000 0000 0000 0022 -600a 150a 0768 616e 646c 6572 120a 2f63 -6f6e 736f 6c65 732f 2247 0800 1100 0000 -0000 0000 001a 1209 0000 0000 0000 e03f -1100 0000 0000 0000 001a 1209 cdcc cccc -cccc ec3f 1100 0000 0000 0000 001a 1209 -ae47 e17a 14ae ef3f 1100 0000 0000 0000 -0022 5c0a 110a 0768 616e 646c 6572 1206 -2f67 7261 7068 2247 0800 1100 0000 0000 -0000 001a 1209 0000 0000 0000 e03f 1100 -0000 0000 0000 001a 1209 cdcc cccc cccc -ec3f 1100 0000 0000 0000 001a 1209 ae47 -e17a 14ae ef3f 1100 0000 0000 0000 0022 -5b0a 100a 0768 616e 646c 6572 1205 2f68 -6561 7022 4708 0011 0000 0000 0000 0000 -1a12 0900 0000 0000 00e0 3f11 0000 0000 -0000 0000 1a12 09cd cccc cccc ccec 3f11 -0000 0000 0000 0000 1a12 09ae 47e1 7a14 -aeef 3f11 0000 0000 0000 0000 225e 0a13 -0a07 6861 6e64 6c65 7212 082f 7374 6174 -6963 2f22 4708 0011 0000 0000 0000 0000 -1a12 0900 0000 0000 00e0 3f11 0000 0000 -0000 0000 1a12 09cd cccc cccc ccec 3f11 -0000 0000 0000 0000 1a12 09ae 47e1 7a14 -aeef 3f11 0000 0000 0000 0000 2260 0a15 -0a07 6861 6e64 6c65 7212 0a70 726f 6d65 -7468 6575 7322 4708 3b11 5b8f c2f5 083f -f440 1a12 0900 0000 0000 00e0 3f11 e17a -14ae c7af 9340 1a12 09cd cccc cccc ccec -3f11 2fdd 2406 81f0 9640 1a12 09ae 47e1 -7a14 aeef 3f11 3d0a d7a3 b095 a740 e608 -0a17 6874 7470 5f72 6571 7565 7374 5f73 -697a 655f 6279 7465 7312 2054 6865 2048 -5454 5020 7265 7175 6573 7420 7369 7a65 -7320 696e 2062 7974 6573 2e18 0222 570a -0c0a 0768 616e 646c 6572 1201 2f22 4708 -0011 0000 0000 0000 0000 1a12 0900 0000 -0000 00e0 3f11 0000 0000 0000 0000 1a12 -09cd cccc cccc ccec 3f11 0000 0000 0000 -0000 1a12 09ae 47e1 7a14 aeef 3f11 0000 -0000 0000 0000 225d 0a12 0a07 6861 6e64 -6c65 7212 072f 616c 6572 7473 2247 0800 -1100 0000 0000 0000 001a 1209 0000 0000 -0000 e03f 1100 0000 0000 0000 001a 1209 -cdcc cccc cccc ec3f 1100 0000 0000 0000 -001a 1209 ae47 e17a 14ae ef3f 1100 0000 -0000 0000 0022 620a 170a 0768 616e 646c -6572 120c 2f61 7069 2f6d 6574 7269 6373 -2247 0800 1100 0000 0000 0000 001a 1209 -0000 0000 0000 e03f 1100 0000 0000 0000 -001a 1209 cdcc cccc cccc ec3f 1100 0000 -0000 0000 001a 1209 ae47 e17a 14ae ef3f -1100 0000 0000 0000 0022 600a 150a 0768 -616e 646c 6572 120a 2f61 7069 2f71 7565 -7279 2247 0800 1100 0000 0000 0000 001a -1209 0000 0000 0000 e03f 1100 0000 0000 -0000 001a 1209 cdcc cccc cccc ec3f 1100 -0000 0000 0000 001a 1209 ae47 e17a 14ae -ef3f 1100 0000 0000 0000 0022 660a 1b0a -0768 616e 646c 6572 1210 2f61 7069 2f71 -7565 7279 5f72 616e 6765 2247 0800 1100 -0000 0000 0000 001a 1209 0000 0000 0000 -e03f 1100 0000 0000 0000 001a 1209 cdcc -cccc cccc ec3f 1100 0000 0000 0000 001a -1209 ae47 e17a 14ae ef3f 1100 0000 0000 -0000 0022 620a 170a 0768 616e 646c 6572 -120c 2f61 7069 2f74 6172 6765 7473 2247 -0800 1100 0000 0000 0000 001a 1209 0000 -0000 0000 e03f 1100 0000 0000 0000 001a -1209 cdcc cccc cccc ec3f 1100 0000 0000 -0000 001a 1209 ae47 e17a 14ae ef3f 1100 -0000 0000 0000 0022 600a 150a 0768 616e -646c 6572 120a 2f63 6f6e 736f 6c65 732f -2247 0800 1100 0000 0000 0000 001a 1209 -0000 0000 0000 e03f 1100 0000 0000 0000 -001a 1209 cdcc cccc cccc ec3f 1100 0000 -0000 0000 001a 1209 ae47 e17a 14ae ef3f -1100 0000 0000 0000 0022 5c0a 110a 0768 -616e 646c 6572 1206 2f67 7261 7068 2247 -0800 1100 0000 0000 0000 001a 1209 0000 -0000 0000 e03f 1100 0000 0000 0000 001a -1209 cdcc cccc cccc ec3f 1100 0000 0000 -0000 001a 1209 ae47 e17a 14ae ef3f 1100 -0000 0000 0000 0022 5b0a 100a 0768 616e -646c 6572 1205 2f68 6561 7022 4708 0011 -0000 0000 0000 0000 1a12 0900 0000 0000 -00e0 3f11 0000 0000 0000 0000 1a12 09cd -cccc cccc ccec 3f11 0000 0000 0000 0000 -1a12 09ae 47e1 7a14 aeef 3f11 0000 0000 -0000 0000 225e 0a13 0a07 6861 6e64 6c65 -7212 082f 7374 6174 6963 2f22 4708 0011 -0000 0000 0000 0000 1a12 0900 0000 0000 -00e0 3f11 0000 0000 0000 0000 1a12 09cd -cccc cccc ccec 3f11 0000 0000 0000 0000 -1a12 09ae 47e1 7a14 aeef 3f11 0000 0000 -0000 0000 2260 0a15 0a07 6861 6e64 6c65 -7212 0a70 726f 6d65 7468 6575 7322 4708 -3b11 0000 0000 40c4 d040 1a12 0900 0000 -0000 00e0 3f11 0000 0000 0030 7240 1a12 -09cd cccc cccc ccec 3f11 0000 0000 0030 -7240 1a12 09ae 47e1 7a14 aeef 3f11 0000 -0000 0030 7240 7c0a 1368 7474 705f 7265 -7175 6573 7473 5f74 6f74 616c 1223 546f -7461 6c20 6e75 6d62 6572 206f 6620 4854 -5450 2072 6571 7565 7374 7320 6d61 6465 -2e18 0022 3e0a 0b0a 0463 6f64 6512 0332 -3030 0a15 0a07 6861 6e64 6c65 7212 0a70 -726f 6d65 7468 6575 730a 0d0a 066d 6574 -686f 6412 0367 6574 1a09 0900 0000 0000 -804d 40e8 080a 1868 7474 705f 7265 7370 -6f6e 7365 5f73 697a 655f 6279 7465 7312 -2154 6865 2048 5454 5020 7265 7370 6f6e -7365 2073 697a 6573 2069 6e20 6279 7465 -732e 1802 2257 0a0c 0a07 6861 6e64 6c65 -7212 012f 2247 0800 1100 0000 0000 0000 -001a 1209 0000 0000 0000 e03f 1100 0000 -0000 0000 001a 1209 cdcc cccc cccc ec3f -1100 0000 0000 0000 001a 1209 ae47 e17a -14ae ef3f 1100 0000 0000 0000 0022 5d0a -120a 0768 616e 646c 6572 1207 2f61 6c65 -7274 7322 4708 0011 0000 0000 0000 0000 -1a12 0900 0000 0000 00e0 3f11 0000 0000 -0000 0000 1a12 09cd cccc cccc ccec 3f11 -0000 0000 0000 0000 1a12 09ae 47e1 7a14 -aeef 3f11 0000 0000 0000 0000 2262 0a17 -0a07 6861 6e64 6c65 7212 0c2f 6170 692f -6d65 7472 6963 7322 4708 0011 0000 0000 -0000 0000 1a12 0900 0000 0000 00e0 3f11 -0000 0000 0000 0000 1a12 09cd cccc cccc -ccec 3f11 0000 0000 0000 0000 1a12 09ae -47e1 7a14 aeef 3f11 0000 0000 0000 0000 -2260 0a15 0a07 6861 6e64 6c65 7212 0a2f -6170 692f 7175 6572 7922 4708 0011 0000 -0000 0000 0000 1a12 0900 0000 0000 00e0 -3f11 0000 0000 0000 0000 1a12 09cd cccc -cccc ccec 3f11 0000 0000 0000 0000 1a12 -09ae 47e1 7a14 aeef 3f11 0000 0000 0000 -0000 2266 0a1b 0a07 6861 6e64 6c65 7212 -102f 6170 692f 7175 6572 795f 7261 6e67 -6522 4708 0011 0000 0000 0000 0000 1a12 -0900 0000 0000 00e0 3f11 0000 0000 0000 -0000 1a12 09cd cccc cccc ccec 3f11 0000 -0000 0000 0000 1a12 09ae 47e1 7a14 aeef -3f11 0000 0000 0000 0000 2262 0a17 0a07 -6861 6e64 6c65 7212 0c2f 6170 692f 7461 -7267 6574 7322 4708 0011 0000 0000 0000 -0000 1a12 0900 0000 0000 00e0 3f11 0000 -0000 0000 0000 1a12 09cd cccc cccc ccec -3f11 0000 0000 0000 0000 1a12 09ae 47e1 -7a14 aeef 3f11 0000 0000 0000 0000 2260 -0a15 0a07 6861 6e64 6c65 7212 0a2f 636f -6e73 6f6c 6573 2f22 4708 0011 0000 0000 -0000 0000 1a12 0900 0000 0000 00e0 3f11 -0000 0000 0000 0000 1a12 09cd cccc cccc -ccec 3f11 0000 0000 0000 0000 1a12 09ae -47e1 7a14 aeef 3f11 0000 0000 0000 0000 -225c 0a11 0a07 6861 6e64 6c65 7212 062f -6772 6170 6822 4708 0011 0000 0000 0000 -0000 1a12 0900 0000 0000 00e0 3f11 0000 -0000 0000 0000 1a12 09cd cccc cccc ccec -3f11 0000 0000 0000 0000 1a12 09ae 47e1 -7a14 aeef 3f11 0000 0000 0000 0000 225b -0a10 0a07 6861 6e64 6c65 7212 052f 6865 -6170 2247 0800 1100 0000 0000 0000 001a -1209 0000 0000 0000 e03f 1100 0000 0000 -0000 001a 1209 cdcc cccc cccc ec3f 1100 -0000 0000 0000 001a 1209 ae47 e17a 14ae -ef3f 1100 0000 0000 0000 0022 5e0a 130a -0768 616e 646c 6572 1208 2f73 7461 7469 -632f 2247 0800 1100 0000 0000 0000 001a -1209 0000 0000 0000 e03f 1100 0000 0000 -0000 001a 1209 cdcc cccc cccc ec3f 1100 -0000 0000 0000 001a 1209 ae47 e17a 14ae -ef3f 1100 0000 0000 0000 0022 600a 150a -0768 616e 646c 6572 120a 7072 6f6d 6574 -6865 7573 2247 083b 1100 0000 00e0 b4fc -401a 1209 0000 0000 0000 e03f 1100 0000 -0000 349f 401a 1209 cdcc cccc cccc ec3f -1100 0000 0000 08a0 401a 1209 ae47 e17a -14ae ef3f 1100 0000 0000 0aa0 405c 0a19 -7072 6f63 6573 735f 6370 755f 7365 636f -6e64 735f 746f 7461 6c12 3054 6f74 616c -2075 7365 7220 616e 6420 7379 7374 656d -2043 5055 2074 696d 6520 7370 656e 7420 -696e 2073 6563 6f6e 6473 2e18 0022 0b1a -0909 a470 3d0a d7a3 d03f 4f0a 1270 726f -6365 7373 5f67 6f72 6f75 7469 6e65 7312 -2a4e 756d 6265 7220 6f66 2067 6f72 6f75 -7469 6e65 7320 7468 6174 2063 7572 7265 -6e74 6c79 2065 7869 7374 2e18 0122 0b12 -0909 0000 0000 0000 5140 4a0a 0f70 726f -6365 7373 5f6d 6178 5f66 6473 1228 4d61 -7869 6d75 6d20 6e75 6d62 6572 206f 6620 -6f70 656e 2066 696c 6520 6465 7363 7269 -7074 6f72 732e 1801 220b 1209 0900 0000 -0000 00c0 4043 0a10 7072 6f63 6573 735f -6f70 656e 5f66 6473 1220 4e75 6d62 6572 -206f 6620 6f70 656e 2066 696c 6520 6465 -7363 7269 7074 6f72 732e 1801 220b 1209 -0900 0000 0000 003d 404e 0a1d 7072 6f63 -6573 735f 7265 7369 6465 6e74 5f6d 656d -6f72 795f 6279 7465 7312 1e52 6573 6964 -656e 7420 6d65 6d6f 7279 2073 697a 6520 -696e 2062 7974 6573 2e18 0122 0b12 0909 -0000 0000 004b 8841 630a 1a70 726f 6365 -7373 5f73 7461 7274 5f74 696d 655f 7365 -636f 6e64 7312 3653 7461 7274 2074 696d -6520 6f66 2074 6865 2070 726f 6365 7373 -2073 696e 6365 2075 6e69 7820 6570 6f63 -6820 696e 2073 6563 6f6e 6473 2e18 0122 -0b12 0909 3d0a 172d e831 d541 4c0a 1c70 -726f 6365 7373 5f76 6972 7475 616c 5f6d -656d 6f72 795f 6279 7465 7312 1d56 6972 -7475 616c 206d 656d 6f72 7920 7369 7a65 -2069 6e20 6279 7465 732e 1801 220b 1209 -0900 0000 0020 12c0 415f 0a27 7072 6f6d -6574 6865 7573 5f64 6e73 5f73 645f 6c6f -6f6b 7570 5f66 6169 6c75 7265 735f 746f -7461 6c12 2554 6865 206e 756d 6265 7220 -6f66 2044 4e53 2d53 4420 6c6f 6f6b 7570 -2066 6169 6c75 7265 732e 1800 220b 1a09 -0900 0000 0000 0000 004f 0a1f 7072 6f6d -6574 6865 7573 5f64 6e73 5f73 645f 6c6f -6f6b 7570 735f 746f 7461 6c12 1d54 6865 -206e 756d 6265 7220 6f66 2044 4e53 2d53 -4420 6c6f 6f6b 7570 732e 1800 220b 1a09 -0900 0000 0000 0008 40cf 010a 2a70 726f -6d65 7468 6575 735f 6576 616c 7561 746f -725f 6475 7261 7469 6f6e 5f6d 696c 6c69 -7365 636f 6e64 7312 2c54 6865 2064 7572 -6174 696f 6e20 666f 7220 616c 6c20 6576 -616c 7561 7469 6f6e 7320 746f 2065 7865 -6375 7465 2e18 0222 7122 6f08 0b11 0000 -0000 0000 2240 1a12 097b 14ae 47e1 7a84 -3f11 0000 0000 0000 0000 1a12 099a 9999 -9999 99a9 3f11 0000 0000 0000 0000 1a12 -0900 0000 0000 00e0 3f11 0000 0000 0000 -0000 1a12 09cd cccc cccc ccec 3f11 0000 -0000 0000 f03f 1a12 09ae 47e1 7a14 aeef -3f11 0000 0000 0000 f03f a301 0a39 7072 -6f6d 6574 6865 7573 5f6c 6f63 616c 5f73 -746f 7261 6765 5f63 6865 636b 706f 696e -745f 6475 7261 7469 6f6e 5f6d 696c 6c69 -7365 636f 6e64 7312 5754 6865 2064 7572 -6174 696f 6e20 2869 6e20 6d69 6c6c 6973 -6563 6f6e 6473 2920 6974 2074 6f6f 6b20 -746f 2063 6865 636b 706f 696e 7420 696e -2d6d 656d 6f72 7920 6d65 7472 6963 7320 -616e 6420 6865 6164 2063 6875 6e6b 732e -1801 220b 1209 0900 0000 0000 0000 00f2 -010a 2870 726f 6d65 7468 6575 735f 6c6f -6361 6c5f 7374 6f72 6167 655f 6368 756e -6b5f 6f70 735f 746f 7461 6c12 3354 6865 -2074 6f74 616c 206e 756d 6265 7220 6f66 -2063 6875 6e6b 206f 7065 7261 7469 6f6e -7320 6279 2074 6865 6972 2074 7970 652e -1800 221b 0a0e 0a04 7479 7065 1206 6372 -6561 7465 1a09 0900 0000 0000 b880 4022 -1c0a 0f0a 0474 7970 6512 0770 6572 7369 -7374 1a09 0900 0000 0000 c05b 4022 180a -0b0a 0474 7970 6512 0370 696e 1a09 0900 -0000 0000 807b 4022 1e0a 110a 0474 7970 -6512 0974 7261 6e73 636f 6465 1a09 0900 -0000 0000 a06b 4022 1a0a 0d0a 0474 7970 -6512 0575 6e70 696e 1a09 0900 0000 0000 -807b 40c4 010a 3c70 726f 6d65 7468 6575 -735f 6c6f 6361 6c5f 7374 6f72 6167 655f -696e 6465 7869 6e67 5f62 6174 6368 5f6c -6174 656e 6379 5f6d 696c 6c69 7365 636f -6e64 7312 3751 7561 6e74 696c 6573 2066 -6f72 2062 6174 6368 2069 6e64 6578 696e -6720 6c61 7465 6e63 6965 7320 696e 206d -696c 6c69 7365 636f 6e64 732e 1802 2249 -2247 0801 1100 0000 0000 0000 001a 1209 -0000 0000 0000 e03f 1100 0000 0000 0000 -001a 1209 cdcc cccc cccc ec3f 1100 0000 -0000 0000 001a 1209 ae47 e17a 14ae ef3f -1100 0000 0000 0000 00bf 010a 2d70 726f -6d65 7468 6575 735f 6c6f 6361 6c5f 7374 -6f72 6167 655f 696e 6465 7869 6e67 5f62 -6174 6368 5f73 697a 6573 1241 5175 616e -7469 6c65 7320 666f 7220 696e 6465 7869 -6e67 2062 6174 6368 2073 697a 6573 2028 -6e75 6d62 6572 206f 6620 6d65 7472 6963 -7320 7065 7220 6261 7463 6829 2e18 0222 -4922 4708 0111 0000 0000 0000 0040 1a12 -0900 0000 0000 00e0 3f11 0000 0000 0000 -0040 1a12 09cd cccc cccc ccec 3f11 0000 -0000 0000 0040 1a12 09ae 47e1 7a14 aeef -3f11 0000 0000 0000 0040 660a 3070 726f -6d65 7468 6575 735f 6c6f 6361 6c5f 7374 -6f72 6167 655f 696e 6465 7869 6e67 5f71 -7565 7565 5f63 6170 6163 6974 7912 2354 -6865 2063 6170 6163 6974 7920 6f66 2074 -6865 2069 6e64 6578 696e 6720 7175 6575 -652e 1801 220b 1209 0900 0000 0000 00d0 -406d 0a2e 7072 6f6d 6574 6865 7573 5f6c -6f63 616c 5f73 746f 7261 6765 5f69 6e64 -6578 696e 675f 7175 6575 655f 6c65 6e67 -7468 122c 5468 6520 6e75 6d62 6572 206f -6620 6d65 7472 6963 7320 7761 6974 696e -6720 746f 2062 6520 696e 6465 7865 642e -1801 220b 1209 0900 0000 0000 0000 0067 -0a2f 7072 6f6d 6574 6865 7573 5f6c 6f63 -616c 5f73 746f 7261 6765 5f69 6e67 6573 -7465 645f 7361 6d70 6c65 735f 746f 7461 -6c12 2554 6865 2074 6f74 616c 206e 756d -6265 7220 6f66 2073 616d 706c 6573 2069 -6e67 6573 7465 642e 1800 220b 1a09 0900 -0000 0080 27cd 40c3 010a 3770 726f 6d65 -7468 6575 735f 6c6f 6361 6c5f 7374 6f72 -6167 655f 696e 7661 6c69 645f 7072 656c -6f61 645f 7265 7175 6573 7473 5f74 6f74 -616c 1279 5468 6520 746f 7461 6c20 6e75 -6d62 6572 206f 6620 7072 656c 6f61 6420 -7265 7175 6573 7473 2072 6566 6572 7269 -6e67 2074 6f20 6120 6e6f 6e2d 6578 6973 -7465 6e74 2073 6572 6965 732e 2054 6869 -7320 6973 2061 6e20 696e 6469 6361 7469 -6f6e 206f 6620 6f75 7464 6174 6564 206c -6162 656c 2069 6e64 6578 6573 2e18 0022 -0b1a 0909 0000 0000 0000 0000 6f0a 2a70 -726f 6d65 7468 6575 735f 6c6f 6361 6c5f -7374 6f72 6167 655f 6d65 6d6f 7279 5f63 -6875 6e6b 6465 7363 7312 3254 6865 2063 -7572 7265 6e74 206e 756d 6265 7220 6f66 -2063 6875 6e6b 2064 6573 6372 6970 746f -7273 2069 6e20 6d65 6d6f 7279 2e18 0122 -0b12 0909 0000 0000 0020 8f40 9c01 0a26 -7072 6f6d 6574 6865 7573 5f6c 6f63 616c -5f73 746f 7261 6765 5f6d 656d 6f72 795f -6368 756e 6b73 1263 5468 6520 6375 7272 -656e 7420 6e75 6d62 6572 206f 6620 6368 -756e 6b73 2069 6e20 6d65 6d6f 7279 2c20 -6578 636c 7564 696e 6720 636c 6f6e 6564 -2063 6875 6e6b 7320 2869 2e65 2e20 6368 -756e 6b73 2077 6974 686f 7574 2061 2064 -6573 6372 6970 746f 7229 2e18 0122 0b12 -0909 0000 0000 00e8 8d40 600a 2670 726f -6d65 7468 6575 735f 6c6f 6361 6c5f 7374 -6f72 6167 655f 6d65 6d6f 7279 5f73 6572 -6965 7312 2754 6865 2063 7572 7265 6e74 -206e 756d 6265 7220 6f66 2073 6572 6965 -7320 696e 206d 656d 6f72 792e 1801 220b -1209 0900 0000 0000 807a 40b7 010a 3570 -726f 6d65 7468 6575 735f 6c6f 6361 6c5f -7374 6f72 6167 655f 7065 7273 6973 745f -6c61 7465 6e63 795f 6d69 6372 6f73 6563 -6f6e 6473 1231 4120 7375 6d6d 6172 7920 -6f66 206c 6174 656e 6369 6573 2066 6f72 -2070 6572 7369 7374 696e 6720 6561 6368 -2063 6875 6e6b 2e18 0222 4922 4708 6f11 -1c2f dd24 e68c cc40 1a12 0900 0000 0000 -00e0 3f11 8d97 6e12 8360 3e40 1a12 09cd -cccc cccc ccec 3f11 0ad7 a370 3d62 6b40 -1a12 09ae 47e1 7a14 aeef 3f11 7b14 ae47 -e1b6 7240 6a0a 2f70 726f 6d65 7468 6575 -735f 6c6f 6361 6c5f 7374 6f72 6167 655f -7065 7273 6973 745f 7175 6575 655f 6361 -7061 6369 7479 1228 5468 6520 746f 7461 -6c20 6361 7061 6369 7479 206f 6620 7468 -6520 7065 7273 6973 7420 7175 6575 652e -1801 220b 1209 0900 0000 0000 0090 407a -0a2d 7072 6f6d 6574 6865 7573 5f6c 6f63 -616c 5f73 746f 7261 6765 5f70 6572 7369 -7374 5f71 7565 7565 5f6c 656e 6774 6812 -3a54 6865 2063 7572 7265 6e74 206e 756d -6265 7220 6f66 2063 6875 6e6b 7320 7761 -6974 696e 6720 696e 2074 6865 2070 6572 -7369 7374 2071 7565 7565 2e18 0122 0b12 -0909 0000 0000 0000 0000 ac01 0a29 7072 -6f6d 6574 6865 7573 5f6c 6f63 616c 5f73 -746f 7261 6765 5f73 6572 6965 735f 6f70 -735f 746f 7461 6c12 3454 6865 2074 6f74 -616c 206e 756d 6265 7220 6f66 2073 6572 -6965 7320 6f70 6572 6174 696f 6e73 2062 -7920 7468 6569 7220 7479 7065 2e18 0022 -1b0a 0e0a 0474 7970 6512 0663 7265 6174 -651a 0909 0000 0000 0000 0040 222a 0a1d -0a04 7479 7065 1215 6d61 696e 7465 6e61 -6e63 655f 696e 5f6d 656d 6f72 791a 0909 -0000 0000 0000 1440 d601 0a2d 7072 6f6d -6574 6865 7573 5f6e 6f74 6966 6963 6174 -696f 6e73 5f6c 6174 656e 6379 5f6d 696c -6c69 7365 636f 6e64 7312 584c 6174 656e -6379 2071 7561 6e74 696c 6573 2066 6f72 -2073 656e 6469 6e67 2061 6c65 7274 206e -6f74 6966 6963 6174 696f 6e73 2028 6e6f -7420 696e 636c 7564 696e 6720 6472 6f70 -7065 6420 6e6f 7469 6669 6361 7469 6f6e -7329 2e18 0222 4922 4708 0011 0000 0000 -0000 0000 1a12 0900 0000 0000 00e0 3f11 -0000 0000 0000 0000 1a12 09cd cccc cccc -ccec 3f11 0000 0000 0000 0000 1a12 09ae -47e1 7a14 aeef 3f11 0000 0000 0000 0000 -680a 2770 726f 6d65 7468 6575 735f 6e6f -7469 6669 6361 7469 6f6e 735f 7175 6575 -655f 6361 7061 6369 7479 122e 5468 6520 -6361 7061 6369 7479 206f 6620 7468 6520 -616c 6572 7420 6e6f 7469 6669 6361 7469 -6f6e 7320 7175 6575 652e 1801 220b 1209 -0900 0000 0000 0059 4067 0a25 7072 6f6d -6574 6865 7573 5f6e 6f74 6966 6963 6174 -696f 6e73 5f71 7565 7565 5f6c 656e 6774 -6812 2f54 6865 206e 756d 6265 7220 6f66 -2061 6c65 7274 206e 6f74 6966 6963 6174 -696f 6e73 2069 6e20 7468 6520 7175 6575 -652e 1801 220b 1209 0900 0000 0000 0000 -009e 020a 3070 726f 6d65 7468 6575 735f -7275 6c65 5f65 7661 6c75 6174 696f 6e5f -6475 7261 7469 6f6e 5f6d 696c 6c69 7365 -636f 6e64 7312 2354 6865 2064 7572 6174 -696f 6e20 666f 7220 6120 7275 6c65 2074 -6f20 6578 6563 7574 652e 1802 2260 0a15 -0a09 7275 6c65 5f74 7970 6512 0861 6c65 -7274 696e 6722 4708 3711 0000 0000 0000 -2840 1a12 0900 0000 0000 00e0 3f11 0000 -0000 0000 0000 1a12 09cd cccc cccc ccec -3f11 0000 0000 0000 0000 1a12 09ae 47e1 -7a14 aeef 3f11 0000 0000 0000 0840 2261 -0a16 0a09 7275 6c65 5f74 7970 6512 0972 -6563 6f72 6469 6e67 2247 0837 1100 0000 -0000 002e 401a 1209 0000 0000 0000 e03f -1100 0000 0000 0000 001a 1209 cdcc cccc -cccc ec3f 1100 0000 0000 0000 001a 1209 -ae47 e17a 14ae ef3f 1100 0000 0000 0008 -4069 0a29 7072 6f6d 6574 6865 7573 5f72 -756c 655f 6576 616c 7561 7469 6f6e 5f66 -6169 6c75 7265 735f 746f 7461 6c12 2d54 -6865 2074 6f74 616c 206e 756d 6265 7220 -6f66 2072 756c 6520 6576 616c 7561 7469 -6f6e 2066 6169 6c75 7265 732e 1800 220b -1a09 0900 0000 0000 0000 0060 0a21 7072 -6f6d 6574 6865 7573 5f73 616d 706c 6573 -5f71 7565 7565 5f63 6170 6163 6974 7912 -2c43 6170 6163 6974 7920 6f66 2074 6865 -2071 7565 7565 2066 6f72 2075 6e77 7269 -7474 656e 2073 616d 706c 6573 2e18 0122 -0b12 0909 0000 0000 0000 b040 da01 0a1f -7072 6f6d 6574 6865 7573 5f73 616d 706c -6573 5f71 7565 7565 5f6c 656e 6774 6812 -a701 4375 7272 656e 7420 6e75 6d62 6572 -206f 6620 6974 656d 7320 696e 2074 6865 -2071 7565 7565 2066 6f72 2075 6e77 7269 -7474 656e 2073 616d 706c 6573 2e20 4561 -6368 2069 7465 6d20 636f 6d70 7269 7365 -7320 616c 6c20 7361 6d70 6c65 7320 6578 -706f 7365 6420 6279 206f 6e65 2074 6172 -6765 7420 6173 206f 6e65 206d 6574 7269 -6320 6661 6d69 6c79 2028 692e 652e 206d -6574 7269 6373 206f 6620 7468 6520 7361 -6d65 206e 616d 6529 2e18 0122 0b12 0909 -0000 0000 0000 0000 d902 0a29 7072 6f6d -6574 6865 7573 5f74 6172 6765 745f 696e -7465 7276 616c 5f6c 656e 6774 685f 7365 -636f 6e64 7312 2141 6374 7561 6c20 696e -7465 7276 616c 7320 6265 7477 6565 6e20 -7363 7261 7065 732e 1802 2282 010a 0f0a -0869 6e74 6572 7661 6c12 0331 3573 226f -0804 1100 0000 0000 804d 401a 1209 7b14 -ae47 e17a 843f 1100 0000 0000 002c 401a -1209 9a99 9999 9999 a93f 1100 0000 0000 -002c 401a 1209 0000 0000 0000 e03f 1100 -0000 0000 002e 401a 1209 cdcc cccc cccc -ec3f 1100 0000 0000 002e 401a 1209 ae47 -e17a 14ae ef3f 1100 0000 0000 002e 4022 -8101 0a0e 0a08 696e 7465 7276 616c 1202 -3173 226f 083a 1100 0000 0000 003c 401a -1209 7b14 ae47 e17a 843f 1100 0000 0000 -0000 001a 1209 9a99 9999 9999 a93f 1100 -0000 0000 0000 001a 1209 0000 0000 0000 -e03f 1100 0000 0000 0000 001a 1209 cdcc -cccc cccc ec3f 1100 0000 0000 00f0 3f1a -1209 ae47 e17a 14ae ef3f 1100 0000 0000 -00f0 3f \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf.gz b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf.gz deleted file mode 100644 index 62fccb616..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/protobuf.gz +++ /dev/null @@ -1,129 +0,0 @@ -1f8b 0808 efa0 c754 0003 7072 6f74 6f62 -7566 00ed 594d 8c1c c515 9eb1 8d3d 5b86 -6037 265e 8c4d ca03 c4bb ceee cc9a 9f58 -01cc f6ca 4424 041b 8837 21c8 24ed daee -9a99 cef6 1f55 d578 c7e4 b004 0e39 8088 -8448 048a 124b 4442 9110 e110 25b9 c54a -9072 01c5 9724 4a24 2472 413e 448a 8592 -1b87 bcea aeda eeea 99d9 3530 49a4 68e7 -b0bb 5355 fdde abf7 bef7 bdf7 7a3f 6ca0 -664f 88c4 61f4 8994 72e1 7829 23c2 8f23 -27f4 5d16 73ea c691 c7ad cf2d f628 fed2 -e2e2 c358 9dc3 0111 3472 7dca b11f e1f2 -d9d6 e496 e6a3 e86a b4a3 4722 2fa0 ccaa -b79b f737 6abb 6bea b3cf 9ac8 ff78 6fbe -bcf6 cedb f2f3 7763 ed8d fbff 766e cf1b -ff28 d69a df44 5621 7847 9bc0 2fc1 c727 -7e09 ed2d c45f dd26 89df 0ea9 60be 3b46 -1d67 d0f5 850e 94e9 008f b2fe f834 74d0 -8d85 865d 8506 8791 a84b ffa3 de12 8475 -e938 2352 f116 208c c701 e563 84d4 e368 -77a1 617b bbcb 48d2 1b9f f4d3 6857 21fd -aa76 8f92 647c c2bf 85ae 2b84 37da 5c40 -e6ba 6374 8de9 fc84 c590 0c3d 9aca f0de -bdfb f40b bffd 5763 fe9f 7659 8314 f0fb -9fbf 6897 35b4 dfbd 65fb d397 7f60 9735 -1c43 7f7e f5cd 975e b3df 6fa0 bd06 fb70 -ff1c 7596 fa82 720b 0f50 8edc cce8 263b -b0c9 339b 3cb3 c933 5afa ff2f cfc8 13f6 -5b17 ed01 0d73 cc1e d090 af99 1a60 ed3b -e8ba 32cd 7047 c482 04d6 cd8b f217 8ed2 -7089 321c 770c bae1 3824 1e6d 4dd6 9af7 -a29d 689b 1b7b d4da 7adb dcdc 085b d135 -68bb fc33 f6ac ad00 cd7d 13b9 b5ab 27ec -4b0d 34a9 b4f3 0470 45cb 2c77 b0c4 72f9 -ee26 cd7d 02ec 6cd2 dc26 cd7d 6ce1 ff73 -9a7b ef17 1f0e d2dc 1d3f 19a4 b9c6 f941 -9a43 e7ed c7d1 0d20 d5a5 9c3b 6e92 3a6a -2053 6437 9793 5dca 81ea c006 ccfb 5cd0 -101f 7ff8 6b58 f821 d04e 4223 2169 676d -8eab 3577 028d fd34 91dd dac5 f987 90a5 -8577 6316 a7c2 8f80 bf0e 9f5c 23cf 6215 -8b1e 11d8 4d19 0391 411f d315 9f8b d664 -bdb9 d352 b458 7bc4 7e00 5dab e585 64c5 -e9c0 9439 7582 acf8 611a 9618 3906 ab70 -c70f 28f6 2877 999f 8898 7153 d405 fb38 -daa5 45c9 f399 2c7c f2a3 c838 669f 4407 -b40c 6062 df03 cb9d 9086 31e4 79ce d437 -7d55 2de3 7c39 e3e9 124d 97c4 7de5 7b0b -2eda a7c5 018e 9870 a48f 7544 accf 9f92 -6bb9 dfc1 4040 0156 a741 6ae4 529c 46fe -0aa6 49ec f68c 88e4 3a8e a1bd b397 8efc -71e1 41b4 5feb 78d2 6722 2581 69f1 81af -e7ab 1b1a 8cad 0b0b 0e3a 5420 d2f1 22b0 -db73 8238 5e4e 13a7 43fc 2005 af28 24dd -2a6b 5611 a2fb 4e9e 9a3d 751f cecf 627d -56c3 47a3 ff21 f499 51f2 b5dc 03eb c8ad -c86b d87f a8a3 c325 81f4 4912 a404 025b -7e81 1104 bef6 f88c 94ad b770 2786 1c08 -02ac 9e82 25c0 6c0c 38a5 6e2a a82c b94f -34e3 c64e 95ba 4d99 6c4f ed91 e9f6 ac91 -e2af bc2c 3f3f 9bff 88f4 7079 7e90 1e2e -cfbf 5a47 5f28 5d28 885d 8827 871b 912e -75dc 1e75 9793 d88f c488 fb3d 6adc 6f2a -7b27 536c 4f63 1fd0 068e 94b7 2c64 0118 -6615 3654 5dce 9801 58d5 8353 69b4 5cc9 -925a ed83 3a9a 5ac7 4878 0432 50c7 f376 -6993 a8b4 58d9 2199 924c f97d a92f f1ef -332c fa49 d66e dd88 3e85 b6c9 2fd6 7697 -5122 a88e faaf 57ed e67e 74ad dadc 0122 -38f0 8ade bd70 da6e 4eca 4e2d dbdd 9af8 -d15a 0ff6 94dd bc09 ca52 be33 21a0 6e73 -d9ce e9fd f3cb 7673 1ff4 6ff9 fe55 6964 -3efb 561d dd33 f2ce 7ee4 01bb 455d 6789 -08b7 e7e4 6fc5 fa66 6c8e 3e92 9248 00ff -f00c 78d9 49ac 1fac be48 2b9e 9330 fc32 -d486 fa58 aacf 6fea 68f6 4a6f 9175 a0d6 -8269 f69a c1b9 fd79 973a 5504 5623 08c2 -921f 991e b8c0 6071 cbd7 aa17 182c 6eb0 -d641 731b db0f 8d59 0a40 2409 717d d187 -061f 10a8 bf69 a65d bb48 76d8 44f8 453b -44ad 2b55 13d0 a82b 7a39 b50c fae1 2cf1 -85d4 0219 b7a4 9452 af9a 4f5d d45e 475b -17c6 10ea 399c 8449 60b2 6f35 abd4 11ac -9f29 b3e5 eaa1 77ec dfd5 d1d1 7514 010d -fa9e 9330 1ac4 c4ab 4e49 fd61 0ad5 d962 -5862 b443 1953 1726 388a a3d9 acec cb82 -092d 07e0 bb85 177b 3e98 2849 46fa c377 -73b2 9215 3a15 1ea4 8107 c9b0 4403 e5ac -8112 121b 8c6f de41 15be 8c5d 6495 e7d6 -6d59 ecf3 1e64 807f 4a8d 4096 76d9 d346 -70f0 0bf6 8fea e8b3 57a4 905b ee3a ca4a -1a66 a0c4 b841 ea49 37b9 411c 51cd b3c0 -d82d dad2 5fce fa30 47a6 02dc 58d8 396d -5877 e979 fbcc c6c6 e57e b70e 0d37 2edf -1d71 fdd5 73f6 afea e8ce 911a 14f9 9608 -aff4 df82 230b 98a7 6148 5896 7305 c149 -1a51 0f4a 0f50 023c 925d 5933 45bc 7b7f -fbdd 5bde 7fee 6d83 299e ff61 643d 73e6 -5e83 29a0 254d 8e2d 2d1b 4c91 95e8 5f32 -fbdb eb24 95b6 bb42 1453 05c6 ab74 a19e -18c6 16df b7cf ad43 aaa6 2a45 1677 ad0b -14cd 1910 930d 54d7 6aaf d7d1 f448 dd79 -6c4b b5f8 8ea1 ac91 23e0 6315 6360 e4e6 -6174 406d 5e1f 12e8 2768 44a0 7905 3e51 -005c 3bbb c7fe 9359 7ea2 58f8 1d45 007c -78d5 fcc6 83f9 2adc be5c 8638 8db2 f4c9 -de55 6043 0e54 a358 f634 3ac3 3c16 2709 -a498 7168 ad2a 8d67 a8eb 196d b379 ad0a -c65a c38a d1b0 6b0c 09f7 6376 17dd ba81 -2285 b0b6 598e 8629 50f0 1a0a ab1f 6f31 -ea2c 4b03 ea14 6df2 88ee f3e6 c1ee 1acb -272b 4db5 1c80 2732 8919 681a 996d 1029 -88c6 51e5 d1a9 613d c215 46a3 6137 09fa -7459 c304 0303 9967 aa68 7d22 15be 9175 -55f7 5426 a5d9 6159 9739 a678 66e4 c474 -061d 2c69 d24d 4005 5433 c72b 80ca f6b3 -10a4 d159 e60b c821 dd1d 98a1 7ed3 fe6b -dd98 c94c 0d0a 4daf d58f 0f90 952f 6868 -8268 843e fc45 c9f0 f238 76e3 3061 8017 -9ecd 5dba 5da1 2b09 140d 4fd2 0e14 439c -bfee c284 67df f246 0adc 0350 ebab 02a9 -9b2b 7559 9003 5887 1fd3 5518 ff65 8b11 -a75c b223 398a 81e7 d5ed d6e6 f183 0b6e -3628 eb7d 2042 2ace 5279 1597 9124 7f0b -fbdd 3acc 1e0d 7dc4 da7a e44e 0e43 e2b6 -1c19 ab27 860c 8933 f6e0 9038 3304 7dad -214d 706b 4813 dcb2 9b4f d781 900b 23b6 -1c91 36dc a5f6 eff9 af0c aaff 06f1 48e5 -4433 2000 00 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/test.gz b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/test.gz deleted file mode 100644 index 3f8199dfb..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/test.gz +++ /dev/null @@ -1,163 +0,0 @@ -1f8b 0808 2aa1 c754 0003 7465 7874 00b5 -5b5d 939b 3816 7def 5fa1 ea79 99a9 4d3c -601b db3c f4c3 5426 55f3 309b ca6e 7ab7 -6a9e 281a d436 150c 04c4 a4bd 5df3 dff7 -4a88 361f 025d 094f 1e92 34e8 1cae 8ea4 -ab7b 04fd 03f9 ede3 ef9f c989 b122 28e9 -b79a 562c 88eb 3264 499e 05e7 242a f38a -4679 1657 e4f1 44c9 6f8f 8f9f 896c 46d2 -90d1 2c4a 6845 928c 749b aeee 7e20 8f7f -7cfe 8861 adea f339 2c2f 77fa a6af a730 -8b53 5a3e dcff 7cff ee5b 1d66 2c49 e9c3 -bdb3 f2ee ff22 ce12 027f 3101 9621 80ee -7659 90a8 28af 3366 8eeb 2042 f887 558b -7553 d158 a8a7 a4b1 d450 7259 2a69 84ee -e28a e4e7 3365 6512 dd40 d429 2e1b 6527 -b96c e5ed 10da 6a6c 4c31 0043 cbf2 7213 -9915 4c96 22ab 9816 48dc d02d 10d8 8440 -050d ca30 3bd2 db89 ace2 5b22 b592 6fa9 -e092 74a9 ec46 3403 0216 9647 7a8b cc3c -c565 29ba 9a6b 81e0 2de1 02b1 cd28 3a60 -f8b9 ca53 5a2d 2f1c 2698 2c44 9e62 b294 -f84a 6729 b029 4107 7a2c c3e2 b458 5a05 -8b85 ac2a 164b 491b 2a4b 394d c01d d889 -86c5 6225 c724 1642 2a48 2c75 144c 9632 -1a60 3ba8 8ac1 ed68 f96a 57f2 5868 a9e6 -b194 b325 b354 d40c 7e05 1665 0e45 dc89 -d68a bdca dd38 fbd5 7aef dd84 90cb e21e -bcc3 6ab7 59df 8690 336e 9cc3 7eb5 396c -8df5 eeb0 425c 7bff 70d8 ad3c 47fe 712d -46a0 4fe8 fa60 96c7 16bc 4afe 4783 a70b -a30a dfcd ef09 cf2d eeab cd76 07af 74d8 -d7fb 26b6 1a81 524c 6a0c 6a16 a675 cd9d -a67a abac 0c07 e98f d158 ac0c 5827 3c29 -c694 819d 9144 0fb1 34ba 6604 6889 4c2c -edb4 4e73 2674 4e2c 1cce cab1 9ac0 4dd4 -427a d359 ad26 fca4 4629 2d6a 81f5 3427 -31d6 0c6b 32f5 ca4d 5942 8c7e 7aac a587 -3423 3051 0fed 1667 959b f477 1ad5 1038 -2b33 6802 c7aa 6560 fb26 b59a b16a 334a -a150 c6ae 0e0b c5ea 83f4 6f93 da4c f8ae -195d b408 537b 8644 6215 c119 b149 41d4 -0e6a 460f 1dc0 c267 e1c1 5851 d08e 6a52 -9749 1f34 230d 0283 334c 6bdf b527 f017 -1368 1866 0cd0 66bb 3d1c b07a 619c 4e15 -b09c 8529 7914 7f67 f5f9 8996 247f ee39 -9e8a 9cc3 982a 8d4e 0b17 4fa6 e59d e2de -6b94 c7d0 edb5 e3dc bf53 4ac3 ff93 c70f -f7b0 8728 e3ac 0ac8 9c74 c292 3537 359e -6ccc 3030 65a3 0638 5786 87f9 96b0 79dc -8c31 1bb7 9d73 6673 1169 ad99 2918 ad85 -de9c e914 195b 2dbd 2e08 8cb1 3fb3 62c0 -eb84 7368 5ab1 d456 0ba1 1812 6868 d22c -f046 9269 6d1a 46b0 91e3 c2c9 a587 5939 -356b 1673 e1f4 5e0d 2ddf d870 1988 8800 -1bdb 352b 0623 0911 860d 239f c279 e1a4 -c300 0d3d 9b05 1e2d 19ca b5e9 0453 1a30 -bd5c 3898 8171 33c4 a245 d25a 379d 4023 -27a6 1747 0fc1 bb37 3328 5a16 9d7f d3a9 -32f4 637a 51b4 0823 0b67 8c46 2b83 3071 -3a71 148e 4caf 0f06 84f4 71ce d65f 4021 -7c98 e31d 9650 341c bb2d 52b1 9e27 5b6f -f79d 7758 5ae1 a6fc 1c5c 8f68 05cd 8b3a -685f 7a75 5d5d 5d81 a703 1252 5d2a 46cf -e4c3 e7ff 1096 9cc1 3515 3463 dc35 0d3f -1c9d 666c 8dde 740b 1819 6f18 d931 2ff3 -9a25 1938 af4f 6f16 b373 919d 4246 a2ba -2c21 9ef4 42e8 4b52 b151 309d f6c7 b03e -d23b c58d bd33 7cf4 397c 099e e38a fc33 -7c49 cef5 b963 7173 e83d 7986 7124 31ad -a232 2958 5e8e 2568 f1fd 47b6 570f aebf -1e3e 91f3 8a9b 9f0c 1ff5 06ec 3feb edf2 -7a34 e230 6992 1834 0bce f49c 432d d498 -db7f cbab a4b9 2acc f1d8 1bcf 73f4 4350 -b7f1 569b c3de f1fc 35fd 87b3 1f86 068b -bc64 019f 66ed fc20 5ff8 a566 e681 2630 -91db c610 6116 5152 67c9 0ba1 451e 9de6 -e6a4 82b8 1fac a281 bbda aed7 9bdd c1df -1e36 3b88 7624 e49f 49c9 ea30 edf7 efbf -cd45 9c8c 4a86 7e60 ca26 de6a eb6e f707 -dfe5 2a1e 3a71 c9a5 1ec4 1974 290e d23c -ff5a 17c1 7398 a435 0c47 bbc0 41c4 eb8c -fef5 d397 f75f 7e25 4d53 d236 ed86 8a22 -edac 7154 7b47 1735 225a 7d94 d8e8 da76 -7b45 54f4 cf30 ad43 587c dd4f 05d2 34e9 -7e63 dfde 21cf 3964 cd34 2512 0497 2051 -e590 9c68 5433 aa8a 5747 df9e 3ae1 21af -ddbd c671 c596 698b f696 a017 81c5 2725 -d660 5334 df70 89bb 3641 8839 45d6 1bc5 -9449 f308 966c 05d8 f048 83e8 44a3 af45 -9e64 0c33 837e 14bf 9871 bdfb 1349 20ff -c12c e5f3 e84a 0549 e5bd cc31 f218 45ec -d650 46c6 d0aa cebe 2a17 8761 606f a9c8 -12af 5ae4 430a 0815 76ab ee6a 6783 6365 -d186 6f87 a55c 504f 17be 1124 2561 9742 -b9a6 e69f a148 06b3 8057 fe98 87fb a8a4 -21e3 8706 9e7f 30c5 42ec 1594 27e2 6ba4 -ad31 38c9 00e8 af1d 5320 2bc3 ace2 27e9 -00df ba9e 29bc ceae 4fd6 8d63 92c5 5080 -65c7 e029 64d1 2968 7ecd e8d2 9f0d ff92 -0bb4 1259 5234 242d 6ef8 8b49 5798 7e7c -31cf 5664 5163 92f9 dcb6 8cce bf31 dd72 -3e91 1117 5234 29d2 359d 3dcd 8b99 fe74 -799b 28cd bc69 9afc 784d 126d 1284 95d6 -34f9 c978 e234 9ca6 3345 a046 5363 bd00 -ef2f c55b 1088 d136 c518 0fef b79a d690 -6dc2 228c 1276 11c9 feed 0759 ddbf 8db3 -686b 3086 036e cdd6 3505 7377 fc7b 53c3 -0ea5 343b b2d3 a052 6d27 e4f7 3061 bc3f -b07b 3fc9 eed1 d8b8 5ff2 1166 bd92 204c -f63e 5270 f971 5085 e722 a573 9bb1 6c41 -5a08 a627 4a72 ed2e 3c81 db38 dbbd bee6 -4a32 a8de 9238 284a 9ae6 613c 7a73 ade8 -996c 7a7d 815d d267 5a96 72ec 4292 e5d9 -7b71 c8c0 5d72 454b d8ab 5640 9480 16bc -f6e2 439b 444d 0dc7 dd7b cd62 4889 316c -6c4f 3495 e38e dacc 6603 47a8 368b d7cf -0569 3445 49c0 0f1e 9af2 549e b38c aab2 -ced1 84d8 b805 58df cbf1 4334 337b 0c70 -1dcf 37ea cc6c 473a d1bf 03b7 16a5 75cc -073e 4af3 8cb6 0535 94e6 2bba 6a7f f89e -b013 0c32 4c8c ab06 883d a71f 9141 af79 -8f11 8598 8434 f373 a2c7 f2a6 f978 4920 -2e6a d978 bbd6 e753 591e 778a 88ce 6f9b -ffd2 6ec9 3cf4 6b99 c88b 0289 e323 4543 -a80a 8450 fade cc3e 4ebb ffcf a147 75c0 -c659 6df6 fb1b 9035 47c6 9b95 b7f1 6fc1 -26e8 76eb dd6a bbdb d8f1 3515 8303 c3bb -9af5 16b3 1cb2 82d8 e3a7 88a2 8490 9971 -5048 4800 b68e 98e0 d74c f509 14ac 54d3 -1e75 6a88 c914 d596 12b0 7017 f710 5750 -2831 fa24 d42c 7d8d ad97 f9c1 ded7 8f9e -a2dd 1c87 88a1 b39f 2980 27a0 e730 8147 -6661 16f1 ad57 a63e f1a6 4521 5296 b3e4 -59d6 0895 daa7 fede 5c24 df7a e6a7 a299 -d88e c467 46a4 4703 1e28 e787 41ed 8e15 -9779 51c0 96d5 6ba4 dc97 10d1 2872 a11e -356f 930d f123 1f6b 8ab7 2018 3b5f 04a6 -c964 aaa5 d107 232c 906a 9427 d7f8 2cfb -6875 cfb6 761d 6cf8 4ac3 a30a 5b66 2aa3 -e8a7 32d3 4c5b 55dc 659d d2e0 7a0c 8f3e -bc27 1ca8 39b3 c771 2b56 0f0a f82a 5a35 -f945 880a eb5a f5ae fff6 bca3 c572 2bde -d189 048a 58bc 0557 91ff 3538 aac7 b135 -6fc6 27f8 fa25 8c71 bf4b b854 c67f c340 -4d10 2f1f a929 62f1 8bb7 8b87 eaca 0eda -9a4b 3b1e ab1e a1eb 2116 bce2 ade7 b004 -114b fd0a 997d fba9 a157 d41e 1a84 2a69 -b547 1d83 ccfc 61b0 4388 db22 5dd5 d9f7 -3261 b01f b507 33aa d027 5847 1976 a2dd -d6f1 77da 5865 26fe 30aa 5d13 46cf fd8d -6022 70f2 915b 38de 1cc4 3c17 25cc 854a -bc4b 6d8f 9ce8 4b01 c621 e665 22b8 72d2 -7c8e 48c2 4afc d41c b7c1 08c2 34ba 48a7 -de1e c149 d580 07f6 2bf8 4b59 0e29 bba3 -9168 66fb 69a2 0b78 7558 c214 904d df3e -2ef8 2512 5f09 b4b7 a1f6 a5ec 3be5 6a44 -6558 a887 5143 a9d8 6ee6 11af edf5 877b -d71b 7ca2 245e 1bbb db1b 9179 3724 f346 -19c5 9ecb bf25 9729 9948 997d 42fe 7ad0 -84a1 c992 238e b55d 8f54 53c0 b90d d568 -1fb4 a6ba 1dd3 e813 017b 2643 aae1 c8f3 -41f3 168d 7bf3 71df feee ff2d f9e8 431a -5200 00 \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/text b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/text deleted file mode 100644 index f3d8c3784..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/testdata/text +++ /dev/null @@ -1,322 +0,0 @@ -# HELP http_request_duration_microseconds The HTTP request latencies in microseconds. -# TYPE http_request_duration_microseconds summary -http_request_duration_microseconds{handler="/",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/"} 0 -http_request_duration_microseconds_count{handler="/"} 0 -http_request_duration_microseconds{handler="/alerts",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/alerts",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/alerts",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/alerts"} 0 -http_request_duration_microseconds_count{handler="/alerts"} 0 -http_request_duration_microseconds{handler="/api/metrics",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/api/metrics",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/api/metrics",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/api/metrics"} 0 -http_request_duration_microseconds_count{handler="/api/metrics"} 0 -http_request_duration_microseconds{handler="/api/query",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/api/query",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/api/query",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/api/query"} 0 -http_request_duration_microseconds_count{handler="/api/query"} 0 -http_request_duration_microseconds{handler="/api/query_range",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/api/query_range",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/api/query_range",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/api/query_range"} 0 -http_request_duration_microseconds_count{handler="/api/query_range"} 0 -http_request_duration_microseconds{handler="/api/targets",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/api/targets",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/api/targets",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/api/targets"} 0 -http_request_duration_microseconds_count{handler="/api/targets"} 0 -http_request_duration_microseconds{handler="/consoles/",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/consoles/",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/consoles/",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/consoles/"} 0 -http_request_duration_microseconds_count{handler="/consoles/"} 0 -http_request_duration_microseconds{handler="/graph",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/graph",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/graph",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/graph"} 0 -http_request_duration_microseconds_count{handler="/graph"} 0 -http_request_duration_microseconds{handler="/heap",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/heap",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/heap",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/heap"} 0 -http_request_duration_microseconds_count{handler="/heap"} 0 -http_request_duration_microseconds{handler="/static/",quantile="0.5"} 0 -http_request_duration_microseconds{handler="/static/",quantile="0.9"} 0 -http_request_duration_microseconds{handler="/static/",quantile="0.99"} 0 -http_request_duration_microseconds_sum{handler="/static/"} 0 -http_request_duration_microseconds_count{handler="/static/"} 0 -http_request_duration_microseconds{handler="prometheus",quantile="0.5"} 1307.275 -http_request_duration_microseconds{handler="prometheus",quantile="0.9"} 1858.632 -http_request_duration_microseconds{handler="prometheus",quantile="0.99"} 3087.384 -http_request_duration_microseconds_sum{handler="prometheus"} 179886.5000000001 -http_request_duration_microseconds_count{handler="prometheus"} 119 -# HELP http_request_size_bytes The HTTP request sizes in bytes. -# TYPE http_request_size_bytes summary -http_request_size_bytes{handler="/",quantile="0.5"} 0 -http_request_size_bytes{handler="/",quantile="0.9"} 0 -http_request_size_bytes{handler="/",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/"} 0 -http_request_size_bytes_count{handler="/"} 0 -http_request_size_bytes{handler="/alerts",quantile="0.5"} 0 -http_request_size_bytes{handler="/alerts",quantile="0.9"} 0 -http_request_size_bytes{handler="/alerts",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/alerts"} 0 -http_request_size_bytes_count{handler="/alerts"} 0 -http_request_size_bytes{handler="/api/metrics",quantile="0.5"} 0 -http_request_size_bytes{handler="/api/metrics",quantile="0.9"} 0 -http_request_size_bytes{handler="/api/metrics",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/api/metrics"} 0 -http_request_size_bytes_count{handler="/api/metrics"} 0 -http_request_size_bytes{handler="/api/query",quantile="0.5"} 0 -http_request_size_bytes{handler="/api/query",quantile="0.9"} 0 -http_request_size_bytes{handler="/api/query",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/api/query"} 0 -http_request_size_bytes_count{handler="/api/query"} 0 -http_request_size_bytes{handler="/api/query_range",quantile="0.5"} 0 -http_request_size_bytes{handler="/api/query_range",quantile="0.9"} 0 -http_request_size_bytes{handler="/api/query_range",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/api/query_range"} 0 -http_request_size_bytes_count{handler="/api/query_range"} 0 -http_request_size_bytes{handler="/api/targets",quantile="0.5"} 0 -http_request_size_bytes{handler="/api/targets",quantile="0.9"} 0 -http_request_size_bytes{handler="/api/targets",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/api/targets"} 0 -http_request_size_bytes_count{handler="/api/targets"} 0 -http_request_size_bytes{handler="/consoles/",quantile="0.5"} 0 -http_request_size_bytes{handler="/consoles/",quantile="0.9"} 0 -http_request_size_bytes{handler="/consoles/",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/consoles/"} 0 -http_request_size_bytes_count{handler="/consoles/"} 0 -http_request_size_bytes{handler="/graph",quantile="0.5"} 0 -http_request_size_bytes{handler="/graph",quantile="0.9"} 0 -http_request_size_bytes{handler="/graph",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/graph"} 0 -http_request_size_bytes_count{handler="/graph"} 0 -http_request_size_bytes{handler="/heap",quantile="0.5"} 0 -http_request_size_bytes{handler="/heap",quantile="0.9"} 0 -http_request_size_bytes{handler="/heap",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/heap"} 0 -http_request_size_bytes_count{handler="/heap"} 0 -http_request_size_bytes{handler="/static/",quantile="0.5"} 0 -http_request_size_bytes{handler="/static/",quantile="0.9"} 0 -http_request_size_bytes{handler="/static/",quantile="0.99"} 0 -http_request_size_bytes_sum{handler="/static/"} 0 -http_request_size_bytes_count{handler="/static/"} 0 -http_request_size_bytes{handler="prometheus",quantile="0.5"} 291 -http_request_size_bytes{handler="prometheus",quantile="0.9"} 291 -http_request_size_bytes{handler="prometheus",quantile="0.99"} 291 -http_request_size_bytes_sum{handler="prometheus"} 34488 -http_request_size_bytes_count{handler="prometheus"} 119 -# HELP http_requests_total Total number of HTTP requests made. -# TYPE http_requests_total counter -http_requests_total{code="200",handler="prometheus",method="get"} 119 -# HELP http_response_size_bytes The HTTP response sizes in bytes. -# TYPE http_response_size_bytes summary -http_response_size_bytes{handler="/",quantile="0.5"} 0 -http_response_size_bytes{handler="/",quantile="0.9"} 0 -http_response_size_bytes{handler="/",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/"} 0 -http_response_size_bytes_count{handler="/"} 0 -http_response_size_bytes{handler="/alerts",quantile="0.5"} 0 -http_response_size_bytes{handler="/alerts",quantile="0.9"} 0 -http_response_size_bytes{handler="/alerts",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/alerts"} 0 -http_response_size_bytes_count{handler="/alerts"} 0 -http_response_size_bytes{handler="/api/metrics",quantile="0.5"} 0 -http_response_size_bytes{handler="/api/metrics",quantile="0.9"} 0 -http_response_size_bytes{handler="/api/metrics",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/api/metrics"} 0 -http_response_size_bytes_count{handler="/api/metrics"} 0 -http_response_size_bytes{handler="/api/query",quantile="0.5"} 0 -http_response_size_bytes{handler="/api/query",quantile="0.9"} 0 -http_response_size_bytes{handler="/api/query",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/api/query"} 0 -http_response_size_bytes_count{handler="/api/query"} 0 -http_response_size_bytes{handler="/api/query_range",quantile="0.5"} 0 -http_response_size_bytes{handler="/api/query_range",quantile="0.9"} 0 -http_response_size_bytes{handler="/api/query_range",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/api/query_range"} 0 -http_response_size_bytes_count{handler="/api/query_range"} 0 -http_response_size_bytes{handler="/api/targets",quantile="0.5"} 0 -http_response_size_bytes{handler="/api/targets",quantile="0.9"} 0 -http_response_size_bytes{handler="/api/targets",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/api/targets"} 0 -http_response_size_bytes_count{handler="/api/targets"} 0 -http_response_size_bytes{handler="/consoles/",quantile="0.5"} 0 -http_response_size_bytes{handler="/consoles/",quantile="0.9"} 0 -http_response_size_bytes{handler="/consoles/",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/consoles/"} 0 -http_response_size_bytes_count{handler="/consoles/"} 0 -http_response_size_bytes{handler="/graph",quantile="0.5"} 0 -http_response_size_bytes{handler="/graph",quantile="0.9"} 0 -http_response_size_bytes{handler="/graph",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/graph"} 0 -http_response_size_bytes_count{handler="/graph"} 0 -http_response_size_bytes{handler="/heap",quantile="0.5"} 0 -http_response_size_bytes{handler="/heap",quantile="0.9"} 0 -http_response_size_bytes{handler="/heap",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/heap"} 0 -http_response_size_bytes_count{handler="/heap"} 0 -http_response_size_bytes{handler="/static/",quantile="0.5"} 0 -http_response_size_bytes{handler="/static/",quantile="0.9"} 0 -http_response_size_bytes{handler="/static/",quantile="0.99"} 0 -http_response_size_bytes_sum{handler="/static/"} 0 -http_response_size_bytes_count{handler="/static/"} 0 -http_response_size_bytes{handler="prometheus",quantile="0.5"} 2049 -http_response_size_bytes{handler="prometheus",quantile="0.9"} 2058 -http_response_size_bytes{handler="prometheus",quantile="0.99"} 2064 -http_response_size_bytes_sum{handler="prometheus"} 247001 -http_response_size_bytes_count{handler="prometheus"} 119 -# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. -# TYPE process_cpu_seconds_total counter -process_cpu_seconds_total 0.55 -# HELP go_goroutines Number of goroutines that currently exist. -# TYPE go_goroutines gauge -go_goroutines 70 -# HELP process_max_fds Maximum number of open file descriptors. -# TYPE process_max_fds gauge -process_max_fds 8192 -# HELP process_open_fds Number of open file descriptors. -# TYPE process_open_fds gauge -process_open_fds 29 -# HELP process_resident_memory_bytes Resident memory size in bytes. -# TYPE process_resident_memory_bytes gauge -process_resident_memory_bytes 5.3870592e+07 -# HELP process_start_time_seconds Start time of the process since unix epoch in seconds. -# TYPE process_start_time_seconds gauge -process_start_time_seconds 1.42236894836e+09 -# HELP process_virtual_memory_bytes Virtual memory size in bytes. -# TYPE process_virtual_memory_bytes gauge -process_virtual_memory_bytes 5.41478912e+08 -# HELP prometheus_dns_sd_lookup_failures_total The number of DNS-SD lookup failures. -# TYPE prometheus_dns_sd_lookup_failures_total counter -prometheus_dns_sd_lookup_failures_total 0 -# HELP prometheus_dns_sd_lookups_total The number of DNS-SD lookups. -# TYPE prometheus_dns_sd_lookups_total counter -prometheus_dns_sd_lookups_total 7 -# HELP prometheus_evaluator_duration_milliseconds The duration for all evaluations to execute. -# TYPE prometheus_evaluator_duration_milliseconds summary -prometheus_evaluator_duration_milliseconds{quantile="0.01"} 0 -prometheus_evaluator_duration_milliseconds{quantile="0.05"} 0 -prometheus_evaluator_duration_milliseconds{quantile="0.5"} 0 -prometheus_evaluator_duration_milliseconds{quantile="0.9"} 1 -prometheus_evaluator_duration_milliseconds{quantile="0.99"} 1 -prometheus_evaluator_duration_milliseconds_sum 12 -prometheus_evaluator_duration_milliseconds_count 23 -# HELP prometheus_local_storage_checkpoint_duration_milliseconds The duration (in milliseconds) it took to checkpoint in-memory metrics and head chunks. -# TYPE prometheus_local_storage_checkpoint_duration_milliseconds gauge -prometheus_local_storage_checkpoint_duration_milliseconds 0 -# HELP prometheus_local_storage_chunk_ops_total The total number of chunk operations by their type. -# TYPE prometheus_local_storage_chunk_ops_total counter -prometheus_local_storage_chunk_ops_total{type="create"} 598 -prometheus_local_storage_chunk_ops_total{type="persist"} 174 -prometheus_local_storage_chunk_ops_total{type="pin"} 920 -prometheus_local_storage_chunk_ops_total{type="transcode"} 415 -prometheus_local_storage_chunk_ops_total{type="unpin"} 920 -# HELP prometheus_local_storage_indexing_batch_latency_milliseconds Quantiles for batch indexing latencies in milliseconds. -# TYPE prometheus_local_storage_indexing_batch_latency_milliseconds summary -prometheus_local_storage_indexing_batch_latency_milliseconds{quantile="0.5"} 0 -prometheus_local_storage_indexing_batch_latency_milliseconds{quantile="0.9"} 0 -prometheus_local_storage_indexing_batch_latency_milliseconds{quantile="0.99"} 0 -prometheus_local_storage_indexing_batch_latency_milliseconds_sum 0 -prometheus_local_storage_indexing_batch_latency_milliseconds_count 1 -# HELP prometheus_local_storage_indexing_batch_sizes Quantiles for indexing batch sizes (number of metrics per batch). -# TYPE prometheus_local_storage_indexing_batch_sizes summary -prometheus_local_storage_indexing_batch_sizes{quantile="0.5"} 2 -prometheus_local_storage_indexing_batch_sizes{quantile="0.9"} 2 -prometheus_local_storage_indexing_batch_sizes{quantile="0.99"} 2 -prometheus_local_storage_indexing_batch_sizes_sum 2 -prometheus_local_storage_indexing_batch_sizes_count 1 -# HELP prometheus_local_storage_indexing_queue_capacity The capacity of the indexing queue. -# TYPE prometheus_local_storage_indexing_queue_capacity gauge -prometheus_local_storage_indexing_queue_capacity 16384 -# HELP prometheus_local_storage_indexing_queue_length The number of metrics waiting to be indexed. -# TYPE prometheus_local_storage_indexing_queue_length gauge -prometheus_local_storage_indexing_queue_length 0 -# HELP prometheus_local_storage_ingested_samples_total The total number of samples ingested. -# TYPE prometheus_local_storage_ingested_samples_total counter -prometheus_local_storage_ingested_samples_total 30473 -# HELP prometheus_local_storage_invalid_preload_requests_total The total number of preload requests referring to a non-existent series. This is an indication of outdated label indexes. -# TYPE prometheus_local_storage_invalid_preload_requests_total counter -prometheus_local_storage_invalid_preload_requests_total 0 -# HELP prometheus_local_storage_memory_chunkdescs The current number of chunk descriptors in memory. -# TYPE prometheus_local_storage_memory_chunkdescs gauge -prometheus_local_storage_memory_chunkdescs 1059 -# HELP prometheus_local_storage_memory_chunks The current number of chunks in memory, excluding cloned chunks (i.e. chunks without a descriptor). -# TYPE prometheus_local_storage_memory_chunks gauge -prometheus_local_storage_memory_chunks 1020 -# HELP prometheus_local_storage_memory_series The current number of series in memory. -# TYPE prometheus_local_storage_memory_series gauge -prometheus_local_storage_memory_series 424 -# HELP prometheus_local_storage_persist_latency_microseconds A summary of latencies for persisting each chunk. -# TYPE prometheus_local_storage_persist_latency_microseconds summary -prometheus_local_storage_persist_latency_microseconds{quantile="0.5"} 30.377 -prometheus_local_storage_persist_latency_microseconds{quantile="0.9"} 203.539 -prometheus_local_storage_persist_latency_microseconds{quantile="0.99"} 2626.463 -prometheus_local_storage_persist_latency_microseconds_sum 20424.415 -prometheus_local_storage_persist_latency_microseconds_count 174 -# HELP prometheus_local_storage_persist_queue_capacity The total capacity of the persist queue. -# TYPE prometheus_local_storage_persist_queue_capacity gauge -prometheus_local_storage_persist_queue_capacity 1024 -# HELP prometheus_local_storage_persist_queue_length The current number of chunks waiting in the persist queue. -# TYPE prometheus_local_storage_persist_queue_length gauge -prometheus_local_storage_persist_queue_length 0 -# HELP prometheus_local_storage_series_ops_total The total number of series operations by their type. -# TYPE prometheus_local_storage_series_ops_total counter -prometheus_local_storage_series_ops_total{type="create"} 2 -prometheus_local_storage_series_ops_total{type="maintenance_in_memory"} 11 -# HELP prometheus_notifications_latency_milliseconds Latency quantiles for sending alert notifications (not including dropped notifications). -# TYPE prometheus_notifications_latency_milliseconds summary -prometheus_notifications_latency_milliseconds{quantile="0.5"} 0 -prometheus_notifications_latency_milliseconds{quantile="0.9"} 0 -prometheus_notifications_latency_milliseconds{quantile="0.99"} 0 -prometheus_notifications_latency_milliseconds_sum 0 -prometheus_notifications_latency_milliseconds_count 0 -# HELP prometheus_notifications_queue_capacity The capacity of the alert notifications queue. -# TYPE prometheus_notifications_queue_capacity gauge -prometheus_notifications_queue_capacity 100 -# HELP prometheus_notifications_queue_length The number of alert notifications in the queue. -# TYPE prometheus_notifications_queue_length gauge -prometheus_notifications_queue_length 0 -# HELP prometheus_rule_evaluation_duration_milliseconds The duration for a rule to execute. -# TYPE prometheus_rule_evaluation_duration_milliseconds summary -prometheus_rule_evaluation_duration_milliseconds{rule_type="alerting",quantile="0.5"} 0 -prometheus_rule_evaluation_duration_milliseconds{rule_type="alerting",quantile="0.9"} 0 -prometheus_rule_evaluation_duration_milliseconds{rule_type="alerting",quantile="0.99"} 2 -prometheus_rule_evaluation_duration_milliseconds_sum{rule_type="alerting"} 12 -prometheus_rule_evaluation_duration_milliseconds_count{rule_type="alerting"} 115 -prometheus_rule_evaluation_duration_milliseconds{rule_type="recording",quantile="0.5"} 0 -prometheus_rule_evaluation_duration_milliseconds{rule_type="recording",quantile="0.9"} 0 -prometheus_rule_evaluation_duration_milliseconds{rule_type="recording",quantile="0.99"} 3 -prometheus_rule_evaluation_duration_milliseconds_sum{rule_type="recording"} 15 -prometheus_rule_evaluation_duration_milliseconds_count{rule_type="recording"} 115 -# HELP prometheus_rule_evaluation_failures_total The total number of rule evaluation failures. -# TYPE prometheus_rule_evaluation_failures_total counter -prometheus_rule_evaluation_failures_total 0 -# HELP prometheus_samples_queue_capacity Capacity of the queue for unwritten samples. -# TYPE prometheus_samples_queue_capacity gauge -prometheus_samples_queue_capacity 4096 -# HELP prometheus_samples_queue_length Current number of items in the queue for unwritten samples. Each item comprises all samples exposed by one target as one metric family (i.e. metrics of the same name). -# TYPE prometheus_samples_queue_length gauge -prometheus_samples_queue_length 0 -# HELP prometheus_target_interval_length_seconds Actual intervals between scrapes. -# TYPE prometheus_target_interval_length_seconds summary -prometheus_target_interval_length_seconds{interval="15s",quantile="0.01"} 14 -prometheus_target_interval_length_seconds{interval="15s",quantile="0.05"} 14 -prometheus_target_interval_length_seconds{interval="15s",quantile="0.5"} 15 -prometheus_target_interval_length_seconds{interval="15s",quantile="0.9"} 15 -prometheus_target_interval_length_seconds{interval="15s",quantile="0.99"} 15 -prometheus_target_interval_length_seconds_sum{interval="15s"} 175 -prometheus_target_interval_length_seconds_count{interval="15s"} 12 -prometheus_target_interval_length_seconds{interval="1s",quantile="0.01"} 0 -prometheus_target_interval_length_seconds{interval="1s",quantile="0.05"} 0 -prometheus_target_interval_length_seconds{interval="1s",quantile="0.5"} 0 -prometheus_target_interval_length_seconds{interval="1s",quantile="0.9"} 1 -prometheus_target_interval_length_seconds{interval="1s",quantile="0.99"} 1 -prometheus_target_interval_length_seconds_sum{interval="1s"} 55 -prometheus_target_interval_length_seconds_count{interval="1s"} 117 diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_create_test.go b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_create_test.go deleted file mode 100644 index e4cc5d803..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_create_test.go +++ /dev/null @@ -1,443 +0,0 @@ -// Copyright 2014 The Prometheus 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 expfmt - -import ( - "bytes" - "math" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - - dto "github.com/prometheus/client_model/go" -) - -func testCreate(t testing.TB) { - var scenarios = []struct { - in *dto.MetricFamily - out string - }{ - // 0: Counter, NaN as value, timestamp given. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("two-line\n doc str\\ing"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(math.NaN()), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(.23), - }, - TimestampMs: proto.Int64(1234567890), - }, - }, - }, - out: `# HELP name two-line\n doc str\\ing -# TYPE name counter -name{labelname="val1",basename="basevalue"} NaN -name{labelname="val2",basename="basevalue"} 0.23 1234567890 -`, - }, - // 1: Gauge, some escaping required, +Inf as value, multi-byte characters in label values. - { - in: &dto.MetricFamily{ - Name: proto.String("gauge_name"), - Help: proto.String("gauge\ndoc\nstr\"ing"), - Type: dto.MetricType_GAUGE.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("val with\nnew line"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("val with \\backslash and \"quotes\""), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(math.Inf(+1)), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("Björn"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("佖佥"), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(3.14E42), - }, - }, - }, - }, - out: `# HELP gauge_name gauge\ndoc\nstr"ing -# TYPE gauge_name gauge -gauge_name{name_1="val with\nnew line",name_2="val with \\backslash and \"quotes\""} +Inf -gauge_name{name_1="Björn",name_2="佖佥"} 3.14e+42 -`, - }, - // 2: Untyped, no help, one sample with no labels and -Inf as value, another sample with one label. - { - in: &dto.MetricFamily{ - Name: proto.String("untyped_name"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("value 1"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(-1.23e-45), - }, - }, - }, - }, - out: `# TYPE untyped_name untyped -untyped_name -Inf -untyped_name{name_1="value 1"} -1.23e-45 -`, - }, - // 3: Summary. - { - in: &dto.MetricFamily{ - Name: proto.String("summary_name"), - Help: proto.String("summary docstring"), - Type: dto.MetricType_SUMMARY.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Summary: &dto.Summary{ - SampleCount: proto.Uint64(42), - SampleSum: proto.Float64(-3.4567), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.5), - Value: proto.Float64(-1.23), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.9), - Value: proto.Float64(.2342354), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.99), - Value: proto.Float64(0), - }, - }, - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("name_1"), - Value: proto.String("value 1"), - }, - &dto.LabelPair{ - Name: proto.String("name_2"), - Value: proto.String("value 2"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(4711), - SampleSum: proto.Float64(2010.1971), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.5), - Value: proto.Float64(1), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.9), - Value: proto.Float64(2), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.99), - Value: proto.Float64(3), - }, - }, - }, - }, - }, - }, - out: `# HELP summary_name summary docstring -# TYPE summary_name summary -summary_name{quantile="0.5"} -1.23 -summary_name{quantile="0.9"} 0.2342354 -summary_name{quantile="0.99"} 0 -summary_name_sum -3.4567 -summary_name_count 42 -summary_name{name_1="value 1",name_2="value 2",quantile="0.5"} 1 -summary_name{name_1="value 1",name_2="value 2",quantile="0.9"} 2 -summary_name{name_1="value 1",name_2="value 2",quantile="0.99"} 3 -summary_name_sum{name_1="value 1",name_2="value 2"} 2010.1971 -summary_name_count{name_1="value 1",name_2="value 2"} 4711 -`, - }, - // 4: Histogram - { - in: &dto.MetricFamily{ - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - &dto.Bucket{ - UpperBound: proto.Float64(math.Inf(+1)), - CumulativeCount: proto.Uint64(2693), - }, - }, - }, - }, - }, - }, - out: `# HELP request_duration_microseconds The response latency. -# TYPE request_duration_microseconds histogram -request_duration_microseconds_bucket{le="100"} 123 -request_duration_microseconds_bucket{le="120"} 412 -request_duration_microseconds_bucket{le="144"} 592 -request_duration_microseconds_bucket{le="172.8"} 1524 -request_duration_microseconds_bucket{le="+Inf"} 2693 -request_duration_microseconds_sum 1.7560473e+06 -request_duration_microseconds_count 2693 -`, - }, - // 5: Histogram with missing +Inf bucket. - { - in: &dto.MetricFamily{ - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - }, - }, - }, - }, - }, - out: `# HELP request_duration_microseconds The response latency. -# TYPE request_duration_microseconds histogram -request_duration_microseconds_bucket{le="100"} 123 -request_duration_microseconds_bucket{le="120"} 412 -request_duration_microseconds_bucket{le="144"} 592 -request_duration_microseconds_bucket{le="172.8"} 1524 -request_duration_microseconds_bucket{le="+Inf"} 2693 -request_duration_microseconds_sum 1.7560473e+06 -request_duration_microseconds_count 2693 -`, - }, - // 6: No metric type, should result in default type Counter. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("doc string"), - Metric: []*dto.Metric{ - &dto.Metric{ - Counter: &dto.Counter{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - out: `# HELP name doc string -# TYPE name counter -name -Inf -`, - }, - } - - for i, scenario := range scenarios { - out := bytes.NewBuffer(make([]byte, 0, len(scenario.out))) - n, err := MetricFamilyToText(out, scenario.in) - if err != nil { - t.Errorf("%d. error: %s", i, err) - continue - } - if expected, got := len(scenario.out), n; expected != got { - t.Errorf( - "%d. expected %d bytes written, got %d", - i, expected, got, - ) - } - if expected, got := scenario.out, out.String(); expected != got { - t.Errorf( - "%d. expected out=%q, got %q", - i, expected, got, - ) - } - } - -} - -func TestCreate(t *testing.T) { - testCreate(t) -} - -func BenchmarkCreate(b *testing.B) { - for i := 0; i < b.N; i++ { - testCreate(b) - } -} - -func testCreateError(t testing.TB) { - var scenarios = []struct { - in *dto.MetricFamily - err string - }{ - // 0: No metric. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("doc string"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{}, - }, - err: "MetricFamily has no metrics", - }, - // 1: No metric name. - { - in: &dto.MetricFamily{ - Help: proto.String("doc string"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - err: "MetricFamily has no name", - }, - // 2: Wrong type. - { - in: &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("doc string"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - err: "expected counter in metric", - }, - } - - for i, scenario := range scenarios { - var out bytes.Buffer - _, err := MetricFamilyToText(&out, scenario.in) - if err == nil { - t.Errorf("%d. expected error, got nil", i) - continue - } - if expected, got := scenario.err, err.Error(); strings.Index(got, expected) != 0 { - t.Errorf( - "%d. expected error starting with %q, got %q", - i, expected, got, - ) - } - } - -} - -func TestCreateError(t *testing.T) { - testCreateError(t) -} - -func BenchmarkCreateError(b *testing.B) { - for i := 0; i < b.N; i++ { - testCreateError(b) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_parse_test.go b/Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_parse_test.go deleted file mode 100644 index 589c87a9d..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/expfmt/text_parse_test.go +++ /dev/null @@ -1,586 +0,0 @@ -// Copyright 2014 The Prometheus 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 expfmt - -import ( - "math" - "strings" - "testing" - - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" -) - -func testTextParse(t testing.TB) { - var scenarios = []struct { - in string - out []*dto.MetricFamily - }{ - // 0: Empty lines as input. - { - in: ` - -`, - out: []*dto.MetricFamily{}, - }, - // 1: Minimal case. - { - in: ` -minimal_metric 1.234 -another_metric -3e3 103948 -# Even that: -no_labels{} 3 -# HELP line for non-existing metric will be ignored. -`, - out: []*dto.MetricFamily{ - &dto.MetricFamily{ - Name: proto.String("minimal_metric"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(1.234), - }, - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("another_metric"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(-3e3), - }, - TimestampMs: proto.Int64(103948), - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("no_labels"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(3), - }, - }, - }, - }, - }, - }, - // 2: Counters & gauges, docstrings, various whitespace, escape sequences. - { - in: ` -# A normal comment. -# -# TYPE name counter -name{labelname="val1",basename="basevalue"} NaN -name {labelname="val2",basename="base\"v\\al\nue"} 0.23 1234567890 -# HELP name two-line\n doc str\\ing - - # HELP name2 doc str"ing 2 - # TYPE name2 gauge -name2{labelname="val2" ,basename = "basevalue2" } +Inf 54321 -name2{ labelname = "val1" , }-Inf -`, - out: []*dto.MetricFamily{ - &dto.MetricFamily{ - Name: proto.String("name"), - Help: proto.String("two-line\n doc str\\ing"), - Type: dto.MetricType_COUNTER.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(math.NaN()), - }, - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("base\"v\\al\nue"), - }, - }, - Counter: &dto.Counter{ - Value: proto.Float64(.23), - }, - TimestampMs: proto.Int64(1234567890), - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("name2"), - Help: proto.String("doc str\"ing 2"), - Type: dto.MetricType_GAUGE.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("basename"), - Value: proto.String("basevalue2"), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(math.Inf(+1)), - }, - TimestampMs: proto.Int64(54321), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("labelname"), - Value: proto.String("val1"), - }, - }, - Gauge: &dto.Gauge{ - Value: proto.Float64(math.Inf(-1)), - }, - }, - }, - }, - }, - }, - // 3: The evil summary, mixed with other types and funny comments. - { - in: ` -# TYPE my_summary summary -my_summary{n1="val1",quantile="0.5"} 110 -decoy -1 -2 -my_summary{n1="val1",quantile="0.9"} 140 1 -my_summary_count{n1="val1"} 42 -# Latest timestamp wins in case of a summary. -my_summary_sum{n1="val1"} 4711 2 -fake_sum{n1="val1"} 2001 -# TYPE another_summary summary -another_summary_count{n2="val2",n1="val1"} 20 -my_summary_count{n2="val2",n1="val1"} 5 5 -another_summary{n1="val1",n2="val2",quantile=".3"} -1.2 -my_summary_sum{n1="val2"} 08 15 -my_summary{n1="val3", quantile="0.2"} 4711 - my_summary{n1="val1",n2="val2",quantile="-12.34",} NaN -# some -# funny comments -# HELP -# HELP -# HELP my_summary -# HELP my_summary -`, - out: []*dto.MetricFamily{ - &dto.MetricFamily{ - Name: proto.String("fake_sum"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Untyped: &dto.Untyped{ - Value: proto.Float64(2001), - }, - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("decoy"), - Type: dto.MetricType_UNTYPED.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Untyped: &dto.Untyped{ - Value: proto.Float64(-1), - }, - TimestampMs: proto.Int64(-2), - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("my_summary"), - Type: dto.MetricType_SUMMARY.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(42), - SampleSum: proto.Float64(4711), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.5), - Value: proto.Float64(110), - }, - &dto.Quantile{ - Quantile: proto.Float64(0.9), - Value: proto.Float64(140), - }, - }, - }, - TimestampMs: proto.Int64(2), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n2"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(5), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(-12.34), - Value: proto.Float64(math.NaN()), - }, - }, - }, - TimestampMs: proto.Int64(5), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val2"), - }, - }, - Summary: &dto.Summary{ - SampleSum: proto.Float64(8), - }, - TimestampMs: proto.Int64(15), - }, - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val3"), - }, - }, - Summary: &dto.Summary{ - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.2), - Value: proto.Float64(4711), - }, - }, - }, - }, - }, - }, - &dto.MetricFamily{ - Name: proto.String("another_summary"), - Type: dto.MetricType_SUMMARY.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Label: []*dto.LabelPair{ - &dto.LabelPair{ - Name: proto.String("n2"), - Value: proto.String("val2"), - }, - &dto.LabelPair{ - Name: proto.String("n1"), - Value: proto.String("val1"), - }, - }, - Summary: &dto.Summary{ - SampleCount: proto.Uint64(20), - Quantile: []*dto.Quantile{ - &dto.Quantile{ - Quantile: proto.Float64(0.3), - Value: proto.Float64(-1.2), - }, - }, - }, - }, - }, - }, - }, - }, - // 4: The histogram. - { - in: ` -# HELP request_duration_microseconds The response latency. -# TYPE request_duration_microseconds histogram -request_duration_microseconds_bucket{le="100"} 123 -request_duration_microseconds_bucket{le="120"} 412 -request_duration_microseconds_bucket{le="144"} 592 -request_duration_microseconds_bucket{le="172.8"} 1524 -request_duration_microseconds_bucket{le="+Inf"} 2693 -request_duration_microseconds_sum 1.7560473e+06 -request_duration_microseconds_count 2693 -`, - out: []*dto.MetricFamily{ - { - Name: proto.String("request_duration_microseconds"), - Help: proto.String("The response latency."), - Type: dto.MetricType_HISTOGRAM.Enum(), - Metric: []*dto.Metric{ - &dto.Metric{ - Histogram: &dto.Histogram{ - SampleCount: proto.Uint64(2693), - SampleSum: proto.Float64(1756047.3), - Bucket: []*dto.Bucket{ - &dto.Bucket{ - UpperBound: proto.Float64(100), - CumulativeCount: proto.Uint64(123), - }, - &dto.Bucket{ - UpperBound: proto.Float64(120), - CumulativeCount: proto.Uint64(412), - }, - &dto.Bucket{ - UpperBound: proto.Float64(144), - CumulativeCount: proto.Uint64(592), - }, - &dto.Bucket{ - UpperBound: proto.Float64(172.8), - CumulativeCount: proto.Uint64(1524), - }, - &dto.Bucket{ - UpperBound: proto.Float64(math.Inf(+1)), - CumulativeCount: proto.Uint64(2693), - }, - }, - }, - }, - }, - }, - }, - }, - } - - for i, scenario := range scenarios { - out, err := parser.TextToMetricFamilies(strings.NewReader(scenario.in)) - if err != nil { - t.Errorf("%d. error: %s", i, err) - continue - } - if expected, got := len(scenario.out), len(out); expected != got { - t.Errorf( - "%d. expected %d MetricFamilies, got %d", - i, expected, got, - ) - } - for _, expected := range scenario.out { - got, ok := out[expected.GetName()] - if !ok { - t.Errorf( - "%d. expected MetricFamily %q, found none", - i, expected.GetName(), - ) - continue - } - if expected.String() != got.String() { - t.Errorf( - "%d. expected MetricFamily %s, got %s", - i, expected, got, - ) - } - } - } -} - -func TestTextParse(t *testing.T) { - testTextParse(t) -} - -func BenchmarkTextParse(b *testing.B) { - for i := 0; i < b.N; i++ { - testTextParse(b) - } -} - -func testTextParseError(t testing.TB) { - var scenarios = []struct { - in string - err string - }{ - // 0: No new-line at end of input. - { - in: `bla 3.14`, - err: "EOF", - }, - // 1: Invalid escape sequence in label value. - { - in: `metric{label="\t"} 3.14`, - err: "text format parsing error in line 1: invalid escape sequence", - }, - // 2: Newline in label value. - { - in: ` -metric{label="new -line"} 3.14 -`, - err: `text format parsing error in line 2: label value "new" contains unescaped new-line`, - }, - // 3: - { - in: `metric{@="bla"} 3.14`, - err: "text format parsing error in line 1: invalid label name for metric", - }, - // 4: - { - in: `metric{__name__="bla"} 3.14`, - err: `text format parsing error in line 1: label name "__name__" is reserved`, - }, - // 5: - { - in: `metric{label+="bla"} 3.14`, - err: "text format parsing error in line 1: expected '=' after label name", - }, - // 6: - { - in: `metric{label=bla} 3.14`, - err: "text format parsing error in line 1: expected '\"' at start of label value", - }, - // 7: - { - in: ` -# TYPE metric summary -metric{quantile="bla"} 3.14 -`, - err: "text format parsing error in line 3: expected float as value for 'quantile' label", - }, - // 8: - { - in: `metric{label="bla"+} 3.14`, - err: "text format parsing error in line 1: unexpected end of label value", - }, - // 9: - { - in: `metric{label="bla"} 3.14 2.72 -`, - err: "text format parsing error in line 1: expected integer as timestamp", - }, - // 10: - { - in: `metric{label="bla"} 3.14 2 3 -`, - err: "text format parsing error in line 1: spurious string after timestamp", - }, - // 11: - { - in: `metric{label="bla"} blubb -`, - err: "text format parsing error in line 1: expected float as value", - }, - // 12: - { - in: ` -# HELP metric one -# HELP metric two -`, - err: "text format parsing error in line 3: second HELP line for metric name", - }, - // 13: - { - in: ` -# TYPE metric counter -# TYPE metric untyped -`, - err: `text format parsing error in line 3: second TYPE line for metric name "metric", or TYPE reported after samples`, - }, - // 14: - { - in: ` -metric 4.12 -# TYPE metric counter -`, - err: `text format parsing error in line 3: second TYPE line for metric name "metric", or TYPE reported after samples`, - }, - // 14: - { - in: ` -# TYPE metric bla -`, - err: "text format parsing error in line 2: unknown metric type", - }, - // 15: - { - in: ` -# TYPE met-ric -`, - err: "text format parsing error in line 2: invalid metric name in comment", - }, - // 16: - { - in: `@invalidmetric{label="bla"} 3.14 2`, - err: "text format parsing error in line 1: invalid metric name", - }, - // 17: - { - in: `{label="bla"} 3.14 2`, - err: "text format parsing error in line 1: invalid metric name", - }, - // 18: - { - in: ` -# TYPE metric histogram -metric_bucket{le="bla"} 3.14 -`, - err: "text format parsing error in line 3: expected float as value for 'le' label", - }, - } - - for i, scenario := range scenarios { - _, err := parser.TextToMetricFamilies(strings.NewReader(scenario.in)) - if err == nil { - t.Errorf("%d. expected error, got nil", i) - continue - } - if expected, got := scenario.err, err.Error(); strings.Index(got, expected) != 0 { - t.Errorf( - "%d. expected error starting with %q, got %q", - i, expected, got, - ) - } - } - -} - -func TestTextParseError(t *testing.T) { - testTextParseError(t) -} - -func BenchmarkParseError(b *testing.B) { - for i := 0; i < b.N; i++ { - testTextParseError(b) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/model/labels_test.go b/Godeps/_workspace/src/github.com/prometheus/common/model/labels_test.go deleted file mode 100644 index ab17025c7..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/model/labels_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2013 The Prometheus 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 model - -import ( - "sort" - "testing" -) - -func testLabelNames(t testing.TB) { - var scenarios = []struct { - in LabelNames - out LabelNames - }{ - { - in: LabelNames{"ZZZ", "zzz"}, - out: LabelNames{"ZZZ", "zzz"}, - }, - { - in: LabelNames{"aaa", "AAA"}, - out: LabelNames{"AAA", "aaa"}, - }, - } - - for i, scenario := range scenarios { - sort.Sort(scenario.in) - - for j, expected := range scenario.out { - if expected != scenario.in[j] { - t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j]) - } - } - } -} - -func TestLabelNames(t *testing.T) { - testLabelNames(t) -} - -func BenchmarkLabelNames(b *testing.B) { - for i := 0; i < b.N; i++ { - testLabelNames(b) - } -} - -func testLabelValues(t testing.TB) { - var scenarios = []struct { - in LabelValues - out LabelValues - }{ - { - in: LabelValues{"ZZZ", "zzz"}, - out: LabelValues{"ZZZ", "zzz"}, - }, - { - in: LabelValues{"aaa", "AAA"}, - out: LabelValues{"AAA", "aaa"}, - }, - } - - for i, scenario := range scenarios { - sort.Sort(scenario.in) - - for j, expected := range scenario.out { - if expected != scenario.in[j] { - t.Errorf("%d.%d expected %s, got %s", i, j, expected, scenario.in[j]) - } - } - } -} - -func TestLabelValues(t *testing.T) { - testLabelValues(t) -} - -func BenchmarkLabelValues(b *testing.B) { - for i := 0; i < b.N; i++ { - testLabelValues(b) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/model/metric_test.go b/Godeps/_workspace/src/github.com/prometheus/common/model/metric_test.go deleted file mode 100644 index 5c7cfceaf..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/model/metric_test.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2013 The Prometheus 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 model - -import "testing" - -func testMetric(t testing.TB) { - var scenarios = []struct { - input LabelSet - fingerprint Fingerprint - fastFingerprint Fingerprint - }{ - { - input: LabelSet{}, - fingerprint: 14695981039346656037, - fastFingerprint: 14695981039346656037, - }, - { - input: LabelSet{ - "first_name": "electro", - "occupation": "robot", - "manufacturer": "westinghouse", - }, - fingerprint: 5911716720268894962, - fastFingerprint: 11310079640881077873, - }, - { - input: LabelSet{ - "x": "y", - }, - fingerprint: 8241431561484471700, - fastFingerprint: 13948396922932177635, - }, - { - input: LabelSet{ - "a": "bb", - "b": "c", - }, - fingerprint: 3016285359649981711, - fastFingerprint: 3198632812309449502, - }, - { - input: LabelSet{ - "a": "b", - "bb": "c", - }, - fingerprint: 7122421792099404749, - fastFingerprint: 5774953389407657638, - }, - } - - for i, scenario := range scenarios { - input := Metric(scenario.input) - - if scenario.fingerprint != input.Fingerprint() { - t.Errorf("%d. expected %d, got %d", i, scenario.fingerprint, input.Fingerprint()) - } - if scenario.fastFingerprint != input.FastFingerprint() { - t.Errorf("%d. expected %d, got %d", i, scenario.fastFingerprint, input.FastFingerprint()) - } - } -} - -func TestMetric(t *testing.T) { - testMetric(t) -} - -func BenchmarkMetric(b *testing.B) { - for i := 0; i < b.N; i++ { - testMetric(b) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/model/signature_test.go b/Godeps/_workspace/src/github.com/prometheus/common/model/signature_test.go deleted file mode 100644 index d9c665f8c..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/model/signature_test.go +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright 2014 The Prometheus 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 model - -import ( - "runtime" - "sync" - "testing" -) - -func TestLabelsToSignature(t *testing.T) { - var scenarios = []struct { - in map[string]string - out uint64 - }{ - { - in: map[string]string{}, - out: 14695981039346656037, - }, - { - in: map[string]string{"name": "garland, briggs", "fear": "love is not enough"}, - out: 5799056148416392346, - }, - } - - for i, scenario := range scenarios { - actual := LabelsToSignature(scenario.in) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestMetricToFingerprint(t *testing.T) { - var scenarios = []struct { - in LabelSet - out Fingerprint - }{ - { - in: LabelSet{}, - out: 14695981039346656037, - }, - { - in: LabelSet{"name": "garland, briggs", "fear": "love is not enough"}, - out: 5799056148416392346, - }, - } - - for i, scenario := range scenarios { - actual := labelSetToFingerprint(scenario.in) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestMetricToFastFingerprint(t *testing.T) { - var scenarios = []struct { - in LabelSet - out Fingerprint - }{ - { - in: LabelSet{}, - out: 14695981039346656037, - }, - { - in: LabelSet{"name": "garland, briggs", "fear": "love is not enough"}, - out: 12952432476264840823, - }, - } - - for i, scenario := range scenarios { - actual := labelSetToFastFingerprint(scenario.in) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestSignatureForLabels(t *testing.T) { - var scenarios = []struct { - in Metric - labels LabelNames - out uint64 - }{ - { - in: Metric{}, - labels: nil, - out: 14695981039346656037, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: LabelNames{"fear", "name"}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"}, - labels: LabelNames{"fear", "name"}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: LabelNames{}, - out: 14695981039346656037, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: nil, - out: 14695981039346656037, - }, - } - - for i, scenario := range scenarios { - actual := SignatureForLabels(scenario.in, scenario.labels...) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func TestSignatureWithoutLabels(t *testing.T) { - var scenarios = []struct { - in Metric - labels map[LabelName]struct{} - out uint64 - }{ - { - in: Metric{}, - labels: nil, - out: 14695981039346656037, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: map[LabelName]struct{}{"fear": struct{}{}, "name": struct{}{}}, - out: 14695981039346656037, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"}, - labels: map[LabelName]struct{}{"foo": struct{}{}}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: map[LabelName]struct{}{}, - out: 5799056148416392346, - }, - { - in: Metric{"name": "garland, briggs", "fear": "love is not enough"}, - labels: nil, - out: 5799056148416392346, - }, - } - - for i, scenario := range scenarios { - actual := SignatureWithoutLabels(scenario.in, scenario.labels) - - if actual != scenario.out { - t.Errorf("%d. expected %d, got %d", i, scenario.out, actual) - } - } -} - -func benchmarkLabelToSignature(b *testing.B, l map[string]string, e uint64) { - for i := 0; i < b.N; i++ { - if a := LabelsToSignature(l); a != e { - b.Fatalf("expected signature of %d for %s, got %d", e, l, a) - } - } -} - -func BenchmarkLabelToSignatureScalar(b *testing.B) { - benchmarkLabelToSignature(b, nil, 14695981039346656037) -} - -func BenchmarkLabelToSignatureSingle(b *testing.B) { - benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value"}, 5146282821936882169) -} - -func BenchmarkLabelToSignatureDouble(b *testing.B) { - benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717) -} - -func BenchmarkLabelToSignatureTriple(b *testing.B) { - benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121) -} - -func benchmarkMetricToFingerprint(b *testing.B, ls LabelSet, e Fingerprint) { - for i := 0; i < b.N; i++ { - if a := labelSetToFingerprint(ls); a != e { - b.Fatalf("expected signature of %d for %s, got %d", e, ls, a) - } - } -} - -func BenchmarkMetricToFingerprintScalar(b *testing.B) { - benchmarkMetricToFingerprint(b, nil, 14695981039346656037) -} - -func BenchmarkMetricToFingerprintSingle(b *testing.B) { - benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5146282821936882169) -} - -func BenchmarkMetricToFingerprintDouble(b *testing.B) { - benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717) -} - -func BenchmarkMetricToFingerprintTriple(b *testing.B) { - benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121) -} - -func benchmarkMetricToFastFingerprint(b *testing.B, ls LabelSet, e Fingerprint) { - for i := 0; i < b.N; i++ { - if a := labelSetToFastFingerprint(ls); a != e { - b.Fatalf("expected signature of %d for %s, got %d", e, ls, a) - } - } -} - -func BenchmarkMetricToFastFingerprintScalar(b *testing.B) { - benchmarkMetricToFastFingerprint(b, nil, 14695981039346656037) -} - -func BenchmarkMetricToFastFingerprintSingle(b *testing.B) { - benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5147259542624943964) -} - -func BenchmarkMetricToFastFingerprintDouble(b *testing.B) { - benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 18269973311206963528) -} - -func BenchmarkMetricToFastFingerprintTriple(b *testing.B) { - benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676) -} - -func BenchmarkEmptyLabelSignature(b *testing.B) { - input := []map[string]string{nil, {}} - - var ms runtime.MemStats - runtime.ReadMemStats(&ms) - - alloc := ms.Alloc - - for _, labels := range input { - LabelsToSignature(labels) - } - - runtime.ReadMemStats(&ms) - - if got := ms.Alloc; alloc != got { - b.Fatal("expected LabelsToSignature with empty labels not to perform allocations") - } -} - -func benchmarkMetricToFastFingerprintConc(b *testing.B, ls LabelSet, e Fingerprint, concLevel int) { - var start, end sync.WaitGroup - start.Add(1) - end.Add(concLevel) - - for i := 0; i < concLevel; i++ { - go func() { - start.Wait() - for j := b.N / concLevel; j >= 0; j-- { - if a := labelSetToFastFingerprint(ls); a != e { - b.Fatalf("expected signature of %d for %s, got %d", e, ls, a) - } - } - end.Done() - }() - } - b.ResetTimer() - start.Done() - end.Wait() -} - -func BenchmarkMetricToFastFingerprintTripleConc1(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 1) -} - -func BenchmarkMetricToFastFingerprintTripleConc2(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 2) -} - -func BenchmarkMetricToFastFingerprintTripleConc4(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 4) -} - -func BenchmarkMetricToFastFingerprintTripleConc8(b *testing.B) { - benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 8) -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/model/time_test.go b/Godeps/_workspace/src/github.com/prometheus/common/model/time_test.go deleted file mode 100644 index 9013a6277..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/model/time_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013 The Prometheus 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 model - -import ( - "testing" - "time" -) - -func TestComparators(t *testing.T) { - t1a := TimeFromUnix(0) - t1b := TimeFromUnix(0) - t2 := TimeFromUnix(2*second - 1) - - if !t1a.Equal(t1b) { - t.Fatalf("Expected %s to be equal to %s", t1a, t1b) - } - if t1a.Equal(t2) { - t.Fatalf("Expected %s to not be equal to %s", t1a, t2) - } - - if !t1a.Before(t2) { - t.Fatalf("Expected %s to be before %s", t1a, t2) - } - if t1a.Before(t1b) { - t.Fatalf("Expected %s to not be before %s", t1a, t1b) - } - - if !t2.After(t1a) { - t.Fatalf("Expected %s to be after %s", t2, t1a) - } - if t1b.After(t1a) { - t.Fatalf("Expected %s to not be after %s", t1b, t1a) - } -} - -func TestTimeConversions(t *testing.T) { - unixSecs := int64(1136239445) - unixNsecs := int64(123456789) - unixNano := unixSecs*1e9 + unixNsecs - - t1 := time.Unix(unixSecs, unixNsecs-unixNsecs%nanosPerTick) - t2 := time.Unix(unixSecs, unixNsecs) - - ts := TimeFromUnixNano(unixNano) - if !ts.Time().Equal(t1) { - t.Fatalf("Expected %s, got %s", t1, ts.Time()) - } - - // Test available precision. - ts = TimeFromUnixNano(t2.UnixNano()) - if !ts.Time().Equal(t1) { - t.Fatalf("Expected %s, got %s", t1, ts.Time()) - } - - if ts.UnixNano() != unixNano-unixNano%nanosPerTick { - t.Fatalf("Expected %d, got %d", unixNano, ts.UnixNano()) - } -} - -func TestDuration(t *testing.T) { - duration := time.Second + time.Minute + time.Hour - goTime := time.Unix(1136239445, 0) - - ts := TimeFromUnix(goTime.Unix()) - if !goTime.Add(duration).Equal(ts.Add(duration).Time()) { - t.Fatalf("Expected %s to be equal to %s", goTime.Add(duration), ts.Add(duration)) - } - - earlier := ts.Add(-duration) - delta := ts.Sub(earlier) - if delta != duration { - t.Fatalf("Expected %s to be equal to %s", delta, duration) - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/common/model/value_test.go b/Godeps/_workspace/src/github.com/prometheus/common/model/value_test.go deleted file mode 100644 index 2e9c7eb09..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/common/model/value_test.go +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright 2013 The Prometheus 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 model - -import ( - "encoding/json" - "math" - "reflect" - "sort" - "testing" -) - -func TestSamplePairJSON(t *testing.T) { - input := []struct { - plain string - value SamplePair - }{ - { - plain: `[1234.567,"123.1"]`, - value: SamplePair{ - Value: 123.1, - Timestamp: 1234567, - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sp SamplePair - err = json.Unmarshal(b, &sp) - if err != nil { - t.Error(err) - continue - } - - if sp != test.value { - t.Errorf("decoding error: expected %v, got %v", test.value, sp) - } - } -} - -func TestSampleJSON(t *testing.T) { - input := []struct { - plain string - value Sample - }{ - { - plain: `{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]}`, - value: Sample{ - Metric: Metric{ - MetricNameLabel: "test_metric", - }, - Value: 123.1, - Timestamp: 1234567, - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sv Sample - err = json.Unmarshal(b, &sv) - if err != nil { - t.Error(err) - continue - } - - if !reflect.DeepEqual(sv, test.value) { - t.Errorf("decoding error: expected %v, got %v", test.value, sv) - } - } -} - -func TestVectorJSON(t *testing.T) { - input := []struct { - plain string - value Vector - }{ - { - plain: `[]`, - value: Vector{}, - }, - { - plain: `[{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]}]`, - value: Vector{&Sample{ - Metric: Metric{ - MetricNameLabel: "test_metric", - }, - Value: 123.1, - Timestamp: 1234567, - }}, - }, - { - plain: `[{"metric":{"__name__":"test_metric"},"value":[1234.567,"123.1"]},{"metric":{"foo":"bar"},"value":[1.234,"+Inf"]}]`, - value: Vector{ - &Sample{ - Metric: Metric{ - MetricNameLabel: "test_metric", - }, - Value: 123.1, - Timestamp: 1234567, - }, - &Sample{ - Metric: Metric{ - "foo": "bar", - }, - Value: SampleValue(math.Inf(1)), - Timestamp: 1234, - }, - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var vec Vector - err = json.Unmarshal(b, &vec) - if err != nil { - t.Error(err) - continue - } - - if !reflect.DeepEqual(vec, test.value) { - t.Errorf("decoding error: expected %v, got %v", test.value, vec) - } - } -} - -func TestScalarJSON(t *testing.T) { - input := []struct { - plain string - value Scalar - }{ - { - plain: `[123.456,"456"]`, - value: Scalar{ - Timestamp: 123456, - Value: 456, - }, - }, - { - plain: `[123123.456,"+Inf"]`, - value: Scalar{ - Timestamp: 123123456, - Value: SampleValue(math.Inf(1)), - }, - }, - { - plain: `[123123.456,"-Inf"]`, - value: Scalar{ - Timestamp: 123123456, - Value: SampleValue(math.Inf(-1)), - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sv Scalar - err = json.Unmarshal(b, &sv) - if err != nil { - t.Error(err) - continue - } - - if sv != test.value { - t.Errorf("decoding error: expected %v, got %v", test.value, sv) - } - } -} - -func TestStringJSON(t *testing.T) { - input := []struct { - plain string - value String - }{ - { - plain: `[123.456,"test"]`, - value: String{ - Timestamp: 123456, - Value: "test", - }, - }, - { - plain: `[123123.456,"台北"]`, - value: String{ - Timestamp: 123123456, - Value: "台北", - }, - }, - } - - for _, test := range input { - b, err := json.Marshal(test.value) - if err != nil { - t.Error(err) - continue - } - - if string(b) != test.plain { - t.Errorf("encoding error: expected %q, got %q", test.plain, b) - continue - } - - var sv String - err = json.Unmarshal(b, &sv) - if err != nil { - t.Error(err) - continue - } - - if sv != test.value { - t.Errorf("decoding error: expected %v, got %v", test.value, sv) - } - } -} - -func TestVectorSort(t *testing.T) { - input := Vector{ - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 2, - }, - } - - expected := Vector{ - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "A", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "B", - }, - Timestamp: 2, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 1, - }, - &Sample{ - Metric: Metric{ - MetricNameLabel: "C", - }, - Timestamp: 2, - }, - } - - sort.Sort(input) - - for i, actual := range input { - actualFp := actual.Metric.Fingerprint() - expectedFp := expected[i].Metric.Fingerprint() - - if actualFp != expectedFp { - t.Fatalf("%d. Incorrect fingerprint. Got %s; want %s", i, actualFp.String(), expectedFp.String()) - } - - if actual.Timestamp != expected[i].Timestamp { - t.Fatalf("%d. Incorrect timestamp. Got %s; want %s", i, actual.Timestamp, expected[i].Timestamp) - } - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/cmdline b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/cmdline deleted file mode 100644 index d2d8ef887..000000000 Binary files a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/cmdline and /dev/null differ diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/0 b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/0 deleted file mode 100644 index e69de29bb..000000000 diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/1 b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/1 deleted file mode 100644 index e69de29bb..000000000 diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/2 b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/2 deleted file mode 100644 index e69de29bb..000000000 diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/3 b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/3 deleted file mode 100644 index e69de29bb..000000000 diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/4 b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/fd/4 deleted file mode 100644 index e69de29bb..000000000 diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/limits b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/limits deleted file mode 100644 index 23c6b6898..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/limits +++ /dev/null @@ -1,17 +0,0 @@ -Limit Soft Limit Hard Limit Units -Max cpu time unlimited unlimited seconds -Max file size unlimited unlimited bytes -Max data size unlimited unlimited bytes -Max stack size 8388608 unlimited bytes -Max core file size 0 unlimited bytes -Max resident set unlimited unlimited bytes -Max processes 62898 62898 processes -Max open files 2048 4096 files -Max locked memory 65536 65536 bytes -Max address space unlimited unlimited bytes -Max file locks unlimited unlimited locks -Max pending signals 62898 62898 signals -Max msgqueue size 819200 819200 bytes -Max nice priority 0 0 -Max realtime priority 0 0 -Max realtime timeout unlimited unlimited us diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/stat b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/stat deleted file mode 100644 index 438aaa9dc..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/26231/stat +++ /dev/null @@ -1 +0,0 @@ -26231 (vim) R 5392 7446 5392 34835 7446 4218880 32533 309516 26 82 1677 44 158 99 20 0 1 0 82375 56274944 1981 18446744073709551615 4194304 6294284 140736914091744 140736914087944 139965136429984 0 0 12288 1870679807 0 0 0 17 0 0 0 31 0 0 8391624 8481048 16420864 140736914093252 140736914093279 140736914093279 140736914096107 0 diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/584/stat b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/584/stat deleted file mode 100644 index 65b9369d1..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/584/stat +++ /dev/null @@ -1,2 +0,0 @@ -1020 ((a b ) ( c d) ) R 28378 1020 28378 34842 1020 4218880 286 0 0 0 0 0 0 0 20 0 1 0 10839175 10395648 155 18446744073709551615 4194304 4238788 140736466511168 140736466511168 140609271124624 0 0 0 0 0 0 0 17 5 0 0 0 0 0 6336016 6337300 25579520 140736466515030 140736466515061 140736466515061 140736466518002 0 -#!/bin/cat /proc/self/stat diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/stat b/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/stat deleted file mode 100644 index dabb96f74..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/fixtures/stat +++ /dev/null @@ -1,16 +0,0 @@ -cpu 301854 612 111922 8979004 3552 2 3944 0 0 0 -cpu0 44490 19 21045 1087069 220 1 3410 0 0 0 -cpu1 47869 23 16474 1110787 591 0 46 0 0 0 -cpu2 46504 36 15916 1112321 441 0 326 0 0 0 -cpu3 47054 102 15683 1113230 533 0 60 0 0 0 -cpu4 28413 25 10776 1140321 217 0 8 0 0 0 -cpu5 29271 101 11586 1136270 672 0 30 0 0 0 -cpu6 29152 36 10276 1139721 319 0 29 0 0 0 -cpu7 29098 268 10164 1139282 555 0 31 0 0 0 -intr 8885917 17 0 0 0 0 0 0 0 1 79281 0 0 0 0 0 0 0 231237 0 0 0 0 250586 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 223424 190745 13 906 1283803 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -ctxt 38014093 -btime 1418183276 -processes 26442 -procs_running 2 -procs_blocked 0 -softirq 5057579 250191 1481983 1647 211099 186066 0 1783454 622196 12499 508444 diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/fs_test.go b/Godeps/_workspace/src/github.com/prometheus/procfs/fs_test.go deleted file mode 100644 index 91f1c6c97..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/fs_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package procfs - -import "testing" - -func TestNewFS(t *testing.T) { - if _, err := NewFS("foobar"); err == nil { - t.Error("want NewFS to fail for non-existing mount point") - } - - if _, err := NewFS("procfs.go"); err == nil { - t.Error("want NewFS to fail if mount point is not a directory") - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/proc_limits_test.go b/Godeps/_workspace/src/github.com/prometheus/procfs/proc_limits_test.go deleted file mode 100644 index ca7a254da..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/proc_limits_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package procfs - -import "testing" - -func TestNewLimits(t *testing.T) { - fs, err := NewFS("fixtures") - if err != nil { - t.Fatal(err) - } - - p, err := fs.NewProc(26231) - if err != nil { - t.Fatal(err) - } - - l, err := p.NewLimits() - if err != nil { - t.Fatal(err) - } - - for _, test := range []struct { - name string - want int - got int - }{ - {name: "cpu time", want: -1, got: l.CPUTime}, - {name: "open files", want: 2048, got: l.OpenFiles}, - {name: "msgqueue size", want: 819200, got: l.MsqqueueSize}, - {name: "nice priority", want: 0, got: l.NicePriority}, - {name: "address space", want: -1, got: l.AddressSpace}, - } { - if test.want != test.got { - t.Errorf("want %s %d, got %d", test.name, test.want, test.got) - } - } -} diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/proc_stat_test.go b/Godeps/_workspace/src/github.com/prometheus/procfs/proc_stat_test.go deleted file mode 100644 index e4d5cacfa..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/proc_stat_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package procfs - -import "testing" - -func TestProcStat(t *testing.T) { - fs, err := NewFS("fixtures") - if err != nil { - t.Fatal(err) - } - - p, err := fs.NewProc(26231) - if err != nil { - t.Fatal(err) - } - - s, err := p.NewStat() - if err != nil { - t.Fatal(err) - } - - for _, test := range []struct { - name string - want int - got int - }{ - {name: "pid", want: 26231, got: s.PID}, - {name: "user time", want: 1677, got: int(s.UTime)}, - {name: "system time", want: 44, got: int(s.STime)}, - {name: "start time", want: 82375, got: int(s.Starttime)}, - {name: "virtual memory size", want: 56274944, got: s.VSize}, - {name: "resident set size", want: 1981, got: s.RSS}, - } { - if test.want != test.got { - t.Errorf("want %s %d, got %d", test.name, test.want, test.got) - } - } -} - -func TestProcStatComm(t *testing.T) { - s1, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - if want, got := "vim", s1.Comm; want != got { - t.Errorf("want comm %s, got %s", want, got) - } - - s2, err := testProcStat(584) - if err != nil { - t.Fatal(err) - } - if want, got := "(a b ) ( c d) ", s2.Comm; want != got { - t.Errorf("want comm %s, got %s", want, got) - } -} - -func TestProcStatVirtualMemory(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - if want, got := 56274944, s.VirtualMemory(); want != got { - t.Errorf("want virtual memory %d, got %d", want, got) - } -} - -func TestProcStatResidentMemory(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - if want, got := 1981*4096, s.ResidentMemory(); want != got { - t.Errorf("want resident memory %d, got %d", want, got) - } -} - -func TestProcStatStartTime(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - time, err := s.StartTime() - if err != nil { - t.Fatal(err) - } - if want, got := 1418184099.75, time; want != got { - t.Errorf("want start time %f, got %f", want, got) - } -} - -func TestProcStatCPUTime(t *testing.T) { - s, err := testProcStat(26231) - if err != nil { - t.Fatal(err) - } - - if want, got := 17.21, s.CPUTime(); want != got { - t.Errorf("want cpu time %f, got %f", want, got) - } -} - -func testProcStat(pid int) (ProcStat, error) { - p, err := testProcess(pid) - if err != nil { - return ProcStat{}, err - } - - return p.NewStat() -} diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/proc_test.go b/Godeps/_workspace/src/github.com/prometheus/procfs/proc_test.go deleted file mode 100644 index bd234a14c..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/proc_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package procfs - -import ( - "os" - "reflect" - "sort" - "testing" -) - -func TestSelf(t *testing.T) { - p1, err := NewProc(os.Getpid()) - if err != nil { - t.Fatal(err) - } - p2, err := Self() - if err != nil { - t.Fatal(err) - } - - if !reflect.DeepEqual(p1, p2) { - t.Errorf("want process %v to equal %v", p1, p2) - } -} - -func TestAllProcs(t *testing.T) { - fs, err := NewFS("fixtures") - if err != nil { - t.Fatal(err) - } - procs, err := fs.AllProcs() - if err != nil { - t.Fatal(err) - } - sort.Sort(procs) - for i, p := range []*Proc{{PID: 584}, {PID: 26231}} { - if want, got := p.PID, procs[i].PID; want != got { - t.Errorf("want processes %d, got %d", want, got) - } - } -} - -func TestCmdLine(t *testing.T) { - p1, err := testProcess(26231) - if err != nil { - t.Fatal(err) - } - c, err := p1.CmdLine() - if err != nil { - t.Fatal(err) - } - if want := []string{"vim", "test.go", "+10"}; !reflect.DeepEqual(want, c) { - t.Errorf("want cmdline %v, got %v", want, c) - } -} - -func TestFileDescriptors(t *testing.T) { - p1, err := testProcess(26231) - if err != nil { - t.Fatal(err) - } - fds, err := p1.FileDescriptors() - if err != nil { - t.Fatal(err) - } - sort.Sort(byUintptr(fds)) - if want := []uintptr{0, 1, 2, 3, 4}; !reflect.DeepEqual(want, fds) { - t.Errorf("want fds %v, got %v", want, fds) - } - - p2, err := Self() - if err != nil { - t.Fatal(err) - } - - fdsBefore, err := p2.FileDescriptors() - if err != nil { - t.Fatal(err) - } - - s, err := os.Open("fixtures") - if err != nil { - t.Fatal(err) - } - defer s.Close() - - fdsAfter, err := p2.FileDescriptors() - if err != nil { - t.Fatal(err) - } - - if len(fdsBefore)+1 != len(fdsAfter) { - t.Errorf("want fds %v+1 to equal %v", fdsBefore, fdsAfter) - } -} - -func TestFileDescriptorsLen(t *testing.T) { - p1, err := testProcess(26231) - if err != nil { - t.Fatal(err) - } - l, err := p1.FileDescriptorsLen() - if err != nil { - t.Fatal(err) - } - if want, got := 5, l; want != got { - t.Errorf("want fds %d, got %d", want, got) - } -} - -func testProcess(pid int) (Proc, error) { - fs, err := NewFS("fixtures") - if err != nil { - return Proc{}, err - } - - return fs.NewProc(pid) -} - -type byUintptr []uintptr - -func (a byUintptr) Len() int { return len(a) } -func (a byUintptr) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byUintptr) Less(i, j int) bool { return a[i] < a[j] } diff --git a/Godeps/_workspace/src/github.com/prometheus/procfs/stat_test.go b/Godeps/_workspace/src/github.com/prometheus/procfs/stat_test.go deleted file mode 100644 index 24b5d61f8..000000000 --- a/Godeps/_workspace/src/github.com/prometheus/procfs/stat_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package procfs - -import "testing" - -func TestStat(t *testing.T) { - fs, err := NewFS("fixtures") - if err != nil { - t.Fatal(err) - } - - s, err := fs.NewStat() - if err != nil { - t.Fatal(err) - } - - if want, got := int64(1418183276), s.BootTime; want != got { - t.Errorf("want boot time %d, got %d", want, got) - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/bash_completions_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/bash_completions_test.go deleted file mode 100644 index 6957f8bd8..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/bash_completions_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package cobra - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "strings" - "testing" -) - -var _ = fmt.Println -var _ = os.Stderr - -func checkOmit(t *testing.T, found, unexpected string) { - if strings.Contains(found, unexpected) { - t.Errorf("Unexpected response.\nGot: %q\nBut should not have!\n", unexpected) - } -} - -func check(t *testing.T, found, expected string) { - if !strings.Contains(found, expected) { - t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - } -} - -func runShellCheck(s string) error { - excluded := []string{ - "SC2034", // PREFIX appears unused. Verify it or export it. - } - cmd := exec.Command("shellcheck", "-s", "bash", "-", "-e", strings.Join(excluded, ",")) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - stdin, err := cmd.StdinPipe() - if err != nil { - return err - } - go func() { - defer stdin.Close() - stdin.Write([]byte(s)) - }() - - return cmd.Run() -} - -// World worst custom function, just keep telling you to enter hello! -const ( - bashCompletionFunc = `__custom_func() { -COMPREPLY=( "hello" ) -} -` -) - -func TestBashCompletions(t *testing.T) { - c := initializeWithRootCmd() - cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdEcho, cmdPrint, cmdDeprecated, cmdColon) - - // custom completion function - c.BashCompletionFunction = bashCompletionFunc - - // required flag - c.MarkFlagRequired("introot") - - // valid nouns - validArgs := []string{"pod", "node", "service", "replicationcontroller"} - c.ValidArgs = validArgs - - // noun aliases - argAliases := []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"} - c.ArgAliases = argAliases - - // filename - var flagval string - c.Flags().StringVar(&flagval, "filename", "", "Enter a filename") - c.MarkFlagFilename("filename", "json", "yaml", "yml") - - // persistent filename - var flagvalPersistent string - c.PersistentFlags().StringVar(&flagvalPersistent, "persistent-filename", "", "Enter a filename") - c.MarkPersistentFlagFilename("persistent-filename") - c.MarkPersistentFlagRequired("persistent-filename") - - // filename extensions - var flagvalExt string - c.Flags().StringVar(&flagvalExt, "filename-ext", "", "Enter a filename (extension limited)") - c.MarkFlagFilename("filename-ext") - - // filename extensions - var flagvalCustom string - c.Flags().StringVar(&flagvalCustom, "custom", "", "Enter a filename (extension limited)") - c.MarkFlagCustom("custom", "__complete_custom") - - // subdirectories in a given directory - var flagvalTheme string - c.Flags().StringVar(&flagvalTheme, "theme", "", "theme to use (located in /themes/THEMENAME/)") - c.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"}) - - out := new(bytes.Buffer) - c.GenBashCompletion(out) - str := out.String() - - check(t, str, "_cobra-test") - check(t, str, "_cobra-test_echo") - check(t, str, "_cobra-test_echo_times") - check(t, str, "_cobra-test_print") - check(t, str, "_cobra-test_cmd__colon") - - // check for required flags - check(t, str, `must_have_one_flag+=("--introot=")`) - check(t, str, `must_have_one_flag+=("--persistent-filename=")`) - // check for custom completion function - check(t, str, `COMPREPLY=( "hello" )`) - // check for required nouns - check(t, str, `must_have_one_noun+=("pod")`) - // check for noun aliases - check(t, str, `noun_aliases+=("pods")`) - check(t, str, `noun_aliases+=("rc")`) - checkOmit(t, str, `must_have_one_noun+=("pods")`) - // check for filename extension flags - check(t, str, `flags_completion+=("_filedir")`) - // check for filename extension flags - check(t, str, `flags_completion+=("__handle_filename_extension_flag json|yaml|yml")`) - // check for custom flags - check(t, str, `flags_completion+=("__complete_custom")`) - // check for subdirs_in_dir flags - check(t, str, `flags_completion+=("__handle_subdirs_in_dir_flag themes")`) - - checkOmit(t, str, cmdDeprecated.Name()) - - // if available, run shellcheck against the script - if err := exec.Command("which", "shellcheck").Run(); err != nil { - return - } - err := runShellCheck(str) - if err != nil { - t.Fatalf("shellcheck failed: %v", err) - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/add.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/add.go deleted file mode 100644 index b89d4c474..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/add.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright © 2015 Steve Francia . -// -// 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 cmd - -import ( - "fmt" - "path/filepath" - "strings" - - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -func init() { - RootCmd.AddCommand(addCmd) -} - -var pName string - -// initialize Command -var addCmd = &cobra.Command{ - Use: "add [command name]", - Aliases: []string{"command"}, - Short: "Add a command to a Cobra Application", - Long: `Add (cobra add) will create a new command, with a license and -the appropriate structure for a Cobra-based CLI application, -and register it to its parent (default RootCmd). - -If you want your command to be public, pass in the command name -with an initial uppercase letter. - -Example: cobra add server -> resulting in a new cmd/server.go - `, - - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 1 { - er("add needs a name for the command") - } - guessProjectPath() - createCmdFile(args[0]) - }, -} - -func init() { - addCmd.Flags().StringVarP(&pName, "parent", "p", "RootCmd", "name of parent command for this command") -} - -func parentName() string { - if !strings.HasSuffix(strings.ToLower(pName), "cmd") { - return pName + "Cmd" - } - - return pName -} - -func createCmdFile(cmdName string) { - lic := getLicense() - - template := `{{ comment .copyright }} -{{ comment .license }} - -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -// {{.cmdName}}Cmd represents the {{.cmdName}} command -var {{ .cmdName }}Cmd = &cobra.Command{ - Use: "{{ .cmdName }}", - Short: "A brief description of your command", - Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples -and usage of using your command. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.` + "`" + `, - Run: func(cmd *cobra.Command, args []string) { - // TODO: Work your own magic here - fmt.Println("{{ .cmdName }} called") - }, -} - -func init() { - {{ .parentName }}.AddCommand({{ .cmdName }}Cmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // {{.cmdName}}Cmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // {{.cmdName}}Cmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") - -} -` - - var data map[string]interface{} - data = make(map[string]interface{}) - - data["copyright"] = copyrightLine() - data["license"] = lic.Header - data["appName"] = projectName() - data["viper"] = viper.GetBool("useViper") - data["parentName"] = parentName() - data["cmdName"] = cmdName - - err := writeTemplateToFile(filepath.Join(ProjectPath(), guessCmdDir()), cmdName+".go", template, data) - if err != nil { - er(err) - } - fmt.Println(cmdName, "created at", filepath.Join(ProjectPath(), guessCmdDir(), cmdName+".go")) -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/helpers.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/helpers.go deleted file mode 100644 index f8b79b1fc..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/helpers.go +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright © 2015 Steve Francia . -// -// 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 cmd - -import ( - "bytes" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "text/template" - "time" - - "github.com/spf13/viper" -) - -// var BaseDir = "" -// var AppName = "" -// var CommandDir = "" - -var funcMap template.FuncMap -var projectPath = "" -var inputPath = "" -var projectBase = "" - -// for testing only -var testWd = "" - -var cmdDirs = []string{"cmd", "cmds", "command", "commands"} - -func init() { - funcMap = template.FuncMap{ - "comment": commentifyString, - } -} - -func er(msg interface{}) { - fmt.Println("Error:", msg) - os.Exit(-1) -} - -// Check if a file or directory exists. -func exists(path string) (bool, error) { - _, err := os.Stat(path) - if err == nil { - return true, nil - } - if os.IsNotExist(err) { - return false, nil - } - return false, err -} - -func ProjectPath() string { - if projectPath == "" { - guessProjectPath() - } - - return projectPath -} - -// wrapper of the os package so we can test better -func getWd() (string, error) { - if testWd == "" { - return os.Getwd() - } - return testWd, nil -} - -func guessCmdDir() string { - guessProjectPath() - if b, _ := isEmpty(projectPath); b { - return "cmd" - } - - files, _ := filepath.Glob(projectPath + string(os.PathSeparator) + "c*") - for _, f := range files { - for _, c := range cmdDirs { - if f == c { - return c - } - } - } - - return "cmd" -} - -func guessImportPath() string { - guessProjectPath() - - if !strings.HasPrefix(projectPath, getSrcPath()) { - er("Cobra only supports project within $GOPATH") - } - - return filepath.ToSlash(filepath.Clean(strings.TrimPrefix(projectPath, getSrcPath()))) -} - -func getSrcPath() string { - return filepath.Join(os.Getenv("GOPATH"), "src") + string(os.PathSeparator) -} - -func projectName() string { - return filepath.Base(ProjectPath()) -} - -func guessProjectPath() { - // if no path is provided... assume CWD. - if inputPath == "" { - x, err := getWd() - if err != nil { - er(err) - } - - // inspect CWD - base := filepath.Base(x) - - // if we are in the cmd directory.. back up - for _, c := range cmdDirs { - if base == c { - projectPath = filepath.Dir(x) - return - } - } - - if projectPath == "" { - projectPath = filepath.Clean(x) - return - } - } - - srcPath := getSrcPath() - // if provided, inspect for logical locations - if strings.ContainsRune(inputPath, os.PathSeparator) { - if filepath.IsAbs(inputPath) || filepath.HasPrefix(inputPath, string(os.PathSeparator)) { - // if Absolute, use it - projectPath = filepath.Clean(inputPath) - return - } - // If not absolute but contains slashes, - // assuming it means create it from $GOPATH - count := strings.Count(inputPath, string(os.PathSeparator)) - - switch count { - // If only one directory deep, assume "github.com" - case 1: - projectPath = filepath.Join(srcPath, "github.com", inputPath) - return - case 2: - projectPath = filepath.Join(srcPath, inputPath) - return - default: - er("Unknown directory") - } - } else { - // hardest case.. just a word. - if projectBase == "" { - x, err := getWd() - if err == nil { - projectPath = filepath.Join(x, inputPath) - return - } - er(err) - } else { - projectPath = filepath.Join(srcPath, projectBase, inputPath) - return - } - } -} - -// isEmpty checks if a given path is empty. -func isEmpty(path string) (bool, error) { - if b, _ := exists(path); !b { - return false, fmt.Errorf("%q path does not exist", path) - } - fi, err := os.Stat(path) - if err != nil { - return false, err - } - if fi.IsDir() { - f, err := os.Open(path) - // FIX: Resource leak - f.close() should be called here by defer or is missed - // if the err != nil branch is taken. - defer f.Close() - if err != nil { - return false, err - } - list, _ := f.Readdir(-1) - // f.Close() - see bug fix above - return len(list) == 0, nil - } - return fi.Size() == 0, nil -} - -// isDir checks if a given path is a directory. -func isDir(path string) (bool, error) { - fi, err := os.Stat(path) - if err != nil { - return false, err - } - return fi.IsDir(), nil -} - -// dirExists checks if a path exists and is a directory. -func dirExists(path string) (bool, error) { - fi, err := os.Stat(path) - if err == nil && fi.IsDir() { - return true, nil - } - if os.IsNotExist(err) { - return false, nil - } - return false, err -} - -func writeTemplateToFile(path string, file string, template string, data interface{}) error { - filename := filepath.Join(path, file) - - r, err := templateToReader(template, data) - - if err != nil { - return err - } - - err = safeWriteToDisk(filename, r) - - if err != nil { - return err - } - return nil -} - -func writeStringToFile(path, file, text string) error { - filename := filepath.Join(path, file) - - r := strings.NewReader(text) - err := safeWriteToDisk(filename, r) - - if err != nil { - return err - } - return nil -} - -func templateToReader(tpl string, data interface{}) (io.Reader, error) { - tmpl := template.New("") - tmpl.Funcs(funcMap) - tmpl, err := tmpl.Parse(tpl) - - if err != nil { - return nil, err - } - buf := new(bytes.Buffer) - err = tmpl.Execute(buf, data) - - return buf, err -} - -// Same as WriteToDisk but checks to see if file/directory already exists. -func safeWriteToDisk(inpath string, r io.Reader) (err error) { - dir, _ := filepath.Split(inpath) - ospath := filepath.FromSlash(dir) - - if ospath != "" { - err = os.MkdirAll(ospath, 0777) // rwx, rw, r - if err != nil { - return - } - } - - ex, err := exists(inpath) - if err != nil { - return - } - if ex { - return fmt.Errorf("%v already exists", inpath) - } - - file, err := os.Create(inpath) - if err != nil { - return - } - defer file.Close() - - _, err = io.Copy(file, r) - return -} - -func getLicense() License { - l := whichLicense() - if l != "" { - if x, ok := Licenses[l]; ok { - return x - } - } - - return Licenses["apache"] -} - -func whichLicense() string { - // if explicitly flagged, use that - if userLicense != "" { - return matchLicense(userLicense) - } - - // if already present in the project, use that - // TODO: Inspect project for existing license - - // default to viper's setting - - return matchLicense(viper.GetString("license")) -} - -func copyrightLine() string { - author := viper.GetString("author") - year := time.Now().Format("2006") - - return "Copyright © " + year + " " + author -} - -func commentifyString(in string) string { - var newlines []string - lines := strings.Split(in, "\n") - for _, x := range lines { - if !strings.HasPrefix(x, "//") { - if x != "" { - newlines = append(newlines, "// "+x) - } else { - newlines = append(newlines, "//") - } - } else { - newlines = append(newlines, x) - } - } - return strings.Join(newlines, "\n") -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/helpers_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/helpers_test.go deleted file mode 100644 index bd0f75951..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/helpers_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "path/filepath" - "testing" -) - -var _ = fmt.Println -var _ = os.Stderr - -func checkGuess(t *testing.T, wd, input, expected string) { - testWd = wd - inputPath = input - guessProjectPath() - - if projectPath != expected { - t.Errorf("Unexpected Project Path. \n Got: %q\nExpected: %q\n", projectPath, expected) - } - - reset() -} - -func reset() { - testWd = "" - inputPath = "" - projectPath = "" -} - -func TestProjectPath(t *testing.T) { - checkGuess(t, "", filepath.Join("github.com", "spf13", "hugo"), filepath.Join(getSrcPath(), "github.com", "spf13", "hugo")) - checkGuess(t, "", filepath.Join("spf13", "hugo"), filepath.Join(getSrcPath(), "github.com", "spf13", "hugo")) - checkGuess(t, "", filepath.Join("/", "bar", "foo"), filepath.Join("/", "bar", "foo")) - checkGuess(t, "/bar/foo", "baz", filepath.Join("/", "bar", "foo", "baz")) - checkGuess(t, "/bar/foo/cmd", "", filepath.Join("/", "bar", "foo")) - checkGuess(t, "/bar/foo/command", "", filepath.Join("/", "bar", "foo")) - checkGuess(t, "/bar/foo/commands", "", filepath.Join("/", "bar", "foo")) - checkGuess(t, "github.com/spf13/hugo/../hugo", "", filepath.Join("github.com", "spf13", "hugo")) -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/init.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/init.go deleted file mode 100644 index 342fb9ccd..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/init.go +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright © 2015 Steve Francia . -// -// 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 cmd - -import ( - "fmt" - "os" - "strings" - - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -func init() { - RootCmd.AddCommand(initCmd) -} - -// initialize Command -var initCmd = &cobra.Command{ - Use: "init [name]", - Aliases: []string{"initialize", "initialise", "create"}, - Short: "Initialize a Cobra Application", - Long: `Initialize (cobra init) will create a new application, with a license -and the appropriate structure for a Cobra-based CLI application. - - * If a name is provided, it will be created in the current directory; - * If no name is provided, the current directory will be assumed; - * If a relative path is provided, it will be created inside $GOPATH - (e.g. github.com/spf13/hugo); - * If an absolute path is provided, it will be created; - * If the directory already exists but is empty, it will be used. - -Init will not use an existing directory with contents.`, - - Run: func(cmd *cobra.Command, args []string) { - switch len(args) { - case 0: - inputPath = "" - - case 1: - inputPath = args[0] - - default: - er("init doesn't support more than 1 parameter") - } - guessProjectPath() - initializePath(projectPath) - }, -} - -func initializePath(path string) { - b, err := exists(path) - if err != nil { - er(err) - } - - if !b { // If path doesn't yet exist, create it - err := os.MkdirAll(path, os.ModePerm) - if err != nil { - er(err) - } - } else { // If path exists and is not empty don't use it - empty, err := exists(path) - if err != nil { - er(err) - } - if !empty { - er("Cobra will not create a new project in a non empty directory") - } - } - // We have a directory and it's empty.. Time to initialize it. - - createLicenseFile() - createMainFile() - createRootCmdFile() -} - -func createLicenseFile() { - lic := getLicense() - - template := lic.Text - - var data map[string]interface{} - data = make(map[string]interface{}) - - // Try to remove the email address, if any - data["copyright"] = strings.Split(copyrightLine(), " <")[0] - - err := writeTemplateToFile(ProjectPath(), "LICENSE", template, data) - _ = err - // if err != nil { - // er(err) - // } -} - -func createMainFile() { - lic := getLicense() - - template := `{{ comment .copyright }} -{{ comment .license }} - -package main - -import "{{ .importpath }}" - -func main() { - cmd.Execute() -} -` - var data map[string]interface{} - data = make(map[string]interface{}) - - data["copyright"] = copyrightLine() - data["license"] = lic.Header - data["importpath"] = guessImportPath() + "/" + guessCmdDir() - - err := writeTemplateToFile(ProjectPath(), "main.go", template, data) - _ = err - // if err != nil { - // er(err) - // } -} - -func createRootCmdFile() { - lic := getLicense() - - template := `{{ comment .copyright }} -{{ comment .license }} - -package cmd - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" -{{ if .viper }} "github.com/spf13/viper" -{{ end }}) -{{if .viper}} -var cfgFile string -{{ end }} -// RootCmd represents the base command when called without any subcommands -var RootCmd = &cobra.Command{ - Use: "{{ .appName }}", - Short: "A brief description of your application", - Long: ` + "`" + `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.` + "`" + `, -// Uncomment the following line if your bare application -// has an action associated with it: -// Run: func(cmd *cobra.Command, args []string) { }, -} - -// Execute adds all child commands to the root command sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} - -func init() { -{{ if .viper }} cobra.OnInitialize(initConfig) - -{{ end }} // Here you will define your flags and configuration settings. - // Cobra supports Persistent Flags, which, if defined here, - // will be global for your application. -{{ if .viper }} - RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)") -{{ else }} - // RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)") -{{ end }} // Cobra also supports local flags, which will only run - // when this action is called directly. - RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} -{{ if .viper }} -// initConfig reads in config file and ENV variables if set. -func initConfig() { - if cfgFile != "" { // enable ability to specify config file via flag - viper.SetConfigFile(cfgFile) - } - - viper.SetConfigName(".{{ .appName }}") // name of config file (without extension) - viper.AddConfigPath("$HOME") // adding home directory as first search path - viper.AutomaticEnv() // read in environment variables that match - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - fmt.Println("Using config file:", viper.ConfigFileUsed()) - } -} -{{ end }}` - - var data map[string]interface{} - data = make(map[string]interface{}) - - data["copyright"] = copyrightLine() - data["license"] = lic.Header - data["appName"] = projectName() - data["viper"] = viper.GetBool("useViper") - - err := writeTemplateToFile(ProjectPath()+string(os.PathSeparator)+guessCmdDir(), "root.go", template, data) - if err != nil { - er(err) - } - - fmt.Println("Your Cobra application is ready at") - fmt.Println(ProjectPath()) - fmt.Println("Give it a try by going there and running `go run main.go`") - fmt.Println("Add commands to it by running `cobra add [cmdname]`") -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/licenses.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/licenses.go deleted file mode 100644 index 5ad9c96ef..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/licenses.go +++ /dev/null @@ -1,1133 +0,0 @@ -// Copyright © 2015 Steve Francia . -// -// 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. - -// Parts inspired by https://github.com/ryanuber/go-license - -package cmd - -import "strings" - -//Licenses contains all possible licenses a user can chose from -var Licenses map[string]License - -//License represents a software license agreement, containing the Name of -// the license, its possible matches (on the command line as given to cobra) -// the header to be used with each file on the file's creating, and the text -// of the license -type License struct { - Name string // The type of license in use - PossibleMatches []string // Similar names to guess - Text string // License text data - Header string // License header for source files -} - -// given a license name (in), try to match the license indicated -func matchLicense(in string) string { - for key, lic := range Licenses { - for _, match := range lic.PossibleMatches { - if strings.EqualFold(in, match) { - return key - } - } - } - return "" -} - -func init() { - Licenses = make(map[string]License) - - Licenses["apache"] = License{ - Name: "Apache 2.0", - PossibleMatches: []string{"apache", "apache20", "apache 2.0", "apache2.0", "apache-2.0"}, - Header: ` -// 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.`, - Text: ` - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. -`, - } - - Licenses["mit"] = License{ - Name: "Mit", - PossibleMatches: []string{"mit"}, - Header: ` -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.`, - Text: `The MIT License (MIT) - -{{ .copyright }} - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -`, - } - - Licenses["bsd"] = License{ - Name: "NewBSD", - PossibleMatches: []string{"bsd", "newbsd", "3 clause bsd"}, - Header: ` -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE.`, - Text: `{{ .copyright }} -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -`, - } - - Licenses["freebsd"] = License{ - Name: "Simplified BSD License", - PossibleMatches: []string{"freebsd", "simpbsd", "simple bsd", "2 clause bsd"}, - Header: ` -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE.`, - Text: `{{ .copyright }} -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -`, - } - - Licenses["gpl3"] = License{ - Name: "GNU General Public License 3.0", - PossibleMatches: []string{"gpl3", "gpl", "gnu gpl3", "gnu gpl"}, - Header: `{{ .copyright }} - - This file is part of {{ .appName }}. - - {{ .appName }} is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - {{ .appName }} is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with {{ .appName }}. If not, see . - `, - Text: ` GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type 'show c' for details. - -The hypothetical commands 'show w' and 'show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. -`, - } - - // Licenses["apache20"] = License{ - // Name: "Apache 2.0", - // PossibleMatches: []string{"apache", "apache20", ""}, - // Header: ` - // `, - // Text: ` - // `, - // } -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/root.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/root.go deleted file mode 100644 index dbe607beb..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/cmd/root.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright © 2015 Steve Francia . -// -// 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 cmd - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var cfgFile string -var userLicense string - -// RootCmd represents the base command when called without any subcommands -var RootCmd = &cobra.Command{ - Use: "cobra", - Short: "A generator for Cobra based Applications", - Long: `Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, -} - -//Execute adds all child commands to the root command sets flags appropriately. -func Execute() { - if err := RootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(-1) - } -} - -func init() { - cobra.OnInitialize(initConfig) - RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - RootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory, e.g. github.com/spf13/") - RootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") - RootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") - RootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") - viper.BindPFlag("author", RootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("projectbase", RootCmd.PersistentFlags().Lookup("projectbase")) - viper.BindPFlag("useViper", RootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") - viper.SetDefault("licenseText", ` -// 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. -`) -} - -// Read in config file and ENV variables if set. -func initConfig() { - if cfgFile != "" { // enable ability to specify config file via flag - viper.SetConfigFile(cfgFile) - } - - viper.SetConfigName(".cobra") // name of config file (without extension) - viper.AddConfigPath("$HOME") // adding home directory as first search path - viper.AutomaticEnv() // read in environment variables that match - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - fmt.Println("Using config file:", viper.ConfigFileUsed()) - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/main.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra/main.go deleted file mode 100644 index c3a9d9cb0..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra/main.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright © 2015 Steve Francia . -// -// 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 "github.com/spf13/cobra/cobra/cmd" - -func main() { - cmd.Execute() -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/cobra_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/cobra_test.go deleted file mode 100644 index 97090b107..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/cobra_test.go +++ /dev/null @@ -1,1188 +0,0 @@ -package cobra - -import ( - "bytes" - "fmt" - "os" - "reflect" - "runtime" - "strings" - "testing" - "text/template" - - "github.com/spf13/pflag" -) - -var _ = fmt.Println -var _ = os.Stderr - -var tp, te, tt, t1, tr []string -var rootPersPre, echoPre, echoPersPre, timesPersPre []string -var flagb1, flagb2, flagb3, flagbr, flagbp bool -var flags1, flags2a, flags2b, flags3, outs string -var flagi1, flagi2, flagi3, flagi4, flagir int -var globalFlag1 bool -var flagEcho, rootcalled bool -var versionUsed int - -const strtwoParentHelp = "help message for parent flag strtwo" -const strtwoChildHelp = "help message for child flag strtwo" - -var cmdHidden = &Command{ - Use: "hide [secret string to print]", - Short: "Print anything to screen (if command is known)", - Long: `an absolutely utterly useless command for testing.`, - Run: func(cmd *Command, args []string) { - outs = "hidden" - }, - Hidden: true, -} - -var cmdPrint = &Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `an absolutely utterly useless command for testing.`, - Run: func(cmd *Command, args []string) { - tp = args - }, -} - -var cmdEcho = &Command{ - Use: "echo [string to echo]", - Aliases: []string{"say"}, - Short: "Echo anything to the screen", - Long: `an utterly useless command for testing.`, - Example: "Just run cobra-test echo", - PersistentPreRun: func(cmd *Command, args []string) { - echoPersPre = args - }, - PreRun: func(cmd *Command, args []string) { - echoPre = args - }, - Run: func(cmd *Command, args []string) { - te = args - }, -} - -var cmdEchoSub = &Command{ - Use: "echosub [string to print]", - Short: "second sub command for echo", - Long: `an absolutely utterly useless command for testing gendocs!.`, - Run: func(cmd *Command, args []string) { - }, -} - -var cmdDeprecated = &Command{ - Use: "deprecated [can't do anything here]", - Short: "A command which is deprecated", - Long: `an absolutely utterly useless command for testing deprecation!.`, - Deprecated: "Please use echo instead", - Run: func(cmd *Command, args []string) { - }, -} - -var cmdTimes = &Command{ - Use: "times [# times] [string to echo]", - SuggestFor: []string{"counts"}, - Short: "Echo anything to the screen more times", - Long: `a slightly useless command for testing.`, - PersistentPreRun: func(cmd *Command, args []string) { - timesPersPre = args - }, - Run: func(cmd *Command, args []string) { - tt = args - }, -} - -var cmdRootNoRun = &Command{ - Use: "cobra-test", - Short: "The root can run its own function", - Long: "The root description for help", - PersistentPreRun: func(cmd *Command, args []string) { - rootPersPre = args - }, -} - -var cmdRootSameName = &Command{ - Use: "print", - Short: "Root with the same name as a subcommand", - Long: "The root description for help", -} - -var cmdRootWithRun = &Command{ - Use: "cobra-test", - Short: "The root can run its own function", - Long: "The root description for help", - Run: func(cmd *Command, args []string) { - tr = args - rootcalled = true - }, -} - -var cmdSubNoRun = &Command{ - Use: "subnorun", - Short: "A subcommand without a Run function", - Long: "A long output about a subcommand without a Run function", -} - -var cmdCustomFlags = &Command{ - Use: "customflags [flags] -- REMOTE_COMMAND", - Short: "A command that expects flags in a custom location", - Long: "A long output about a command that expects flags in a custom location", - Run: func(cmd *Command, args []string) { - }, -} - -var cmdVersion1 = &Command{ - Use: "version", - Short: "Print the version number", - Long: `First version of the version command`, - Run: func(cmd *Command, args []string) { - versionUsed = 1 - }, -} - -var cmdVersion2 = &Command{ - Use: "version", - Short: "Print the version number", - Long: `Second version of the version command`, - Run: func(cmd *Command, args []string) { - versionUsed = 2 - }, -} - -var cmdColon = &Command{ - Use: "cmd:colon", - Run: func(cmd *Command, args []string) { - }, -} - -func flagInit() { - cmdEcho.ResetFlags() - cmdPrint.ResetFlags() - cmdTimes.ResetFlags() - cmdRootNoRun.ResetFlags() - cmdRootSameName.ResetFlags() - cmdRootWithRun.ResetFlags() - cmdSubNoRun.ResetFlags() - cmdCustomFlags.ResetFlags() - cmdRootNoRun.PersistentFlags().StringVarP(&flags2a, "strtwo", "t", "two", strtwoParentHelp) - cmdEcho.Flags().IntVarP(&flagi1, "intone", "i", 123, "help message for flag intone") - cmdTimes.Flags().IntVarP(&flagi2, "inttwo", "j", 234, "help message for flag inttwo") - cmdPrint.Flags().IntVarP(&flagi3, "intthree", "i", 345, "help message for flag intthree") - cmdCustomFlags.Flags().IntVar(&flagi4, "intfour", 456, "help message for flag intfour") - cmdEcho.PersistentFlags().StringVarP(&flags1, "strone", "s", "one", "help message for flag strone") - cmdEcho.PersistentFlags().BoolVarP(&flagbp, "persistentbool", "p", false, "help message for flag persistentbool") - cmdTimes.PersistentFlags().StringVarP(&flags2b, "strtwo", "t", "2", strtwoChildHelp) - cmdPrint.PersistentFlags().StringVarP(&flags3, "strthree", "s", "three", "help message for flag strthree") - cmdEcho.Flags().BoolVarP(&flagb1, "boolone", "b", true, "help message for flag boolone") - cmdTimes.Flags().BoolVarP(&flagb2, "booltwo", "c", false, "help message for flag booltwo") - cmdPrint.Flags().BoolVarP(&flagb3, "boolthree", "b", true, "help message for flag boolthree") - cmdVersion1.ResetFlags() - cmdVersion2.ResetFlags() -} - -func commandInit() { - cmdEcho.ResetCommands() - cmdPrint.ResetCommands() - cmdTimes.ResetCommands() - cmdRootNoRun.ResetCommands() - cmdRootSameName.ResetCommands() - cmdRootWithRun.ResetCommands() - cmdSubNoRun.ResetCommands() - cmdCustomFlags.ResetCommands() -} - -func initialize() *Command { - tt, tp, te = nil, nil, nil - rootPersPre, echoPre, echoPersPre, timesPersPre = nil, nil, nil, nil - - var c = cmdRootNoRun - flagInit() - commandInit() - return c -} - -func initializeWithSameName() *Command { - tt, tp, te = nil, nil, nil - rootPersPre, echoPre, echoPersPre, timesPersPre = nil, nil, nil, nil - var c = cmdRootSameName - flagInit() - commandInit() - return c -} - -func initializeWithRootCmd() *Command { - cmdRootWithRun.ResetCommands() - tt, tp, te, tr, rootcalled = nil, nil, nil, nil, false - flagInit() - cmdRootWithRun.Flags().BoolVarP(&flagbr, "boolroot", "b", false, "help message for flag boolroot") - cmdRootWithRun.Flags().IntVarP(&flagir, "introot", "i", 321, "help message for flag introot") - commandInit() - return cmdRootWithRun -} - -type resulter struct { - Error error - Output string - Command *Command -} - -func fullSetupTest(input string) resulter { - c := initializeWithRootCmd() - - return fullTester(c, input) -} - -func noRRSetupTestSilenced(input string) resulter { - c := initialize() - c.SilenceErrors = true - c.SilenceUsage = true - return fullTester(c, input) -} - -func noRRSetupTest(input string) resulter { - c := initialize() - - return fullTester(c, input) -} - -func rootOnlySetupTest(input string) resulter { - c := initializeWithRootCmd() - - return simpleTester(c, input) -} - -func simpleTester(c *Command, input string) resulter { - buf := new(bytes.Buffer) - // Testing flag with invalid input - c.SetOutput(buf) - c.SetArgs(strings.Split(input, " ")) - - err := c.Execute() - output := buf.String() - - return resulter{err, output, c} -} - -func simpleTesterC(c *Command, input string) resulter { - buf := new(bytes.Buffer) - // Testing flag with invalid input - c.SetOutput(buf) - c.SetArgs(strings.Split(input, " ")) - - cmd, err := c.ExecuteC() - output := buf.String() - - return resulter{err, output, cmd} -} - -func fullTester(c *Command, input string) resulter { - buf := new(bytes.Buffer) - // Testing flag with invalid input - c.SetOutput(buf) - cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun, cmdCustomFlags, cmdDeprecated) - c.SetArgs(strings.Split(input, " ")) - - err := c.Execute() - output := buf.String() - - return resulter{err, output, c} -} - -func logErr(t *testing.T, found, expected string) { - out := new(bytes.Buffer) - - _, _, line, ok := runtime.Caller(2) - if ok { - fmt.Fprintf(out, "Line: %d ", line) - } - fmt.Fprintf(out, "Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - t.Errorf(out.String()) -} - -func checkStringContains(t *testing.T, found, expected string) { - if !strings.Contains(found, expected) { - logErr(t, found, expected) - } -} - -func checkResultContains(t *testing.T, x resulter, check string) { - checkStringContains(t, x.Output, check) -} - -func checkStringOmits(t *testing.T, found, expected string) { - if strings.Contains(found, expected) { - logErr(t, found, expected) - } -} - -func checkResultOmits(t *testing.T, x resulter, check string) { - checkStringOmits(t, x.Output, check) -} - -func checkOutputContains(t *testing.T, c *Command, check string) { - buf := new(bytes.Buffer) - c.SetOutput(buf) - c.Execute() - - if !strings.Contains(buf.String(), check) { - logErr(t, buf.String(), check) - } -} - -func TestSingleCommand(t *testing.T) { - noRRSetupTest("print one two") - - if te != nil || tt != nil { - t.Error("Wrong command called") - } - if tp == nil { - t.Error("Wrong command called") - } - if strings.Join(tp, " ") != "one two" { - t.Error("Command didn't parse correctly") - } -} - -func TestChildCommand(t *testing.T) { - noRRSetupTest("echo times one two") - - if te != nil || tp != nil { - t.Error("Wrong command called") - } - if tt == nil { - t.Error("Wrong command called") - } - if strings.Join(tt, " ") != "one two" { - t.Error("Command didn't parse correctly") - } -} - -func TestCommandAlias(t *testing.T) { - noRRSetupTest("say times one two") - - if te != nil || tp != nil { - t.Error("Wrong command called") - } - if tt == nil { - t.Error("Wrong command called") - } - if strings.Join(tt, " ") != "one two" { - t.Error("Command didn't parse correctly") - } -} - -func TestPrefixMatching(t *testing.T) { - EnablePrefixMatching = true - noRRSetupTest("ech times one two") - - if te != nil || tp != nil { - t.Error("Wrong command called") - } - if tt == nil { - t.Error("Wrong command called") - } - if strings.Join(tt, " ") != "one two" { - t.Error("Command didn't parse correctly") - } - - EnablePrefixMatching = false -} - -func TestNoPrefixMatching(t *testing.T) { - EnablePrefixMatching = false - - noRRSetupTest("ech times one two") - - if !(tt == nil && te == nil && tp == nil) { - t.Error("Wrong command called") - } -} - -func TestAliasPrefixMatching(t *testing.T) { - EnablePrefixMatching = true - noRRSetupTest("sa times one two") - - if te != nil || tp != nil { - t.Error("Wrong command called") - } - if tt == nil { - t.Error("Wrong command called") - } - if strings.Join(tt, " ") != "one two" { - t.Error("Command didn't parse correctly") - } - EnablePrefixMatching = false -} - -func TestChildSameName(t *testing.T) { - c := initializeWithSameName() - c.AddCommand(cmdPrint, cmdEcho) - c.SetArgs(strings.Split("print one two", " ")) - c.Execute() - - if te != nil || tt != nil { - t.Error("Wrong command called") - } - if tp == nil { - t.Error("Wrong command called") - } - if strings.Join(tp, " ") != "one two" { - t.Error("Command didn't parse correctly") - } -} - -func TestGrandChildSameName(t *testing.T) { - c := initializeWithSameName() - cmdTimes.AddCommand(cmdPrint) - c.AddCommand(cmdTimes) - c.SetArgs(strings.Split("times print one two", " ")) - c.Execute() - - if te != nil || tt != nil { - t.Error("Wrong command called") - } - if tp == nil { - t.Error("Wrong command called") - } - if strings.Join(tp, " ") != "one two" { - t.Error("Command didn't parse correctly") - } -} - -func TestUsage(t *testing.T) { - x := fullSetupTest("help") - checkResultContains(t, x, cmdRootWithRun.Use+" [flags]") - x = fullSetupTest("help customflags") - checkResultContains(t, x, cmdCustomFlags.Use) - checkResultOmits(t, x, cmdCustomFlags.Use+" [flags]") -} - -func TestFlagLong(t *testing.T) { - noRRSetupTest("echo --intone=13 something -- here") - - if cmdEcho.ArgsLenAtDash() != 1 { - t.Errorf("expected argsLenAtDash: %d but got %d", 1, cmdRootNoRun.ArgsLenAtDash()) - } - if strings.Join(te, " ") != "something here" { - t.Errorf("flags didn't leave proper args remaining..%s given", te) - } - if flagi1 != 13 { - t.Errorf("int flag didn't get correct value, had %d", flagi1) - } - if flagi2 != 234 { - t.Errorf("default flag value changed, 234 expected, %d given", flagi2) - } -} - -func TestFlagShort(t *testing.T) { - noRRSetupTest("echo -i13 -- something here") - - if cmdEcho.ArgsLenAtDash() != 0 { - t.Errorf("expected argsLenAtDash: %d but got %d", 0, cmdRootNoRun.ArgsLenAtDash()) - } - if strings.Join(te, " ") != "something here" { - t.Errorf("flags didn't leave proper args remaining..%s given", te) - } - if flagi1 != 13 { - t.Errorf("int flag didn't get correct value, had %d", flagi1) - } - if flagi2 != 234 { - t.Errorf("default flag value changed, 234 expected, %d given", flagi2) - } - - noRRSetupTest("echo -i 13 something here") - - if strings.Join(te, " ") != "something here" { - t.Errorf("flags didn't leave proper args remaining..%s given", te) - } - if flagi1 != 13 { - t.Errorf("int flag didn't get correct value, had %d", flagi1) - } - if flagi2 != 234 { - t.Errorf("default flag value changed, 234 expected, %d given", flagi2) - } - - noRRSetupTest("print -i99 one two") - - if strings.Join(tp, " ") != "one two" { - t.Errorf("flags didn't leave proper args remaining..%s given", tp) - } - if flagi3 != 99 { - t.Errorf("int flag didn't get correct value, had %d", flagi3) - } - if flagi1 != 123 { - t.Errorf("default flag value changed on different command with same shortname, 234 expected, %d given", flagi2) - } -} - -func TestChildCommandFlags(t *testing.T) { - noRRSetupTest("echo times -j 99 one two") - - if strings.Join(tt, " ") != "one two" { - t.Errorf("flags didn't leave proper args remaining..%s given", tt) - } - - // Testing with flag that shouldn't be persistent - r := noRRSetupTest("echo times -j 99 -i77 one two") - - if r.Error == nil { - t.Errorf("invalid flag should generate error") - } - - if !strings.Contains(r.Error.Error(), "unknown shorthand") { - t.Errorf("Wrong error message displayed, \n %s", r.Error) - } - - if flagi2 != 99 { - t.Errorf("flag value should be 99, %d given", flagi2) - } - - if flagi1 != 123 { - t.Errorf("unset flag should have default value, expecting 123, given %d", flagi1) - } - - // Testing with flag only existing on child - r = noRRSetupTest("echo -j 99 -i77 one two") - - if r.Error == nil { - t.Errorf("invalid flag should generate error") - } - if !strings.Contains(r.Error.Error(), "unknown shorthand flag") { - t.Errorf("Wrong error message displayed, \n %s", r.Error) - } - - // Testing with persistent flag overwritten by child - noRRSetupTest("echo times --strtwo=child one two") - - if flags2b != "child" { - t.Errorf("flag value should be child, %s given", flags2b) - } - - if flags2a != "two" { - t.Errorf("unset flag should have default value, expecting two, given %s", flags2a) - } - - // Testing flag with invalid input - r = noRRSetupTest("echo -i10E") - - if r.Error == nil { - t.Errorf("invalid input should generate error") - } - if !strings.Contains(r.Error.Error(), "invalid argument \"10E\" for i10E") { - t.Errorf("Wrong error message displayed, \n %s", r.Error) - } -} - -func TestTrailingCommandFlags(t *testing.T) { - x := fullSetupTest("echo two -x") - - if x.Error == nil { - t.Errorf("invalid flag should generate error") - } -} - -func TestInvalidSubcommandFlags(t *testing.T) { - cmd := initializeWithRootCmd() - cmd.AddCommand(cmdTimes) - - result := simpleTester(cmd, "times --inttwo=2 --badflag=bar") - // given that we are not checking here result.Error we check for - // stock usage message - checkResultContains(t, result, "cobra-test times [# times]") - if strings.Contains(result.Error.Error(), "unknown flag: --inttwo") { - t.Errorf("invalid --badflag flag shouldn't fail on 'unknown' --inttwo flag") - } - -} - -func TestSubcommandExecuteC(t *testing.T) { - cmd := initializeWithRootCmd() - double := &Command{ - Use: "double message", - Run: func(c *Command, args []string) { - msg := strings.Join(args, " ") - c.Println(msg, msg) - }, - } - - echo := &Command{ - Use: "echo message", - Run: func(c *Command, args []string) { - msg := strings.Join(args, " ") - c.Println(msg, msg) - }, - } - - cmd.AddCommand(double, echo) - - result := simpleTesterC(cmd, "double hello world") - checkResultContains(t, result, "hello world hello world") - - if result.Command.Name() != "double" { - t.Errorf("invalid cmd returned from ExecuteC: should be 'double' but got %s", result.Command.Name()) - } - - result = simpleTesterC(cmd, "echo msg to be echoed") - checkResultContains(t, result, "msg to be echoed") - - if result.Command.Name() != "echo" { - t.Errorf("invalid cmd returned from ExecuteC: should be 'echo' but got %s", result.Command.Name()) - } -} - -func TestSubcommandArgEvaluation(t *testing.T) { - cmd := initializeWithRootCmd() - - first := &Command{ - Use: "first", - Run: func(cmd *Command, args []string) { - }, - } - cmd.AddCommand(first) - - second := &Command{ - Use: "second", - Run: func(cmd *Command, args []string) { - fmt.Fprintf(cmd.Out(), "%v", args) - }, - } - first.AddCommand(second) - - result := simpleTester(cmd, "first second first third") - - expectedOutput := fmt.Sprintf("%v", []string{"first third"}) - if result.Output != expectedOutput { - t.Errorf("exptected %v, got %v", expectedOutput, result.Output) - } -} - -func TestPersistentFlags(t *testing.T) { - fullSetupTest("echo -s something -p more here") - - // persistentFlag should act like normal flag on its own command - if strings.Join(te, " ") != "more here" { - t.Errorf("flags didn't leave proper args remaining..%s given", te) - } - if flags1 != "something" { - t.Errorf("string flag didn't get correct value, had %v", flags1) - } - if !flagbp { - t.Errorf("persistent bool flag not parsed correctly. Expected true, had %v", flagbp) - } - - // persistentFlag should act like normal flag on its own command - fullSetupTest("echo times -s again -c -p test here") - - if strings.Join(tt, " ") != "test here" { - t.Errorf("flags didn't leave proper args remaining..%s given", tt) - } - - if flags1 != "again" { - t.Errorf("string flag didn't get correct value, had %v", flags1) - } - - if !flagb2 { - t.Errorf("local flag not parsed correctly. Expected true, had %v", flagb2) - } - if !flagbp { - t.Errorf("persistent bool flag not parsed correctly. Expected true, had %v", flagbp) - } -} - -func TestHelpCommand(t *testing.T) { - x := fullSetupTest("help") - checkResultContains(t, x, cmdRootWithRun.Long) - - x = fullSetupTest("help echo") - checkResultContains(t, x, cmdEcho.Long) - - x = fullSetupTest("help echo times") - checkResultContains(t, x, cmdTimes.Long) -} - -func TestChildCommandHelp(t *testing.T) { - c := noRRSetupTest("print --help") - checkResultContains(t, c, strtwoParentHelp) - r := noRRSetupTest("echo times --help") - checkResultContains(t, r, strtwoChildHelp) -} - -func TestNonRunChildHelp(t *testing.T) { - x := noRRSetupTest("subnorun") - checkResultContains(t, x, cmdSubNoRun.Long) -} - -func TestRunnableRootCommand(t *testing.T) { - x := fullSetupTest("") - - if rootcalled != true { - t.Errorf("Root Function was not called\n out:%v", x.Error) - } -} - -func TestVisitParents(t *testing.T) { - c := &Command{Use: "app"} - sub := &Command{Use: "sub"} - dsub := &Command{Use: "dsub"} - sub.AddCommand(dsub) - c.AddCommand(sub) - total := 0 - add := func(x *Command) { - total++ - } - sub.VisitParents(add) - if total != 1 { - t.Errorf("Should have visited 1 parent but visited %d", total) - } - - total = 0 - dsub.VisitParents(add) - if total != 2 { - t.Errorf("Should have visited 2 parent but visited %d", total) - } - - total = 0 - c.VisitParents(add) - if total != 0 { - t.Errorf("Should have not visited any parent but visited %d", total) - } -} - -func TestRunnableRootCommandNilInput(t *testing.T) { - var emptyArg []string - c := initializeWithRootCmd() - - buf := new(bytes.Buffer) - // Testing flag with invalid input - c.SetOutput(buf) - cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdPrint, cmdEcho) - c.SetArgs(emptyArg) - - err := c.Execute() - if err != nil { - t.Errorf("Execute() failed with %v", err) - } - - if rootcalled != true { - t.Errorf("Root Function was not called") - } -} - -func TestRunnableRootCommandEmptyInput(t *testing.T) { - args := make([]string, 3) - args[0] = "" - args[1] = "--introot=12" - args[2] = "" - c := initializeWithRootCmd() - - buf := new(bytes.Buffer) - // Testing flag with invalid input - c.SetOutput(buf) - cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdPrint, cmdEcho) - c.SetArgs(args) - - c.Execute() - - if rootcalled != true { - t.Errorf("Root Function was not called.\n\nOutput was:\n\n%s\n", buf) - } -} - -func TestInvalidSubcommandWhenArgsAllowed(t *testing.T) { - fullSetupTest("echo invalid-sub") - - if te[0] != "invalid-sub" { - t.Errorf("Subcommand didn't work...") - } -} - -func TestRootFlags(t *testing.T) { - fullSetupTest("-i 17 -b") - - if flagbr != true { - t.Errorf("flag value should be true, %v given", flagbr) - } - - if flagir != 17 { - t.Errorf("flag value should be 17, %d given", flagir) - } -} - -func TestRootHelp(t *testing.T) { - x := fullSetupTest("--help") - - checkResultContains(t, x, "Available Commands:") - checkResultContains(t, x, "for more information about a command") - - if strings.Contains(x.Output, "unknown flag: --help") { - t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) - } - - if strings.Contains(x.Output, cmdEcho.Use) { - t.Errorf("--help shouldn't display subcommand's usage, Got: \n %s", x.Output) - } - - x = fullSetupTest("echo --help") - - if strings.Contains(x.Output, cmdTimes.Use) { - t.Errorf("--help shouldn't display subsubcommand's usage, Got: \n %s", x.Output) - } - - checkResultContains(t, x, "Available Commands:") - checkResultContains(t, x, "for more information about a command") - - if strings.Contains(x.Output, "unknown flag: --help") { - t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) - } - -} - -func TestFlagAccess(t *testing.T) { - initialize() - - local := cmdTimes.LocalFlags() - inherited := cmdTimes.InheritedFlags() - - for _, f := range []string{"inttwo", "strtwo", "booltwo"} { - if local.Lookup(f) == nil { - t.Errorf("LocalFlags expected to contain %s, Got: nil", f) - } - } - if inherited.Lookup("strone") == nil { - t.Errorf("InheritedFlags expected to contain strone, Got: nil") - } - if inherited.Lookup("strtwo") != nil { - t.Errorf("InheritedFlags shouldn not contain overwritten flag strtwo") - - } -} - -func TestNoNRunnableRootCommandNilInput(t *testing.T) { - var args []string - c := initialize() - - buf := new(bytes.Buffer) - // Testing flag with invalid input - c.SetOutput(buf) - cmdEcho.AddCommand(cmdTimes) - c.AddCommand(cmdPrint, cmdEcho) - c.SetArgs(args) - - c.Execute() - - if !strings.Contains(buf.String(), cmdRootNoRun.Long) { - t.Errorf("Expected to get help output, Got: \n %s", buf) - } -} - -func TestRootNoCommandHelp(t *testing.T) { - x := rootOnlySetupTest("--help") - - checkResultOmits(t, x, "Available Commands:") - checkResultOmits(t, x, "for more information about a command") - - if strings.Contains(x.Output, "unknown flag: --help") { - t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) - } - - x = rootOnlySetupTest("echo --help") - - checkResultOmits(t, x, "Available Commands:") - checkResultOmits(t, x, "for more information about a command") - - if strings.Contains(x.Output, "unknown flag: --help") { - t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output) - } -} - -func TestRootUnknownCommand(t *testing.T) { - r := noRRSetupTest("bogus") - s := "Error: unknown command \"bogus\" for \"cobra-test\"\nRun 'cobra-test --help' for usage.\n" - - if r.Output != s { - t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output) - } - - r = noRRSetupTest("--strtwo=a bogus") - if r.Output != s { - t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output) - } -} - -func TestRootUnknownCommandSilenced(t *testing.T) { - r := noRRSetupTestSilenced("bogus") - s := "Run 'cobra-test --help' for usage.\n" - - if r.Output != "" { - t.Errorf("Unexpected response.\nExpecting to be: \n\"\"\n Got:\n %q\n", s, r.Output) - } - - r = noRRSetupTestSilenced("--strtwo=a bogus") - if r.Output != "" { - t.Errorf("Unexpected response.\nExpecting to be:\n\"\"\nGot:\n %q\n", s, r.Output) - } -} - -func TestRootSuggestions(t *testing.T) { - outputWithSuggestions := "Error: unknown command \"%s\" for \"cobra-test\"\n\nDid you mean this?\n\t%s\n\nRun 'cobra-test --help' for usage.\n" - outputWithoutSuggestions := "Error: unknown command \"%s\" for \"cobra-test\"\nRun 'cobra-test --help' for usage.\n" - - cmd := initializeWithRootCmd() - cmd.AddCommand(cmdTimes) - - tests := map[string]string{ - "time": "times", - "tiems": "times", - "tims": "times", - "timeS": "times", - "rimes": "times", - "ti": "times", - "t": "times", - "timely": "times", - "ri": "", - "timezone": "", - "foo": "", - "counts": "times", - } - - for typo, suggestion := range tests { - for _, suggestionsDisabled := range []bool{false, true} { - cmd.DisableSuggestions = suggestionsDisabled - result := simpleTester(cmd, typo) - expected := "" - if len(suggestion) == 0 || suggestionsDisabled { - expected = fmt.Sprintf(outputWithoutSuggestions, typo) - } else { - expected = fmt.Sprintf(outputWithSuggestions, typo, suggestion) - } - if result.Output != expected { - t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", expected, result.Output) - } - } - } -} - -func TestFlagsBeforeCommand(t *testing.T) { - // short without space - x := fullSetupTest("-i10 echo") - if x.Error != nil { - t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error) - } - - // short (int) with equals - // It appears that pflags doesn't support this... - // Commenting out until support can be added - - //x = noRRSetupTest("echo -i=10") - //if x.Error != nil { - //t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error) - //} - - // long with equals - x = noRRSetupTest("--intone=123 echo one two") - if x.Error != nil { - t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error) - } - - // With parsing error properly reported - x = fullSetupTest("-i10E echo") - if !strings.Contains(x.Error.Error(), "invalid argument \"10E\" for i10E") { - t.Errorf("Wrong error message displayed, \n %s", x.Error) - } - - //With quotes - x = fullSetupTest("-s=\"walking\" echo") - if x.Error != nil { - t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error) - } - - //With quotes and space - x = fullSetupTest("-s=\"walking fast\" echo") - if x.Error != nil { - t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error) - } - - //With inner quote - x = fullSetupTest("-s=\"walking \\\"Inner Quote\\\" fast\" echo") - if x.Error != nil { - t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error) - } - - //With quotes and space - x = fullSetupTest("-s=\"walking \\\"Inner Quote\\\" fast\" echo") - if x.Error != nil { - t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error) - } - -} - -func TestRemoveCommand(t *testing.T) { - versionUsed = 0 - c := initializeWithRootCmd() - c.AddCommand(cmdVersion1) - c.RemoveCommand(cmdVersion1) - x := fullTester(c, "version") - if x.Error == nil { - t.Errorf("Removed command should not have been called\n") - return - } -} - -func TestCommandWithoutSubcommands(t *testing.T) { - c := initializeWithRootCmd() - - x := simpleTester(c, "") - if x.Error != nil { - t.Errorf("Calling command without subcommands should not have error: %v", x.Error) - return - } -} - -func TestCommandWithoutSubcommandsWithArg(t *testing.T) { - c := initializeWithRootCmd() - expectedArgs := []string{"arg"} - - x := simpleTester(c, "arg") - if x.Error != nil { - t.Errorf("Calling command without subcommands but with arg should not have error: %v", x.Error) - return - } - if !reflect.DeepEqual(expectedArgs, tr) { - t.Errorf("Calling command without subcommands but with arg has wrong args: expected: %v, actual: %v", expectedArgs, tr) - return - } -} - -func TestReplaceCommandWithRemove(t *testing.T) { - versionUsed = 0 - c := initializeWithRootCmd() - c.AddCommand(cmdVersion1) - c.RemoveCommand(cmdVersion1) - c.AddCommand(cmdVersion2) - x := fullTester(c, "version") - if x.Error != nil { - t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error) - return - } - if versionUsed == 1 { - t.Errorf("Removed command shouldn't be called\n") - } - if versionUsed != 2 { - t.Errorf("Replacing command should have been called but didn't\n") - } -} - -func TestDeprecatedSub(t *testing.T) { - c := fullSetupTest("deprecated") - - checkResultContains(t, c, cmdDeprecated.Deprecated) -} - -func TestPreRun(t *testing.T) { - noRRSetupTest("echo one two") - if echoPre == nil || echoPersPre == nil { - t.Error("PreRun or PersistentPreRun not called") - } - if rootPersPre != nil || timesPersPre != nil { - t.Error("Wrong *Pre functions called!") - } - - noRRSetupTest("echo times one two") - if timesPersPre == nil { - t.Error("PreRun or PersistentPreRun not called") - } - if echoPre != nil || echoPersPre != nil || rootPersPre != nil { - t.Error("Wrong *Pre functions called!") - } - - noRRSetupTest("print one two") - if rootPersPre == nil { - t.Error("Parent PersistentPreRun not called but should not have been") - } - if echoPre != nil || echoPersPre != nil || timesPersPre != nil { - t.Error("Wrong *Pre functions called!") - } -} - -// Check if cmdEchoSub gets PersistentPreRun from rootCmd even if is added last -func TestPeristentPreRunPropagation(t *testing.T) { - rootCmd := initialize() - - // First add the cmdEchoSub to cmdPrint - cmdPrint.AddCommand(cmdEchoSub) - // Now add cmdPrint to rootCmd - rootCmd.AddCommand(cmdPrint) - - rootCmd.SetArgs(strings.Split("print echosub lala", " ")) - rootCmd.Execute() - - if rootPersPre == nil || len(rootPersPre) == 0 || rootPersPre[0] != "lala" { - t.Error("RootCmd PersistentPreRun not called but should have been") - } -} - -func TestGlobalNormFuncPropagation(t *testing.T) { - normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName { - return pflag.NormalizedName(name) - } - - rootCmd := initialize() - rootCmd.SetGlobalNormalizationFunc(normFunc) - if reflect.ValueOf(normFunc) != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()) { - t.Error("rootCmd seems to have a wrong normalization function") - } - - // First add the cmdEchoSub to cmdPrint - cmdPrint.AddCommand(cmdEchoSub) - if cmdPrint.GlobalNormalizationFunc() != nil && cmdEchoSub.GlobalNormalizationFunc() != nil { - t.Error("cmdPrint and cmdEchoSub should had no normalization functions") - } - - // Now add cmdPrint to rootCmd - rootCmd.AddCommand(cmdPrint) - if reflect.ValueOf(cmdPrint.GlobalNormalizationFunc()).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() || - reflect.ValueOf(cmdEchoSub.GlobalNormalizationFunc()).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() { - t.Error("cmdPrint and cmdEchoSub should had the normalization function of rootCmd") - } -} - -func TestFlagOnPflagCommandLine(t *testing.T) { - flagName := "flagOnCommandLine" - pflag.CommandLine.String(flagName, "", "about my flag") - r := fullSetupTest("--help") - - checkResultContains(t, r, flagName) -} - -func TestAddTemplateFunctions(t *testing.T) { - AddTemplateFunc("t", func() bool { return true }) - AddTemplateFuncs(template.FuncMap{ - "f": func() bool { return false }, - "h": func() string { return "Hello," }, - "w": func() string { return "world." }}) - - const usage = "Hello, world." - - c := &Command{} - c.SetUsageTemplate(`{{if t}}{{h}}{{end}}{{if f}}{{h}}{{end}} {{w}}`) - - if us := c.UsageString(); us != usage { - t.Errorf("c.UsageString() != \"%s\", is \"%s\"", usage, us) - } -} - -func TestUsageIsNotPrintedTwice(t *testing.T) { - var cmd = &Command{Use: "root"} - var sub = &Command{Use: "sub"} - cmd.AddCommand(sub) - - r := simpleTester(cmd, "") - if strings.Count(r.Output, "Usage:") != 1 { - t.Error("Usage output is not printed exactly once") - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/command_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/command_test.go deleted file mode 100644 index 43ed7a34f..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/command_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package cobra - -import ( - "reflect" - "testing" -) - -// test to ensure hidden commands run as intended -func TestHiddenCommandExecutes(t *testing.T) { - - // ensure that outs does not already equal what the command will be setting it - // to, if it did this test would not actually be testing anything... - if outs == "hidden" { - t.Errorf("outs should NOT EQUAL hidden") - } - - cmdHidden.Execute() - - // upon running the command, the value of outs should now be 'hidden' - if outs != "hidden" { - t.Errorf("Hidden command failed to run!") - } -} - -// test to ensure hidden commands do not show up in usage/help text -func TestHiddenCommandIsHidden(t *testing.T) { - if cmdHidden.IsAvailableCommand() { - t.Errorf("Hidden command found!") - } -} - -func TestStripFlags(t *testing.T) { - tests := []struct { - input []string - output []string - }{ - { - []string{"foo", "bar"}, - []string{"foo", "bar"}, - }, - { - []string{"foo", "--bar", "-b"}, - []string{"foo"}, - }, - { - []string{"-b", "foo", "--bar", "bar"}, - []string{}, - }, - { - []string{"-i10", "echo"}, - []string{"echo"}, - }, - { - []string{"-i=10", "echo"}, - []string{"echo"}, - }, - { - []string{"--int=100", "echo"}, - []string{"echo"}, - }, - { - []string{"-ib", "echo", "-bfoo", "baz"}, - []string{"echo", "baz"}, - }, - { - []string{"-i=baz", "bar", "-i", "foo", "blah"}, - []string{"bar", "blah"}, - }, - { - []string{"--int=baz", "-bbar", "-i", "foo", "blah"}, - []string{"blah"}, - }, - { - []string{"--cat", "bar", "-i", "foo", "blah"}, - []string{"bar", "blah"}, - }, - { - []string{"-c", "bar", "-i", "foo", "blah"}, - []string{"bar", "blah"}, - }, - { - []string{"--persist", "bar"}, - []string{"bar"}, - }, - { - []string{"-p", "bar"}, - []string{"bar"}, - }, - } - - cmdPrint := &Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `an utterly useless command for testing.`, - Run: func(cmd *Command, args []string) { - tp = args - }, - } - - var flagi int - var flagstr string - var flagbool bool - cmdPrint.PersistentFlags().BoolVarP(&flagbool, "persist", "p", false, "help for persistent one") - cmdPrint.Flags().IntVarP(&flagi, "int", "i", 345, "help message for flag int") - cmdPrint.Flags().StringVarP(&flagstr, "bar", "b", "bar", "help message for flag string") - cmdPrint.Flags().BoolVarP(&flagbool, "cat", "c", false, "help message for flag bool") - - for _, test := range tests { - output := stripFlags(test.input, cmdPrint) - if !reflect.DeepEqual(test.output, output) { - t.Errorf("expected: %v, got: %v", test.output, output) - } - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/cmd_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/doc/cmd_test.go deleted file mode 100644 index a4b5568fa..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/cmd_test.go +++ /dev/null @@ -1,145 +0,0 @@ -package doc - -import ( - "bytes" - "fmt" - "runtime" - "strings" - "testing" - - "github.com/spf13/cobra" -) - -var flagb1, flagb2, flagb3, flagbr, flagbp bool -var flags1, flags2a, flags2b, flags3 string -var flagi1, flagi2, flagi3, flagir int - -const strtwoParentHelp = "help message for parent flag strtwo" -const strtwoChildHelp = "help message for child flag strtwo" - -var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Aliases: []string{"say"}, - Short: "Echo anything to the screen", - Long: `an utterly useless command for testing.`, - Example: "Just run cobra-test echo", -} - -var cmdEchoSub = &cobra.Command{ - Use: "echosub [string to print]", - Short: "second sub command for echo", - Long: `an absolutely utterly useless command for testing gendocs!.`, - Run: func(cmd *cobra.Command, args []string) {}, -} - -var cmdDeprecated = &cobra.Command{ - Use: "deprecated [can't do anything here]", - Short: "A command which is deprecated", - Long: `an absolutely utterly useless command for testing deprecation!.`, - Deprecated: "Please use echo instead", -} - -var cmdTimes = &cobra.Command{ - Use: "times [# times] [string to echo]", - SuggestFor: []string{"counts"}, - Short: "Echo anything to the screen more times", - Long: `a slightly useless command for testing.`, - PersistentPreRun: func(cmd *cobra.Command, args []string) {}, - Run: func(cmd *cobra.Command, args []string) {}, -} - -var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `an absolutely utterly useless command for testing.`, -} - -var cmdRootNoRun = &cobra.Command{ - Use: "cobra-test", - Short: "The root can run its own function", - Long: "The root description for help", -} - -var cmdRootSameName = &cobra.Command{ - Use: "print", - Short: "Root with the same name as a subcommand", - Long: "The root description for help", -} - -var cmdRootWithRun = &cobra.Command{ - Use: "cobra-test", - Short: "The root can run its own function", - Long: "The root description for help", -} - -var cmdSubNoRun = &cobra.Command{ - Use: "subnorun", - Short: "A subcommand without a Run function", - Long: "A long output about a subcommand without a Run function", -} - -var cmdVersion1 = &cobra.Command{ - Use: "version", - Short: "Print the version number", - Long: `First version of the version command`, -} - -var cmdVersion2 = &cobra.Command{ - Use: "version", - Short: "Print the version number", - Long: `Second version of the version command`, -} - -func flagInit() { - cmdEcho.ResetFlags() - cmdPrint.ResetFlags() - cmdTimes.ResetFlags() - cmdRootNoRun.ResetFlags() - cmdRootSameName.ResetFlags() - cmdRootWithRun.ResetFlags() - cmdSubNoRun.ResetFlags() - cmdRootNoRun.PersistentFlags().StringVarP(&flags2a, "strtwo", "t", "two", strtwoParentHelp) - cmdEcho.Flags().IntVarP(&flagi1, "intone", "i", 123, "help message for flag intone") - cmdTimes.Flags().IntVarP(&flagi2, "inttwo", "j", 234, "help message for flag inttwo") - cmdPrint.Flags().IntVarP(&flagi3, "intthree", "i", 345, "help message for flag intthree") - cmdEcho.PersistentFlags().StringVarP(&flags1, "strone", "s", "one", "help message for flag strone") - cmdEcho.PersistentFlags().BoolVarP(&flagbp, "persistentbool", "p", false, "help message for flag persistentbool") - cmdTimes.PersistentFlags().StringVarP(&flags2b, "strtwo", "t", "2", strtwoChildHelp) - cmdPrint.PersistentFlags().StringVarP(&flags3, "strthree", "s", "three", "help message for flag strthree") - cmdEcho.Flags().BoolVarP(&flagb1, "boolone", "b", true, "help message for flag boolone") - cmdTimes.Flags().BoolVarP(&flagb2, "booltwo", "c", false, "help message for flag booltwo") - cmdPrint.Flags().BoolVarP(&flagb3, "boolthree", "b", true, "help message for flag boolthree") - cmdVersion1.ResetFlags() - cmdVersion2.ResetFlags() -} - -func initializeWithRootCmd() *cobra.Command { - cmdRootWithRun.ResetCommands() - flagInit() - cmdRootWithRun.Flags().BoolVarP(&flagbr, "boolroot", "b", false, "help message for flag boolroot") - cmdRootWithRun.Flags().IntVarP(&flagir, "introot", "i", 321, "help message for flag introot") - return cmdRootWithRun -} - -func checkStringContains(t *testing.T, found, expected string) { - if !strings.Contains(found, expected) { - logErr(t, found, expected) - } -} - -func checkStringOmits(t *testing.T, found, expected string) { - if strings.Contains(found, expected) { - logErr(t, found, expected) - } -} - -func logErr(t *testing.T, found, expected string) { - out := new(bytes.Buffer) - - _, _, line, ok := runtime.Caller(2) - if ok { - fmt.Fprintf(out, "Line: %d ", line) - } - fmt.Fprintf(out, "Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - t.Errorf(out.String()) -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs.go b/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs.go deleted file mode 100644 index a98674bf3..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2015 Red Hat 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 doc - -import ( - "bytes" - "fmt" - "io" - "os" - "path/filepath" - "sort" - "strings" - "time" - - mangen "github.com/cpuguy83/go-md2man/md2man" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -// GenManTree will generate a man page for this command and all decendants -// in the directory given. The header may be nil. This function may not work -// correctly if your command names have - in them. If you have `cmd` with two -// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third` -// it is undefined which help output will be in the file `cmd-sub-third.1`. -func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error { - if header == nil { - header = &GenManHeader{} - } - for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsHelpCommand() { - continue - } - if err := GenManTree(c, header, dir); err != nil { - return err - } - } - needToResetTitle := header.Title == "" - - basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".1" - filename := filepath.Join(dir, basename) - f, err := os.Create(filename) - if err != nil { - return err - } - defer f.Close() - - if err := GenMan(cmd, header, f); err != nil { - return err - } - - if needToResetTitle { - header.Title = "" - } - return nil -} - -// GenManHeader is a lot like the .TH header at the start of man pages. These -// include the title, section, date, source, and manual. We will use the -// current time if Date if unset and will use "Auto generated by spf13/cobra" -// if the Source is unset. -type GenManHeader struct { - Title string - Section string - Date *time.Time - date string - Source string - Manual string -} - -// GenMan will generate a man page for the given command and write it to -// w. The header argument may be nil, however obviously w may not. -func GenMan(cmd *cobra.Command, header *GenManHeader, w io.Writer) error { - if header == nil { - header = &GenManHeader{} - } - b := genMan(cmd, header) - final := mangen.Render(b) - _, err := w.Write(final) - return err -} - -func fillHeader(header *GenManHeader, name string) { - if header.Title == "" { - header.Title = strings.ToUpper(strings.Replace(name, " ", "\\-", -1)) - } - if header.Section == "" { - header.Section = "1" - } - if header.Date == nil { - now := time.Now() - header.Date = &now - } - header.date = (*header.Date).Format("Jan 2006") - if header.Source == "" { - header.Source = "Auto generated by spf13/cobra" - } -} - -func manPreamble(out io.Writer, header *GenManHeader, name, short, long string) { - dashName := strings.Replace(name, " ", "-", -1) - fmt.Fprintf(out, `%% %s(%s)%s -%% %s -%% %s -# NAME -`, header.Title, header.Section, header.date, header.Source, header.Manual) - fmt.Fprintf(out, "%s \\- %s\n\n", dashName, short) - fmt.Fprintf(out, "# SYNOPSIS\n") - fmt.Fprintf(out, "**%s** [OPTIONS]\n\n", name) - fmt.Fprintf(out, "# DESCRIPTION\n") - fmt.Fprintf(out, "%s\n\n", long) -} - -func manPrintFlags(out io.Writer, flags *pflag.FlagSet) { - flags.VisitAll(func(flag *pflag.Flag) { - if len(flag.Deprecated) > 0 || flag.Hidden { - return - } - format := "" - if len(flag.Shorthand) > 0 { - format = "**-%s**, **--%s**" - } else { - format = "%s**--%s**" - } - if len(flag.NoOptDefVal) > 0 { - format = format + "[" - } - if flag.Value.Type() == "string" { - // put quotes on the value - format = format + "=%q" - } else { - format = format + "=%s" - } - if len(flag.NoOptDefVal) > 0 { - format = format + "]" - } - format = format + "\n\t%s\n\n" - fmt.Fprintf(out, format, flag.Shorthand, flag.Name, flag.DefValue, flag.Usage) - }) -} - -func manPrintOptions(out io.Writer, command *cobra.Command) { - flags := command.NonInheritedFlags() - if flags.HasFlags() { - fmt.Fprintf(out, "# OPTIONS\n") - manPrintFlags(out, flags) - fmt.Fprintf(out, "\n") - } - flags = command.InheritedFlags() - if flags.HasFlags() { - fmt.Fprintf(out, "# OPTIONS INHERITED FROM PARENT COMMANDS\n") - manPrintFlags(out, flags) - fmt.Fprintf(out, "\n") - } -} - -func genMan(cmd *cobra.Command, header *GenManHeader) []byte { - // something like `rootcmd subcmd1 subcmd2` - commandName := cmd.CommandPath() - // something like `rootcmd-subcmd1-subcmd2` - dashCommandName := strings.Replace(commandName, " ", "-", -1) - - fillHeader(header, commandName) - - buf := new(bytes.Buffer) - - short := cmd.Short - long := cmd.Long - if len(long) == 0 { - long = short - } - - manPreamble(buf, header, commandName, short, long) - manPrintOptions(buf, cmd) - if len(cmd.Example) > 0 { - fmt.Fprintf(buf, "# EXAMPLE\n") - fmt.Fprintf(buf, "```\n%s\n```\n", cmd.Example) - } - if hasSeeAlso(cmd) { - fmt.Fprintf(buf, "# SEE ALSO\n") - seealsos := make([]string, 0) - if cmd.HasParent() { - parentPath := cmd.Parent().CommandPath() - dashParentPath := strings.Replace(parentPath, " ", "-", -1) - seealso := fmt.Sprintf("**%s(%s)**", dashParentPath, header.Section) - seealsos = append(seealsos, seealso) - cmd.VisitParents(func(c *cobra.Command) { - if c.DisableAutoGenTag { - cmd.DisableAutoGenTag = c.DisableAutoGenTag - } - }) - } - children := cmd.Commands() - sort.Sort(byName(children)) - for _, c := range children { - if !c.IsAvailableCommand() || c.IsHelpCommand() { - continue - } - seealso := fmt.Sprintf("**%s-%s(%s)**", dashCommandName, c.Name(), header.Section) - seealsos = append(seealsos, seealso) - } - fmt.Fprintf(buf, "%s\n", strings.Join(seealsos, ", ")) - } - if !cmd.DisableAutoGenTag { - fmt.Fprintf(buf, "# HISTORY\n%s Auto generated by spf13/cobra\n", header.Date.Format("2-Jan-2006")) - } - return buf.Bytes() -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs.md b/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs.md deleted file mode 100644 index 5fe957a35..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs.md +++ /dev/null @@ -1,26 +0,0 @@ -# Generating Man Pages For Your Own cobra.Command - -Generating man pages from a cobra command is incredibly easy. An example is as follows: - -```go -package main - -import ( - "github.com/spf13/cobra" - "github.com/spf13/cobra/doc" -) - -func main() { - cmd := &cobra.Command{ - Use: "test", - Short: "my test program", - } - header := &cobra.GenManHeader{ - Title: "MINE", - Section: "3", - } - doc.GenManTree(cmd, header, "/tmp") -} -``` - -That will get you a man page `/tmp/test.1` diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs_test.go deleted file mode 100644 index e6e6263c2..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_docs_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package doc - -import ( - "bufio" - "bytes" - "fmt" - "os" - "strings" - "testing" - - "github.com/spf13/cobra" -) - -var _ = fmt.Println -var _ = os.Stderr - -func translate(in string) string { - return strings.Replace(in, "-", "\\-", -1) -} - -func TestGenManDoc(t *testing.T) { - c := initializeWithRootCmd() - // Need two commands to run the command alphabetical sort - cmdEcho.AddCommand(cmdTimes, cmdEchoSub, cmdDeprecated) - c.AddCommand(cmdPrint, cmdEcho) - cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) - - out := new(bytes.Buffer) - - header := &GenManHeader{ - Title: "Project", - Section: "2", - } - // We generate on a subcommand so we have both subcommands and parents - if err := GenMan(cmdEcho, header, out); err != nil { - t.Fatal(err) - } - found := out.String() - - // Make sure parent has - in CommandPath() in SEE ALSO: - parentPath := cmdEcho.Parent().CommandPath() - dashParentPath := strings.Replace(parentPath, " ", "-", -1) - expected := translate(dashParentPath) - expected = expected + "(" + header.Section + ")" - checkStringContains(t, found, expected) - - // Our description - expected = translate(cmdEcho.Name()) - checkStringContains(t, found, expected) - - // Better have our example - expected = translate(cmdEcho.Name()) - checkStringContains(t, found, expected) - - // A local flag - expected = "boolone" - checkStringContains(t, found, expected) - - // persistent flag on parent - expected = "rootflag" - checkStringContains(t, found, expected) - - // We better output info about our parent - expected = translate(cmdRootWithRun.Name()) - checkStringContains(t, found, expected) - - // And about subcommands - expected = translate(cmdEchoSub.Name()) - checkStringContains(t, found, expected) - - unexpected := translate(cmdDeprecated.Name()) - checkStringOmits(t, found, unexpected) - - // auto generated - expected = translate("Auto generated") - checkStringContains(t, found, expected) -} - -func TestGenManNoGenTag(t *testing.T) { - c := initializeWithRootCmd() - // Need two commands to run the command alphabetical sort - cmdEcho.AddCommand(cmdTimes, cmdEchoSub, cmdDeprecated) - c.AddCommand(cmdPrint, cmdEcho) - cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) - cmdEcho.DisableAutoGenTag = true - out := new(bytes.Buffer) - - header := &GenManHeader{ - Title: "Project", - Section: "2", - } - // We generate on a subcommand so we have both subcommands and parents - if err := GenMan(cmdEcho, header, out); err != nil { - t.Fatal(err) - } - found := out.String() - - unexpected := translate("#HISTORY") - checkStringOmits(t, found, unexpected) -} - -func TestGenManSeeAlso(t *testing.T) { - noop := func(cmd *cobra.Command, args []string) {} - - top := &cobra.Command{Use: "top", Run: noop} - aaa := &cobra.Command{Use: "aaa", Run: noop, Hidden: true} // #229 - bbb := &cobra.Command{Use: "bbb", Run: noop} - ccc := &cobra.Command{Use: "ccc", Run: noop} - top.AddCommand(aaa, bbb, ccc) - - out := new(bytes.Buffer) - header := &GenManHeader{} - if err := GenMan(top, header, out); err != nil { - t.Fatal(err) - } - - scanner := bufio.NewScanner(out) - - if err := AssertLineFound(scanner, ".SH SEE ALSO"); err != nil { - t.Fatal(fmt.Errorf("Couldn't find SEE ALSO section header: %s", err.Error())) - } - - if err := AssertNextLineEquals(scanner, ".PP"); err != nil { - t.Fatal(fmt.Errorf("First line after SEE ALSO wasn't break-indent: %s", err.Error())) - } - - if err := AssertNextLineEquals(scanner, `\fBtop\-bbb(1)\fP, \fBtop\-ccc(1)\fP`); err != nil { - t.Fatal(fmt.Errorf("Second line after SEE ALSO wasn't correct: %s", err.Error())) - } -} - -func AssertLineFound(scanner *bufio.Scanner, expectedLine string) error { - for scanner.Scan() { - line := scanner.Text() - if line == expectedLine { - return nil - } - } - - if err := scanner.Err(); err != nil { - return fmt.Errorf("AssertLineFound: scan failed: %s", err.Error()) - } - - return fmt.Errorf("AssertLineFound: hit EOF before finding %#v", expectedLine) -} - -func AssertNextLineEquals(scanner *bufio.Scanner, expectedLine string) error { - if scanner.Scan() { - line := scanner.Text() - if line == expectedLine { - return nil - } - return fmt.Errorf("AssertNextLineEquals: got %#v, not %#v", line, expectedLine) - } - - if err := scanner.Err(); err != nil { - return fmt.Errorf("AssertNextLineEquals: scan failed: %s", err.Error()) - } - - return fmt.Errorf("AssertNextLineEquals: hit EOF before finding %#v", expectedLine) -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_examples_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_examples_test.go deleted file mode 100644 index 3593853b0..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/man_examples_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package doc_test - -import ( - "bytes" - "fmt" - - "github.com/spf13/cobra" - "github.com/spf13/cobra/doc" -) - -func ExampleCommand_GenManTree() { - cmd := &cobra.Command{ - Use: "test", - Short: "my test program", - } - header := &doc.GenManHeader{ - Title: "MINE", - Section: "3", - } - doc.GenManTree(cmd, header, "/tmp") -} - -func ExampleCommand_GenMan() { - cmd := &cobra.Command{ - Use: "test", - Short: "my test program", - } - header := &doc.GenManHeader{ - Title: "MINE", - Section: "3", - } - out := new(bytes.Buffer) - doc.GenMan(cmd, header, out) - fmt.Print(out.String()) -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs.go b/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs.go deleted file mode 100644 index fa1363180..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs.go +++ /dev/null @@ -1,175 +0,0 @@ -//Copyright 2015 Red Hat 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 doc - -import ( - "fmt" - "io" - "os" - "path/filepath" - "sort" - "strings" - "time" - - "github.com/spf13/cobra" -) - -func printOptions(w io.Writer, cmd *cobra.Command, name string) error { - flags := cmd.NonInheritedFlags() - flags.SetOutput(w) - if flags.HasFlags() { - if _, err := fmt.Fprintf(w, "### Options\n\n```\n"); err != nil { - return err - } - flags.PrintDefaults() - if _, err := fmt.Fprintf(w, "```\n\n"); err != nil { - return err - } - } - - parentFlags := cmd.InheritedFlags() - parentFlags.SetOutput(w) - if parentFlags.HasFlags() { - if _, err := fmt.Fprintf(w, "### Options inherited from parent commands\n\n```\n"); err != nil { - return err - } - parentFlags.PrintDefaults() - if _, err := fmt.Fprintf(w, "```\n\n"); err != nil { - return err - } - } - return nil -} - -func GenMarkdown(cmd *cobra.Command, w io.Writer) error { - return GenMarkdownCustom(cmd, w, func(s string) string { return s }) -} - -func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { - name := cmd.CommandPath() - - short := cmd.Short - long := cmd.Long - if len(long) == 0 { - long = short - } - - if _, err := fmt.Fprintf(w, "## %s\n\n", name); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "%s\n\n", short); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "### Synopsis\n\n"); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "\n%s\n\n", long); err != nil { - return err - } - - if cmd.Runnable() { - if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.UseLine()); err != nil { - return err - } - } - - if len(cmd.Example) > 0 { - if _, err := fmt.Fprintf(w, "### Examples\n\n"); err != nil { - return err - } - if _, err := fmt.Fprintf(w, "```\n%s\n```\n\n", cmd.Example); err != nil { - return err - } - } - - if err := printOptions(w, cmd, name); err != nil { - return err - } - if hasSeeAlso(cmd) { - if _, err := fmt.Fprintf(w, "### SEE ALSO\n"); err != nil { - return err - } - if cmd.HasParent() { - parent := cmd.Parent() - pname := parent.CommandPath() - link := pname + ".md" - link = strings.Replace(link, " ", "_", -1) - if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", pname, linkHandler(link), parent.Short); err != nil { - return err - } - cmd.VisitParents(func(c *cobra.Command) { - if c.DisableAutoGenTag { - cmd.DisableAutoGenTag = c.DisableAutoGenTag - } - }) - } - - children := cmd.Commands() - sort.Sort(byName(children)) - - for _, child := range children { - if !child.IsAvailableCommand() || child.IsHelpCommand() { - continue - } - cname := name + " " + child.Name() - link := cname + ".md" - link = strings.Replace(link, " ", "_", -1) - if _, err := fmt.Fprintf(w, "* [%s](%s)\t - %s\n", cname, linkHandler(link), child.Short); err != nil { - return err - } - } - if _, err := fmt.Fprintf(w, "\n"); err != nil { - return err - } - } - if !cmd.DisableAutoGenTag { - if _, err := fmt.Fprintf(w, "###### Auto generated by spf13/cobra on %s\n", time.Now().Format("2-Jan-2006")); err != nil { - return err - } - } - return nil -} - -func GenMarkdownTree(cmd *cobra.Command, dir string) error { - identity := func(s string) string { return s } - emptyStr := func(s string) string { return "" } - return GenMarkdownTreeCustom(cmd, dir, emptyStr, identity) -} - -func GenMarkdownTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { - for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsHelpCommand() { - continue - } - if err := GenMarkdownTreeCustom(c, dir, filePrepender, linkHandler); err != nil { - return err - } - } - - basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".md" - filename := filepath.Join(dir, basename) - f, err := os.Create(filename) - if err != nil { - return err - } - defer f.Close() - - if _, err := io.WriteString(f, filePrepender(filename)); err != nil { - return err - } - if err := GenMarkdownCustom(cmd, f, linkHandler); err != nil { - return err - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs.md b/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs.md deleted file mode 100644 index 0c3b96e27..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs.md +++ /dev/null @@ -1,104 +0,0 @@ -# Generating Markdown Docs For Your Own cobra.Command - -Generating man pages from a cobra command is incredibly easy. An example is as follows: - -```go -package main - -import ( - "github.com/spf13/cobra" - "github.com/spf13/cobra/doc" -) - -func main() { - cmd := &cobra.Command{ - Use: "test", - Short: "my test program", - } - doc.GenMarkdownTree(cmd, "/tmp") -} -``` - -That will get you a Markdown document `/tmp/test.md` - -## Generate markdown docs for the entire command tree - -This program can actually generate docs for the kubectl command in the kubernetes project - -```go -package main - -import ( - "io/ioutil" - "os" - - kubectlcmd "k8s.io/kubernetes/pkg/kubectl/cmd" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - - "github.com/spf13/cobra/doc" -) - -func main() { - cmd := kubectlcmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) - doc.GenMarkdownTree(cmd, "./") -} -``` - -This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") - -## Generate markdown docs for a single command - -You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenMarkdown` instead of `GenMarkdownTree` - -```go - out := new(bytes.Buffer) - doc.GenMarkdown(cmd, out) -``` - -This will write the markdown doc for ONLY "cmd" into the out, buffer. - -## Customize the output - -Both `GenMarkdown` and `GenMarkdownTree` have alternate versions with callbacks to get some control of the output: - -```go -func GenMarkdownTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error { - //... -} -``` - -```go -func GenMarkdownCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error { - //... -} -``` - -The `filePrepender` will prepend the return value given the full filepath to the rendered Markdown file. A common use case is to add front matter to use the generated documentation with [Hugo](http://gohugo.io/): - -```go -const fmTemplate = `--- -date: %s -title: "%s" -slug: %s -url: %s ---- -` - -filePrepender := func(filename string) string { - now := time.Now().Format(time.RFC3339) - name := filepath.Base(filename) - base := strings.TrimSuffix(name, path.Ext(name)) - url := "/commands/" + strings.ToLower(base) + "/" - return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) -} -``` - -The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename: - -```go -linkHandler := func(name string) string { - base := strings.TrimSuffix(name, path.Ext(name)) - return "/commands/" + strings.ToLower(base) + "/" -} -``` - diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs_test.go b/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs_test.go deleted file mode 100644 index 86ee02930..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/md_docs_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package doc - -import ( - "bytes" - "fmt" - "os" - "strings" - "testing" -) - -var _ = fmt.Println -var _ = os.Stderr - -func TestGenMdDoc(t *testing.T) { - c := initializeWithRootCmd() - // Need two commands to run the command alphabetical sort - cmdEcho.AddCommand(cmdTimes, cmdEchoSub, cmdDeprecated) - c.AddCommand(cmdPrint, cmdEcho) - cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) - - out := new(bytes.Buffer) - - // We generate on s subcommand so we have both subcommands and parents - if err := GenMarkdown(cmdEcho, out); err != nil { - t.Fatal(err) - } - found := out.String() - - // Our description - expected := cmdEcho.Long - if !strings.Contains(found, expected) { - t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - } - - // Better have our example - expected = cmdEcho.Example - if !strings.Contains(found, expected) { - t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - } - - // A local flag - expected = "boolone" - if !strings.Contains(found, expected) { - t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - } - - // persistent flag on parent - expected = "rootflag" - if !strings.Contains(found, expected) { - t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - } - - // We better output info about our parent - expected = cmdRootWithRun.Short - if !strings.Contains(found, expected) { - t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - } - - // And about subcommands - expected = cmdEchoSub.Short - if !strings.Contains(found, expected) { - t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) - } - - unexpected := cmdDeprecated.Short - if strings.Contains(found, unexpected) { - t.Errorf("Unexpected response.\nFound: %v\nBut should not have!!\n", unexpected) - } -} - -func TestGenMdNoTag(t *testing.T) { - c := initializeWithRootCmd() - // Need two commands to run the command alphabetical sort - cmdEcho.AddCommand(cmdTimes, cmdEchoSub, cmdDeprecated) - c.AddCommand(cmdPrint, cmdEcho) - c.DisableAutoGenTag = true - cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) - out := new(bytes.Buffer) - - if err := GenMarkdown(c, out); err != nil { - t.Fatal(err) - } - found := out.String() - - unexpected := "Auto generated" - checkStringOmits(t, found, unexpected) - -} diff --git a/Godeps/_workspace/src/github.com/spf13/cobra/doc/util.go b/Godeps/_workspace/src/github.com/spf13/cobra/doc/util.go deleted file mode 100644 index a1c6b89ba..000000000 --- a/Godeps/_workspace/src/github.com/spf13/cobra/doc/util.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 Red Hat 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 doc - -import "github.com/spf13/cobra" - -// Test to see if we have a reason to print See Also information in docs -// Basically this is a test for a parent commend or a subcommand which is -// both not deprecated and not the autogenerated help command. -func hasSeeAlso(cmd *cobra.Command) bool { - if cmd.HasParent() { - return true - } - for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsHelpCommand() { - continue - } - return true - } - return false -} - -type byName []*cobra.Command - -func (s byName) Len() int { return len(s) } -func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/bool_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/bool_test.go deleted file mode 100644 index afd25ae2f..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/bool_test.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "bytes" - "fmt" - "strconv" - "testing" -) - -// This value can be a boolean ("true", "false") or "maybe" -type triStateValue int - -const ( - triStateFalse triStateValue = 0 - triStateTrue triStateValue = 1 - triStateMaybe triStateValue = 2 -) - -const strTriStateMaybe = "maybe" - -func (v *triStateValue) IsBoolFlag() bool { - return true -} - -func (v *triStateValue) Get() interface{} { - return triStateValue(*v) -} - -func (v *triStateValue) Set(s string) error { - if s == strTriStateMaybe { - *v = triStateMaybe - return nil - } - boolVal, err := strconv.ParseBool(s) - if boolVal { - *v = triStateTrue - } else { - *v = triStateFalse - } - return err -} - -func (v *triStateValue) String() string { - if *v == triStateMaybe { - return strTriStateMaybe - } - return fmt.Sprintf("%v", bool(*v == triStateTrue)) -} - -// The type of the flag as required by the pflag.Value interface -func (v *triStateValue) Type() string { - return "version" -} - -func setUpFlagSet(tristate *triStateValue) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - *tristate = triStateFalse - flag := f.VarPF(tristate, "tristate", "t", "tristate value (true, maybe or false)") - flag.NoOptDefVal = "true" - return f -} - -func TestExplicitTrue(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate=true"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } -} - -func TestImplicitTrue(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } -} - -func TestShortFlag(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"-t"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } -} - -func TestShortFlagExtraArgument(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - // The"maybe"turns into an arg, since short boolean options will only do true/false - err := f.Parse([]string{"-t", "maybe"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateTrue { - t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") - } - args := f.Args() - if len(args) != 1 || args[0] != "maybe" { - t.Fatal("expected an extra 'maybe' argument to stick around") - } -} - -func TestExplicitMaybe(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate=maybe"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateMaybe { - t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead") - } -} - -func TestExplicitFalse(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{"--tristate=false"}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateFalse { - t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead") - } -} - -func TestImplicitFalse(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - if tristate != triStateFalse { - t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead") - } -} - -func TestInvalidValue(t *testing.T) { - var tristate triStateValue - f := setUpFlagSet(&tristate) - var buf bytes.Buffer - f.SetOutput(&buf) - err := f.Parse([]string{"--tristate=invalid"}) - if err == nil { - t.Fatal("expected an error but did not get any, tristate has value", tristate) - } -} - -func TestBoolP(t *testing.T) { - b := BoolP("bool", "b", false, "bool value in CommandLine") - c := BoolP("c", "c", false, "other bool value") - args := []string{"--bool"} - if err := CommandLine.Parse(args); err != nil { - t.Error("expected no error, got ", err) - } - if *b != true { - t.Errorf("expected b=true got b=%s", b) - } - if *c != false { - t.Errorf("expect c=false got c=%s", c) - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/count_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/count_test.go deleted file mode 100644 index 716765cba..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/count_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package pflag - -import ( - "fmt" - "os" - "testing" -) - -var _ = fmt.Printf - -func setUpCount(c *int) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.CountVarP(c, "verbose", "v", "a counter") - return f -} - -func TestCount(t *testing.T) { - testCases := []struct { - input []string - success bool - expected int - }{ - {[]string{"-vvv"}, true, 3}, - {[]string{"-v", "-v", "-v"}, true, 3}, - {[]string{"-v", "--verbose", "-v"}, true, 3}, - {[]string{"-v=3", "-v"}, true, 4}, - {[]string{"-v=a"}, false, 0}, - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - for i := range testCases { - var count int - f := setUpCount(&count) - - tc := &testCases[i] - - err := f.Parse(tc.input) - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - t.Errorf("expected failure, got success") - continue - } else if tc.success { - c, err := f.GetCount("verbose") - if err != nil { - t.Errorf("Got error trying to fetch the counter flag") - } - if c != tc.expected { - t.Errorf("expected %q, got %q", tc.expected, c) - } - } - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/example_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/example_test.go deleted file mode 100644 index 9be7a49f2..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/example_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// These examples demonstrate more intricate uses of the flag package. -package pflag_test - -import ( - "errors" - "fmt" - "strings" - "time" - - flag "github.com/spf13/pflag" -) - -// Example 1: A single string flag called "species" with default value "gopher". -var species = flag.String("species", "gopher", "the species we are studying") - -// Example 2: A flag with a shorthand letter. -var gopherType = flag.StringP("gopher_type", "g", "pocket", "the variety of gopher") - -// Example 3: A user-defined flag type, a slice of durations. -type interval []time.Duration - -// String is the method to format the flag's value, part of the flag.Value interface. -// The String method's output will be used in diagnostics. -func (i *interval) String() string { - return fmt.Sprint(*i) -} - -func (i *interval) Type() string { - return "interval" -} - -// Set is the method to set the flag value, part of the flag.Value interface. -// Set's argument is a string to be parsed to set the flag. -// It's a comma-separated list, so we split it. -func (i *interval) Set(value string) error { - // If we wanted to allow the flag to be set multiple times, - // accumulating values, we would delete this if statement. - // That would permit usages such as - // -deltaT 10s -deltaT 15s - // and other combinations. - if len(*i) > 0 { - return errors.New("interval flag already set") - } - for _, dt := range strings.Split(value, ",") { - duration, err := time.ParseDuration(dt) - if err != nil { - return err - } - *i = append(*i, duration) - } - return nil -} - -// Define a flag to accumulate durations. Because it has a special type, -// we need to use the Var function and therefore create the flag during -// init. - -var intervalFlag interval - -func init() { - // Tie the command-line flag to the intervalFlag variable and - // set a usage message. - flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events") -} - -func Example() { - // All the interesting pieces are with the variables declared above, but - // to enable the flag package to see the flags defined there, one must - // execute, typically at the start of main (not init!): - // flag.Parse() - // We don't run it here because this is not a main function and - // the testing suite has already parsed the flags. -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/export_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/export_test.go deleted file mode 100644 index 9318fee00..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/export_test.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "io/ioutil" - "os" -) - -// Additional routines compiled into the package only during testing. - -// ResetForTesting clears all flag state and sets the usage function as directed. -// After calling ResetForTesting, parse errors in flag handling will not -// exit the program. -func ResetForTesting(usage func()) { - CommandLine = &FlagSet{ - name: os.Args[0], - errorHandling: ContinueOnError, - output: ioutil.Discard, - } - Usage = usage -} - -// GetCommandLine returns the default FlagSet. -func GetCommandLine() *FlagSet { - return CommandLine -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/flag_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/flag_test.go deleted file mode 100644 index e17b2aad8..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/flag_test.go +++ /dev/null @@ -1,874 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "net" - "os" - "reflect" - "sort" - "strings" - "testing" - "time" -) - -var ( - testBool = Bool("test_bool", false, "bool value") - testInt = Int("test_int", 0, "int value") - testInt64 = Int64("test_int64", 0, "int64 value") - testUint = Uint("test_uint", 0, "uint value") - testUint64 = Uint64("test_uint64", 0, "uint64 value") - testString = String("test_string", "0", "string value") - testFloat = Float64("test_float64", 0, "float64 value") - testDuration = Duration("test_duration", 0, "time.Duration value") - testOptionalInt = Int("test_optional_int", 0, "optional int value") - normalizeFlagNameInvocations = 0 -) - -func boolString(s string) string { - if s == "0" { - return "false" - } - return "true" -} - -func TestEverything(t *testing.T) { - m := make(map[string]*Flag) - desired := "0" - visitor := func(f *Flag) { - if len(f.Name) > 5 && f.Name[0:5] == "test_" { - m[f.Name] = f - ok := false - switch { - case f.Value.String() == desired: - ok = true - case f.Name == "test_bool" && f.Value.String() == boolString(desired): - ok = true - case f.Name == "test_duration" && f.Value.String() == desired+"s": - ok = true - } - if !ok { - t.Error("Visit: bad value", f.Value.String(), "for", f.Name) - } - } - } - VisitAll(visitor) - if len(m) != 9 { - t.Error("VisitAll misses some flags") - for k, v := range m { - t.Log(k, *v) - } - } - m = make(map[string]*Flag) - Visit(visitor) - if len(m) != 0 { - t.Errorf("Visit sees unset flags") - for k, v := range m { - t.Log(k, *v) - } - } - // Now set all flags - Set("test_bool", "true") - Set("test_int", "1") - Set("test_int64", "1") - Set("test_uint", "1") - Set("test_uint64", "1") - Set("test_string", "1") - Set("test_float64", "1") - Set("test_duration", "1s") - Set("test_optional_int", "1") - desired = "1" - Visit(visitor) - if len(m) != 9 { - t.Error("Visit fails after set") - for k, v := range m { - t.Log(k, *v) - } - } - // Now test they're visited in sort order. - var flagNames []string - Visit(func(f *Flag) { flagNames = append(flagNames, f.Name) }) - if !sort.StringsAreSorted(flagNames) { - t.Errorf("flag names not sorted: %v", flagNames) - } -} - -func TestUsage(t *testing.T) { - called := false - ResetForTesting(func() { called = true }) - if GetCommandLine().Parse([]string{"--x"}) == nil { - t.Error("parse did not fail for unknown flag") - } - if !called { - t.Error("did not call Usage for unknown flag") - } -} - -func TestAddFlagSet(t *testing.T) { - oldSet := NewFlagSet("old", ContinueOnError) - newSet := NewFlagSet("new", ContinueOnError) - - oldSet.String("flag1", "flag1", "flag1") - oldSet.String("flag2", "flag2", "flag2") - - newSet.String("flag2", "flag2", "flag2") - newSet.String("flag3", "flag3", "flag3") - - oldSet.AddFlagSet(newSet) - - if len(oldSet.formal) != 3 { - t.Errorf("Unexpected result adding a FlagSet to a FlagSet %v", oldSet) - } -} - -func TestAnnotation(t *testing.T) { - f := NewFlagSet("shorthand", ContinueOnError) - - if err := f.SetAnnotation("missing-flag", "key", nil); err == nil { - t.Errorf("Expected error setting annotation on non-existent flag") - } - - f.StringP("stringa", "a", "", "string value") - if err := f.SetAnnotation("stringa", "key", nil); err != nil { - t.Errorf("Unexpected error setting new nil annotation: %v", err) - } - if annotation := f.Lookup("stringa").Annotations["key"]; annotation != nil { - t.Errorf("Unexpected annotation: %v", annotation) - } - - f.StringP("stringb", "b", "", "string2 value") - if err := f.SetAnnotation("stringb", "key", []string{"value1"}); err != nil { - t.Errorf("Unexpected error setting new annotation: %v", err) - } - if annotation := f.Lookup("stringb").Annotations["key"]; !reflect.DeepEqual(annotation, []string{"value1"}) { - t.Errorf("Unexpected annotation: %v", annotation) - } - - if err := f.SetAnnotation("stringb", "key", []string{"value2"}); err != nil { - t.Errorf("Unexpected error updating annotation: %v", err) - } - if annotation := f.Lookup("stringb").Annotations["key"]; !reflect.DeepEqual(annotation, []string{"value2"}) { - t.Errorf("Unexpected annotation: %v", annotation) - } -} - -func testParse(f *FlagSet, t *testing.T) { - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - boolFlag := f.Bool("bool", false, "bool value") - bool2Flag := f.Bool("bool2", false, "bool2 value") - bool3Flag := f.Bool("bool3", false, "bool3 value") - intFlag := f.Int("int", 0, "int value") - int8Flag := f.Int8("int8", 0, "int value") - int32Flag := f.Int32("int32", 0, "int value") - int64Flag := f.Int64("int64", 0, "int64 value") - uintFlag := f.Uint("uint", 0, "uint value") - uint8Flag := f.Uint8("uint8", 0, "uint value") - uint16Flag := f.Uint16("uint16", 0, "uint value") - uint32Flag := f.Uint32("uint32", 0, "uint value") - uint64Flag := f.Uint64("uint64", 0, "uint64 value") - stringFlag := f.String("string", "0", "string value") - float32Flag := f.Float32("float32", 0, "float32 value") - float64Flag := f.Float64("float64", 0, "float64 value") - ipFlag := f.IP("ip", net.ParseIP("127.0.0.1"), "ip value") - maskFlag := f.IPMask("mask", ParseIPv4Mask("0.0.0.0"), "mask value") - durationFlag := f.Duration("duration", 5*time.Second, "time.Duration value") - optionalIntNoValueFlag := f.Int("optional-int-no-value", 0, "int value") - f.Lookup("optional-int-no-value").NoOptDefVal = "9" - optionalIntWithValueFlag := f.Int("optional-int-with-value", 0, "int value") - f.Lookup("optional-int-no-value").NoOptDefVal = "9" - extra := "one-extra-argument" - args := []string{ - "--bool", - "--bool2=true", - "--bool3=false", - "--int=22", - "--int8=-8", - "--int32=-32", - "--int64=0x23", - "--uint", "24", - "--uint8=8", - "--uint16=16", - "--uint32=32", - "--uint64=25", - "--string=hello", - "--float32=-172e12", - "--float64=2718e28", - "--ip=10.11.12.13", - "--mask=255.255.255.0", - "--duration=2m", - "--optional-int-no-value", - "--optional-int-with-value=42", - extra, - } - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolFlag != true { - t.Error("bool flag should be true, is ", *boolFlag) - } - if v, err := f.GetBool("bool"); err != nil || v != *boolFlag { - t.Error("GetBool does not work.") - } - if *bool2Flag != true { - t.Error("bool2 flag should be true, is ", *bool2Flag) - } - if *bool3Flag != false { - t.Error("bool3 flag should be false, is ", *bool2Flag) - } - if *intFlag != 22 { - t.Error("int flag should be 22, is ", *intFlag) - } - if v, err := f.GetInt("int"); err != nil || v != *intFlag { - t.Error("GetInt does not work.") - } - if *int8Flag != -8 { - t.Error("int8 flag should be 0x23, is ", *int8Flag) - } - if v, err := f.GetInt8("int8"); err != nil || v != *int8Flag { - t.Error("GetInt8 does not work.") - } - if *int32Flag != -32 { - t.Error("int32 flag should be 0x23, is ", *int32Flag) - } - if v, err := f.GetInt32("int32"); err != nil || v != *int32Flag { - t.Error("GetInt32 does not work.") - } - if *int64Flag != 0x23 { - t.Error("int64 flag should be 0x23, is ", *int64Flag) - } - if v, err := f.GetInt64("int64"); err != nil || v != *int64Flag { - t.Error("GetInt64 does not work.") - } - if *uintFlag != 24 { - t.Error("uint flag should be 24, is ", *uintFlag) - } - if v, err := f.GetUint("uint"); err != nil || v != *uintFlag { - t.Error("GetUint does not work.") - } - if *uint8Flag != 8 { - t.Error("uint8 flag should be 8, is ", *uint8Flag) - } - if v, err := f.GetUint8("uint8"); err != nil || v != *uint8Flag { - t.Error("GetUint8 does not work.") - } - if *uint16Flag != 16 { - t.Error("uint16 flag should be 16, is ", *uint16Flag) - } - if v, err := f.GetUint16("uint16"); err != nil || v != *uint16Flag { - t.Error("GetUint16 does not work.") - } - if *uint32Flag != 32 { - t.Error("uint32 flag should be 32, is ", *uint32Flag) - } - if v, err := f.GetUint32("uint32"); err != nil || v != *uint32Flag { - t.Error("GetUint32 does not work.") - } - if *uint64Flag != 25 { - t.Error("uint64 flag should be 25, is ", *uint64Flag) - } - if v, err := f.GetUint64("uint64"); err != nil || v != *uint64Flag { - t.Error("GetUint64 does not work.") - } - if *stringFlag != "hello" { - t.Error("string flag should be `hello`, is ", *stringFlag) - } - if v, err := f.GetString("string"); err != nil || v != *stringFlag { - t.Error("GetString does not work.") - } - if *float32Flag != -172e12 { - t.Error("float32 flag should be -172e12, is ", *float32Flag) - } - if v, err := f.GetFloat32("float32"); err != nil || v != *float32Flag { - t.Errorf("GetFloat32 returned %v but float32Flag was %v", v, *float32Flag) - } - if *float64Flag != 2718e28 { - t.Error("float64 flag should be 2718e28, is ", *float64Flag) - } - if v, err := f.GetFloat64("float64"); err != nil || v != *float64Flag { - t.Errorf("GetFloat64 returned %v but float64Flag was %v", v, *float64Flag) - } - if !(*ipFlag).Equal(net.ParseIP("10.11.12.13")) { - t.Error("ip flag should be 10.11.12.13, is ", *ipFlag) - } - if v, err := f.GetIP("ip"); err != nil || !v.Equal(*ipFlag) { - t.Errorf("GetIP returned %v but ipFlag was %v", v, *ipFlag) - } - if (*maskFlag).String() != ParseIPv4Mask("255.255.255.0").String() { - t.Error("mask flag should be 255.255.255.0, is ", (*maskFlag).String()) - } - if v, err := f.GetIPv4Mask("mask"); err != nil || v.String() != (*maskFlag).String() { - t.Errorf("GetIP returned %v maskFlag was %v error was %v", v, *maskFlag, err) - } - if *durationFlag != 2*time.Minute { - t.Error("duration flag should be 2m, is ", *durationFlag) - } - if v, err := f.GetDuration("duration"); err != nil || v != *durationFlag { - t.Error("GetDuration does not work.") - } - if _, err := f.GetInt("duration"); err == nil { - t.Error("GetInt parsed a time.Duration?!?!") - } - if *optionalIntNoValueFlag != 9 { - t.Error("optional int flag should be the default value, is ", *optionalIntNoValueFlag) - } - if *optionalIntWithValueFlag != 42 { - t.Error("optional int flag should be 42, is ", *optionalIntWithValueFlag) - } - if len(f.Args()) != 1 { - t.Error("expected one argument, got", len(f.Args())) - } else if f.Args()[0] != extra { - t.Errorf("expected argument %q got %q", extra, f.Args()[0]) - } -} - -func TestShorthand(t *testing.T) { - f := NewFlagSet("shorthand", ContinueOnError) - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - boolaFlag := f.BoolP("boola", "a", false, "bool value") - boolbFlag := f.BoolP("boolb", "b", false, "bool2 value") - boolcFlag := f.BoolP("boolc", "c", false, "bool3 value") - booldFlag := f.BoolP("boold", "d", false, "bool4 value") - stringaFlag := f.StringP("stringa", "s", "0", "string value") - stringzFlag := f.StringP("stringz", "z", "0", "string value") - extra := "interspersed-argument" - notaflag := "--i-look-like-a-flag" - args := []string{ - "-ab", - extra, - "-cs", - "hello", - "-z=something", - "-d=true", - "--", - notaflag, - } - f.SetOutput(ioutil.Discard) - if err := f.Parse(args); err != nil { - t.Error("expected no error, got ", err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolaFlag != true { - t.Error("boola flag should be true, is ", *boolaFlag) - } - if *boolbFlag != true { - t.Error("boolb flag should be true, is ", *boolbFlag) - } - if *boolcFlag != true { - t.Error("boolc flag should be true, is ", *boolcFlag) - } - if *booldFlag != true { - t.Error("boold flag should be true, is ", *booldFlag) - } - if *stringaFlag != "hello" { - t.Error("stringa flag should be `hello`, is ", *stringaFlag) - } - if *stringzFlag != "something" { - t.Error("stringz flag should be `something`, is ", *stringzFlag) - } - if len(f.Args()) != 2 { - t.Error("expected one argument, got", len(f.Args())) - } else if f.Args()[0] != extra { - t.Errorf("expected argument %q got %q", extra, f.Args()[0]) - } else if f.Args()[1] != notaflag { - t.Errorf("expected argument %q got %q", notaflag, f.Args()[1]) - } - if f.ArgsLenAtDash() != 1 { - t.Errorf("expected argsLenAtDash %d got %d", f.ArgsLenAtDash(), 1) - } -} - -func TestParse(t *testing.T) { - ResetForTesting(func() { t.Error("bad parse") }) - testParse(GetCommandLine(), t) -} - -func TestFlagSetParse(t *testing.T) { - testParse(NewFlagSet("test", ContinueOnError), t) -} - -func TestChangedHelper(t *testing.T) { - f := NewFlagSet("changedtest", ContinueOnError) - _ = f.Bool("changed", false, "changed bool") - _ = f.Bool("settrue", true, "true to true") - _ = f.Bool("setfalse", false, "false to false") - _ = f.Bool("unchanged", false, "unchanged bool") - - args := []string{"--changed", "--settrue", "--setfalse=false"} - if err := f.Parse(args); err != nil { - t.Error("f.Parse() = false after Parse") - } - if !f.Changed("changed") { - t.Errorf("--changed wasn't changed!") - } - if !f.Changed("settrue") { - t.Errorf("--settrue wasn't changed!") - } - if !f.Changed("setfalse") { - t.Errorf("--setfalse wasn't changed!") - } - if f.Changed("unchanged") { - t.Errorf("--unchanged was changed!") - } - if f.Changed("invalid") { - t.Errorf("--invalid was changed!") - } - if f.ArgsLenAtDash() != -1 { - t.Errorf("Expected argsLenAtDash: %d but got %d", -1, f.ArgsLenAtDash()) - } -} - -func replaceSeparators(name string, from []string, to string) string { - result := name - for _, sep := range from { - result = strings.Replace(result, sep, to, -1) - } - // Type convert to indicate normalization has been done. - return result -} - -func wordSepNormalizeFunc(f *FlagSet, name string) NormalizedName { - seps := []string{"-", "_"} - name = replaceSeparators(name, seps, ".") - normalizeFlagNameInvocations++ - - return NormalizedName(name) -} - -func testWordSepNormalizedNames(args []string, t *testing.T) { - f := NewFlagSet("normalized", ContinueOnError) - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - withDashFlag := f.Bool("with-dash-flag", false, "bool value") - // Set this after some flags have been added and before others. - f.SetNormalizeFunc(wordSepNormalizeFunc) - withUnderFlag := f.Bool("with_under_flag", false, "bool value") - withBothFlag := f.Bool("with-both_flag", false, "bool value") - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *withDashFlag != true { - t.Error("withDashFlag flag should be true, is ", *withDashFlag) - } - if *withUnderFlag != true { - t.Error("withUnderFlag flag should be true, is ", *withUnderFlag) - } - if *withBothFlag != true { - t.Error("withBothFlag flag should be true, is ", *withBothFlag) - } -} - -func TestWordSepNormalizedNames(t *testing.T) { - args := []string{ - "--with-dash-flag", - "--with-under-flag", - "--with-both-flag", - } - testWordSepNormalizedNames(args, t) - - args = []string{ - "--with_dash_flag", - "--with_under_flag", - "--with_both_flag", - } - testWordSepNormalizedNames(args, t) - - args = []string{ - "--with-dash_flag", - "--with-under_flag", - "--with-both_flag", - } - testWordSepNormalizedNames(args, t) -} - -func aliasAndWordSepFlagNames(f *FlagSet, name string) NormalizedName { - seps := []string{"-", "_"} - - oldName := replaceSeparators("old-valid_flag", seps, ".") - newName := replaceSeparators("valid-flag", seps, ".") - - name = replaceSeparators(name, seps, ".") - switch name { - case oldName: - name = newName - break - } - - return NormalizedName(name) -} - -func TestCustomNormalizedNames(t *testing.T) { - f := NewFlagSet("normalized", ContinueOnError) - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - - validFlag := f.Bool("valid-flag", false, "bool value") - f.SetNormalizeFunc(aliasAndWordSepFlagNames) - someOtherFlag := f.Bool("some-other-flag", false, "bool value") - - args := []string{"--old_valid_flag", "--some-other_flag"} - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - - if *validFlag != true { - t.Errorf("validFlag is %v even though we set the alias --old_valid_falg", *validFlag) - } - if *someOtherFlag != true { - t.Error("someOtherFlag should be true, is ", *someOtherFlag) - } -} - -// Every flag we add, the name (displayed also in usage) should normalized -func TestNormalizationFuncShouldChangeFlagName(t *testing.T) { - // Test normalization after addition - f := NewFlagSet("normalized", ContinueOnError) - - f.Bool("valid_flag", false, "bool value") - if f.Lookup("valid_flag").Name != "valid_flag" { - t.Error("The new flag should have the name 'valid_flag' instead of ", f.Lookup("valid_flag").Name) - } - - f.SetNormalizeFunc(wordSepNormalizeFunc) - if f.Lookup("valid_flag").Name != "valid.flag" { - t.Error("The new flag should have the name 'valid.flag' instead of ", f.Lookup("valid_flag").Name) - } - - // Test normalization before addition - f = NewFlagSet("normalized", ContinueOnError) - f.SetNormalizeFunc(wordSepNormalizeFunc) - - f.Bool("valid_flag", false, "bool value") - if f.Lookup("valid_flag").Name != "valid.flag" { - t.Error("The new flag should have the name 'valid.flag' instead of ", f.Lookup("valid_flag").Name) - } -} - -// Declare a user-defined flag type. -type flagVar []string - -func (f *flagVar) String() string { - return fmt.Sprint([]string(*f)) -} - -func (f *flagVar) Set(value string) error { - *f = append(*f, value) - return nil -} - -func (f *flagVar) Type() string { - return "flagVar" -} - -func TestUserDefined(t *testing.T) { - var flags FlagSet - flags.Init("test", ContinueOnError) - var v flagVar - flags.VarP(&v, "v", "v", "usage") - if err := flags.Parse([]string{"--v=1", "-v2", "-v", "3"}); err != nil { - t.Error(err) - } - if len(v) != 3 { - t.Fatal("expected 3 args; got ", len(v)) - } - expect := "[1 2 3]" - if v.String() != expect { - t.Errorf("expected value %q got %q", expect, v.String()) - } -} - -func TestSetOutput(t *testing.T) { - var flags FlagSet - var buf bytes.Buffer - flags.SetOutput(&buf) - flags.Init("test", ContinueOnError) - flags.Parse([]string{"--unknown"}) - if out := buf.String(); !strings.Contains(out, "--unknown") { - t.Logf("expected output mentioning unknown; got %q", out) - } -} - -// This tests that one can reset the flags. This still works but not well, and is -// superseded by FlagSet. -func TestChangingArgs(t *testing.T) { - ResetForTesting(func() { t.Fatal("bad parse") }) - oldArgs := os.Args - defer func() { os.Args = oldArgs }() - os.Args = []string{"cmd", "--before", "subcmd"} - before := Bool("before", false, "") - if err := GetCommandLine().Parse(os.Args[1:]); err != nil { - t.Fatal(err) - } - cmd := Arg(0) - os.Args = []string{"subcmd", "--after", "args"} - after := Bool("after", false, "") - Parse() - args := Args() - - if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" { - t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args) - } -} - -// Test that -help invokes the usage message and returns ErrHelp. -func TestHelp(t *testing.T) { - var helpCalled = false - fs := NewFlagSet("help test", ContinueOnError) - fs.Usage = func() { helpCalled = true } - var flag bool - fs.BoolVar(&flag, "flag", false, "regular flag") - // Regular flag invocation should work - err := fs.Parse([]string{"--flag=true"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - if !flag { - t.Error("flag was not set by --flag") - } - if helpCalled { - t.Error("help called for regular flag") - helpCalled = false // reset for next test - } - // Help flag should work as expected. - err = fs.Parse([]string{"--help"}) - if err == nil { - t.Fatal("error expected") - } - if err != ErrHelp { - t.Fatal("expected ErrHelp; got ", err) - } - if !helpCalled { - t.Fatal("help was not called") - } - // If we define a help flag, that should override. - var help bool - fs.BoolVar(&help, "help", false, "help flag") - helpCalled = false - err = fs.Parse([]string{"--help"}) - if err != nil { - t.Fatal("expected no error for defined --help; got ", err) - } - if helpCalled { - t.Fatal("help was called; should not have been for defined help flag") - } -} - -func TestNoInterspersed(t *testing.T) { - f := NewFlagSet("test", ContinueOnError) - f.SetInterspersed(false) - f.Bool("true", true, "always true") - f.Bool("false", false, "always false") - err := f.Parse([]string{"--true", "break", "--false"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - args := f.Args() - if len(args) != 2 || args[0] != "break" || args[1] != "--false" { - t.Fatal("expected interspersed options/non-options to fail") - } -} - -func TestTermination(t *testing.T) { - f := NewFlagSet("termination", ContinueOnError) - boolFlag := f.BoolP("bool", "l", false, "bool value") - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - arg1 := "ls" - arg2 := "-l" - args := []string{ - "--", - arg1, - arg2, - } - f.SetOutput(ioutil.Discard) - if err := f.Parse(args); err != nil { - t.Fatal("expected no error; got ", err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolFlag { - t.Error("expected boolFlag=false, got true") - } - if len(f.Args()) != 2 { - t.Errorf("expected 2 arguments, got %d: %v", len(f.Args()), f.Args()) - } - if f.Args()[0] != arg1 { - t.Errorf("expected argument %q got %q", arg1, f.Args()[0]) - } - if f.Args()[1] != arg2 { - t.Errorf("expected argument %q got %q", arg2, f.Args()[1]) - } - if f.ArgsLenAtDash() != 0 { - t.Errorf("expected argsLenAtDash %d got %d", 0, f.ArgsLenAtDash()) - } -} - -func TestDeprecatedFlagInDocs(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("badflag", true, "always true") - f.MarkDeprecated("badflag", "use --good-flag instead") - - out := new(bytes.Buffer) - f.SetOutput(out) - f.PrintDefaults() - - if strings.Contains(out.String(), "badflag") { - t.Errorf("found deprecated flag in usage!") - } -} - -func TestDeprecatedFlagShorthandInDocs(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - name := "noshorthandflag" - f.BoolP(name, "n", true, "always true") - f.MarkShorthandDeprecated("noshorthandflag", fmt.Sprintf("use --%s instead", name)) - - out := new(bytes.Buffer) - f.SetOutput(out) - f.PrintDefaults() - - if strings.Contains(out.String(), "-n,") { - t.Errorf("found deprecated flag shorthand in usage!") - } -} - -func parseReturnStderr(t *testing.T, f *FlagSet, args []string) (string, error) { - oldStderr := os.Stderr - r, w, _ := os.Pipe() - os.Stderr = w - - err := f.Parse(args) - - outC := make(chan string) - // copy the output in a separate goroutine so printing can't block indefinitely - go func() { - var buf bytes.Buffer - io.Copy(&buf, r) - outC <- buf.String() - }() - - w.Close() - os.Stderr = oldStderr - out := <-outC - - return out, err -} - -func TestDeprecatedFlagUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("badflag", true, "always true") - usageMsg := "use --good-flag instead" - f.MarkDeprecated("badflag", usageMsg) - - args := []string{"--badflag"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if !strings.Contains(out, usageMsg) { - t.Errorf("usageMsg not printed when using a deprecated flag!") - } -} - -func TestDeprecatedFlagShorthandUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - name := "noshorthandflag" - f.BoolP(name, "n", true, "always true") - usageMsg := fmt.Sprintf("use --%s instead", name) - f.MarkShorthandDeprecated(name, usageMsg) - - args := []string{"-n"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if !strings.Contains(out, usageMsg) { - t.Errorf("usageMsg not printed when using a deprecated flag!") - } -} - -func TestDeprecatedFlagUsageNormalized(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("bad-double_flag", true, "always true") - f.SetNormalizeFunc(wordSepNormalizeFunc) - usageMsg := "use --good-flag instead" - f.MarkDeprecated("bad_double-flag", usageMsg) - - args := []string{"--bad_double_flag"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if !strings.Contains(out, usageMsg) { - t.Errorf("usageMsg not printed when using a deprecated flag!") - } -} - -// Name normalization function should be called only once on flag addition -func TestMultipleNormalizeFlagNameInvocations(t *testing.T) { - normalizeFlagNameInvocations = 0 - - f := NewFlagSet("normalized", ContinueOnError) - f.SetNormalizeFunc(wordSepNormalizeFunc) - f.Bool("with_under_flag", false, "bool value") - - if normalizeFlagNameInvocations != 1 { - t.Fatal("Expected normalizeFlagNameInvocations to be 1; got ", normalizeFlagNameInvocations) - } -} - -// -func TestHiddenFlagInUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("secretFlag", true, "shhh") - f.MarkHidden("secretFlag") - - out := new(bytes.Buffer) - f.SetOutput(out) - f.PrintDefaults() - - if strings.Contains(out.String(), "secretFlag") { - t.Errorf("found hidden flag in usage!") - } -} - -// -func TestHiddenFlagUsage(t *testing.T) { - f := NewFlagSet("bob", ContinueOnError) - f.Bool("secretFlag", true, "shhh") - f.MarkHidden("secretFlag") - - args := []string{"--secretFlag"} - out, err := parseReturnStderr(t, f, args) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - if strings.Contains(out, "shhh") { - t.Errorf("usage message printed when using a hidden flag!") - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/golangflag_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/golangflag_test.go deleted file mode 100644 index 77e2d7d80..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/golangflag_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - goflag "flag" - "testing" -) - -func TestGoflags(t *testing.T) { - goflag.String("stringFlag", "stringFlag", "stringFlag") - goflag.Bool("boolFlag", false, "boolFlag") - - f := NewFlagSet("test", ContinueOnError) - - f.AddGoFlagSet(goflag.CommandLine) - err := f.Parse([]string{"--stringFlag=bob", "--boolFlag"}) - if err != nil { - t.Fatal("expected no error; get", err) - } - - getString, err := f.GetString("stringFlag") - if err != nil { - t.Fatal("expected no error; get", err) - } - if getString != "bob" { - t.Fatalf("expected getString=bob but got getString=%s", getString) - } - - getBool, err := f.GetBool("boolFlag") - if err != nil { - t.Fatal("expected no error; get", err) - } - if getBool != true { - t.Fatalf("expected getBool=true but got getBool=%v", getBool) - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/int_slice_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/int_slice_test.go deleted file mode 100644 index 5f2eee66a..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/int_slice_test.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpISFlagSet(isp *[]int) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IntSliceVar(isp, "is", []int{}, "Command separated list!") - return f -} - -func setUpISFlagSetWithDefault(isp *[]int) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IntSliceVar(isp, "is", []int{0, 1}, "Command separated list!") - return f -} - -func TestEmptyIS(t *testing.T) { - var is []int - f := setUpISFlagSet(&is) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getIS, err := f.GetIntSlice("is") - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - if len(getIS) != 0 { - t.Fatalf("got is %v with len=%d but expected length=0", getIS, len(getIS)) - } -} - -func TestIS(t *testing.T) { - var is []int - f := setUpISFlagSet(&is) - - vals := []string{"1", "2", "4", "3"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d", i, vals[i], v) - } - } - getIS, err := f.GetIntSlice("is") - for i, v := range getIS { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d from GetIntSlice", i, vals[i], v) - } - } -} - -func TestISDefault(t *testing.T) { - var is []int - f := setUpISFlagSetWithDefault(&is) - - vals := []string{"0", "1"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getIS, err := f.GetIntSlice("is") - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - for i, v := range getIS { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d from GetIntSlice but got: %d", i, d, v) - } - } -} - -func TestISWithDefault(t *testing.T) { - var is []int - f := setUpISFlagSetWithDefault(&is) - - vals := []string{"1", "2"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getIS, err := f.GetIntSlice("is") - if err != nil { - t.Fatal("got an error from GetIntSlice():", err) - } - for i, v := range getIS { - d, err := strconv.Atoi(vals[i]) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d from GetIntSlice but got: %d", i, d, v) - } - } -} - -func TestISCalledTwice(t *testing.T) { - var is []int - f := setUpISFlagSet(&is) - - in := []string{"1,2", "3"} - expected := []int{1, 2, 3} - argfmt := "--is=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - if expected[i] != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, expected[i], v) - } - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/ip_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/ip_test.go deleted file mode 100644 index 1fec50e42..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/ip_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package pflag - -import ( - "fmt" - "net" - "os" - "testing" -) - -func setUpIP(ip *net.IP) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.IPVar(ip, "address", net.ParseIP("0.0.0.0"), "IP Address") - return f -} - -func TestIP(t *testing.T) { - testCases := []struct { - input string - success bool - expected string - }{ - {"0.0.0.0", true, "0.0.0.0"}, - {" 0.0.0.0 ", true, "0.0.0.0"}, - {"1.2.3.4", true, "1.2.3.4"}, - {"127.0.0.1", true, "127.0.0.1"}, - {"255.255.255.255", true, "255.255.255.255"}, - {"", false, ""}, - {"0", false, ""}, - {"localhost", false, ""}, - {"0.0.0", false, ""}, - {"0.0.0.", false, ""}, - {"0.0.0.0.", false, ""}, - {"0.0.0.256", false, ""}, - {"0 . 0 . 0 . 0", false, ""}, - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - for i := range testCases { - var addr net.IP - f := setUpIP(&addr) - - tc := &testCases[i] - - arg := fmt.Sprintf("--address=%s", tc.input) - err := f.Parse([]string{arg}) - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - t.Errorf("expected failure") - continue - } else if tc.success { - ip, err := f.GetIP("address") - if err != nil { - t.Errorf("Got error trying to fetch the IP flag: %v", err) - } - if ip.String() != tc.expected { - t.Errorf("expected %q, got %q", tc.expected, ip.String()) - } - } - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/ipnet_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/ipnet_test.go deleted file mode 100644 index 335b6fa15..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/ipnet_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package pflag - -import ( - "fmt" - "net" - "os" - "testing" -) - -func setUpIPNet(ip *net.IPNet) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - _, def, _ := net.ParseCIDR("0.0.0.0/0") - f.IPNetVar(ip, "address", *def, "IP Address") - return f -} - -func TestIPNet(t *testing.T) { - testCases := []struct { - input string - success bool - expected string - }{ - {"0.0.0.0/0", true, "0.0.0.0/0"}, - {" 0.0.0.0/0 ", true, "0.0.0.0/0"}, - {"1.2.3.4/8", true, "1.0.0.0/8"}, - {"127.0.0.1/16", true, "127.0.0.0/16"}, - {"255.255.255.255/19", true, "255.255.224.0/19"}, - {"255.255.255.255/32", true, "255.255.255.255/32"}, - {"", false, ""}, - {"/0", false, ""}, - {"0", false, ""}, - {"0/0", false, ""}, - {"localhost/0", false, ""}, - {"0.0.0/4", false, ""}, - {"0.0.0./8", false, ""}, - {"0.0.0.0./12", false, ""}, - {"0.0.0.256/16", false, ""}, - {"0.0.0.0 /20", false, ""}, - {"0.0.0.0/ 24", false, ""}, - {"0 . 0 . 0 . 0 / 28", false, ""}, - {"0.0.0.0/33", false, ""}, - } - - devnull, _ := os.Open(os.DevNull) - os.Stderr = devnull - for i := range testCases { - var addr net.IPNet - f := setUpIPNet(&addr) - - tc := &testCases[i] - - arg := fmt.Sprintf("--address=%s", tc.input) - err := f.Parse([]string{arg}) - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - t.Errorf("expected failure") - continue - } else if tc.success { - ip, err := f.GetIPNet("address") - if err != nil { - t.Errorf("Got error trying to fetch the IP flag: %v", err) - } - if ip.String() != tc.expected { - t.Errorf("expected %q, got %q", tc.expected, ip.String()) - } - } - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/string_slice_test.go b/Godeps/_workspace/src/github.com/spf13/pflag/string_slice_test.go deleted file mode 100644 index c7fdc70b4..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/string_slice_test.go +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strings" - "testing" -) - -func setUpSSFlagSet(ssp *[]string) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringSliceVar(ssp, "ss", []string{}, "Command separated list!") - return f -} - -func setUpSSFlagSetWithDefault(ssp *[]string) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringSliceVar(ssp, "ss", []string{"default", "values"}, "Command separated list!") - return f -} - -func TestEmptySS(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - if len(getSS) != 0 { - t.Fatalf("got ss %v with len=%d but expected length=0", getSS, len(getSS)) - } -} - -func TestSS(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - vals := []string{"one", "two", "4", "3"} - arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - for i, v := range getSS { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v) - } - } -} - -func TestSSDefault(t *testing.T) { - var ss []string - f := setUpSSFlagSetWithDefault(&ss) - - vals := []string{"default", "values"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - for i, v := range getSS { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v) - } - } -} - -func TestSSWithDefault(t *testing.T) { - var ss []string - f := setUpSSFlagSetWithDefault(&ss) - - vals := []string{"one", "two", "4", "3"} - arg := fmt.Sprintf("--ss=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, vals[i], v) - } - } - - getSS, err := f.GetStringSlice("ss") - if err != nil { - t.Fatal("got an error from GetStringSlice():", err) - } - for i, v := range getSS { - if vals[i] != v { - t.Fatalf("expected ss[%d] to be %s from GetStringSlice but got: %s", i, vals[i], v) - } - } -} - -func TestSSCalledTwice(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - in := []string{"one,two", "three"} - expected := []string{"one", "two", "three"} - argfmt := "--ss=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if expected[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v) - } - } -} - -func TestSSWithComma(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - in := []string{`"one,two"`, `"three"`} - expected := []string{"one,two", "three"} - argfmt := "--ss=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range ss { - if expected[i] != v { - t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v) - } - } -} diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/verify/all.sh b/Godeps/_workspace/src/github.com/spf13/pflag/verify/all.sh deleted file mode 100644 index 739f89c0b..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/verify/all.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash - -set -o errexit -set -o nounset -set -o pipefail - -ROOT=$(dirname "${BASH_SOURCE}")/.. - -# Some useful colors. -if [[ -z "${color_start-}" ]]; then - declare -r color_start="\033[" - declare -r color_red="${color_start}0;31m" - declare -r color_yellow="${color_start}0;33m" - declare -r color_green="${color_start}0;32m" - declare -r color_norm="${color_start}0m" -fi - -SILENT=true - -function is-excluded { - for e in $EXCLUDE; do - if [[ $1 -ef ${BASH_SOURCE} ]]; then - return - fi - if [[ $1 -ef "$ROOT/hack/$e" ]]; then - return - fi - done - return 1 -} - -while getopts ":v" opt; do - case $opt in - v) - SILENT=false - ;; - \?) - echo "Invalid flag: -$OPTARG" >&2 - exit 1 - ;; - esac -done - -if $SILENT ; then - echo "Running in the silent mode, run with -v if you want to see script logs." -fi - -EXCLUDE="all.sh" - -ret=0 -for t in `ls $ROOT/verify/*.sh` -do - if is-excluded $t ; then - echo "Skipping $t" - continue - fi - if $SILENT ; then - echo -e "Verifying $t" - if bash "$t" &> /dev/null; then - echo -e "${color_green}SUCCESS${color_norm}" - else - echo -e "${color_red}FAILED${color_norm}" - ret=1 - fi - else - bash "$t" || ret=1 - fi -done -exit $ret diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/verify/gofmt.sh b/Godeps/_workspace/src/github.com/spf13/pflag/verify/gofmt.sh deleted file mode 100644 index f66acf803..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/verify/gofmt.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -set -o errexit -set -o nounset -set -o pipefail - -ROOT=$(dirname "${BASH_SOURCE}")/.. - -pushd "${ROOT}" > /dev/null - -GOFMT=${GOFMT:-"gofmt"} -bad_files=$(find . -name '*.go' | xargs $GOFMT -s -l) -if [[ -n "${bad_files}" ]]; then - echo "!!! '$GOFMT' needs to be run on the following files: " - echo "${bad_files}" - exit 1 -fi - -# ex: ts=2 sw=2 et filetype=sh diff --git a/Godeps/_workspace/src/github.com/spf13/pflag/verify/golint.sh b/Godeps/_workspace/src/github.com/spf13/pflag/verify/golint.sh deleted file mode 100644 index 685c1778e..000000000 --- a/Godeps/_workspace/src/github.com/spf13/pflag/verify/golint.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -ROOT=$(dirname "${BASH_SOURCE}")/.. -GOLINT=${GOLINT:-"golint"} - -pushd "${ROOT}" > /dev/null - bad_files=$($GOLINT -min_confidence=0.9 ./...) - if [[ -n "${bad_files}" ]]; then - echo "!!! '$GOLINT' problems: " - echo "${bad_files}" - exit 1 - fi -popd > /dev/null - -# ex: ts=2 sw=2 et filetype=sh diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/cbor_test.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/cbor_test.go deleted file mode 100644 index 205dffa7d..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/cbor_test.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -package codec - -import ( - "bufio" - "bytes" - "encoding/hex" - "math" - "os" - "regexp" - "strings" - "testing" -) - -func TestCborIndefiniteLength(t *testing.T) { - oldMapType := testCborH.MapType - defer func() { - testCborH.MapType = oldMapType - }() - testCborH.MapType = testMapStrIntfTyp - // var ( - // M1 map[string][]byte - // M2 map[uint64]bool - // L1 []interface{} - // S1 []string - // B1 []byte - // ) - var v, vv interface{} - // define it (v), encode it using indefinite lengths, decode it (vv), compare v to vv - v = map[string]interface{}{ - "one-byte-key": []byte{1, 2, 3, 4, 5, 6}, - "two-string-key": "two-value", - "three-list-key": []interface{}{true, false, uint64(1), int64(-1)}, - } - var buf bytes.Buffer - // buf.Reset() - e := NewEncoder(&buf, testCborH) - buf.WriteByte(cborBdIndefiniteMap) - //---- - buf.WriteByte(cborBdIndefiniteString) - e.MustEncode("one-") - e.MustEncode("byte-") - e.MustEncode("key") - buf.WriteByte(cborBdBreak) - - buf.WriteByte(cborBdIndefiniteBytes) - e.MustEncode([]byte{1, 2, 3}) - e.MustEncode([]byte{4, 5, 6}) - buf.WriteByte(cborBdBreak) - - //---- - buf.WriteByte(cborBdIndefiniteString) - e.MustEncode("two-") - e.MustEncode("string-") - e.MustEncode("key") - buf.WriteByte(cborBdBreak) - - buf.WriteByte(cborBdIndefiniteString) - e.MustEncode([]byte("two-")) // encode as bytes, to check robustness of code - e.MustEncode([]byte("value")) - buf.WriteByte(cborBdBreak) - - //---- - buf.WriteByte(cborBdIndefiniteString) - e.MustEncode("three-") - e.MustEncode("list-") - e.MustEncode("key") - buf.WriteByte(cborBdBreak) - - buf.WriteByte(cborBdIndefiniteArray) - e.MustEncode(true) - e.MustEncode(false) - e.MustEncode(uint64(1)) - e.MustEncode(int64(-1)) - buf.WriteByte(cborBdBreak) - - buf.WriteByte(cborBdBreak) // close map - - NewDecoderBytes(buf.Bytes(), testCborH).MustDecode(&vv) - if err := deepEqual(v, vv); err != nil { - logT(t, "-------- Before and After marshal do not match: Error: %v", err) - logT(t, " ....... GOLDEN: (%T) %#v", v, v) - logT(t, " ....... DECODED: (%T) %#v", vv, vv) - failT(t) - } -} - -type testCborGolden struct { - Base64 string `codec:"cbor"` - Hex string `codec:"hex"` - Roundtrip bool `codec:"roundtrip"` - Decoded interface{} `codec:"decoded"` - Diagnostic string `codec:"diagnostic"` - Skip bool `codec:"skip"` -} - -// Some tests are skipped because they include numbers outside the range of int64/uint64 -func doTestCborGoldens(t *testing.T) { - oldMapType := testCborH.MapType - defer func() { - testCborH.MapType = oldMapType - }() - testCborH.MapType = testMapStrIntfTyp - // decode test-cbor-goldens.json into a list of []*testCborGolden - // for each one, - // - decode hex into []byte bs - // - decode bs into interface{} v - // - compare both using deepequal - // - for any miss, record it - var gs []*testCborGolden - f, err := os.Open("test-cbor-goldens.json") - if err != nil { - logT(t, "error opening test-cbor-goldens.json: %v", err) - failT(t) - } - defer f.Close() - jh := new(JsonHandle) - jh.MapType = testMapStrIntfTyp - // d := NewDecoder(f, jh) - d := NewDecoder(bufio.NewReader(f), jh) - // err = d.Decode(&gs) - d.MustDecode(&gs) - if err != nil { - logT(t, "error json decoding test-cbor-goldens.json: %v", err) - failT(t) - } - - tagregex := regexp.MustCompile(`[\d]+\(.+?\)`) - hexregex := regexp.MustCompile(`h'([0-9a-fA-F]*)'`) - for i, g := range gs { - // fmt.Printf("%v, skip: %v, isTag: %v, %s\n", i, g.Skip, tagregex.MatchString(g.Diagnostic), g.Diagnostic) - // skip tags or simple or those with prefix, as we can't verify them. - if g.Skip || strings.HasPrefix(g.Diagnostic, "simple(") || tagregex.MatchString(g.Diagnostic) { - // fmt.Printf("%v: skipped\n", i) - logT(t, "[%v] skipping because skip=true OR unsupported simple value or Tag Value", i) - continue - } - // println("++++++++++++", i, "g.Diagnostic", g.Diagnostic) - if hexregex.MatchString(g.Diagnostic) { - // println(i, "g.Diagnostic matched hex") - if s2 := g.Diagnostic[2 : len(g.Diagnostic)-1]; s2 == "" { - g.Decoded = zeroByteSlice - } else if bs2, err2 := hex.DecodeString(s2); err2 == nil { - g.Decoded = bs2 - } - // fmt.Printf("%v: hex: %v\n", i, g.Decoded) - } - bs, err := hex.DecodeString(g.Hex) - if err != nil { - logT(t, "[%v] error hex decoding %s [%v]: %v", i, g.Hex, err) - failT(t) - } - var v interface{} - NewDecoderBytes(bs, testCborH).MustDecode(&v) - if _, ok := v.(RawExt); ok { - continue - } - // check the diagnostics to compare - switch g.Diagnostic { - case "Infinity": - b := math.IsInf(v.(float64), 1) - testCborError(t, i, math.Inf(1), v, nil, &b) - case "-Infinity": - b := math.IsInf(v.(float64), -1) - testCborError(t, i, math.Inf(-1), v, nil, &b) - case "NaN": - // println(i, "checking NaN") - b := math.IsNaN(v.(float64)) - testCborError(t, i, math.NaN(), v, nil, &b) - case "undefined": - b := v == nil - testCborError(t, i, nil, v, nil, &b) - default: - v0 := g.Decoded - // testCborCoerceJsonNumber(reflect.ValueOf(&v0)) - testCborError(t, i, v0, v, deepEqual(v0, v), nil) - } - } -} - -func testCborError(t *testing.T, i int, v0, v1 interface{}, err error, equal *bool) { - if err == nil && equal == nil { - // fmt.Printf("%v testCborError passed (err and equal nil)\n", i) - return - } - if err != nil { - logT(t, "[%v] deepEqual error: %v", i, err) - logT(t, " ....... GOLDEN: (%T) %#v", v0, v0) - logT(t, " ....... DECODED: (%T) %#v", v1, v1) - failT(t) - } - if equal != nil && !*equal { - logT(t, "[%v] values not equal", i) - logT(t, " ....... GOLDEN: (%T) %#v", v0, v0) - logT(t, " ....... DECODED: (%T) %#v", v1, v1) - failT(t) - } - // fmt.Printf("%v testCborError passed (checks passed)\n", i) -} - -func TestCborGoldens(t *testing.T) { - doTestCborGoldens(t) -} diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/codec_test.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/codec_test.go deleted file mode 100644 index 33bbed723..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/codec_test.go +++ /dev/null @@ -1,1459 +0,0 @@ -// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -package codec - -// Test works by using a slice of interfaces. -// It can test for encoding/decoding into/from a nil interface{} -// or passing the object to encode/decode into. -// -// There are basically 2 main tests here. -// First test internally encodes and decodes things and verifies that -// the artifact was as expected. -// Second test will use python msgpack to create a bunch of golden files, -// read those files, and compare them to what it should be. It then -// writes those files back out and compares the byte streams. -// -// Taken together, the tests are pretty extensive. -// -// The following manual tests must be done: -// - TestCodecUnderlyingType - -import ( - "bytes" - "encoding/gob" - "flag" - "fmt" - "io/ioutil" - "math" - "math/rand" - "net" - "net/rpc" - "os" - "os/exec" - "path/filepath" - "reflect" - "runtime" - "strconv" - "strings" - "sync/atomic" - "testing" - "time" -) - -func init() { - testInitFlags() - testPreInitFns = append(testPreInitFns, testInit) -} - -// make this a mapbyslice -type testMbsT []interface{} - -func (_ testMbsT) MapBySlice() {} - -type testVerifyArg int - -const ( - testVerifyMapTypeSame testVerifyArg = iota - testVerifyMapTypeStrIntf - testVerifyMapTypeIntfIntf - // testVerifySliceIntf - testVerifyForPython -) - -const testSkipRPCTests = false - -var ( - testTableNumPrimitives int - testTableIdxTime int - testTableNumMaps int -) - -var ( - testVerbose bool - testInitDebug bool - testUseIoEncDec bool - testStructToArray bool - testCanonical bool - testUseReset bool - testWriteNoSymbols bool - testSkipIntf bool - testInternStr bool - testUseMust bool - testCheckCircRef bool - testJsonIndent int - - skipVerifyVal interface{} = &(struct{}{}) - - testMapStrIntfTyp = reflect.TypeOf(map[string]interface{}(nil)) - - // For Go Time, do not use a descriptive timezone. - // It's unnecessary, and makes it harder to do a reflect.DeepEqual. - // The Offset already tells what the offset should be, if not on UTC and unknown zone name. - timeLoc = time.FixedZone("", -8*60*60) // UTC-08:00 //time.UTC-8 - timeToCompare1 = time.Date(2012, 2, 2, 2, 2, 2, 2000, timeLoc).UTC() - timeToCompare2 = time.Date(1900, 2, 2, 2, 2, 2, 2000, timeLoc).UTC() - timeToCompare3 = time.Unix(0, 270).UTC() // use value that must be encoded as uint64 for nanoseconds (for cbor/msgpack comparison) - //timeToCompare4 = time.Time{}.UTC() // does not work well with simple cbor time encoding (overflow) - timeToCompare4 = time.Unix(-2013855848, 4223).UTC() - - table []interface{} // main items we encode - tableVerify []interface{} // we verify encoded things against this after decode - tableTestNilVerify []interface{} // for nil interface, use this to verify (rules are different) - tablePythonVerify []interface{} // for verifying for python, since Python sometimes - // will encode a float32 as float64, or large int as uint - testRpcInt = new(TestRpcInt) -) - -func testInitFlags() { - // delete(testDecOpts.ExtFuncs, timeTyp) - flag.BoolVar(&testVerbose, "tv", false, "Test Verbose") - flag.BoolVar(&testInitDebug, "tg", false, "Test Init Debug") - flag.BoolVar(&testUseIoEncDec, "ti", false, "Use IO Reader/Writer for Marshal/Unmarshal") - flag.BoolVar(&testStructToArray, "ts", false, "Set StructToArray option") - flag.BoolVar(&testWriteNoSymbols, "tn", false, "Set NoSymbols option") - flag.BoolVar(&testCanonical, "tc", false, "Set Canonical option") - flag.BoolVar(&testInternStr, "te", false, "Set InternStr option") - flag.BoolVar(&testSkipIntf, "tf", false, "Skip Interfaces") - flag.BoolVar(&testUseReset, "tr", false, "Use Reset") - flag.IntVar(&testJsonIndent, "td", 0, "Use JSON Indent") - flag.BoolVar(&testUseMust, "tm", true, "Use Must(En|De)code") - flag.BoolVar(&testCheckCircRef, "tl", false, "Use Check Circular Ref") -} - -func testByteBuf(in []byte) *bytes.Buffer { - return bytes.NewBuffer(in) -} - -type TestABC struct { - A, B, C string -} - -func (x *TestABC) MarshalBinary() ([]byte, error) { - return []byte(fmt.Sprintf("%s %s %s", x.A, x.B, x.C)), nil -} -func (x *TestABC) MarshalText() ([]byte, error) { - return []byte(fmt.Sprintf("%s %s %s", x.A, x.B, x.C)), nil -} -func (x *TestABC) MarshalJSON() ([]byte, error) { - return []byte(fmt.Sprintf(`"%s %s %s"`, x.A, x.B, x.C)), nil -} - -func (x *TestABC) UnmarshalBinary(data []byte) (err error) { - ss := strings.Split(string(data), " ") - x.A, x.B, x.C = ss[0], ss[1], ss[2] - return -} -func (x *TestABC) UnmarshalText(data []byte) (err error) { - return x.UnmarshalBinary(data) -} -func (x *TestABC) UnmarshalJSON(data []byte) (err error) { - return x.UnmarshalBinary(data[1 : len(data)-1]) -} - -type TestABC2 struct { - A, B, C string -} - -func (x TestABC2) MarshalText() ([]byte, error) { - return []byte(fmt.Sprintf("%s %s %s", x.A, x.B, x.C)), nil -} -func (x *TestABC2) UnmarshalText(data []byte) (err error) { - ss := strings.Split(string(data), " ") - x.A, x.B, x.C = ss[0], ss[1], ss[2] - return - // _, err = fmt.Sscanf(string(data), "%s %s %s", &x.A, &x.B, &x.C) -} - -type TestRpcABC struct { - A, B, C string -} - -type TestRpcInt struct { - i int -} - -func (r *TestRpcInt) Update(n int, res *int) error { r.i = n; *res = r.i; return nil } -func (r *TestRpcInt) Square(ignore int, res *int) error { *res = r.i * r.i; return nil } -func (r *TestRpcInt) Mult(n int, res *int) error { *res = r.i * n; return nil } -func (r *TestRpcInt) EchoStruct(arg TestRpcABC, res *string) error { - *res = fmt.Sprintf("%#v", arg) - return nil -} -func (r *TestRpcInt) Echo123(args []string, res *string) error { - *res = fmt.Sprintf("%#v", args) - return nil -} - -type testUnixNanoTimeExt struct { - // keep timestamp here, so that do not incur interface-conversion costs - ts int64 -} - -// func (x *testUnixNanoTimeExt) WriteExt(interface{}) []byte { panic("unsupported") } -// func (x *testUnixNanoTimeExt) ReadExt(interface{}, []byte) { panic("unsupported") } -func (x *testUnixNanoTimeExt) ConvertExt(v interface{}) interface{} { - switch v2 := v.(type) { - case time.Time: - x.ts = v2.UTC().UnixNano() - case *time.Time: - x.ts = v2.UTC().UnixNano() - default: - panic(fmt.Sprintf("unsupported format for time conversion: expecting time.Time; got %T", v)) - } - return &x.ts -} -func (x *testUnixNanoTimeExt) UpdateExt(dest interface{}, v interface{}) { - // fmt.Printf("testUnixNanoTimeExt.UpdateExt: v: %v\n", v) - tt := dest.(*time.Time) - switch v2 := v.(type) { - case int64: - *tt = time.Unix(0, v2).UTC() - case *int64: - *tt = time.Unix(0, *v2).UTC() - case uint64: - *tt = time.Unix(0, int64(v2)).UTC() - case *uint64: - *tt = time.Unix(0, int64(*v2)).UTC() - //case float64: - //case string: - default: - panic(fmt.Sprintf("unsupported format for time conversion: expecting int64/uint64; got %T", v)) - } - // fmt.Printf("testUnixNanoTimeExt.UpdateExt: v: %v, tt: %#v\n", v, tt) -} - -func testVerifyVal(v interface{}, arg testVerifyArg) (v2 interface{}) { - //for python msgpack, - // - all positive integers are unsigned 64-bit ints - // - all floats are float64 - switch iv := v.(type) { - case int8: - if iv >= 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case int16: - if iv >= 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case int32: - if iv >= 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case int64: - if iv >= 0 { - v2 = uint64(iv) - } else { - v2 = int64(iv) - } - case uint8: - v2 = uint64(iv) - case uint16: - v2 = uint64(iv) - case uint32: - v2 = uint64(iv) - case uint64: - v2 = uint64(iv) - case float32: - v2 = float64(iv) - case float64: - v2 = float64(iv) - case []interface{}: - m2 := make([]interface{}, len(iv)) - for j, vj := range iv { - m2[j] = testVerifyVal(vj, arg) - } - v2 = m2 - case testMbsT: - m2 := make([]interface{}, len(iv)) - for j, vj := range iv { - m2[j] = testVerifyVal(vj, arg) - } - v2 = testMbsT(m2) - case map[string]bool: - switch arg { - case testVerifyMapTypeSame: - m2 := make(map[string]bool) - for kj, kv := range iv { - m2[kj] = kv - } - v2 = m2 - case testVerifyMapTypeStrIntf, testVerifyForPython: - m2 := make(map[string]interface{}) - for kj, kv := range iv { - m2[kj] = kv - } - v2 = m2 - case testVerifyMapTypeIntfIntf: - m2 := make(map[interface{}]interface{}) - for kj, kv := range iv { - m2[kj] = kv - } - v2 = m2 - } - case map[string]interface{}: - switch arg { - case testVerifyMapTypeSame: - m2 := make(map[string]interface{}) - for kj, kv := range iv { - m2[kj] = testVerifyVal(kv, arg) - } - v2 = m2 - case testVerifyMapTypeStrIntf, testVerifyForPython: - m2 := make(map[string]interface{}) - for kj, kv := range iv { - m2[kj] = testVerifyVal(kv, arg) - } - v2 = m2 - case testVerifyMapTypeIntfIntf: - m2 := make(map[interface{}]interface{}) - for kj, kv := range iv { - m2[kj] = testVerifyVal(kv, arg) - } - v2 = m2 - } - case map[interface{}]interface{}: - m2 := make(map[interface{}]interface{}) - for kj, kv := range iv { - m2[testVerifyVal(kj, arg)] = testVerifyVal(kv, arg) - } - v2 = m2 - case time.Time: - switch arg { - case testVerifyForPython: - if iv2 := iv.UnixNano(); iv2 >= 0 { - v2 = uint64(iv2) - } else { - v2 = int64(iv2) - } - default: - v2 = v - } - default: - v2 = v - } - return -} - -func testInit() { - gob.Register(new(TestStruc)) - if testInitDebug { - ts0 := newTestStruc(2, false, !testSkipIntf, false) - fmt.Printf("====> depth: %v, ts: %#v\n", 2, ts0) - } - - for _, v := range testHandles { - bh := v.getBasicHandle() - bh.InternString = testInternStr - bh.Canonical = testCanonical - bh.CheckCircularRef = testCheckCircRef - bh.StructToArray = testStructToArray - // mostly doing this for binc - if testWriteNoSymbols { - bh.AsSymbols = AsSymbolNone - } else { - bh.AsSymbols = AsSymbolAll - } - } - - testJsonH.Indent = int8(testJsonIndent) - testMsgpackH.RawToString = true - - // testMsgpackH.AddExt(byteSliceTyp, 0, testMsgpackH.BinaryEncodeExt, testMsgpackH.BinaryDecodeExt) - // testMsgpackH.AddExt(timeTyp, 1, testMsgpackH.TimeEncodeExt, testMsgpackH.TimeDecodeExt) - - // add extensions for msgpack, simple for time.Time, so we can encode/decode same way. - // use different flavors of XXXExt calls, including deprecated ones. - // NOTE: - // DO NOT set extensions for JsonH, so we can test json(M|Unm)arshal support. - testSimpleH.AddExt(timeTyp, 1, timeExtEncFn, timeExtDecFn) - testMsgpackH.SetBytesExt(timeTyp, 1, timeExt{}) - testCborH.SetInterfaceExt(timeTyp, 1, &testUnixNanoTimeExt{}) - // testJsonH.SetInterfaceExt(timeTyp, 1, &testUnixNanoTimeExt{}) - - // primitives MUST be an even number, so it can be used as a mapBySlice also. - primitives := []interface{}{ - int8(-8), - int16(-1616), - int32(-32323232), - int64(-6464646464646464), - uint8(192), - uint16(1616), - uint32(32323232), - uint64(6464646464646464), - byte(192), - float32(-3232.0), - float64(-6464646464.0), - float32(3232.0), - float64(6464.0), - float64(6464646464.0), - false, - true, - "null", - nil, - "someday", - timeToCompare1, - "", - timeToCompare2, - "bytestring", - timeToCompare3, - "none", - timeToCompare4, - } - - maps := []interface{}{ - map[string]bool{ - "true": true, - "false": false, - }, - map[string]interface{}{ - "true": "True", - "false": false, - "uint16(1616)": uint16(1616), - }, - //add a complex combo map in here. (map has list which has map) - //note that after the first thing, everything else should be generic. - map[string]interface{}{ - "list": []interface{}{ - int16(1616), - int32(32323232), - true, - float32(-3232.0), - map[string]interface{}{ - "TRUE": true, - "FALSE": false, - }, - []interface{}{true, false}, - }, - "int32": int32(32323232), - "bool": true, - "LONG STRING": "123456789012345678901234567890123456789012345678901234567890", - "SHORT STRING": "1234567890", - }, - map[interface{}]interface{}{ - true: "true", - uint8(138): false, - "false": uint8(200), - }, - } - - testTableNumPrimitives = len(primitives) - testTableIdxTime = testTableNumPrimitives - 8 - testTableNumMaps = len(maps) - - table = []interface{}{} - table = append(table, primitives...) - table = append(table, primitives) - table = append(table, testMbsT(primitives)) - table = append(table, maps...) - table = append(table, newTestStruc(0, false, !testSkipIntf, false)) - - tableVerify = make([]interface{}, len(table)) - tableTestNilVerify = make([]interface{}, len(table)) - tablePythonVerify = make([]interface{}, len(table)) - - lp := testTableNumPrimitives + 4 - av := tableVerify - for i, v := range table { - if i == lp { - av[i] = skipVerifyVal - continue - } - //av[i] = testVerifyVal(v, testVerifyMapTypeSame) - switch v.(type) { - case []interface{}: - av[i] = testVerifyVal(v, testVerifyMapTypeSame) - case testMbsT: - av[i] = testVerifyVal(v, testVerifyMapTypeSame) - case map[string]interface{}: - av[i] = testVerifyVal(v, testVerifyMapTypeSame) - case map[interface{}]interface{}: - av[i] = testVerifyVal(v, testVerifyMapTypeSame) - default: - av[i] = v - } - } - - av = tableTestNilVerify - for i, v := range table { - if i > lp { - av[i] = skipVerifyVal - continue - } - av[i] = testVerifyVal(v, testVerifyMapTypeStrIntf) - } - - av = tablePythonVerify - for i, v := range table { - if i == testTableNumPrimitives+1 || i > lp { // testTableNumPrimitives+1 is the mapBySlice - av[i] = skipVerifyVal - continue - } - av[i] = testVerifyVal(v, testVerifyForPython) - } - - // only do the python verify up to the maps, skipping the last 2 maps. - tablePythonVerify = tablePythonVerify[:testTableNumPrimitives+2+testTableNumMaps-2] -} - -func testUnmarshal(v interface{}, data []byte, h Handle) (err error) { - return testCodecDecode(data, v, h) -} - -func testMarshal(v interface{}, h Handle) (bs []byte, err error) { - return testCodecEncode(v, nil, testByteBuf, h) -} - -func testMarshalErr(v interface{}, h Handle, t *testing.T, name string) (bs []byte, err error) { - if bs, err = testMarshal(v, h); err != nil { - logT(t, "Error encoding %s: %v, Err: %v", name, v, err) - t.FailNow() - } - return -} - -func testUnmarshalErr(v interface{}, data []byte, h Handle, t *testing.T, name string) (err error) { - if err = testUnmarshal(v, data, h); err != nil { - logT(t, "Error Decoding into %s: %v, Err: %v", name, v, err) - t.FailNow() - } - return -} - -// doTestCodecTableOne allows us test for different variations based on arguments passed. -func doTestCodecTableOne(t *testing.T, testNil bool, h Handle, - vs []interface{}, vsVerify []interface{}) { - //if testNil, then just test for when a pointer to a nil interface{} is passed. It should work. - //Current setup allows us test (at least manually) the nil interface or typed interface. - logT(t, "================ TestNil: %v ================\n", testNil) - for i, v0 := range vs { - logT(t, "..............................................") - logT(t, " Testing: #%d:, %T, %#v\n", i, v0, v0) - b0, err := testMarshalErr(v0, h, t, "v0") - if err != nil { - continue - } - if h.isBinary() { - logT(t, " Encoded bytes: len: %v, %v\n", len(b0), b0) - } else { - logT(t, " Encoded string: len: %v, %v\n", len(string(b0)), string(b0)) - // println("########### encoded string: " + string(b0)) - } - var v1 interface{} - - if testNil { - err = testUnmarshal(&v1, b0, h) - } else { - if v0 != nil { - v0rt := reflect.TypeOf(v0) // ptr - rv1 := reflect.New(v0rt) - err = testUnmarshal(rv1.Interface(), b0, h) - v1 = rv1.Elem().Interface() - // v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() - } - } - - logT(t, " v1 returned: %T, %#v", v1, v1) - // if v1 != nil { - // logT(t, " v1 returned: %T, %#v", v1, v1) - // //we always indirect, because ptr to typed value may be passed (if not testNil) - // v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() - // } - if err != nil { - logT(t, "-------- Error: %v. Partial return: %v", err, v1) - failT(t) - continue - } - v0check := vsVerify[i] - if v0check == skipVerifyVal { - logT(t, " Nil Check skipped: Decoded: %T, %#v\n", v1, v1) - continue - } - - if err = deepEqual(v0check, v1); err == nil { - logT(t, "++++++++ Before and After marshal matched\n") - } else { - // logT(t, "-------- Before and After marshal do not match: Error: %v"+ - // " ====> GOLDEN: (%T) %#v, DECODED: (%T) %#v\n", err, v0check, v0check, v1, v1) - logT(t, "-------- Before and After marshal do not match: Error: %v", err) - logT(t, " ....... GOLDEN: (%T) %#v", v0check, v0check) - logT(t, " ....... DECODED: (%T) %#v", v1, v1) - failT(t) - } - } -} - -func testCodecTableOne(t *testing.T, h Handle) { - testOnce.Do(testInitAll) - // func TestMsgpackAllExperimental(t *testing.T) { - // dopts := testDecOpts(nil, nil, false, true, true), - - numPrim, numMap, idxTime, idxMap := testTableNumPrimitives, testTableNumMaps, testTableIdxTime, testTableNumPrimitives+2 - - //println("#################") - switch v := h.(type) { - case *MsgpackHandle: - var oldWriteExt, oldRawToString bool - oldWriteExt, v.WriteExt = v.WriteExt, true - oldRawToString, v.RawToString = v.RawToString, true - doTestCodecTableOne(t, false, h, table, tableVerify) - v.WriteExt, v.RawToString = oldWriteExt, oldRawToString - case *JsonHandle: - //skip []interface{} containing time.Time, as it encodes as a number, but cannot decode back to time.Time. - //As there is no real support for extension tags in json, this must be skipped. - doTestCodecTableOne(t, false, h, table[:numPrim], tableVerify[:numPrim]) - doTestCodecTableOne(t, false, h, table[idxMap:], tableVerify[idxMap:]) - default: - doTestCodecTableOne(t, false, h, table, tableVerify) - } - // func TestMsgpackAll(t *testing.T) { - - // //skip []interface{} containing time.Time - // doTestCodecTableOne(t, false, h, table[:numPrim], tableVerify[:numPrim]) - // doTestCodecTableOne(t, false, h, table[numPrim+1:], tableVerify[numPrim+1:]) - // func TestMsgpackNilStringMap(t *testing.T) { - var oldMapType reflect.Type - v := h.getBasicHandle() - - oldMapType, v.MapType = v.MapType, testMapStrIntfTyp - - //skip time.Time, []interface{} containing time.Time, last map, and newStruc - doTestCodecTableOne(t, true, h, table[:idxTime], tableTestNilVerify[:idxTime]) - doTestCodecTableOne(t, true, h, table[idxMap:idxMap+numMap-1], tableTestNilVerify[idxMap:idxMap+numMap-1]) - - v.MapType = oldMapType - - // func TestMsgpackNilIntf(t *testing.T) { - - //do last map and newStruc - idx2 := idxMap + numMap - 1 - doTestCodecTableOne(t, true, h, table[idx2:], tableTestNilVerify[idx2:]) - //TODO? What is this one? - //doTestCodecTableOne(t, true, h, table[17:18], tableTestNilVerify[17:18]) -} - -func testCodecMiscOne(t *testing.T, h Handle) { - testOnce.Do(testInitAll) - b, err := testMarshalErr(32, h, t, "32") - // Cannot do this nil one, because faster type assertion decoding will panic - // var i *int32 - // if err = testUnmarshal(b, i, nil); err == nil { - // logT(t, "------- Expecting error because we cannot unmarshal to int32 nil ptr") - // t.FailNow() - // } - var i2 int32 = 0 - err = testUnmarshalErr(&i2, b, h, t, "int32-ptr") - if i2 != int32(32) { - logT(t, "------- didn't unmarshal to 32: Received: %d", i2) - t.FailNow() - } - - // func TestMsgpackDecodePtr(t *testing.T) { - ts := newTestStruc(0, false, !testSkipIntf, false) - b, err = testMarshalErr(ts, h, t, "pointer-to-struct") - if len(b) < 40 { - logT(t, "------- Size must be > 40. Size: %d", len(b)) - t.FailNow() - } - if h.isBinary() { - logT(t, "------- b: %v", b) - } else { - logT(t, "------- b: %s", b) - } - ts2 := new(TestStruc) - err = testUnmarshalErr(ts2, b, h, t, "pointer-to-struct") - if ts2.I64 != math.MaxInt64*2/3 { - logT(t, "------- Unmarshal wrong. Expect I64 = 64. Got: %v", ts2.I64) - t.FailNow() - } - - // func TestMsgpackIntfDecode(t *testing.T) { - m := map[string]int{"A": 2, "B": 3} - p := []interface{}{m} - bs, err := testMarshalErr(p, h, t, "p") - - m2 := map[string]int{} - p2 := []interface{}{m2} - err = testUnmarshalErr(&p2, bs, h, t, "&p2") - - if m2["A"] != 2 || m2["B"] != 3 { - logT(t, "m2 not as expected: expecting: %v, got: %v", m, m2) - t.FailNow() - } - // log("m: %v, m2: %v, p: %v, p2: %v", m, m2, p, p2) - checkEqualT(t, p, p2, "p=p2") - checkEqualT(t, m, m2, "m=m2") - if err = deepEqual(p, p2); err == nil { - logT(t, "p and p2 match") - } else { - logT(t, "Not Equal: %v. p: %v, p2: %v", err, p, p2) - t.FailNow() - } - if err = deepEqual(m, m2); err == nil { - logT(t, "m and m2 match") - } else { - logT(t, "Not Equal: %v. m: %v, m2: %v", err, m, m2) - t.FailNow() - } - - // func TestMsgpackDecodeStructSubset(t *testing.T) { - // test that we can decode a subset of the stream - mm := map[string]interface{}{"A": 5, "B": 99, "C": 333} - bs, err = testMarshalErr(mm, h, t, "mm") - type ttt struct { - A uint8 - C int32 - } - var t2 ttt - testUnmarshalErr(&t2, bs, h, t, "t2") - t3 := ttt{5, 333} - checkEqualT(t, t2, t3, "t2=t3") - - // println(">>>>>") - // test simple arrays, non-addressable arrays, slices - type tarr struct { - A int64 - B [3]int64 - C []byte - D [3]byte - } - var tarr0 = tarr{1, [3]int64{2, 3, 4}, []byte{4, 5, 6}, [3]byte{7, 8, 9}} - // test both pointer and non-pointer (value) - for _, tarr1 := range []interface{}{tarr0, &tarr0} { - bs, err = testMarshalErr(tarr1, h, t, "tarr1") - if err != nil { - logT(t, "Error marshalling: %v", err) - t.FailNow() - } - if _, ok := h.(*JsonHandle); ok { - logT(t, "Marshal as: %s", bs) - } - var tarr2 tarr - testUnmarshalErr(&tarr2, bs, h, t, "tarr2") - checkEqualT(t, tarr0, tarr2, "tarr0=tarr2") - // fmt.Printf(">>>> err: %v. tarr1: %v, tarr2: %v\n", err, tarr0, tarr2) - } - - // test byte array, even if empty (msgpack only) - if h == testMsgpackH { - type ystruct struct { - Anarray []byte - } - var ya = ystruct{} - testUnmarshalErr(&ya, []byte{0x91, 0x90}, h, t, "ya") - } -} - -func testCodecEmbeddedPointer(t *testing.T, h Handle) { - testOnce.Do(testInitAll) - type Z int - type A struct { - AnInt int - } - type B struct { - *Z - *A - MoreInt int - } - var z Z = 4 - x1 := &B{&z, &A{5}, 6} - bs, err := testMarshalErr(x1, h, t, "x1") - // fmt.Printf("buf: len(%v): %x\n", buf.Len(), buf.Bytes()) - var x2 = new(B) - err = testUnmarshalErr(x2, bs, h, t, "x2") - err = checkEqualT(t, x1, x2, "x1=x2") - _ = err -} - -func testCodecUnderlyingType(t *testing.T, h Handle) { - testOnce.Do(testInitAll) - // Manual Test. - // Run by hand, with accompanying print statements in fast-path.go - // to ensure that the fast functions are called. - type T1 map[string]string - v := T1{"1": "1s", "2": "2s"} - var bs []byte - var err error - NewEncoderBytes(&bs, h).MustEncode(v) - if err != nil { - logT(t, "Error during encode: %v", err) - failT(t) - } - var v2 T1 - NewDecoderBytes(bs, h).MustDecode(&v2) - if err != nil { - logT(t, "Error during decode: %v", err) - failT(t) - } -} - -func testCodecChan(t *testing.T, h Handle) { - // - send a slice []*int64 (sl1) into an chan (ch1) with cap > len(s1) - // - encode ch1 as a stream array - // - decode a chan (ch2), with cap > len(s1) from the stream array - // - receive from ch2 into slice sl2 - // - compare sl1 and sl2 - // - do this for codecs: json, cbor (covers all types) - sl1 := make([]*int64, 4) - for i := range sl1 { - var j int64 = int64(i) - sl1[i] = &j - } - ch1 := make(chan *int64, 4) - for _, j := range sl1 { - ch1 <- j - } - var bs []byte - NewEncoderBytes(&bs, h).MustEncode(ch1) - // if !h.isBinary() { - // fmt.Printf("before: len(ch1): %v, bs: %s\n", len(ch1), bs) - // } - // var ch2 chan *int64 // this will block if json, etc. - ch2 := make(chan *int64, 8) - NewDecoderBytes(bs, h).MustDecode(&ch2) - // logT(t, "Len(ch2): %v", len(ch2)) - // fmt.Printf("after: len(ch2): %v, ch2: %v\n", len(ch2), ch2) - close(ch2) - var sl2 []*int64 - for j := range ch2 { - sl2 = append(sl2, j) - } - if err := deepEqual(sl1, sl2); err != nil { - logT(t, "Not Match: %v; len: %v, %v", err, len(sl1), len(sl2)) - failT(t) - } -} - -func testCodecRpcOne(t *testing.T, rr Rpc, h Handle, doRequest bool, exitSleepMs time.Duration, -) (port int) { - testOnce.Do(testInitAll) - if testSkipRPCTests { - return - } - // rpc needs EOF, which is sent via a panic, and so must be recovered. - if !recoverPanicToErr { - logT(t, "EXPECTED. set recoverPanicToErr=true, since rpc needs EOF") - t.FailNow() - } - srv := rpc.NewServer() - srv.Register(testRpcInt) - ln, err := net.Listen("tcp", "127.0.0.1:0") - // log("listener: %v", ln.Addr()) - checkErrT(t, err) - port = (ln.Addr().(*net.TCPAddr)).Port - // var opts *DecoderOptions - // opts := testDecOpts - // opts.MapType = mapStrIntfTyp - // opts.RawToString = false - serverExitChan := make(chan bool, 1) - var serverExitFlag uint64 = 0 - serverFn := func() { - for { - conn1, err1 := ln.Accept() - // if err1 != nil { - // //fmt.Printf("accept err1: %v\n", err1) - // continue - // } - if atomic.LoadUint64(&serverExitFlag) == 1 { - serverExitChan <- true - conn1.Close() - return // exit serverFn goroutine - } - if err1 == nil { - var sc rpc.ServerCodec = rr.ServerCodec(conn1, h) - srv.ServeCodec(sc) - } - } - } - - clientFn := func(cc rpc.ClientCodec) { - cl := rpc.NewClientWithCodec(cc) - defer cl.Close() - // defer func() { println("##### client closing"); cl.Close() }() - var up, sq, mult int - var rstr string - // log("Calling client") - checkErrT(t, cl.Call("TestRpcInt.Update", 5, &up)) - // log("Called TestRpcInt.Update") - checkEqualT(t, testRpcInt.i, 5, "testRpcInt.i=5") - checkEqualT(t, up, 5, "up=5") - checkErrT(t, cl.Call("TestRpcInt.Square", 1, &sq)) - checkEqualT(t, sq, 25, "sq=25") - checkErrT(t, cl.Call("TestRpcInt.Mult", 20, &mult)) - checkEqualT(t, mult, 100, "mult=100") - checkErrT(t, cl.Call("TestRpcInt.EchoStruct", TestRpcABC{"Aa", "Bb", "Cc"}, &rstr)) - checkEqualT(t, rstr, fmt.Sprintf("%#v", TestRpcABC{"Aa", "Bb", "Cc"}), "rstr=") - checkErrT(t, cl.Call("TestRpcInt.Echo123", []string{"A1", "B2", "C3"}, &rstr)) - checkEqualT(t, rstr, fmt.Sprintf("%#v", []string{"A1", "B2", "C3"}), "rstr=") - } - - connFn := func() (bs net.Conn) { - // log("calling f1") - bs, err2 := net.Dial(ln.Addr().Network(), ln.Addr().String()) - //fmt.Printf("f1. bs: %v, err2: %v\n", bs, err2) - checkErrT(t, err2) - return - } - - exitFn := func() { - atomic.StoreUint64(&serverExitFlag, 1) - bs := connFn() - <-serverExitChan - bs.Close() - // serverExitChan <- true - } - - go serverFn() - runtime.Gosched() - //time.Sleep(100 * time.Millisecond) - if exitSleepMs == 0 { - defer ln.Close() - defer exitFn() - } - if doRequest { - bs := connFn() - cc := rr.ClientCodec(bs, h) - clientFn(cc) - } - if exitSleepMs != 0 { - go func() { - defer ln.Close() - time.Sleep(exitSleepMs) - exitFn() - }() - } - return -} - -func doTestMapEncodeForCanonical(t *testing.T, name string, h Handle) { - v1 := map[string]interface{}{ - "a": 1, - "b": "hello", - "c": map[string]interface{}{ - "c/a": 1, - "c/b": "world", - "c/c": []int{1, 2, 3, 4}, - "c/d": map[string]interface{}{ - "c/d/a": "fdisajfoidsajfopdjsaopfjdsapofda", - "c/d/b": "fdsafjdposakfodpsakfopdsakfpodsakfpodksaopfkdsopafkdopsa", - "c/d/c": "poir02 ir30qif4p03qir0pogjfpoaerfgjp ofke[padfk[ewapf kdp[afep[aw", - "c/d/d": "fdsopafkd[sa f-32qor-=4qeof -afo-erfo r-eafo 4e- o r4-qwo ag", - "c/d/e": "kfep[a sfkr0[paf[a foe-[wq ewpfao-q ro3-q ro-4qof4-qor 3-e orfkropzjbvoisdb", - "c/d/f": "", - }, - "c/e": map[int]string{ - 1: "1", - 22: "22", - 333: "333", - 4444: "4444", - 55555: "55555", - }, - "c/f": map[string]int{ - "1": 1, - "22": 22, - "333": 333, - "4444": 4444, - "55555": 55555, - }, - }, - } - var v2 map[string]interface{} - var b1, b2 []byte - - // encode v1 into b1, decode b1 into v2, encode v2 into b2, compare b1 and b2 - - bh := h.getBasicHandle() - if !bh.Canonical { - bh.Canonical = true - defer func() { bh.Canonical = false }() - } - - e1 := NewEncoderBytes(&b1, h) - e1.MustEncode(v1) - d1 := NewDecoderBytes(b1, h) - d1.MustDecode(&v2) - e2 := NewEncoderBytes(&b2, h) - e2.MustEncode(v2) - if !bytes.Equal(b1, b2) { - logT(t, "Unequal bytes: %v VS %v", b1, b2) - t.FailNow() - } -} - -func doTestStdEncIntf(t *testing.T, name string, h Handle) { - args := [][2]interface{}{ - {&TestABC{"A", "BB", "CCC"}, new(TestABC)}, - {&TestABC2{"AAA", "BB", "C"}, new(TestABC2)}, - } - for _, a := range args { - var b []byte - e := NewEncoderBytes(&b, h) - e.MustEncode(a[0]) - d := NewDecoderBytes(b, h) - d.MustDecode(a[1]) - if err := deepEqual(a[0], a[1]); err == nil { - logT(t, "++++ Objects match") - } else { - logT(t, "---- Objects do not match: y1: %v, err: %v", a[1], err) - failT(t) - } - } -} - -func doTestEncCircularRef(t *testing.T, name string, h Handle) { - type T1 struct { - S string - B bool - T interface{} - } - type T2 struct { - S string - T *T1 - } - type T3 struct { - S string - T *T2 - } - t1 := T1{"t1", true, nil} - t2 := T2{"t2", &t1} - t3 := T3{"t3", &t2} - t1.T = &t3 - - var bs []byte - var err error - - bh := h.getBasicHandle() - if !bh.CheckCircularRef { - bh.CheckCircularRef = true - defer func() { bh.CheckCircularRef = false }() - } - err = NewEncoderBytes(&bs, h).Encode(&t3) - if err == nil { - logT(t, "expecting error due to circular reference. found none") - t.FailNow() - } - if x := err.Error(); strings.Contains(x, "circular") || strings.Contains(x, "cyclic") { - logT(t, "error detected as expected: %v", x) - } else { - logT(t, "error detected was not as expected: %v", x) - t.FailNow() - } -} - -// TestAnonCycleT{1,2,3} types are used to test anonymous cycles. -// They are top-level, so that they can have circular references. -type ( - TestAnonCycleT1 struct { - S string - TestAnonCycleT2 - } - TestAnonCycleT2 struct { - S2 string - TestAnonCycleT3 - } - TestAnonCycleT3 struct { - *TestAnonCycleT1 - } -) - -func doTestAnonCycle(t *testing.T, name string, h Handle) { - var x TestAnonCycleT1 - x.S = "hello" - x.TestAnonCycleT2.S2 = "hello.2" - x.TestAnonCycleT2.TestAnonCycleT3.TestAnonCycleT1 = &x - - // just check that you can get typeInfo for T1 - rt := reflect.TypeOf((*TestAnonCycleT1)(nil)).Elem() - rtid := reflect.ValueOf(rt).Pointer() - pti := h.getBasicHandle().getTypeInfo(rtid, rt) - logT(t, "pti: %v", pti) -} - -func doTestJsonLargeInteger(t *testing.T, v interface{}, ias uint8) { - logT(t, "Running doTestJsonLargeInteger: v: %#v, ias: %c", v, ias) - oldIAS := testJsonH.IntegerAsString - defer func() { testJsonH.IntegerAsString = oldIAS }() - testJsonH.IntegerAsString = ias - - var vu uint - var vi int - var vb bool - var b []byte - e := NewEncoderBytes(&b, testJsonH) - e.MustEncode(v) - e.MustEncode(true) - d := NewDecoderBytes(b, testJsonH) - // below, we validate that the json string or number was encoded, - // then decode, and validate that the correct value was decoded. - fnStrChk := func() { - // check that output started with ", and ended with "true - if !(b[0] == '"' && string(b[len(b)-5:]) == `"true`) { - logT(t, "Expecting a JSON string, got: %s", b) - failT(t) - } - } - - switch ias { - case 'L': - switch v2 := v.(type) { - case int: - if v2 > 1<<53 || (v2 < 0 && -v2 > 1<<53) { - fnStrChk() - } - case uint: - if v2 > 1<<53 { - fnStrChk() - } - } - case 'A': - fnStrChk() - default: - // check that output doesn't contain " at all - for _, i := range b { - if i == '"' { - logT(t, "Expecting a JSON Number without quotation: got: %s", b) - failT(t) - } - } - } - switch v2 := v.(type) { - case int: - d.MustDecode(&vi) - d.MustDecode(&vb) - // check that vb = true, and vi == v2 - if !(vb && vi == v2) { - logT(t, "Expecting equal values from %s: got golden: %v, decoded: %v", b, v2, vi) - failT(t) - } - case uint: - d.MustDecode(&vu) - d.MustDecode(&vb) - // check that vb = true, and vi == v2 - if !(vb && vu == v2) { - logT(t, "Expecting equal values from %s: got golden: %v, decoded: %v", b, v2, vu) - failT(t) - } - // fmt.Printf("%v: %s, decode: %d, bool: %v, equal_on_decode: %v\n", v, b, vu, vb, vu == v.(uint)) - } -} - -// Comprehensive testing that generates data encoded from python handle (cbor, msgpack), -// and validates that our code can read and write it out accordingly. -// We keep this unexported here, and put actual test in ext_dep_test.go. -// This way, it can be excluded by excluding file completely. -func doTestPythonGenStreams(t *testing.T, name string, h Handle) { - logT(t, "TestPythonGenStreams-%v", name) - tmpdir, err := ioutil.TempDir("", "golang-"+name+"-test") - if err != nil { - logT(t, "-------- Unable to create temp directory\n") - t.FailNow() - } - defer os.RemoveAll(tmpdir) - logT(t, "tmpdir: %v", tmpdir) - cmd := exec.Command("python", "test.py", "testdata", tmpdir) - //cmd.Stdin = strings.NewReader("some input") - //cmd.Stdout = &out - var cmdout []byte - if cmdout, err = cmd.CombinedOutput(); err != nil { - logT(t, "-------- Error running test.py testdata. Err: %v", err) - logT(t, " %v", string(cmdout)) - t.FailNow() - } - - bh := h.getBasicHandle() - - oldMapType := bh.MapType - for i, v := range tablePythonVerify { - // if v == uint64(0) && h == testMsgpackH { - // v = int64(0) - // } - bh.MapType = oldMapType - //load up the golden file based on number - //decode it - //compare to in-mem object - //encode it again - //compare to output stream - logT(t, "..............................................") - logT(t, " Testing: #%d: %T, %#v\n", i, v, v) - var bss []byte - bss, err = ioutil.ReadFile(filepath.Join(tmpdir, strconv.Itoa(i)+"."+name+".golden")) - if err != nil { - logT(t, "-------- Error reading golden file: %d. Err: %v", i, err) - failT(t) - continue - } - bh.MapType = testMapStrIntfTyp - - var v1 interface{} - if err = testUnmarshal(&v1, bss, h); err != nil { - logT(t, "-------- Error decoding stream: %d: Err: %v", i, err) - failT(t) - continue - } - if v == skipVerifyVal { - continue - } - //no need to indirect, because we pass a nil ptr, so we already have the value - //if v1 != nil { v1 = reflect.Indirect(reflect.ValueOf(v1)).Interface() } - if err = deepEqual(v, v1); err == nil { - logT(t, "++++++++ Objects match: %T, %v", v, v) - } else { - logT(t, "-------- Objects do not match: %v. Source: %T. Decoded: %T", err, v, v1) - logT(t, "-------- GOLDEN: %#v", v) - // logT(t, "-------- DECODED: %#v <====> %#v", v1, reflect.Indirect(reflect.ValueOf(v1)).Interface()) - logT(t, "-------- DECODED: %#v <====> %#v", v1, reflect.Indirect(reflect.ValueOf(v1)).Interface()) - failT(t) - } - bsb, err := testMarshal(v1, h) - if err != nil { - logT(t, "Error encoding to stream: %d: Err: %v", i, err) - failT(t) - continue - } - if err = deepEqual(bsb, bss); err == nil { - logT(t, "++++++++ Bytes match") - } else { - logT(t, "???????? Bytes do not match. %v.", err) - xs := "--------" - if reflect.ValueOf(v).Kind() == reflect.Map { - xs = " " - logT(t, "%s It's a map. Ok that they don't match (dependent on ordering).", xs) - } else { - logT(t, "%s It's not a map. They should match.", xs) - failT(t) - } - logT(t, "%s FROM_FILE: %4d] %v", xs, len(bss), bss) - logT(t, "%s ENCODED: %4d] %v", xs, len(bsb), bsb) - } - } - bh.MapType = oldMapType -} - -// To test MsgpackSpecRpc, we test 3 scenarios: -// - Go Client to Go RPC Service (contained within TestMsgpackRpcSpec) -// - Go client to Python RPC Service (contained within doTestMsgpackRpcSpecGoClientToPythonSvc) -// - Python Client to Go RPC Service (contained within doTestMsgpackRpcSpecPythonClientToGoSvc) -// -// This allows us test the different calling conventions -// - Go Service requires only one argument -// - Python Service allows multiple arguments - -func doTestMsgpackRpcSpecGoClientToPythonSvc(t *testing.T) { - if testSkipRPCTests { - return - } - // openPorts are between 6700 and 6800 - r := rand.New(rand.NewSource(time.Now().UnixNano())) - openPort := strconv.FormatInt(6700+r.Int63n(99), 10) - // openPort := "6792" - cmd := exec.Command("python", "test.py", "rpc-server", openPort, "4") - checkErrT(t, cmd.Start()) - bs, err2 := net.Dial("tcp", ":"+openPort) - for i := 0; i < 10 && err2 != nil; i++ { - time.Sleep(50 * time.Millisecond) // time for python rpc server to start - bs, err2 = net.Dial("tcp", ":"+openPort) - } - checkErrT(t, err2) - cc := MsgpackSpecRpc.ClientCodec(bs, testMsgpackH) - cl := rpc.NewClientWithCodec(cc) - defer cl.Close() - var rstr string - checkErrT(t, cl.Call("EchoStruct", TestRpcABC{"Aa", "Bb", "Cc"}, &rstr)) - //checkEqualT(t, rstr, "{'A': 'Aa', 'B': 'Bb', 'C': 'Cc'}") - var mArgs MsgpackSpecRpcMultiArgs = []interface{}{"A1", "B2", "C3"} - checkErrT(t, cl.Call("Echo123", mArgs, &rstr)) - checkEqualT(t, rstr, "1:A1 2:B2 3:C3", "rstr=") - cmd.Process.Kill() -} - -func doTestMsgpackRpcSpecPythonClientToGoSvc(t *testing.T) { - if testSkipRPCTests { - return - } - port := testCodecRpcOne(t, MsgpackSpecRpc, testMsgpackH, false, 1*time.Second) - //time.Sleep(1000 * time.Millisecond) - cmd := exec.Command("python", "test.py", "rpc-client-go-service", strconv.Itoa(port)) - var cmdout []byte - var err error - if cmdout, err = cmd.CombinedOutput(); err != nil { - logT(t, "-------- Error running test.py rpc-client-go-service. Err: %v", err) - logT(t, " %v", string(cmdout)) - t.FailNow() - } - checkEqualT(t, string(cmdout), - fmt.Sprintf("%#v\n%#v\n", []string{"A1", "B2", "C3"}, TestRpcABC{"Aa", "Bb", "Cc"}), "cmdout=") -} - -func TestBincCodecsTable(t *testing.T) { - testCodecTableOne(t, testBincH) -} - -func TestBincCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testBincH) -} - -func TestBincCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testBincH) -} - -func TestBincStdEncIntf(t *testing.T) { - doTestStdEncIntf(t, "binc", testBincH) -} - -func TestSimpleCodecsTable(t *testing.T) { - testCodecTableOne(t, testSimpleH) -} - -func TestSimpleCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testSimpleH) -} - -func TestSimpleCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testSimpleH) -} - -func TestSimpleStdEncIntf(t *testing.T) { - doTestStdEncIntf(t, "simple", testSimpleH) -} - -func TestMsgpackCodecsTable(t *testing.T) { - testCodecTableOne(t, testMsgpackH) -} - -func TestMsgpackCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testMsgpackH) -} - -func TestMsgpackCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testMsgpackH) -} - -func TestMsgpackStdEncIntf(t *testing.T) { - doTestStdEncIntf(t, "msgpack", testMsgpackH) -} - -func TestCborCodecsTable(t *testing.T) { - testCodecTableOne(t, testCborH) -} - -func TestCborCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testCborH) -} - -func TestCborCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testCborH) -} - -func TestCborMapEncodeForCanonical(t *testing.T) { - doTestMapEncodeForCanonical(t, "cbor", testCborH) -} - -func TestCborCodecChan(t *testing.T) { - testCodecChan(t, testCborH) -} - -func TestCborStdEncIntf(t *testing.T) { - doTestStdEncIntf(t, "cbor", testCborH) -} - -func TestJsonCodecsTable(t *testing.T) { - testCodecTableOne(t, testJsonH) -} - -func TestJsonCodecsMisc(t *testing.T) { - testCodecMiscOne(t, testJsonH) -} - -func TestJsonCodecsEmbeddedPointer(t *testing.T) { - testCodecEmbeddedPointer(t, testJsonH) -} - -func TestJsonCodecChan(t *testing.T) { - testCodecChan(t, testJsonH) -} - -func TestJsonStdEncIntf(t *testing.T) { - doTestStdEncIntf(t, "json", testJsonH) -} - -// ----- ALL (framework based) ----- - -func TestAllEncCircularRef(t *testing.T) { - doTestEncCircularRef(t, "cbor", testCborH) -} - -func TestAllAnonCycle(t *testing.T) { - doTestAnonCycle(t, "cbor", testCborH) -} - -// ----- RPC ----- - -func TestBincRpcGo(t *testing.T) { - testCodecRpcOne(t, GoRpc, testBincH, true, 0) -} - -func TestSimpleRpcGo(t *testing.T) { - testCodecRpcOne(t, GoRpc, testSimpleH, true, 0) -} - -func TestMsgpackRpcGo(t *testing.T) { - testCodecRpcOne(t, GoRpc, testMsgpackH, true, 0) -} - -func TestCborRpcGo(t *testing.T) { - testCodecRpcOne(t, GoRpc, testCborH, true, 0) -} - -func TestJsonRpcGo(t *testing.T) { - testCodecRpcOne(t, GoRpc, testJsonH, true, 0) -} - -func TestMsgpackRpcSpec(t *testing.T) { - testCodecRpcOne(t, MsgpackSpecRpc, testMsgpackH, true, 0) -} - -func TestBincUnderlyingType(t *testing.T) { - testCodecUnderlyingType(t, testBincH) -} - -func TestJsonLargeInteger(t *testing.T) { - for _, i := range []uint8{'L', 'A', 0} { - for _, j := range []interface{}{ - 1 << 60, - -(1 << 60), - 0, - 1 << 20, - -(1 << 20), - uint(1 << 60), - uint(0), - uint(1 << 20), - } { - doTestJsonLargeInteger(t, j, i) - } - } -} - -// TODO: -// Add Tests for: -// - decoding empty list/map in stream into a nil slice/map -// - binary(M|Unm)arsher support for time.Time (e.g. cbor encoding) -// - text(M|Unm)arshaler support for time.Time (e.g. json encoding) -// - non fast-path scenarios e.g. map[string]uint16, []customStruct. -// Expand cbor to include indefinite length stuff for this non-fast-path types. -// This may not be necessary, since we have the manual tests (fastpathEnabled=false) to test/validate with. -// - CodecSelfer -// Ensure it is called when (en|de)coding interface{} or reflect.Value (2 different codepaths). -// - interfaces: textMarshaler, binaryMarshaler, codecSelfer -// - struct tags: -// on anonymous fields, _struct (all fields), etc -// - codecgen of struct containing channels. -// - bad input with large array length prefix -// -// Cleanup tests: -// - The are brittle in their handling of validation and skipping diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/README.md b/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/README.md deleted file mode 100644 index 3ae8a056f..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# codecgen tool - -Generate is given a list of *.go files to parse, and an output file (fout), -codecgen will create an output file __file.go__ which -contains `codec.Selfer` implementations for the named types found -in the files parsed. - -Using codecgen is very straightforward. - -**Download and install the tool** - -`go get -u github.com/ugorji/go/codec/codecgen` - -**Run the tool on your files** - -The command line format is: - -`codecgen [options] (-o outfile) (infile ...)` - -```sh -% codecgen -? -Usage of codecgen: - -c="github.com/ugorji/go/codec": codec path - -o="": out file - -r=".*": regex for type name to match - -rt="": tags for go run - -t="": build tag to put in file - -u=false: Use unsafe, e.g. to avoid unnecessary allocation on []byte->string - -x=false: keep temp file - -% codecgen -o values_codecgen.go values.go values2.go moretypedefs.go -``` - -Please see the [blog article](http://ugorji.net/blog/go-codecgen) -for more information on how to use the tool. - diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/gen.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/gen.go deleted file mode 100644 index f370b4c79..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/gen.go +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -// codecgen generates codec.Selfer implementations for a set of types. -package main - -import ( - "bufio" - "bytes" - "errors" - "flag" - "fmt" - "go/ast" - "go/build" - "go/parser" - "go/token" - "math/rand" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "text/template" - "time" -) - -const genCodecPkg = "codec1978" // keep this in sync with codec.genCodecPkg - -const genFrunMainTmpl = `//+build ignore - -package main -{{ if .Types }}import "{{ .ImportPath }}"{{ end }} -func main() { - {{ $.PackageName }}.CodecGenTempWrite{{ .RandString }}() -} -` - -// const genFrunPkgTmpl = `//+build codecgen -const genFrunPkgTmpl = ` -package {{ $.PackageName }} - -import ( - {{ if not .CodecPkgFiles }}{{ .CodecPkgName }} "{{ .CodecImportPath }}"{{ end }} - "os" - "reflect" - "bytes" - "strings" - "go/format" -) - -func CodecGenTempWrite{{ .RandString }}() { - fout, err := os.Create("{{ .OutFile }}") - if err != nil { - panic(err) - } - defer fout.Close() - var out bytes.Buffer - - var typs []reflect.Type -{{ range $index, $element := .Types }} - var t{{ $index }} {{ . }} - typs = append(typs, reflect.TypeOf(t{{ $index }})) -{{ end }} - {{ if not .CodecPkgFiles }}{{ .CodecPkgName }}.{{ end }}Gen(&out, "{{ .BuildTag }}", "{{ .PackageName }}", "{{ .RandString }}", {{ .UseUnsafe }}, {{ if not .CodecPkgFiles }}{{ .CodecPkgName }}.{{ end }}NewTypeInfos(strings.Split("{{ .StructTags }}", ",")), typs...) - bout, err := format.Source(out.Bytes()) - if err != nil { - fout.Write(out.Bytes()) - panic(err) - } - fout.Write(bout) -} - -` - -// Generate is given a list of *.go files to parse, and an output file (fout). -// -// It finds all types T in the files, and it creates 2 tmp files (frun). -// - main package file passed to 'go run' -// - package level file which calls *genRunner.Selfer to write Selfer impls for each T. -// We use a package level file so that it can reference unexported types in the package being worked on. -// Tool then executes: "go run __frun__" which creates fout. -// fout contains Codec(En|De)codeSelf implementations for every type T. -// -func Generate(outfile, buildTag, codecPkgPath string, uid int64, useUnsafe bool, goRunTag string, - st string, regexName *regexp.Regexp, deleteTempFile bool, infiles ...string) (err error) { - // For each file, grab AST, find each type, and write a call to it. - if len(infiles) == 0 { - return - } - if outfile == "" || codecPkgPath == "" { - err = errors.New("outfile and codec package path cannot be blank") - return - } - if uid < 0 { - uid = -uid - } - if uid == 0 { - rr := rand.New(rand.NewSource(time.Now().UnixNano())) - uid = 101 + rr.Int63n(9777) - } - // We have to parse dir for package, before opening the temp file for writing (else ImportDir fails). - // Also, ImportDir(...) must take an absolute path. - lastdir := filepath.Dir(outfile) - absdir, err := filepath.Abs(lastdir) - if err != nil { - return - } - pkg, err := build.Default.ImportDir(absdir, build.AllowBinary) - if err != nil { - return - } - type tmplT struct { - CodecPkgName string - CodecImportPath string - ImportPath string - OutFile string - PackageName string - RandString string - BuildTag string - StructTags string - Types []string - CodecPkgFiles bool - UseUnsafe bool - } - tv := tmplT{ - CodecPkgName: genCodecPkg, - OutFile: outfile, - CodecImportPath: codecPkgPath, - BuildTag: buildTag, - UseUnsafe: useUnsafe, - RandString: strconv.FormatInt(uid, 10), - StructTags: st, - } - tv.ImportPath = pkg.ImportPath - if tv.ImportPath == tv.CodecImportPath { - tv.CodecPkgFiles = true - tv.CodecPkgName = "codec" - } - astfiles := make([]*ast.File, len(infiles)) - for i, infile := range infiles { - if filepath.Dir(infile) != lastdir { - err = errors.New("in files must all be in same directory as outfile") - return - } - fset := token.NewFileSet() - astfiles[i], err = parser.ParseFile(fset, infile, nil, 0) - if err != nil { - return - } - if i == 0 { - tv.PackageName = astfiles[i].Name.Name - if tv.PackageName == "main" { - // codecgen cannot be run on types in the 'main' package. - // A temporary 'main' package must be created, and should reference the fully built - // package containing the types. - // Also, the temporary main package will conflict with the main package which already has a main method. - err = errors.New("codecgen cannot be run on types in the 'main' package") - return - } - } - } - - for _, f := range astfiles { - for _, d := range f.Decls { - if gd, ok := d.(*ast.GenDecl); ok { - for _, dd := range gd.Specs { - if td, ok := dd.(*ast.TypeSpec); ok { - // if len(td.Name.Name) == 0 || td.Name.Name[0] > 'Z' || td.Name.Name[0] < 'A' { - if len(td.Name.Name) == 0 { - continue - } - - // only generate for: - // struct: StructType - // primitives (numbers, bool, string): Ident - // map: MapType - // slice, array: ArrayType - // chan: ChanType - // do not generate: - // FuncType, InterfaceType, StarExpr (ptr), etc - switch td.Type.(type) { - case *ast.StructType, *ast.Ident, *ast.MapType, *ast.ArrayType, *ast.ChanType: - if regexName.FindStringIndex(td.Name.Name) != nil { - tv.Types = append(tv.Types, td.Name.Name) - } - } - } - } - } - } - } - - if len(tv.Types) == 0 { - return - } - - // we cannot use ioutil.TempFile, because we cannot guarantee the file suffix (.go). - // Also, we cannot create file in temp directory, - // because go run will not work (as it needs to see the types here). - // Consequently, create the temp file in the current directory, and remove when done. - - // frun, err = ioutil.TempFile("", "codecgen-") - // frunName := filepath.Join(os.TempDir(), "codecgen-"+strconv.FormatInt(time.Now().UnixNano(), 10)+".go") - - frunMainName := "codecgen-main-" + tv.RandString + ".generated.go" - frunPkgName := "codecgen-pkg-" + tv.RandString + ".generated.go" - if deleteTempFile { - defer os.Remove(frunMainName) - defer os.Remove(frunPkgName) - } - // var frunMain, frunPkg *os.File - if _, err = gen1(frunMainName, genFrunMainTmpl, &tv); err != nil { - return - } - if _, err = gen1(frunPkgName, genFrunPkgTmpl, &tv); err != nil { - return - } - - // remove outfile, so "go run ..." will not think that types in outfile already exist. - os.Remove(outfile) - - // execute go run frun - cmd := exec.Command("go", "run", "-tags="+goRunTag, frunMainName) //, frunPkg.Name()) - var buf bytes.Buffer - cmd.Stdout = &buf - cmd.Stderr = &buf - if err = cmd.Run(); err != nil { - err = fmt.Errorf("error running 'go run %s': %v, console: %s", - frunMainName, err, buf.Bytes()) - return - } - os.Stdout.Write(buf.Bytes()) - return -} - -func gen1(frunName, tmplStr string, tv interface{}) (frun *os.File, err error) { - os.Remove(frunName) - if frun, err = os.Create(frunName); err != nil { - return - } - defer frun.Close() - - t := template.New("") - if t, err = t.Parse(tmplStr); err != nil { - return - } - bw := bufio.NewWriter(frun) - if err = t.Execute(bw, tv); err != nil { - return - } - if err = bw.Flush(); err != nil { - return - } - return -} - -func main() { - o := flag.String("o", "", "out file") - c := flag.String("c", genCodecPath, "codec path") - t := flag.String("t", "", "build tag to put in file") - r := flag.String("r", ".*", "regex for type name to match") - rt := flag.String("rt", "", "tags for go run") - st := flag.String("st", "codec,json", "struct tag keys to introspect") - x := flag.Bool("x", false, "keep temp file") - u := flag.Bool("u", false, "Use unsafe, e.g. to avoid unnecessary allocation on []byte->string") - d := flag.Int64("d", 0, "random identifier for use in generated code") - flag.Parse() - if err := Generate(*o, *t, *c, *d, *u, *rt, *st, - regexp.MustCompile(*r), !*x, flag.Args()...); err != nil { - fmt.Fprintf(os.Stderr, "codecgen error: %v\n", err) - os.Exit(1) - } -} diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/z.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/z.go deleted file mode 100644 index e120a4eb9..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen/z.go +++ /dev/null @@ -1,3 +0,0 @@ -package main - -const genCodecPath = "github.com/ugorji/go/codec" diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen_test.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen_test.go deleted file mode 100644 index a73497e91..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/codecgen_test.go +++ /dev/null @@ -1,24 +0,0 @@ -//+build x,codecgen - -package codec - -import ( - "fmt" - "testing" -) - -func _TestCodecgenJson1(t *testing.T) { - // This is just a simplistic test for codecgen. - // It is typically disabled. We only enable it for debugging purposes. - const callCodecgenDirect bool = true - v := newTestStruc(2, false, !testSkipIntf, false) - var bs []byte - e := NewEncoderBytes(&bs, testJsonH) - if callCodecgenDirect { - v.CodecEncodeSelf(e) - e.w.atEndOfEncode() - } else { - e.MustEncode(v) - } - fmt.Printf("%s\n", bs) -} diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/helper_test.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/helper_test.go deleted file mode 100644 index e1dea52f4..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/helper_test.go +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -package codec - -// All non-std package dependencies related to testing live in this file, -// so porting to different environment is easy (just update functions). -// -// This file sets up the variables used, including testInitFns. -// Each file should add initialization that should be performed -// after flags are parsed. -// -// init is a multi-step process: -// - setup vars (handled by init functions in each file) -// - parse flags -// - setup derived vars (handled by pre-init registered functions - registered in init function) -// - post init (handled by post-init registered functions - registered in init function) -// This way, no one has to manage carefully control the initialization -// using file names, etc. -// -// Tests which require external dependencies need the -tag=x parameter. -// They should be run as: -// go test -tags=x -run=. -// Benchmarks should also take this parameter, to include the sereal, xdr, etc. -// To run against codecgen, etc, make sure you pass extra parameters. -// Example usage: -// go test "-tags=x codecgen unsafe" -bench=. -// -// To fully test everything: -// go test -tags=x -benchtime=100ms -tv -bg -bi -brw -bu -v -run=. -bench=. - -// Handling flags -// codec_test.go will define a set of global flags for testing, including: -// - Use Reset -// - Use IO reader/writer (vs direct bytes) -// - Set Canonical -// - Set InternStrings -// - Use Symbols -// -// This way, we can test them all by running same set of tests with a different -// set of flags. -// -// Following this, all the benchmarks will utilize flags set by codec_test.go -// and will not redefine these "global" flags. - -import ( - "bytes" - "errors" - "flag" - "fmt" - "reflect" - "sync" - "testing" -) - -type testHED struct { - H Handle - E *Encoder - D *Decoder -} - -var ( - testNoopH = NoopHandle(8) - testMsgpackH = &MsgpackHandle{} - testBincH = &BincHandle{} - testSimpleH = &SimpleHandle{} - testCborH = &CborHandle{} - testJsonH = &JsonHandle{} - - testHandles []Handle - testPreInitFns []func() - testPostInitFns []func() - - testOnce sync.Once - - testHEDs []testHED -) - -func init() { - testHEDs = make([]testHED, 0, 32) - testHandles = append(testHandles, - testNoopH, testMsgpackH, testBincH, testSimpleH, - testCborH, testJsonH) -} - -func testHEDGet(h Handle) *testHED { - for i := range testHEDs { - v := &testHEDs[i] - if v.H == h { - return v - } - } - testHEDs = append(testHEDs, testHED{h, NewEncoder(nil, h), NewDecoder(nil, h)}) - return &testHEDs[len(testHEDs)-1] -} - -func testInitAll() { - flag.Parse() - for _, f := range testPreInitFns { - f() - } - for _, f := range testPostInitFns { - f() - } -} - -func testCodecEncode(ts interface{}, bsIn []byte, - fn func([]byte) *bytes.Buffer, h Handle) (bs []byte, err error) { - // bs = make([]byte, 0, approxSize) - var e *Encoder - var buf *bytes.Buffer - if testUseReset { - e = testHEDGet(h).E - } else { - e = NewEncoder(nil, h) - } - if testUseIoEncDec { - buf = fn(bsIn) - e.Reset(buf) - } else { - bs = bsIn - e.ResetBytes(&bs) - } - if testUseMust { - e.MustEncode(ts) - } else { - err = e.Encode(ts) - } - if testUseIoEncDec { - bs = buf.Bytes() - } - return -} - -func testCodecDecode(bs []byte, ts interface{}, h Handle) (err error) { - var d *Decoder - var buf *bytes.Reader - if testUseReset { - d = testHEDGet(h).D - } else { - d = NewDecoder(nil, h) - } - if testUseIoEncDec { - buf = bytes.NewReader(bs) - d.Reset(buf) - } else { - d.ResetBytes(bs) - } - if testUseMust { - d.MustDecode(ts) - } else { - err = d.Decode(ts) - } - return -} - -// ----- functions below are used only by tests (not benchmarks) - -const ( - testLogToT = true - failNowOnFail = true -) - -func checkErrT(t *testing.T, err error) { - if err != nil { - logT(t, err.Error()) - failT(t) - } -} - -func checkEqualT(t *testing.T, v1 interface{}, v2 interface{}, desc string) (err error) { - if err = deepEqual(v1, v2); err != nil { - logT(t, "Not Equal: %s: %v. v1: %v, v2: %v", desc, err, v1, v2) - failT(t) - } - return -} - -func failT(t *testing.T) { - if failNowOnFail { - t.FailNow() - } else { - t.Fail() - } -} - -// --- these functions are used by both benchmarks and tests - -func deepEqual(v1, v2 interface{}) (err error) { - if !reflect.DeepEqual(v1, v2) { - err = errors.New("Not Match") - } - return -} - -func logT(x interface{}, format string, args ...interface{}) { - if t, ok := x.(*testing.T); ok && t != nil && testLogToT { - if testVerbose { - t.Logf(format, args...) - } - } else if b, ok := x.(*testing.B); ok && b != nil && testLogToT { - b.Logf(format, args...) - } else { - if len(format) == 0 || format[len(format)-1] != '\n' { - format = format + "\n" - } - fmt.Printf(format, args...) - } -} - -func approxDataSize(rv reflect.Value) (sum int) { - switch rk := rv.Kind(); rk { - case reflect.Invalid: - case reflect.Ptr, reflect.Interface: - sum += int(rv.Type().Size()) - sum += approxDataSize(rv.Elem()) - case reflect.Slice: - sum += int(rv.Type().Size()) - for j := 0; j < rv.Len(); j++ { - sum += approxDataSize(rv.Index(j)) - } - case reflect.String: - sum += int(rv.Type().Size()) - sum += rv.Len() - case reflect.Map: - sum += int(rv.Type().Size()) - for _, mk := range rv.MapKeys() { - sum += approxDataSize(mk) - sum += approxDataSize(rv.MapIndex(mk)) - } - case reflect.Struct: - //struct size already includes the full data size. - //sum += int(rv.Type().Size()) - for j := 0; j < rv.NumField(); j++ { - sum += approxDataSize(rv.Field(j)) - } - default: - //pure value types - sum += int(rv.Type().Size()) - } - return -} diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/py_test.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/py_test.go deleted file mode 100644 index bedd7b0dc..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/py_test.go +++ /dev/null @@ -1,30 +0,0 @@ -//+build x - -// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -package codec - -// These tests are used to verify msgpack and cbor implementations against their python libraries. -// If you have the library installed, you can enable the tests back by running: go test -tags=x . -// Look at test.py for how to setup your environment. - -import ( - "testing" -) - -func TestMsgpackPythonGenStreams(t *testing.T) { - doTestPythonGenStreams(t, "msgpack", testMsgpackH) -} - -func TestCborPythonGenStreams(t *testing.T) { - doTestPythonGenStreams(t, "cbor", testCborH) -} - -func TestMsgpackRpcSpecGoClientToPythonSvc(t *testing.T) { - doTestMsgpackRpcSpecGoClientToPythonSvc(t) -} - -func TestMsgpackRpcSpecPythonClientToGoSvc(t *testing.T) { - doTestMsgpackRpcSpecPythonClientToGoSvc(t) -} diff --git a/Godeps/_workspace/src/github.com/ugorji/go/codec/values_test.go b/Godeps/_workspace/src/github.com/ugorji/go/codec/values_test.go deleted file mode 100644 index 4ec28e131..000000000 --- a/Godeps/_workspace/src/github.com/ugorji/go/codec/values_test.go +++ /dev/null @@ -1,203 +0,0 @@ -// // +build testing - -// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -package codec - -// This file contains values used by tests and benchmarks. -// JSON/BSON do not like maps with keys that are not strings, -// so we only use maps with string keys here. - -import ( - "math" - "time" -) - -var testStrucTime = time.Date(2012, 2, 2, 2, 2, 2, 2000, time.UTC).UTC() - -type AnonInTestStruc struct { - AS string - AI64 int64 - AI16 int16 - AUi64 uint64 - ASslice []string - AI64slice []int64 - AF64slice []float64 - // AMI32U32 map[int32]uint32 - // AMU32F64 map[uint32]float64 // json/bson do not like it - AMSU16 map[string]uint16 -} - -type AnonInTestStrucIntf struct { - Islice []interface{} - Ms map[string]interface{} - Nintf interface{} //don't set this, so we can test for nil - T time.Time -} - -type TestStruc struct { - _struct struct{} `codec:",omitempty"` //set omitempty for every field - - S string - I64 int64 - I16 int16 - Ui64 uint64 - Ui8 uint8 - B bool - By uint8 // byte: msgp doesn't like byte - - Sslice []string - I64slice []int64 - I16slice []int16 - Ui64slice []uint64 - Ui8slice []uint8 - Bslice []bool - Byslice []byte - - Iptrslice []*int64 - - // TODO: test these separately, specifically for reflection and codecgen. - // Unfortunately, ffjson doesn't support these. Its compilation even fails. - // Ui64array [4]uint64 - // Ui64slicearray [][4]uint64 - - AnonInTestStruc - - //M map[interface{}]interface{} `json:"-",bson:"-"` - Msi64 map[string]int64 - - // make this a ptr, so that it could be set or not. - // for comparison (e.g. with msgp), give it a struct tag (so it is not inlined), - // make this one omitempty (so it is included if nil). - *AnonInTestStrucIntf `codec:",omitempty"` - - Nmap map[string]bool //don't set this, so we can test for nil - Nslice []byte //don't set this, so we can test for nil - Nint64 *int64 //don't set this, so we can test for nil - Mtsptr map[string]*TestStruc - Mts map[string]TestStruc - Its []*TestStruc - Nteststruc *TestStruc -} - -// small struct for testing that codecgen works for unexported types -type tLowerFirstLetter struct { - I int - u uint64 - S string - b []byte -} - -func newTestStruc(depth int, bench bool, useInterface, useStringKeyOnly bool) (ts *TestStruc) { - var i64a, i64b, i64c, i64d int64 = 64, 6464, 646464, 64646464 - - ts = &TestStruc{ - S: "some string", - I64: math.MaxInt64 * 2 / 3, // 64, - I16: 1616, - Ui64: uint64(int64(math.MaxInt64 * 2 / 3)), // 64, //don't use MaxUint64, as bson can't write it - Ui8: 160, - B: true, - By: 5, - - Sslice: []string{"one", "two", "three"}, - I64slice: []int64{1111, 2222, 3333}, - I16slice: []int16{44, 55, 66}, - Ui64slice: []uint64{12121212, 34343434, 56565656}, - Ui8slice: []uint8{210, 211, 212}, - Bslice: []bool{true, false, true, false}, - Byslice: []byte{13, 14, 15}, - - Msi64: map[string]int64{ - "one": 1, - "two": 2, - }, - AnonInTestStruc: AnonInTestStruc{ - // There's more leeway in altering this. - AS: "A-String", - AI64: -64646464, - AI16: 1616, - AUi64: 64646464, - // (U+1D11E)G-clef character may be represented in json as "\uD834\uDD1E". - // single reverse solidus character may be represented in json as "\u005C". - // include these in ASslice below. - ASslice: []string{"Aone", "Atwo", "Athree", - "Afour.reverse_solidus.\u005c", "Afive.Gclef.\U0001d11E"}, - AI64slice: []int64{1, -22, 333, -4444, 55555, -666666}, - AMSU16: map[string]uint16{"1": 1, "22": 2, "333": 3, "4444": 4}, - AF64slice: []float64{11.11e-11, 22.22E+22, 33.33E-33, 44.44e+44, 555.55E-6, 666.66E6}, - }, - } - if useInterface { - ts.AnonInTestStrucIntf = &AnonInTestStrucIntf{ - Islice: []interface{}{"true", true, "no", false, uint64(288), float64(0.4)}, - Ms: map[string]interface{}{ - "true": "true", - "int64(9)": false, - }, - T: testStrucTime, - } - } - - //For benchmarks, some things will not work. - if !bench { - //json and bson require string keys in maps - //ts.M = map[interface{}]interface{}{ - // true: "true", - // int8(9): false, - //} - //gob cannot encode nil in element in array (encodeArray: nil element) - ts.Iptrslice = []*int64{nil, &i64a, nil, &i64b, nil, &i64c, nil, &i64d, nil} - // ts.Iptrslice = nil - } - if !useStringKeyOnly { - // ts.AnonInTestStruc.AMU32F64 = map[uint32]float64{1: 1, 2: 2, 3: 3} // Json/Bson barf - } - if depth > 0 { - depth-- - if ts.Mtsptr == nil { - ts.Mtsptr = make(map[string]*TestStruc) - } - if ts.Mts == nil { - ts.Mts = make(map[string]TestStruc) - } - ts.Mtsptr["0"] = newTestStruc(depth, bench, useInterface, useStringKeyOnly) - ts.Mts["0"] = *(ts.Mtsptr["0"]) - ts.Its = append(ts.Its, ts.Mtsptr["0"]) - } - return -} - -// Some other types - -type Sstring string -type Bbool bool -type Sstructsmall struct { - A int -} - -type Sstructbig struct { - A int - B bool - c string - // Sval Sstruct - Ssmallptr *Sstructsmall - Ssmall *Sstructsmall - Sptr *Sstructbig -} - -type SstructbigMapBySlice struct { - _struct struct{} `codec:",toarray"` - A int - B bool - c string - // Sval Sstruct - Ssmallptr *Sstructsmall - Ssmall *Sstructsmall - Sptr *Sstructbig -} - -type Sinterface interface { - Noop() -} diff --git a/Godeps/_workspace/src/golang.org/x/net/context/context_test.go b/Godeps/_workspace/src/golang.org/x/net/context/context_test.go deleted file mode 100644 index e64afa64c..000000000 --- a/Godeps/_workspace/src/golang.org/x/net/context/context_test.go +++ /dev/null @@ -1,575 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package context - -import ( - "fmt" - "math/rand" - "runtime" - "strings" - "sync" - "testing" - "time" -) - -// otherContext is a Context that's not one of the types defined in context.go. -// This lets us test code paths that differ based on the underlying type of the -// Context. -type otherContext struct { - Context -} - -func TestBackground(t *testing.T) { - c := Background() - if c == nil { - t.Fatalf("Background returned nil") - } - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - if got, want := fmt.Sprint(c), "context.Background"; got != want { - t.Errorf("Background().String() = %q want %q", got, want) - } -} - -func TestTODO(t *testing.T) { - c := TODO() - if c == nil { - t.Fatalf("TODO returned nil") - } - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - if got, want := fmt.Sprint(c), "context.TODO"; got != want { - t.Errorf("TODO().String() = %q want %q", got, want) - } -} - -func TestWithCancel(t *testing.T) { - c1, cancel := WithCancel(Background()) - - if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want { - t.Errorf("c1.String() = %q want %q", got, want) - } - - o := otherContext{c1} - c2, _ := WithCancel(o) - contexts := []Context{c1, o, c2} - - for i, c := range contexts { - if d := c.Done(); d == nil { - t.Errorf("c[%d].Done() == %v want non-nil", i, d) - } - if e := c.Err(); e != nil { - t.Errorf("c[%d].Err() == %v want nil", i, e) - } - - select { - case x := <-c.Done(): - t.Errorf("<-c.Done() == %v want nothing (it should block)", x) - default: - } - } - - cancel() - time.Sleep(100 * time.Millisecond) // let cancelation propagate - - for i, c := range contexts { - select { - case <-c.Done(): - default: - t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i) - } - if e := c.Err(); e != Canceled { - t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled) - } - } -} - -func TestParentFinishesChild(t *testing.T) { - // Context tree: - // parent -> cancelChild - // parent -> valueChild -> timerChild - parent, cancel := WithCancel(Background()) - cancelChild, stop := WithCancel(parent) - defer stop() - valueChild := WithValue(parent, "key", "value") - timerChild, stop := WithTimeout(valueChild, 10000*time.Hour) - defer stop() - - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - case x := <-cancelChild.Done(): - t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x) - case x := <-timerChild.Done(): - t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x) - case x := <-valueChild.Done(): - t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x) - default: - } - - // The parent's children should contain the two cancelable children. - pc := parent.(*cancelCtx) - cc := cancelChild.(*cancelCtx) - tc := timerChild.(*timerCtx) - pc.mu.Lock() - if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] { - t.Errorf("bad linkage: pc.children = %v, want %v and %v", - pc.children, cc, tc) - } - pc.mu.Unlock() - - if p, ok := parentCancelCtx(cc.Context); !ok || p != pc { - t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc) - } - if p, ok := parentCancelCtx(tc.Context); !ok || p != pc { - t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc) - } - - cancel() - - pc.mu.Lock() - if len(pc.children) != 0 { - t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children) - } - pc.mu.Unlock() - - // parent and children should all be finished. - check := func(ctx Context, name string) { - select { - case <-ctx.Done(): - default: - t.Errorf("<-%s.Done() blocked, but shouldn't have", name) - } - if e := ctx.Err(); e != Canceled { - t.Errorf("%s.Err() == %v want %v", name, e, Canceled) - } - } - check(parent, "parent") - check(cancelChild, "cancelChild") - check(valueChild, "valueChild") - check(timerChild, "timerChild") - - // WithCancel should return a canceled context on a canceled parent. - precanceledChild := WithValue(parent, "key", "value") - select { - case <-precanceledChild.Done(): - default: - t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have") - } - if e := precanceledChild.Err(); e != Canceled { - t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled) - } -} - -func TestChildFinishesFirst(t *testing.T) { - cancelable, stop := WithCancel(Background()) - defer stop() - for _, parent := range []Context{Background(), cancelable} { - child, cancel := WithCancel(parent) - - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - case x := <-child.Done(): - t.Errorf("<-child.Done() == %v want nothing (it should block)", x) - default: - } - - cc := child.(*cancelCtx) - pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background() - if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) { - t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok) - } - - if pcok { - pc.mu.Lock() - if len(pc.children) != 1 || !pc.children[cc] { - t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc) - } - pc.mu.Unlock() - } - - cancel() - - if pcok { - pc.mu.Lock() - if len(pc.children) != 0 { - t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children) - } - pc.mu.Unlock() - } - - // child should be finished. - select { - case <-child.Done(): - default: - t.Errorf("<-child.Done() blocked, but shouldn't have") - } - if e := child.Err(); e != Canceled { - t.Errorf("child.Err() == %v want %v", e, Canceled) - } - - // parent should not be finished. - select { - case x := <-parent.Done(): - t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) - default: - } - if e := parent.Err(); e != nil { - t.Errorf("parent.Err() == %v want nil", e) - } - } -} - -func testDeadline(c Context, wait time.Duration, t *testing.T) { - select { - case <-time.After(wait): - t.Fatalf("context should have timed out") - case <-c.Done(): - } - if e := c.Err(); e != DeadlineExceeded { - t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded) - } -} - -func TestDeadline(t *testing.T) { - c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond)) - if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { - t.Errorf("c.String() = %q want prefix %q", got, prefix) - } - testDeadline(c, 200*time.Millisecond, t) - - c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond)) - o := otherContext{c} - testDeadline(o, 200*time.Millisecond, t) - - c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond)) - o = otherContext{c} - c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond)) - testDeadline(c, 200*time.Millisecond, t) -} - -func TestTimeout(t *testing.T) { - c, _ := WithTimeout(Background(), 100*time.Millisecond) - if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { - t.Errorf("c.String() = %q want prefix %q", got, prefix) - } - testDeadline(c, 200*time.Millisecond, t) - - c, _ = WithTimeout(Background(), 100*time.Millisecond) - o := otherContext{c} - testDeadline(o, 200*time.Millisecond, t) - - c, _ = WithTimeout(Background(), 100*time.Millisecond) - o = otherContext{c} - c, _ = WithTimeout(o, 300*time.Millisecond) - testDeadline(c, 200*time.Millisecond, t) -} - -func TestCanceledTimeout(t *testing.T) { - c, _ := WithTimeout(Background(), 200*time.Millisecond) - o := otherContext{c} - c, cancel := WithTimeout(o, 400*time.Millisecond) - cancel() - time.Sleep(100 * time.Millisecond) // let cancelation propagate - select { - case <-c.Done(): - default: - t.Errorf("<-c.Done() blocked, but shouldn't have") - } - if e := c.Err(); e != Canceled { - t.Errorf("c.Err() == %v want %v", e, Canceled) - } -} - -type key1 int -type key2 int - -var k1 = key1(1) -var k2 = key2(1) // same int as k1, different type -var k3 = key2(3) // same type as k2, different int - -func TestValues(t *testing.T) { - check := func(c Context, nm, v1, v2, v3 string) { - if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 { - t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0) - } - if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 { - t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0) - } - if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 { - t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0) - } - } - - c0 := Background() - check(c0, "c0", "", "", "") - - c1 := WithValue(Background(), k1, "c1k1") - check(c1, "c1", "c1k1", "", "") - - if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want { - t.Errorf("c.String() = %q want %q", got, want) - } - - c2 := WithValue(c1, k2, "c2k2") - check(c2, "c2", "c1k1", "c2k2", "") - - c3 := WithValue(c2, k3, "c3k3") - check(c3, "c2", "c1k1", "c2k2", "c3k3") - - c4 := WithValue(c3, k1, nil) - check(c4, "c4", "", "c2k2", "c3k3") - - o0 := otherContext{Background()} - check(o0, "o0", "", "", "") - - o1 := otherContext{WithValue(Background(), k1, "c1k1")} - check(o1, "o1", "c1k1", "", "") - - o2 := WithValue(o1, k2, "o2k2") - check(o2, "o2", "c1k1", "o2k2", "") - - o3 := otherContext{c4} - check(o3, "o3", "", "c2k2", "c3k3") - - o4 := WithValue(o3, k3, nil) - check(o4, "o4", "", "c2k2", "") -} - -func TestAllocs(t *testing.T) { - bg := Background() - for _, test := range []struct { - desc string - f func() - limit float64 - gccgoLimit float64 - }{ - { - desc: "Background()", - f: func() { Background() }, - limit: 0, - gccgoLimit: 0, - }, - { - desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1), - f: func() { - c := WithValue(bg, k1, nil) - c.Value(k1) - }, - limit: 3, - gccgoLimit: 3, - }, - { - desc: "WithTimeout(bg, 15*time.Millisecond)", - f: func() { - c, _ := WithTimeout(bg, 15*time.Millisecond) - <-c.Done() - }, - limit: 8, - gccgoLimit: 15, - }, - { - desc: "WithCancel(bg)", - f: func() { - c, cancel := WithCancel(bg) - cancel() - <-c.Done() - }, - limit: 5, - gccgoLimit: 8, - }, - { - desc: "WithTimeout(bg, 100*time.Millisecond)", - f: func() { - c, cancel := WithTimeout(bg, 100*time.Millisecond) - cancel() - <-c.Done() - }, - limit: 8, - gccgoLimit: 25, - }, - } { - limit := test.limit - if runtime.Compiler == "gccgo" { - // gccgo does not yet do escape analysis. - // TOOD(iant): Remove this when gccgo does do escape analysis. - limit = test.gccgoLimit - } - if n := testing.AllocsPerRun(100, test.f); n > limit { - t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit)) - } - } -} - -func TestSimultaneousCancels(t *testing.T) { - root, cancel := WithCancel(Background()) - m := map[Context]CancelFunc{root: cancel} - q := []Context{root} - // Create a tree of contexts. - for len(q) != 0 && len(m) < 100 { - parent := q[0] - q = q[1:] - for i := 0; i < 4; i++ { - ctx, cancel := WithCancel(parent) - m[ctx] = cancel - q = append(q, ctx) - } - } - // Start all the cancels in a random order. - var wg sync.WaitGroup - wg.Add(len(m)) - for _, cancel := range m { - go func(cancel CancelFunc) { - cancel() - wg.Done() - }(cancel) - } - // Wait on all the contexts in a random order. - for ctx := range m { - select { - case <-ctx.Done(): - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n]) - } - } - // Wait for all the cancel functions to return. - done := make(chan struct{}) - go func() { - wg.Wait() - close(done) - }() - select { - case <-done: - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n]) - } -} - -func TestInterlockedCancels(t *testing.T) { - parent, cancelParent := WithCancel(Background()) - child, cancelChild := WithCancel(parent) - go func() { - parent.Done() - cancelChild() - }() - cancelParent() - select { - case <-child.Done(): - case <-time.After(1 * time.Second): - buf := make([]byte, 10<<10) - n := runtime.Stack(buf, true) - t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n]) - } -} - -func TestLayersCancel(t *testing.T) { - testLayers(t, time.Now().UnixNano(), false) -} - -func TestLayersTimeout(t *testing.T) { - testLayers(t, time.Now().UnixNano(), true) -} - -func testLayers(t *testing.T, seed int64, testTimeout bool) { - rand.Seed(seed) - errorf := func(format string, a ...interface{}) { - t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...) - } - const ( - timeout = 200 * time.Millisecond - minLayers = 30 - ) - type value int - var ( - vals []*value - cancels []CancelFunc - numTimers int - ctx = Background() - ) - for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ { - switch rand.Intn(3) { - case 0: - v := new(value) - ctx = WithValue(ctx, v, v) - vals = append(vals, v) - case 1: - var cancel CancelFunc - ctx, cancel = WithCancel(ctx) - cancels = append(cancels, cancel) - case 2: - var cancel CancelFunc - ctx, cancel = WithTimeout(ctx, timeout) - cancels = append(cancels, cancel) - numTimers++ - } - } - checkValues := func(when string) { - for _, key := range vals { - if val := ctx.Value(key).(*value); key != val { - errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key) - } - } - } - select { - case <-ctx.Done(): - errorf("ctx should not be canceled yet") - default: - } - if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) { - t.Errorf("ctx.String() = %q want prefix %q", s, prefix) - } - t.Log(ctx) - checkValues("before cancel") - if testTimeout { - select { - case <-ctx.Done(): - case <-time.After(timeout + timeout/10): - errorf("ctx should have timed out") - } - checkValues("after timeout") - } else { - cancel := cancels[rand.Intn(len(cancels))] - cancel() - select { - case <-ctx.Done(): - default: - errorf("ctx should be canceled") - } - checkValues("after cancel") - } -} - -func TestCancelRemoves(t *testing.T) { - checkChildren := func(when string, ctx Context, want int) { - if got := len(ctx.(*cancelCtx).children); got != want { - t.Errorf("%s: context has %d children, want %d", when, got, want) - } - } - - ctx, _ := WithCancel(Background()) - checkChildren("after creation", ctx, 0) - _, cancel := WithCancel(ctx) - checkChildren("with WithCancel child ", ctx, 1) - cancel() - checkChildren("after cancelling WithCancel child", ctx, 0) - - ctx, _ = WithCancel(Background()) - checkChildren("after creation", ctx, 0) - _, cancel = WithTimeout(ctx, 60*time.Minute) - checkChildren("with WithTimeout child ", ctx, 1) - cancel() - checkChildren("after cancelling WithTimeout child", ctx, 0) -} diff --git a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp_test.go b/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp_test.go deleted file mode 100644 index 47b53d7f1..000000000 --- a/Godeps/_workspace/src/golang.org/x/net/context/ctxhttp/ctxhttp_test.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ctxhttp - -import ( - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - "time" - - "golang.org/x/net/context" -) - -const ( - requestDuration = 100 * time.Millisecond - requestBody = "ok" -) - -func TestNoTimeout(t *testing.T) { - ctx := context.Background() - resp, err := doRequest(ctx) - - if resp == nil || err != nil { - t.Fatalf("error received from client: %v %v", err, resp) - } -} -func TestCancel(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - go func() { - time.Sleep(requestDuration / 2) - cancel() - }() - - resp, err := doRequest(ctx) - - if resp != nil || err == nil { - t.Fatalf("expected error, didn't get one. resp: %v", resp) - } - if err != ctx.Err() { - t.Fatalf("expected error from context but got: %v", err) - } -} - -func TestCancelAfterRequest(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - - resp, err := doRequest(ctx) - - // Cancel before reading the body. - // Request.Body should still be readable after the context is canceled. - cancel() - - b, err := ioutil.ReadAll(resp.Body) - if err != nil || string(b) != requestBody { - t.Fatalf("could not read body: %q %v", b, err) - } -} - -func doRequest(ctx context.Context) (*http.Response, error) { - var okHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - time.Sleep(requestDuration) - w.Write([]byte(requestBody)) - }) - - serv := httptest.NewServer(okHandler) - defer serv.Close() - - return Get(ctx, nil, serv.URL) -} diff --git a/Godeps/_workspace/src/golang.org/x/net/context/withtimeout_test.go b/Godeps/_workspace/src/golang.org/x/net/context/withtimeout_test.go deleted file mode 100644 index a6754dc36..000000000 --- a/Godeps/_workspace/src/golang.org/x/net/context/withtimeout_test.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package context_test - -import ( - "fmt" - "time" - - "golang.org/x/net/context" -) - -func ExampleWithTimeout() { - // Pass a context with a timeout to tell a blocking function that it - // should abandon its work after the timeout elapses. - ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond) - select { - case <-time.After(200 * time.Millisecond): - fmt.Println("overslept") - case <-ctx.Done(): - fmt.Println(ctx.Err()) // prints "context deadline exceeded" - } - // Output: - // context deadline exceeded -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials.go b/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials.go deleted file mode 100644 index 452fb8c12..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package clientcredentials implements the OAuth2.0 "client credentials" token flow, -// also known as the "two-legged OAuth 2.0". -// -// This should be used when the client is acting on its own behalf or when the client -// is the resource owner. It may also be used when requesting access to protected -// resources based on an authorization previously arranged with the authorization -// server. -// -// See http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.4 -package clientcredentials - -import ( - "net/http" - "net/url" - "strings" - - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/internal" -) - -// tokenFromInternal maps an *internal.Token struct into -// an *oauth2.Token struct. -func tokenFromInternal(t *internal.Token) *oauth2.Token { - if t == nil { - return nil - } - tk := &oauth2.Token{ - AccessToken: t.AccessToken, - TokenType: t.TokenType, - RefreshToken: t.RefreshToken, - Expiry: t.Expiry, - } - return tk.WithExtra(t.Raw) -} - -// retrieveToken takes a *Config and uses that to retrieve an *internal.Token. -// This token is then mapped from *internal.Token into an *oauth2.Token which is -// returned along with an error. -func retrieveToken(ctx context.Context, c *Config, v url.Values) (*oauth2.Token, error) { - tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.TokenURL, v) - if err != nil { - return nil, err - } - return tokenFromInternal(tk), nil -} - -// Client Credentials Config describes a 2-legged OAuth2 flow, with both the -// client application information and the server's endpoint URLs. -type Config struct { - // ClientID is the application's ID. - ClientID string - - // ClientSecret is the application's secret. - ClientSecret string - - // TokenURL is the resource server's token endpoint - // URL. This is a constant specific to each server. - TokenURL string - - // Scope specifies optional requested permissions. - Scopes []string -} - -// Token uses client credentials to retreive a token. -// The HTTP client to use is derived from the context. -// If nil, http.DefaultClient is used. -func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) { - return retrieveToken(ctx, c, url.Values{ - "grant_type": {"client_credentials"}, - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - }) -} - -// Client returns an HTTP client using the provided token. -// The token will auto-refresh as necessary. The underlying -// HTTP transport will be obtained using the provided context. -// The returned client and its Transport should not be modified. -func (c *Config) Client(ctx context.Context) *http.Client { - return oauth2.NewClient(ctx, c.TokenSource(ctx)) -} - -// TokenSource returns a TokenSource that returns t until t expires, -// automatically refreshing it as necessary using the provided context and the -// client ID and client secret. -// -// Most users will use Config.Client instead. -func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource { - source := &tokenSource{ - ctx: ctx, - conf: c, - } - return oauth2.ReuseTokenSource(nil, source) -} - -type tokenSource struct { - ctx context.Context - conf *Config -} - -// Token refreshes the token by using a new client credentials request. -// tokens received this way do not include a refresh token -func (c *tokenSource) Token() (*oauth2.Token, error) { - return retrieveToken(c.ctx, c.conf, url.Values{ - "grant_type": {"client_credentials"}, - "scope": internal.CondVal(strings.Join(c.conf.Scopes, " ")), - }) -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials_test.go deleted file mode 100644 index ab319e082..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/clientcredentials/clientcredentials_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package clientcredentials - -import ( - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - - "golang.org/x/oauth2" -) - -func newConf(url string) *Config { - return &Config{ - ClientID: "CLIENT_ID", - ClientSecret: "CLIENT_SECRET", - Scopes: []string{"scope1", "scope2"}, - TokenURL: url + "/token", - } -} - -type mockTransport struct { - rt func(req *http.Request) (resp *http.Response, err error) -} - -func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { - return t.rt(req) -} - -func TestTokenRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() != "/token" { - t.Errorf("authenticate client request URL = %q; want %q", r.URL, "/token") - } - headerAuth := r.Header.Get("Authorization") - if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" { - t.Errorf("Unexpected authorization header, %v is found.", headerAuth) - } - if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want { - t.Errorf("Content-Type header = %q; want %q", got, want) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - r.Body.Close() - } - if err != nil { - t.Errorf("failed reading request body: %s.", err) - } - if string(body) != "client_id=CLIENT_ID&grant_type=client_credentials&scope=scope1+scope2" { - t.Errorf("payload = %q; want %q", string(body), "client_id=CLIENT_ID&grant_type=client_credentials&scope=scope1+scope2") - } - w.Header().Set("Content-Type", "application/x-www-form-urlencoded") - w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&token_type=bearer")) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.Token(oauth2.NoContext) - if err != nil { - t.Error(err) - } - if !tok.Valid() { - t.Fatalf("token invalid. got: %#v", tok) - } - if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" { - t.Errorf("Access token = %q; want %q", tok.AccessToken, "90d64460d14870c08c81352a05dedd3465940a7c") - } - if tok.TokenType != "bearer" { - t.Errorf("token type = %q; want %q", tok.TokenType, "bearer") - } -} - -func TestTokenRefreshRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() == "/somethingelse" { - return - } - if r.URL.String() != "/token" { - t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, _ := ioutil.ReadAll(r.Body) - if string(body) != "client_id=CLIENT_ID&grant_type=client_credentials&scope=scope1+scope2" { - t.Errorf("Unexpected refresh token payload, %v is found.", string(body)) - } - })) - defer ts.Close() - conf := newConf(ts.URL) - c := conf.Client(oauth2.NoContext) - c.Get(ts.URL + "/somethingelse") -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/example_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/example_test.go deleted file mode 100644 index 8be278855..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/example_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2_test - -import ( - "fmt" - "log" - - "golang.org/x/oauth2" -) - -func ExampleConfig() { - conf := &oauth2.Config{ - ClientID: "YOUR_CLIENT_ID", - ClientSecret: "YOUR_CLIENT_SECRET", - Scopes: []string{"SCOPE1", "SCOPE2"}, - Endpoint: oauth2.Endpoint{ - AuthURL: "https://provider.com/o/oauth2/auth", - TokenURL: "https://provider.com/o/oauth2/token", - }, - } - - // Redirect user to consent page to ask for permission - // for the scopes specified above. - url := conf.AuthCodeURL("state", oauth2.AccessTypeOffline) - fmt.Printf("Visit the URL for the auth dialog: %v", url) - - // Use the authorization code that is pushed to the redirect URL. - // NewTransportWithCode will do the handshake to retrieve - // an access token and initiate a Transport that is - // authorized and authenticated by the retrieved token. - var code string - if _, err := fmt.Scan(&code); err != nil { - log.Fatal(err) - } - tok, err := conf.Exchange(oauth2.NoContext, code) - if err != nil { - log.Fatal(err) - } - - client := conf.Client(oauth2.NoContext, tok) - client.Get("...") -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/facebook/facebook.go b/Godeps/_workspace/src/golang.org/x/oauth2/facebook/facebook.go deleted file mode 100644 index 9c816ff80..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/facebook/facebook.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package facebook provides constants for using OAuth2 to access Facebook. -package facebook - -import ( - "golang.org/x/oauth2" -) - -// Endpoint is Facebook's OAuth 2.0 endpoint. -var Endpoint = oauth2.Endpoint{ - AuthURL: "https://www.facebook.com/dialog/oauth", - TokenURL: "https://graph.facebook.com/oauth/access_token", -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/github/github.go b/Godeps/_workspace/src/golang.org/x/oauth2/github/github.go deleted file mode 100644 index 82ca623dd..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/github/github.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package github provides constants for using OAuth2 to access Github. -package github - -import ( - "golang.org/x/oauth2" -) - -// Endpoint is Github's OAuth 2.0 endpoint. -var Endpoint = oauth2.Endpoint{ - AuthURL: "https://github.com/login/oauth/authorize", - TokenURL: "https://github.com/login/oauth/access_token", -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/example_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/example_test.go deleted file mode 100644 index 17262802a..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/example_test.go +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build appenginevm !appengine - -package google_test - -import ( - "fmt" - "io/ioutil" - "log" - "net/http" - - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "golang.org/x/oauth2/jwt" - "google.golang.org/appengine" - "google.golang.org/appengine/urlfetch" -) - -func ExampleDefaultClient() { - client, err := google.DefaultClient(oauth2.NoContext, - "https://www.googleapis.com/auth/devstorage.full_control") - if err != nil { - log.Fatal(err) - } - client.Get("...") -} - -func Example_webServer() { - // Your credentials should be obtained from the Google - // Developer Console (https://console.developers.google.com). - conf := &oauth2.Config{ - ClientID: "YOUR_CLIENT_ID", - ClientSecret: "YOUR_CLIENT_SECRET", - RedirectURL: "YOUR_REDIRECT_URL", - Scopes: []string{ - "https://www.googleapis.com/auth/bigquery", - "https://www.googleapis.com/auth/blogger", - }, - Endpoint: google.Endpoint, - } - // Redirect user to Google's consent page to ask for permission - // for the scopes specified above. - url := conf.AuthCodeURL("state") - fmt.Printf("Visit the URL for the auth dialog: %v", url) - - // Handle the exchange code to initiate a transport. - tok, err := conf.Exchange(oauth2.NoContext, "authorization-code") - if err != nil { - log.Fatal(err) - } - client := conf.Client(oauth2.NoContext, tok) - client.Get("...") -} - -func ExampleJWTConfigFromJSON() { - // Your credentials should be obtained from the Google - // Developer Console (https://console.developers.google.com). - // Navigate to your project, then see the "Credentials" page - // under "APIs & Auth". - // To create a service account client, click "Create new Client ID", - // select "Service Account", and click "Create Client ID". A JSON - // key file will then be downloaded to your computer. - data, err := ioutil.ReadFile("/path/to/your-project-key.json") - if err != nil { - log.Fatal(err) - } - conf, err := google.JWTConfigFromJSON(data, "https://www.googleapis.com/auth/bigquery") - if err != nil { - log.Fatal(err) - } - // Initiate an http.Client. The following GET request will be - // authorized and authenticated on the behalf of - // your service account. - client := conf.Client(oauth2.NoContext) - client.Get("...") -} - -func ExampleSDKConfig() { - // The credentials will be obtained from the first account that - // has been authorized with `gcloud auth login`. - conf, err := google.NewSDKConfig("") - if err != nil { - log.Fatal(err) - } - // Initiate an http.Client. The following GET request will be - // authorized and authenticated on the behalf of the SDK user. - client := conf.Client(oauth2.NoContext) - client.Get("...") -} - -func Example_serviceAccount() { - // Your credentials should be obtained from the Google - // Developer Console (https://console.developers.google.com). - conf := &jwt.Config{ - Email: "xxx@developer.gserviceaccount.com", - // The contents of your RSA private key or your PEM file - // that contains a private key. - // If you have a p12 file instead, you - // can use `openssl` to export the private key into a pem file. - // - // $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes - // - // The field only supports PEM containers with no passphrase. - // The openssl command will convert p12 keys to passphrase-less PEM containers. - PrivateKey: []byte("-----BEGIN RSA PRIVATE KEY-----..."), - Scopes: []string{ - "https://www.googleapis.com/auth/bigquery", - "https://www.googleapis.com/auth/blogger", - }, - TokenURL: google.JWTTokenURL, - // If you would like to impersonate a user, you can - // create a transport with a subject. The following GET - // request will be made on the behalf of user@example.com. - // Optional. - Subject: "user@example.com", - } - // Initiate an http.Client, the following GET request will be - // authorized and authenticated on the behalf of user@example.com. - client := conf.Client(oauth2.NoContext) - client.Get("...") -} - -func ExampleAppEngineTokenSource() { - var req *http.Request // from the ServeHTTP handler - ctx := appengine.NewContext(req) - client := &http.Client{ - Transport: &oauth2.Transport{ - Source: google.AppEngineTokenSource(ctx, "https://www.googleapis.com/auth/bigquery"), - Base: &urlfetch.Transport{ - Context: ctx, - }, - }, - } - client.Get("...") -} - -func ExampleComputeTokenSource() { - client := &http.Client{ - Transport: &oauth2.Transport{ - // Fetch from Google Compute Engine's metadata server to retrieve - // an access token for the provided account. - // If no account is specified, "default" is used. - Source: google.ComputeTokenSource(""), - }, - } - client.Get("...") -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/google_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/google_test.go deleted file mode 100644 index 4cc01884b..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/google_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package google - -import ( - "strings" - "testing" -) - -var webJSONKey = []byte(` -{ - "web": { - "auth_uri": "https://google.com/o/oauth2/auth", - "client_secret": "3Oknc4jS_wA2r9i", - "token_uri": "https://google.com/o/oauth2/token", - "client_email": "222-nprqovg5k43uum874cs9osjt2koe97g8@developer.gserviceaccount.com", - "redirect_uris": ["https://www.example.com/oauth2callback"], - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/222-nprqovg5k43uum874cs9osjt2koe97g8@developer.gserviceaccount.com", - "client_id": "222-nprqovg5k43uum874cs9osjt2koe97g8.apps.googleusercontent.com", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "javascript_origins": ["https://www.example.com"] - } -}`) - -var installedJSONKey = []byte(`{ - "installed": { - "client_id": "222-installed.apps.googleusercontent.com", - "redirect_uris": ["https://www.example.com/oauth2callback"] - } -}`) - -func TestConfigFromJSON(t *testing.T) { - conf, err := ConfigFromJSON(webJSONKey, "scope1", "scope2") - if err != nil { - t.Error(err) - } - if got, want := conf.ClientID, "222-nprqovg5k43uum874cs9osjt2koe97g8.apps.googleusercontent.com"; got != want { - t.Errorf("ClientID = %q; want %q", got, want) - } - if got, want := conf.ClientSecret, "3Oknc4jS_wA2r9i"; got != want { - t.Errorf("ClientSecret = %q; want %q", got, want) - } - if got, want := conf.RedirectURL, "https://www.example.com/oauth2callback"; got != want { - t.Errorf("RedictURL = %q; want %q", got, want) - } - if got, want := strings.Join(conf.Scopes, ","), "scope1,scope2"; got != want { - t.Errorf("Scopes = %q; want %q", got, want) - } - if got, want := conf.Endpoint.AuthURL, "https://google.com/o/oauth2/auth"; got != want { - t.Errorf("AuthURL = %q; want %q", got, want) - } - if got, want := conf.Endpoint.TokenURL, "https://google.com/o/oauth2/token"; got != want { - t.Errorf("TokenURL = %q; want %q", got, want) - } -} - -func TestConfigFromJSON_Installed(t *testing.T) { - conf, err := ConfigFromJSON(installedJSONKey) - if err != nil { - t.Error(err) - } - if got, want := conf.ClientID, "222-installed.apps.googleusercontent.com"; got != want { - t.Errorf("ClientID = %q; want %q", got, want) - } -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/sdk_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/google/sdk_test.go deleted file mode 100644 index 79df88964..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/sdk_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package google - -import "testing" - -func TestSDKConfig(t *testing.T) { - sdkConfigPath = func() (string, error) { - return "testdata/gcloud", nil - } - - tests := []struct { - account string - accessToken string - err bool - }{ - {"", "bar_access_token", false}, - {"foo@example.com", "foo_access_token", false}, - {"bar@example.com", "bar_access_token", false}, - {"baz@serviceaccount.example.com", "", true}, - } - for _, tt := range tests { - c, err := NewSDKConfig(tt.account) - if got, want := err != nil, tt.err; got != want { - if !tt.err { - t.Errorf("expected no error, got error: %v", tt.err, err) - } else { - t.Errorf("expected error, got none") - } - continue - } - if err != nil { - continue - } - tok := c.initialToken - if tok == nil { - t.Errorf("expected token %q, got: nil", tt.accessToken) - continue - } - if tok.AccessToken != tt.accessToken { - t.Errorf("expected token %q, got: %q", tt.accessToken, tok.AccessToken) - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/testdata/gcloud/credentials b/Godeps/_workspace/src/golang.org/x/oauth2/google/testdata/gcloud/credentials deleted file mode 100644 index ff5eefbd0..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/testdata/gcloud/credentials +++ /dev/null @@ -1,122 +0,0 @@ -{ - "data": [ - { - "credential": { - "_class": "OAuth2Credentials", - "_module": "oauth2client.client", - "access_token": "foo_access_token", - "client_id": "foo_client_id", - "client_secret": "foo_client_secret", - "id_token": { - "at_hash": "foo_at_hash", - "aud": "foo_aud", - "azp": "foo_azp", - "cid": "foo_cid", - "email": "foo@example.com", - "email_verified": true, - "exp": 1420573614, - "iat": 1420569714, - "id": "1337", - "iss": "accounts.google.com", - "sub": "1337", - "token_hash": "foo_token_hash", - "verified_email": true - }, - "invalid": false, - "refresh_token": "foo_refresh_token", - "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", - "token_expiry": "2015-01-09T00:51:51Z", - "token_response": { - "access_token": "foo_access_token", - "expires_in": 3600, - "id_token": "foo_id_token", - "token_type": "Bearer" - }, - "token_uri": "https://accounts.google.com/o/oauth2/token", - "user_agent": "Cloud SDK Command Line Tool" - }, - "key": { - "account": "foo@example.com", - "clientId": "foo_client_id", - "scope": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting", - "type": "google-cloud-sdk" - } - }, - { - "credential": { - "_class": "OAuth2Credentials", - "_module": "oauth2client.client", - "access_token": "bar_access_token", - "client_id": "bar_client_id", - "client_secret": "bar_client_secret", - "id_token": { - "at_hash": "bar_at_hash", - "aud": "bar_aud", - "azp": "bar_azp", - "cid": "bar_cid", - "email": "bar@example.com", - "email_verified": true, - "exp": 1420573614, - "iat": 1420569714, - "id": "1337", - "iss": "accounts.google.com", - "sub": "1337", - "token_hash": "bar_token_hash", - "verified_email": true - }, - "invalid": false, - "refresh_token": "bar_refresh_token", - "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", - "token_expiry": "2015-01-09T00:51:51Z", - "token_response": { - "access_token": "bar_access_token", - "expires_in": 3600, - "id_token": "bar_id_token", - "token_type": "Bearer" - }, - "token_uri": "https://accounts.google.com/o/oauth2/token", - "user_agent": "Cloud SDK Command Line Tool" - }, - "key": { - "account": "bar@example.com", - "clientId": "bar_client_id", - "scope": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting", - "type": "google-cloud-sdk" - } - }, - { - "credential": { - "_class": "ServiceAccountCredentials", - "_kwargs": {}, - "_module": "oauth2client.client", - "_private_key_id": "00000000000000000000000000000000", - "_private_key_pkcs8_text": "-----BEGIN RSA PRIVATE KEY-----\nMIICWwIBAAKBgQCt3fpiynPSaUhWSIKMGV331zudwJ6GkGmvQtwsoK2S2LbvnSwU\nNxgj4fp08kIDR5p26wF4+t/HrKydMwzftXBfZ9UmLVJgRdSswmS5SmChCrfDS5OE\nvFFcN5+6w1w8/Nu657PF/dse8T0bV95YrqyoR0Osy8WHrUOMSIIbC3hRuwIDAQAB\nAoGAJrGE/KFjn0sQ7yrZ6sXmdLawrM3mObo/2uI9T60+k7SpGbBX0/Pi6nFrJMWZ\nTVONG7P3Mu5aCPzzuVRYJB0j8aldSfzABTY3HKoWCczqw1OztJiEseXGiYz4QOyr\nYU3qDyEpdhS6q6wcoLKGH+hqRmz6pcSEsc8XzOOu7s4xW8kCQQDkc75HjhbarCnd\nJJGMe3U76+6UGmdK67ltZj6k6xoB5WbTNChY9TAyI2JC+ppYV89zv3ssj4L+02u3\nHIHFGxsHAkEAwtU1qYb1tScpchPobnYUFiVKJ7KA8EZaHVaJJODW/cghTCV7BxcJ\nbgVvlmk4lFKn3lPKAgWw7PdQsBTVBUcCrQJATPwoIirizrv3u5soJUQxZIkENAqV\nxmybZx9uetrzP7JTrVbFRf0SScMcyN90hdLJiQL8+i4+gaszgFht7sNMnwJAAbfj\nq0UXcauQwALQ7/h2oONfTg5S+MuGC/AxcXPSMZbMRGGoPh3D5YaCv27aIuS/ukQ+\n6dmm/9AGlCb64fsIWQJAPaokbjIifo+LwC5gyK73Mc4t8nAOSZDenzd/2f6TCq76\nS1dcnKiPxaED7W/y6LJiuBT2rbZiQ2L93NJpFZD/UA==\n-----END RSA PRIVATE KEY-----\n", - "_revoke_uri": "https://accounts.google.com/o/oauth2/revoke", - "_scopes": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting", - "_service_account_email": "baz@serviceaccount.example.com", - "_service_account_id": "baz.serviceaccount.example.com", - "_token_uri": "https://accounts.google.com/o/oauth2/token", - "_user_agent": "Cloud SDK Command Line Tool", - "access_token": null, - "assertion_type": null, - "client_id": null, - "client_secret": null, - "id_token": null, - "invalid": false, - "refresh_token": null, - "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", - "service_account_name": "baz@serviceaccount.example.com", - "token_expiry": null, - "token_response": null, - "user_agent": "Cloud SDK Command Line Tool" - }, - "key": { - "account": "baz@serviceaccount.example.com", - "clientId": "baz_client_id", - "scope": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/ndev.cloudman https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/sqlservice.admin https://www.googleapis.com/auth/prediction https://www.googleapis.com/auth/projecthosting", - "type": "google-cloud-sdk" - } - } - ], - "file_version": 1 -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/google/testdata/gcloud/properties b/Godeps/_workspace/src/golang.org/x/oauth2/google/testdata/gcloud/properties deleted file mode 100644 index 025de886c..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/google/testdata/gcloud/properties +++ /dev/null @@ -1,2 +0,0 @@ -[core] -account = bar@example.com \ No newline at end of file diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/internal/oauth2_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/internal/oauth2_test.go deleted file mode 100644 index 014a351e0..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/internal/oauth2_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package internal contains support packages for oauth2 package. -package internal - -import ( - "reflect" - "strings" - "testing" -) - -func TestParseINI(t *testing.T) { - tests := []struct { - ini string - want map[string]map[string]string - }{ - { - `root = toor -[foo] -bar = hop -ini = nin -`, - map[string]map[string]string{ - "": map[string]string{"root": "toor"}, - "foo": map[string]string{"bar": "hop", "ini": "nin"}, - }, - }, - { - `[empty] -[section] -empty= -`, - map[string]map[string]string{ - "": map[string]string{}, - "empty": map[string]string{}, - "section": map[string]string{"empty": ""}, - }, - }, - { - `ignore -[invalid -=stuff -;comment=true -`, - map[string]map[string]string{ - "": map[string]string{}, - }, - }, - } - for _, tt := range tests { - result, err := ParseINI(strings.NewReader(tt.ini)) - if err != nil { - t.Errorf("ParseINI(%q) error %v, want: no error", tt.ini, err) - continue - } - if !reflect.DeepEqual(result, tt.want) { - t.Errorf("ParseINI(%q) = %#v, want: %#v", tt.ini, result, tt.want) - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/internal/token_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/internal/token_test.go deleted file mode 100644 index 864f6fa07..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/internal/token_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package internal contains support packages for oauth2 package. -package internal - -import ( - "fmt" - "testing" -) - -func Test_providerAuthHeaderWorks(t *testing.T) { - for _, p := range brokenAuthHeaderProviders { - if providerAuthHeaderWorks(p) { - t.Errorf("URL: %s not found in list", p) - } - p := fmt.Sprintf("%ssomesuffix", p) - if providerAuthHeaderWorks(p) { - t.Errorf("URL: %s not found in list", p) - } - } - p := "https://api.not-in-the-list-example.com/" - if !providerAuthHeaderWorks(p) { - t.Errorf("URL: %s found in list", p) - } - -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/jwt/example_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/jwt/example_test.go deleted file mode 100644 index 6d618836e..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/jwt/example_test.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jwt_test - -import ( - "golang.org/x/oauth2" - "golang.org/x/oauth2/jwt" -) - -func ExampleJWTConfig() { - conf := &jwt.Config{ - Email: "xxx@developer.com", - // The contents of your RSA private key or your PEM file - // that contains a private key. - // If you have a p12 file instead, you - // can use `openssl` to export the private key into a pem file. - // - // $ openssl pkcs12 -in key.p12 -out key.pem -nodes - // - // It only supports PEM containers with no passphrase. - PrivateKey: []byte("-----BEGIN RSA PRIVATE KEY-----..."), - Subject: "user@example.com", - TokenURL: "https://provider.com/o/oauth2/token", - } - // Initiate an http.Client, the following GET request will be - // authorized and authenticated on the behalf of user@example.com. - client := conf.Client(oauth2.NoContext) - client.Get("...") -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/jwt/jwt_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/jwt/jwt_test.go deleted file mode 100644 index da922c3d0..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/jwt/jwt_test.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jwt - -import ( - "net/http" - "net/http/httptest" - "testing" - - "golang.org/x/oauth2" -) - -var dummyPrivateKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAx4fm7dngEmOULNmAs1IGZ9Apfzh+BkaQ1dzkmbUgpcoghucE -DZRnAGd2aPyB6skGMXUytWQvNYav0WTR00wFtX1ohWTfv68HGXJ8QXCpyoSKSSFY -fuP9X36wBSkSX9J5DVgiuzD5VBdzUISSmapjKm+DcbRALjz6OUIPEWi1Tjl6p5RK -1w41qdbmt7E5/kGhKLDuT7+M83g4VWhgIvaAXtnhklDAggilPPa8ZJ1IFe31lNlr -k4DRk38nc6sEutdf3RL7QoH7FBusI7uXV03DC6dwN1kP4GE7bjJhcRb/7jYt7CQ9 -/E9Exz3c0yAp0yrTg0Fwh+qxfH9dKwN52S7SBwIDAQABAoIBAQCaCs26K07WY5Jt -3a2Cw3y2gPrIgTCqX6hJs7O5ByEhXZ8nBwsWANBUe4vrGaajQHdLj5OKfsIDrOvn -2NI1MqflqeAbu/kR32q3tq8/Rl+PPiwUsW3E6Pcf1orGMSNCXxeducF2iySySzh3 -nSIhCG5uwJDWI7a4+9KiieFgK1pt/Iv30q1SQS8IEntTfXYwANQrfKUVMmVF9aIK -6/WZE2yd5+q3wVVIJ6jsmTzoDCX6QQkkJICIYwCkglmVy5AeTckOVwcXL0jqw5Kf -5/soZJQwLEyBoQq7Kbpa26QHq+CJONetPP8Ssy8MJJXBT+u/bSseMb3Zsr5cr43e -DJOhwsThAoGBAPY6rPKl2NT/K7XfRCGm1sbWjUQyDShscwuWJ5+kD0yudnT/ZEJ1 -M3+KS/iOOAoHDdEDi9crRvMl0UfNa8MAcDKHflzxg2jg/QI+fTBjPP5GOX0lkZ9g -z6VePoVoQw2gpPFVNPPTxKfk27tEzbaffvOLGBEih0Kb7HTINkW8rIlzAoGBAM9y -1yr+jvfS1cGFtNU+Gotoihw2eMKtIqR03Yn3n0PK1nVCDKqwdUqCypz4+ml6cxRK -J8+Pfdh7D+ZJd4LEG6Y4QRDLuv5OA700tUoSHxMSNn3q9As4+T3MUyYxWKvTeu3U -f2NWP9ePU0lV8ttk7YlpVRaPQmc1qwooBA/z/8AdAoGAW9x0HWqmRICWTBnpjyxx -QGlW9rQ9mHEtUotIaRSJ6K/F3cxSGUEkX1a3FRnp6kPLcckC6NlqdNgNBd6rb2rA -cPl/uSkZP42Als+9YMoFPU/xrrDPbUhu72EDrj3Bllnyb168jKLa4VBOccUvggxr -Dm08I1hgYgdN5huzs7y6GeUCgYEAj+AZJSOJ6o1aXS6rfV3mMRve9bQ9yt8jcKXw -5HhOCEmMtaSKfnOF1Ziih34Sxsb7O2428DiX0mV/YHtBnPsAJidL0SdLWIapBzeg -KHArByIRkwE6IvJvwpGMdaex1PIGhx5i/3VZL9qiq/ElT05PhIb+UXgoWMabCp84 -OgxDK20CgYAeaFo8BdQ7FmVX2+EEejF+8xSge6WVLtkaon8bqcn6P0O8lLypoOhd -mJAYH8WU+UAy9pecUnDZj14LAGNVmYcse8HFX71MoshnvCTFEPVo4rZxIAGwMpeJ -5jgQ3slYLpqrGlcbLgUXBUgzEO684Wk/UV9DFPlHALVqCfXQ9dpJPg== ------END RSA PRIVATE KEY-----`) - -func TestJWTFetch_JSONResponse(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{ - "access_token": "90d64460d14870c08c81352a05dedd3465940a7c", - "scope": "user", - "token_type": "bearer", - "expires_in": 3600 - }`)) - })) - defer ts.Close() - - conf := &Config{ - Email: "aaa@xxx.com", - PrivateKey: dummyPrivateKey, - TokenURL: ts.URL, - } - tok, err := conf.TokenSource(oauth2.NoContext).Token() - if err != nil { - t.Fatal(err) - } - if !tok.Valid() { - t.Errorf("Token invalid") - } - if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" { - t.Errorf("Unexpected access token, %#v", tok.AccessToken) - } - if tok.TokenType != "bearer" { - t.Errorf("Unexpected token type, %#v", tok.TokenType) - } - if tok.Expiry.IsZero() { - t.Errorf("Unexpected token expiry, %#v", tok.Expiry) - } - scope := tok.Extra("scope") - if scope != "user" { - t.Errorf("Unexpected value for scope: %v", scope) - } -} - -func TestJWTFetch_BadResponse(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"scope": "user", "token_type": "bearer"}`)) - })) - defer ts.Close() - - conf := &Config{ - Email: "aaa@xxx.com", - PrivateKey: dummyPrivateKey, - TokenURL: ts.URL, - } - tok, err := conf.TokenSource(oauth2.NoContext).Token() - if err != nil { - t.Fatal(err) - } - if tok == nil { - t.Fatalf("token is nil") - } - if tok.Valid() { - t.Errorf("token is valid. want invalid.") - } - if tok.AccessToken != "" { - t.Errorf("Unexpected non-empty access token %q.", tok.AccessToken) - } - if want := "bearer"; tok.TokenType != want { - t.Errorf("TokenType = %q; want %q", tok.TokenType, want) - } - scope := tok.Extra("scope") - if want := "user"; scope != want { - t.Errorf("token scope = %q; want %q", scope, want) - } -} - -func TestJWTFetch_BadResponseType(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token":123, "scope": "user", "token_type": "bearer"}`)) - })) - defer ts.Close() - conf := &Config{ - Email: "aaa@xxx.com", - PrivateKey: dummyPrivateKey, - TokenURL: ts.URL, - } - tok, err := conf.TokenSource(oauth2.NoContext).Token() - if err == nil { - t.Error("got a token; expected error") - if tok.AccessToken != "" { - t.Errorf("Unexpected access token, %#v.", tok.AccessToken) - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/linkedin/linkedin.go b/Godeps/_workspace/src/golang.org/x/oauth2/linkedin/linkedin.go deleted file mode 100644 index d93fded6a..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/linkedin/linkedin.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package linkedin provides constants for using OAuth2 to access LinkedIn. -package linkedin - -import ( - "golang.org/x/oauth2" -) - -// Endpoint is LinkedIn's OAuth 2.0 endpoint. -var Endpoint = oauth2.Endpoint{ - AuthURL: "https://www.linkedin.com/uas/oauth2/authorization", - TokenURL: "https://www.linkedin.com/uas/oauth2/accessToken", -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/oauth2_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/oauth2_test.go deleted file mode 100644 index 2f7d731c1..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/oauth2_test.go +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2 - -import ( - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "reflect" - "strconv" - "testing" - "time" - - "golang.org/x/net/context" -) - -type mockTransport struct { - rt func(req *http.Request) (resp *http.Response, err error) -} - -func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { - return t.rt(req) -} - -type mockCache struct { - token *Token - readErr error -} - -func (c *mockCache) ReadToken() (*Token, error) { - return c.token, c.readErr -} - -func (c *mockCache) WriteToken(*Token) { - // do nothing -} - -func newConf(url string) *Config { - return &Config{ - ClientID: "CLIENT_ID", - ClientSecret: "CLIENT_SECRET", - RedirectURL: "REDIRECT_URL", - Scopes: []string{"scope1", "scope2"}, - Endpoint: Endpoint{ - AuthURL: url + "/auth", - TokenURL: url + "/token", - }, - } -} - -func TestAuthCodeURL(t *testing.T) { - conf := newConf("server") - url := conf.AuthCodeURL("foo", AccessTypeOffline, ApprovalForce) - if url != "server/auth?access_type=offline&approval_prompt=force&client_id=CLIENT_ID&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=foo" { - t.Errorf("Auth code URL doesn't match the expected, found: %v", url) - } -} - -func TestAuthCodeURL_CustomParam(t *testing.T) { - conf := newConf("server") - param := SetAuthURLParam("foo", "bar") - url := conf.AuthCodeURL("baz", param) - if url != "server/auth?client_id=CLIENT_ID&foo=bar&redirect_uri=REDIRECT_URL&response_type=code&scope=scope1+scope2&state=baz" { - t.Errorf("Auth code URL doesn't match the expected, found: %v", url) - } -} - -func TestAuthCodeURL_Optional(t *testing.T) { - conf := &Config{ - ClientID: "CLIENT_ID", - Endpoint: Endpoint{ - AuthURL: "/auth-url", - TokenURL: "/token-url", - }, - } - url := conf.AuthCodeURL("") - if url != "/auth-url?client_id=CLIENT_ID&response_type=code" { - t.Fatalf("Auth code URL doesn't match the expected, found: %v", url) - } -} - -func TestExchangeRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() != "/token" { - t.Errorf("Unexpected exchange request URL, %v is found.", r.URL) - } - headerAuth := r.Header.Get("Authorization") - if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" { - t.Errorf("Unexpected authorization header, %v is found.", headerAuth) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Failed reading request body: %s.", err) - } - if string(body) != "client_id=CLIENT_ID&code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL&scope=scope1+scope2" { - t.Errorf("Unexpected exchange payload, %v is found.", string(body)) - } - w.Header().Set("Content-Type", "application/x-www-form-urlencoded") - w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer")) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.Exchange(NoContext, "exchange-code") - if err != nil { - t.Error(err) - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" { - t.Errorf("Unexpected access token, %#v.", tok.AccessToken) - } - if tok.TokenType != "bearer" { - t.Errorf("Unexpected token type, %#v.", tok.TokenType) - } - scope := tok.Extra("scope") - if scope != "user" { - t.Errorf("Unexpected value for scope: %v", scope) - } -} - -func TestExchangeRequest_JSONResponse(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() != "/token" { - t.Errorf("Unexpected exchange request URL, %v is found.", r.URL) - } - headerAuth := r.Header.Get("Authorization") - if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" { - t.Errorf("Unexpected authorization header, %v is found.", headerAuth) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Failed reading request body: %s.", err) - } - if string(body) != "client_id=CLIENT_ID&code=exchange-code&grant_type=authorization_code&redirect_uri=REDIRECT_URL&scope=scope1+scope2" { - t.Errorf("Unexpected exchange payload, %v is found.", string(body)) - } - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token": "90d64460d14870c08c81352a05dedd3465940a7c", "scope": "user", "token_type": "bearer", "expires_in": 86400}`)) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.Exchange(NoContext, "exchange-code") - if err != nil { - t.Error(err) - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" { - t.Errorf("Unexpected access token, %#v.", tok.AccessToken) - } - if tok.TokenType != "bearer" { - t.Errorf("Unexpected token type, %#v.", tok.TokenType) - } - scope := tok.Extra("scope") - if scope != "user" { - t.Errorf("Unexpected value for scope: %v", scope) - } -} - -const day = 24 * time.Hour - -func TestExchangeRequest_JSONResponse_Expiry(t *testing.T) { - seconds := int32(day.Seconds()) - jsonNumberType := reflect.TypeOf(json.Number("0")) - for _, c := range []struct { - expires string - expect error - }{ - {fmt.Sprintf(`"expires_in": %d`, seconds), nil}, - {fmt.Sprintf(`"expires_in": "%d"`, seconds), nil}, // PayPal case - {fmt.Sprintf(`"expires": %d`, seconds), nil}, // Facebook case - {`"expires": false`, &json.UnmarshalTypeError{Value: "bool", Type: jsonNumberType}}, // wrong type - {`"expires": {}`, &json.UnmarshalTypeError{Value: "object", Type: jsonNumberType}}, // wrong type - {`"expires": "zzz"`, &strconv.NumError{Func: "ParseInt", Num: "zzz", Err: strconv.ErrSyntax}}, // wrong value - } { - testExchangeRequest_JSONResponse_expiry(t, c.expires, c.expect) - } -} - -func testExchangeRequest_JSONResponse_expiry(t *testing.T, exp string, expect error) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(fmt.Sprintf(`{"access_token": "90d", "scope": "user", "token_type": "bearer", %s}`, exp))) - })) - defer ts.Close() - conf := newConf(ts.URL) - t1 := time.Now().Add(day) - tok, err := conf.Exchange(NoContext, "exchange-code") - t2 := time.Now().Add(day) - // Do a fmt.Sprint comparison so either side can be - // nil. fmt.Sprint just stringifies them to "", and no - // non-nil expected error ever stringifies as "", so this - // isn't terribly disgusting. We do this because Go 1.4 and - // Go 1.5 return a different deep value for - // json.UnmarshalTypeError. In Go 1.5, the - // json.UnmarshalTypeError contains a new field with a new - // non-zero value. Rather than ignore it here with reflect or - // add new files and +build tags, just look at the strings. - if fmt.Sprint(err) != fmt.Sprint(expect) { - t.Errorf("Error = %v; want %v", err, expect) - } - if err != nil { - return - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - expiry := tok.Expiry - if expiry.Before(t1) || expiry.After(t2) { - t.Errorf("Unexpected value for Expiry: %v (shold be between %v and %v)", expiry, t1, t2) - } -} - -func TestExchangeRequest_BadResponse(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"scope": "user", "token_type": "bearer"}`)) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.Exchange(NoContext, "code") - if err != nil { - t.Fatal(err) - } - if tok.AccessToken != "" { - t.Errorf("Unexpected access token, %#v.", tok.AccessToken) - } -} - -func TestExchangeRequest_BadResponseType(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token":123, "scope": "user", "token_type": "bearer"}`)) - })) - defer ts.Close() - conf := newConf(ts.URL) - _, err := conf.Exchange(NoContext, "exchange-code") - if err == nil { - t.Error("expected error from invalid access_token type") - } -} - -func TestExchangeRequest_NonBasicAuth(t *testing.T) { - tr := &mockTransport{ - rt: func(r *http.Request) (w *http.Response, err error) { - headerAuth := r.Header.Get("Authorization") - if headerAuth != "" { - t.Errorf("Unexpected authorization header, %v is found.", headerAuth) - } - return nil, errors.New("no response") - }, - } - c := &http.Client{Transport: tr} - conf := &Config{ - ClientID: "CLIENT_ID", - Endpoint: Endpoint{ - AuthURL: "https://accounts.google.com/auth", - TokenURL: "https://accounts.google.com/token", - }, - } - - ctx := context.WithValue(context.Background(), HTTPClient, c) - conf.Exchange(ctx, "code") -} - -func TestPasswordCredentialsTokenRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer r.Body.Close() - expected := "/token" - if r.URL.String() != expected { - t.Errorf("URL = %q; want %q", r.URL, expected) - } - headerAuth := r.Header.Get("Authorization") - expected = "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" - if headerAuth != expected { - t.Errorf("Authorization header = %q; want %q", headerAuth, expected) - } - headerContentType := r.Header.Get("Content-Type") - expected = "application/x-www-form-urlencoded" - if headerContentType != expected { - t.Errorf("Content-Type header = %q; want %q", headerContentType, expected) - } - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Failed reading request body: %s.", err) - } - expected = "client_id=CLIENT_ID&grant_type=password&password=password1&scope=scope1+scope2&username=user1" - if string(body) != expected { - t.Errorf("res.Body = %q; want %q", string(body), expected) - } - w.Header().Set("Content-Type", "application/x-www-form-urlencoded") - w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&scope=user&token_type=bearer")) - })) - defer ts.Close() - conf := newConf(ts.URL) - tok, err := conf.PasswordCredentialsToken(NoContext, "user1", "password1") - if err != nil { - t.Error(err) - } - if !tok.Valid() { - t.Fatalf("Token invalid. Got: %#v", tok) - } - expected := "90d64460d14870c08c81352a05dedd3465940a7c" - if tok.AccessToken != expected { - t.Errorf("AccessToken = %q; want %q", tok.AccessToken, expected) - } - expected = "bearer" - if tok.TokenType != expected { - t.Errorf("TokenType = %q; want %q", tok.TokenType, expected) - } -} - -func TestTokenRefreshRequest(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() == "/somethingelse" { - return - } - if r.URL.String() != "/token" { - t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, _ := ioutil.ReadAll(r.Body) - if string(body) != "client_id=CLIENT_ID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN" { - t.Errorf("Unexpected refresh token payload, %v is found.", string(body)) - } - })) - defer ts.Close() - conf := newConf(ts.URL) - c := conf.Client(NoContext, &Token{RefreshToken: "REFRESH_TOKEN"}) - c.Get(ts.URL + "/somethingelse") -} - -func TestFetchWithNoRefreshToken(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.String() == "/somethingelse" { - return - } - if r.URL.String() != "/token" { - t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL) - } - headerContentType := r.Header.Get("Content-Type") - if headerContentType != "application/x-www-form-urlencoded" { - t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType) - } - body, _ := ioutil.ReadAll(r.Body) - if string(body) != "client_id=CLIENT_ID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN" { - t.Errorf("Unexpected refresh token payload, %v is found.", string(body)) - } - })) - defer ts.Close() - conf := newConf(ts.URL) - c := conf.Client(NoContext, nil) - _, err := c.Get(ts.URL + "/somethingelse") - if err == nil { - t.Errorf("Fetch should return an error if no refresh token is set") - } -} - -func TestRefreshToken_RefreshTokenReplacement(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token":"ACCESS TOKEN", "scope": "user", "token_type": "bearer", "refresh_token": "NEW REFRESH TOKEN"}`)) - return - })) - defer ts.Close() - conf := newConf(ts.URL) - tkr := tokenRefresher{ - conf: conf, - ctx: NoContext, - refreshToken: "OLD REFRESH TOKEN", - } - tk, err := tkr.Token() - if err != nil { - t.Errorf("Unexpected refreshToken error returned: %v", err) - return - } - if tk.RefreshToken != tkr.refreshToken { - t.Errorf("tokenRefresher.refresh_token = %s; want %s", tkr.refreshToken, tk.RefreshToken) - } -} - -func TestConfigClientWithToken(t *testing.T) { - tok := &Token{ - AccessToken: "abc123", - } - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Authorization"), fmt.Sprintf("Bearer %s", tok.AccessToken); got != want { - t.Errorf("Authorization header = %q; want %q", got, want) - } - return - })) - defer ts.Close() - conf := newConf(ts.URL) - - c := conf.Client(NoContext, tok) - req, err := http.NewRequest("GET", ts.URL, nil) - if err != nil { - t.Error(err) - } - _, err = c.Do(req) - if err != nil { - t.Error(err) - } -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go b/Godeps/_workspace/src/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go deleted file mode 100644 index f0b66f97d..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package odnoklassniki provides constants for using OAuth2 to access Odnoklassniki. -package odnoklassniki - -import ( - "golang.org/x/oauth2" -) - -// Endpoint is Odnoklassniki's OAuth 2.0 endpoint. -var Endpoint = oauth2.Endpoint{ - AuthURL: "https://www.odnoklassniki.ru/oauth/authorize", - TokenURL: "https://api.odnoklassniki.ru/oauth/token.do", -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/paypal/paypal.go b/Godeps/_workspace/src/golang.org/x/oauth2/paypal/paypal.go deleted file mode 100644 index a99366b6e..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/paypal/paypal.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package paypal provides constants for using OAuth2 to access PayPal. -package paypal - -import ( - "golang.org/x/oauth2" -) - -// Endpoint is PayPal's OAuth 2.0 endpoint in live (production) environment. -var Endpoint = oauth2.Endpoint{ - AuthURL: "https://www.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize", - TokenURL: "https://api.paypal.com/v1/identity/openidconnect/tokenservice", -} - -// SandboxEndpoint is PayPal's OAuth 2.0 endpoint in sandbox (testing) environment. -var SandboxEndpoint = oauth2.Endpoint{ - AuthURL: "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize", - TokenURL: "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice", -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/token_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/token_test.go deleted file mode 100644 index 739eeb2a2..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/token_test.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2014 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package oauth2 - -import ( - "testing" - "time" -) - -func TestTokenExtra(t *testing.T) { - type testCase struct { - key string - val interface{} - want interface{} - } - const key = "extra-key" - cases := []testCase{ - {key: key, val: "abc", want: "abc"}, - {key: key, val: 123, want: 123}, - {key: key, val: "", want: ""}, - {key: "other-key", val: "def", want: nil}, - } - for _, tc := range cases { - extra := make(map[string]interface{}) - extra[tc.key] = tc.val - tok := &Token{raw: extra} - if got, want := tok.Extra(key), tc.want; got != want { - t.Errorf("Extra(%q) = %q; want %q", key, got, want) - } - } -} - -func TestTokenExpiry(t *testing.T) { - now := time.Now() - cases := []struct { - name string - tok *Token - want bool - }{ - {name: "12 seconds", tok: &Token{Expiry: now.Add(12 * time.Second)}, want: false}, - {name: "10 seconds", tok: &Token{Expiry: now.Add(expiryDelta)}, want: true}, - } - for _, tc := range cases { - if got, want := tc.tok.expired(), tc.want; got != want { - t.Errorf("expired (%q) = %v; want %v", tc.name, got, want) - } - } -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/transport_test.go b/Godeps/_workspace/src/golang.org/x/oauth2/transport_test.go deleted file mode 100644 index 35cb25ed5..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/transport_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package oauth2 - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" -) - -type tokenSource struct{ token *Token } - -func (t *tokenSource) Token() (*Token, error) { - return t.token, nil -} - -func TestTransportTokenSource(t *testing.T) { - ts := &tokenSource{ - token: &Token{ - AccessToken: "abc", - }, - } - tr := &Transport{ - Source: ts, - } - server := newMockServer(func(w http.ResponseWriter, r *http.Request) { - if r.Header.Get("Authorization") != "Bearer abc" { - t.Errorf("Transport doesn't set the Authorization header from the fetched token") - } - }) - defer server.Close() - client := http.Client{Transport: tr} - client.Get(server.URL) -} - -// Test for case-sensitive token types, per https://github.com/golang/oauth2/issues/113 -func TestTransportTokenSourceTypes(t *testing.T) { - const val = "abc" - tests := []struct { - key string - val string - want string - }{ - {key: "bearer", val: val, want: "Bearer abc"}, - {key: "mac", val: val, want: "MAC abc"}, - {key: "basic", val: val, want: "Basic abc"}, - } - for _, tc := range tests { - ts := &tokenSource{ - token: &Token{ - AccessToken: tc.val, - TokenType: tc.key, - }, - } - tr := &Transport{ - Source: ts, - } - server := newMockServer(func(w http.ResponseWriter, r *http.Request) { - if got, want := r.Header.Get("Authorization"), tc.want; got != want { - t.Errorf("Authorization header (%q) = %q; want %q", val, got, want) - } - }) - defer server.Close() - client := http.Client{Transport: tr} - client.Get(server.URL) - } -} - -func TestTokenValidNoAccessToken(t *testing.T) { - token := &Token{} - if token.Valid() { - t.Errorf("Token should not be valid with no access token") - } -} - -func TestExpiredWithExpiry(t *testing.T) { - token := &Token{ - Expiry: time.Now().Add(-5 * time.Hour), - } - if token.Valid() { - t.Errorf("Token should not be valid if it expired in the past") - } -} - -func newMockServer(handler func(w http.ResponseWriter, r *http.Request)) *httptest.Server { - return httptest.NewServer(http.HandlerFunc(handler)) -} diff --git a/Godeps/_workspace/src/golang.org/x/oauth2/vk/vk.go b/Godeps/_workspace/src/golang.org/x/oauth2/vk/vk.go deleted file mode 100644 index 00e929357..000000000 --- a/Godeps/_workspace/src/golang.org/x/oauth2/vk/vk.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The oauth2 Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package vk provides constants for using OAuth2 to access VK.com. -package vk - -import ( - "golang.org/x/oauth2" -) - -// Endpoint is VK's OAuth 2.0 endpoint. -var Endpoint = oauth2.Endpoint{ - AuthURL: "https://oauth.vk.com/authorize", - TokenURL: "https://oauth.vk.com/access_token", -} diff --git a/Godeps/_workspace/src/google.golang.org/api/gensupport/json_test.go b/Godeps/_workspace/src/google.golang.org/api/gensupport/json_test.go deleted file mode 100644 index b2f921913..000000000 --- a/Godeps/_workspace/src/google.golang.org/api/gensupport/json_test.go +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gensupport - -import ( - "encoding/json" - "reflect" - "testing" - - "google.golang.org/api/googleapi" -) - -type schema struct { - // Basic types - B bool `json:"b,omitempty"` - F float64 `json:"f,omitempty"` - I int64 `json:"i,omitempty"` - Istr int64 `json:"istr,omitempty,string"` - Str string `json:"str,omitempty"` - - // Pointers to basic types - PB *bool `json:"pb,omitempty"` - PF *float64 `json:"pf,omitempty"` - PI *int64 `json:"pi,omitempty"` - PIStr *int64 `json:"pistr,omitempty,string"` - PStr *string `json:"pstr,omitempty"` - - // Other types - Int64s googleapi.Int64s `json:"i64s,omitempty"` - S []int `json:"s,omitempty"` - M map[string]string `json:"m,omitempty"` - Any interface{} `json:"any,omitempty"` - Child *child `json:"child,omitempty"` - - ForceSendFields []string `json:"-"` -} - -type child struct { - B bool `json:"childbool,omitempty"` -} - -type testCase struct { - s schema - want string -} - -func TestBasics(t *testing.T) { - for _, tc := range []testCase{ - { - s: schema{}, - want: `{}`, - }, - { - s: schema{ - ForceSendFields: []string{"B", "F", "I", "Istr", "Str", "PB", "PF", "PI", "PIStr", "PStr"}, - }, - want: `{"b":false,"f":0.0,"i":0,"istr":"0","str":""}`, - }, - { - s: schema{ - B: true, - F: 1.2, - I: 1, - Istr: 2, - Str: "a", - PB: googleapi.Bool(true), - PF: googleapi.Float64(1.2), - PI: googleapi.Int64(int64(1)), - PIStr: googleapi.Int64(int64(2)), - PStr: googleapi.String("a"), - }, - want: `{"b":true,"f":1.2,"i":1,"istr":"2","str":"a","pb":true,"pf":1.2,"pi":1,"pistr":"2","pstr":"a"}`, - }, - { - s: schema{ - B: false, - F: 0.0, - I: 0, - Istr: 0, - Str: "", - PB: googleapi.Bool(false), - PF: googleapi.Float64(0.0), - PI: googleapi.Int64(int64(0)), - PIStr: googleapi.Int64(int64(0)), - PStr: googleapi.String(""), - }, - want: `{"pb":false,"pf":0.0,"pi":0,"pistr":"0","pstr":""}`, - }, - { - s: schema{ - B: false, - F: 0.0, - I: 0, - Istr: 0, - Str: "", - PB: googleapi.Bool(false), - PF: googleapi.Float64(0.0), - PI: googleapi.Int64(int64(0)), - PIStr: googleapi.Int64(int64(0)), - PStr: googleapi.String(""), - ForceSendFields: []string{"B", "F", "I", "Istr", "Str", "PB", "PF", "PI", "PIStr", "PStr"}, - }, - want: `{"b":false,"f":0.0,"i":0,"istr":"0","str":"","pb":false,"pf":0.0,"pi":0,"pistr":"0","pstr":""}`, - }, - } { - checkMarshalJSON(t, tc) - } -} - -func TestSliceFields(t *testing.T) { - for _, tc := range []testCase{ - { - s: schema{}, - want: `{}`, - }, - { - s: schema{S: []int{}, Int64s: googleapi.Int64s{}}, - want: `{}`, - }, - { - s: schema{S: []int{1}, Int64s: googleapi.Int64s{1}}, - want: `{"s":[1],"i64s":["1"]}`, - }, - { - s: schema{ - ForceSendFields: []string{"S", "Int64s"}, - }, - want: `{"s":[],"i64s":[]}`, - }, - { - s: schema{ - S: []int{}, - Int64s: googleapi.Int64s{}, - ForceSendFields: []string{"S", "Int64s"}, - }, - want: `{"s":[],"i64s":[]}`, - }, - { - s: schema{ - S: []int{1}, - Int64s: googleapi.Int64s{1}, - ForceSendFields: []string{"S", "Int64s"}, - }, - want: `{"s":[1],"i64s":["1"]}`, - }, - } { - checkMarshalJSON(t, tc) - } -} - -func TestMapField(t *testing.T) { - for _, tc := range []testCase{ - { - s: schema{}, - want: `{}`, - }, - { - s: schema{M: make(map[string]string)}, - want: `{}`, - }, - { - s: schema{M: map[string]string{"a": "b"}}, - want: `{"m":{"a":"b"}}`, - }, - { - s: schema{ - ForceSendFields: []string{"M"}, - }, - want: `{"m":{}}`, - }, - { - s: schema{ - M: make(map[string]string), - ForceSendFields: []string{"M"}, - }, - want: `{"m":{}}`, - }, - { - s: schema{ - M: map[string]string{"a": "b"}, - ForceSendFields: []string{"M"}, - }, - want: `{"m":{"a":"b"}}`, - }, - } { - checkMarshalJSON(t, tc) - } -} - -type anyType struct { - Field int -} - -func (a anyType) MarshalJSON() ([]byte, error) { - return []byte(`"anyType value"`), nil -} - -func TestAnyField(t *testing.T) { - // ForceSendFields has no effect on nil interfaces and interfaces that contain nil pointers. - var nilAny *anyType - for _, tc := range []testCase{ - { - s: schema{}, - want: `{}`, - }, - { - s: schema{Any: nilAny}, - want: `{"any": null}`, - }, - { - s: schema{Any: &anyType{}}, - want: `{"any":"anyType value"}`, - }, - { - s: schema{Any: anyType{}}, - want: `{"any":"anyType value"}`, - }, - { - s: schema{ - ForceSendFields: []string{"Any"}, - }, - want: `{}`, - }, - { - s: schema{ - Any: nilAny, - ForceSendFields: []string{"Any"}, - }, - want: `{"any": null}`, - }, - { - s: schema{ - Any: &anyType{}, - ForceSendFields: []string{"Any"}, - }, - want: `{"any":"anyType value"}`, - }, - { - s: schema{ - Any: anyType{}, - ForceSendFields: []string{"Any"}, - }, - want: `{"any":"anyType value"}`, - }, - } { - checkMarshalJSON(t, tc) - } -} - -func TestSubschema(t *testing.T) { - // Subschemas are always stored as pointers, so ForceSendFields has no effect on them. - for _, tc := range []testCase{ - { - s: schema{}, - want: `{}`, - }, - { - s: schema{ - ForceSendFields: []string{"Child"}, - }, - want: `{}`, - }, - { - s: schema{Child: &child{}}, - want: `{"child":{}}`, - }, - { - s: schema{ - Child: &child{}, - ForceSendFields: []string{"Child"}, - }, - want: `{"child":{}}`, - }, - { - s: schema{Child: &child{B: true}}, - want: `{"child":{"childbool":true}}`, - }, - - { - s: schema{ - Child: &child{B: true}, - ForceSendFields: []string{"Child"}, - }, - want: `{"child":{"childbool":true}}`, - }, - } { - checkMarshalJSON(t, tc) - } -} - -// checkMarshalJSON verifies that calling schemaToMap on tc.s yields a result which is equivalent to tc.want. -func checkMarshalJSON(t *testing.T, tc testCase) { - doCheckMarshalJSON(t, tc.s, tc.s.ForceSendFields, tc.want) - if len(tc.s.ForceSendFields) == 0 { - // verify that the code path used when ForceSendFields - // is non-empty produces the same output as the fast - // path that is used when it is empty. - doCheckMarshalJSON(t, tc.s, []string{"dummy"}, tc.want) - } -} - -func doCheckMarshalJSON(t *testing.T, s schema, forceSendFields []string, wantJSON string) { - encoded, err := MarshalJSON(s, forceSendFields) - if err != nil { - t.Fatalf("encoding json:\n got err: %v", err) - } - - // The expected and obtained JSON can differ in field ordering, so unmarshal before comparing. - var got interface{} - var want interface{} - err = json.Unmarshal(encoded, &got) - if err != nil { - t.Fatalf("decoding json:\n got err: %v", err) - } - err = json.Unmarshal([]byte(wantJSON), &want) - if err != nil { - t.Fatalf("decoding json:\n got err: %v", err) - } - if !reflect.DeepEqual(got, want) { - t.Errorf("schemaToMap:\ngot :%s\nwant:%s", got, want) - } -} - -func TestParseJSONTag(t *testing.T) { - for _, tc := range []struct { - tag string - want jsonTag - }{ - { - tag: "-", - want: jsonTag{ignore: true}, - }, { - tag: "name,omitempty", - want: jsonTag{apiName: "name"}, - }, { - tag: "name,omitempty,string", - want: jsonTag{apiName: "name", stringFormat: true}, - }, - } { - got, err := parseJSONTag(tc.tag) - if err != nil { - t.Fatalf("parsing json:\n got err: %v\ntag: %q", err, tc.tag) - } - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("parseJSONTage:\ngot :%s\nwant:%s", got, tc.want) - } - } -} -func TestParseMalformedJSONTag(t *testing.T) { - for _, tag := range []string{ - "", - "name", - "name,", - "name,blah", - "name,blah,string", - ",omitempty", - ",omitempty,string", - "name,omitempty,string,blah", - } { - _, err := parseJSONTag(tag) - if err == nil { - t.Fatalf("parsing json: expected err, got nil for tag: %v", tag) - } - } -} diff --git a/Godeps/_workspace/src/google.golang.org/api/gensupport/media_test.go b/Godeps/_workspace/src/google.golang.org/api/gensupport/media_test.go deleted file mode 100644 index 72edb453e..000000000 --- a/Godeps/_workspace/src/google.golang.org/api/gensupport/media_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gensupport - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "reflect" - "testing" -) - -// errReader reads out of a buffer until it is empty, then returns the specified error. -type errReader struct { - buf []byte - err error -} - -var errBang error = errors.New("bang") - -func (er *errReader) Read(p []byte) (int, error) { - if len(er.buf) == 0 { - if er.err == nil { - return 0, io.EOF - } - return 0, er.err - } - n := copy(p, er.buf) - er.buf = er.buf[n:] - return n, nil -} - -func TestAll(t *testing.T) { - type testCase struct { - data []byte // the data to read from the Reader - finalErr error // error to return after data has been read - - wantContentType string - wantContentTypeResult bool - } - - for _, tc := range []testCase{ - { - data: []byte{0, 0, 0, 0}, - finalErr: nil, - wantContentType: "application/octet-stream", - wantContentTypeResult: true, - }, - { - data: []byte(""), - finalErr: nil, - wantContentType: "text/plain; charset=utf-8", - wantContentTypeResult: true, - }, - { - data: []byte(""), - finalErr: errBang, - wantContentType: "text/plain; charset=utf-8", - wantContentTypeResult: false, - }, - { - data: []byte("abc"), - finalErr: nil, - wantContentType: "text/plain; charset=utf-8", - wantContentTypeResult: true, - }, - { - data: []byte("abc"), - finalErr: errBang, - wantContentType: "text/plain; charset=utf-8", - wantContentTypeResult: false, - }, - // The following examples contain more bytes than are buffered for sniffing. - { - data: bytes.Repeat([]byte("a"), 513), - finalErr: nil, - wantContentType: "text/plain; charset=utf-8", - wantContentTypeResult: true, - }, - { - data: bytes.Repeat([]byte("a"), 513), - finalErr: errBang, - wantContentType: "text/plain; charset=utf-8", - wantContentTypeResult: true, // true because error is after first 512 bytes. - }, - } { - er := &errReader{buf: tc.data, err: tc.finalErr} - - sct := NewContentSniffer(er) - - // Even if was an error during the first 512 bytes, we should still be able to read those bytes. - buf, err := ioutil.ReadAll(sct) - - if !reflect.DeepEqual(buf, tc.data) { - t.Fatalf("Failed reading buffer: got: %q; want:%q", buf, tc.data) - } - - if err != tc.finalErr { - t.Fatalf("Reading buffer error: got: %v; want: %v", err, tc.finalErr) - } - - ct, ok := sct.ContentType() - if ok != tc.wantContentTypeResult { - t.Fatalf("Content type result got: %v; want: %v", ok, tc.wantContentTypeResult) - } - if ok && ct != tc.wantContentType { - t.Fatalf("Content type got: %q; want: %q", ct, tc.wantContentType) - } - } -} diff --git a/Godeps/_workspace/src/google.golang.org/api/googleapi/googleapi_test.go b/Godeps/_workspace/src/google.golang.org/api/googleapi/googleapi_test.go deleted file mode 100644 index 75d33ea09..000000000 --- a/Godeps/_workspace/src/google.golang.org/api/googleapi/googleapi_test.go +++ /dev/null @@ -1,599 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package googleapi - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "os" - "reflect" - "regexp" - "strconv" - "strings" - "testing" - "time" - - "golang.org/x/net/context" -) - -type SetOpaqueTest struct { - in *url.URL - wantRequestURI string -} - -var setOpaqueTests = []SetOpaqueTest{ - // no path - { - &url.URL{ - Scheme: "http", - Host: "www.golang.org", - }, - "http://www.golang.org", - }, - // path - { - &url.URL{ - Scheme: "http", - Host: "www.golang.org", - Path: "/", - }, - "http://www.golang.org/", - }, - // file with hex escaping - { - &url.URL{ - Scheme: "https", - Host: "www.golang.org", - Path: "/file%20one&two", - }, - "https://www.golang.org/file%20one&two", - }, - // query - { - &url.URL{ - Scheme: "http", - Host: "www.golang.org", - Path: "/", - RawQuery: "q=go+language", - }, - "http://www.golang.org/?q=go+language", - }, - // file with hex escaping in path plus query - { - &url.URL{ - Scheme: "https", - Host: "www.golang.org", - Path: "/file%20one&two", - RawQuery: "q=go+language", - }, - "https://www.golang.org/file%20one&two?q=go+language", - }, - // query with hex escaping - { - &url.URL{ - Scheme: "http", - Host: "www.golang.org", - Path: "/", - RawQuery: "q=go%20language", - }, - "http://www.golang.org/?q=go%20language", - }, -} - -// prefixTmpl is a template for the expected prefix of the output of writing -// an HTTP request. -const prefixTmpl = "GET %v HTTP/1.1\r\nHost: %v\r\n" - -func TestSetOpaque(t *testing.T) { - for _, test := range setOpaqueTests { - u := *test.in - SetOpaque(&u) - - w := &bytes.Buffer{} - r := &http.Request{URL: &u} - if err := r.Write(w); err != nil { - t.Errorf("write request: %v", err) - continue - } - - prefix := fmt.Sprintf(prefixTmpl, test.wantRequestURI, test.in.Host) - if got := string(w.Bytes()); !strings.HasPrefix(got, prefix) { - t.Errorf("got %q expected prefix %q", got, prefix) - } - } -} - -type ExpandTest struct { - in string - expansions map[string]string - want string -} - -var expandTests = []ExpandTest{ - // no expansions - { - "http://www.golang.org/", - map[string]string{}, - "http://www.golang.org/", - }, - // one expansion, no escaping - { - "http://www.golang.org/{bucket}/delete", - map[string]string{ - "bucket": "red", - }, - "http://www.golang.org/red/delete", - }, - // one expansion, with hex escapes - { - "http://www.golang.org/{bucket}/delete", - map[string]string{ - "bucket": "red/blue", - }, - "http://www.golang.org/red%2Fblue/delete", - }, - // one expansion, with space - { - "http://www.golang.org/{bucket}/delete", - map[string]string{ - "bucket": "red or blue", - }, - "http://www.golang.org/red%20or%20blue/delete", - }, - // expansion not found - { - "http://www.golang.org/{object}/delete", - map[string]string{ - "bucket": "red or blue", - }, - "http://www.golang.org//delete", - }, - // multiple expansions - { - "http://www.golang.org/{one}/{two}/{three}/get", - map[string]string{ - "one": "ONE", - "two": "TWO", - "three": "THREE", - }, - "http://www.golang.org/ONE/TWO/THREE/get", - }, - // utf-8 characters - { - "http://www.golang.org/{bucket}/get", - map[string]string{ - "bucket": "£100", - }, - "http://www.golang.org/%C2%A3100/get", - }, - // punctuations - { - "http://www.golang.org/{bucket}/get", - map[string]string{ - "bucket": `/\@:,.`, - }, - "http://www.golang.org/%2F%5C%40%3A%2C./get", - }, - // mis-matched brackets - { - "http://www.golang.org/{bucket/get", - map[string]string{ - "bucket": "red", - }, - "http://www.golang.org/{bucket/get", - }, - // "+" prefix for suppressing escape - // See also: http://tools.ietf.org/html/rfc6570#section-3.2.3 - { - "http://www.golang.org/{+topic}", - map[string]string{ - "topic": "/topics/myproject/mytopic", - }, - // The double slashes here look weird, but it's intentional - "http://www.golang.org//topics/myproject/mytopic", - }, -} - -func TestExpand(t *testing.T) { - for i, test := range expandTests { - u := url.URL{ - Path: test.in, - } - Expand(&u, test.expansions) - got := u.Path - if got != test.want { - t.Errorf("got %q expected %q in test %d", got, test.want, i+1) - } - } -} - -type CheckResponseTest struct { - in *http.Response - bodyText string - want error - errText string -} - -var checkResponseTests = []CheckResponseTest{ - { - &http.Response{ - StatusCode: http.StatusOK, - }, - "", - nil, - "", - }, - { - &http.Response{ - StatusCode: http.StatusInternalServerError, - }, - `{"error":{}}`, - &Error{ - Code: http.StatusInternalServerError, - Body: `{"error":{}}`, - }, - `googleapi: got HTTP response code 500 with body: {"error":{}}`, - }, - { - &http.Response{ - StatusCode: http.StatusNotFound, - }, - `{"error":{"message":"Error message for StatusNotFound."}}`, - &Error{ - Code: http.StatusNotFound, - Message: "Error message for StatusNotFound.", - Body: `{"error":{"message":"Error message for StatusNotFound."}}`, - }, - "googleapi: Error 404: Error message for StatusNotFound.", - }, - { - &http.Response{ - StatusCode: http.StatusBadRequest, - }, - `{"error":"invalid_token","error_description":"Invalid Value"}`, - &Error{ - Code: http.StatusBadRequest, - Body: `{"error":"invalid_token","error_description":"Invalid Value"}`, - }, - `googleapi: got HTTP response code 400 with body: {"error":"invalid_token","error_description":"Invalid Value"}`, - }, - { - &http.Response{ - StatusCode: http.StatusBadRequest, - }, - `{"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}`, - &Error{ - Code: http.StatusBadRequest, - Errors: []ErrorItem{ - { - Reason: "keyInvalid", - Message: "Bad Request", - }, - }, - Body: `{"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}`, - Message: "Bad Request", - }, - "googleapi: Error 400: Bad Request, keyInvalid", - }, -} - -func TestCheckResponse(t *testing.T) { - for _, test := range checkResponseTests { - res := test.in - if test.bodyText != "" { - res.Body = ioutil.NopCloser(strings.NewReader(test.bodyText)) - } - g := CheckResponse(res) - if !reflect.DeepEqual(g, test.want) { - t.Errorf("CheckResponse: got %v, want %v", g, test.want) - gotJson, err := json.Marshal(g) - if err != nil { - t.Error(err) - } - wantJson, err := json.Marshal(test.want) - if err != nil { - t.Error(err) - } - t.Errorf("json(got): %q\njson(want): %q", string(gotJson), string(wantJson)) - } - if g != nil && g.Error() != test.errText { - t.Errorf("CheckResponse: unexpected error message.\nGot: %q\nwant: %q", g, test.errText) - } - } -} - -type VariantPoint struct { - Type string - Coordinates []float64 -} - -type VariantTest struct { - in map[string]interface{} - result bool - want VariantPoint -} - -var coords = []interface{}{1.0, 2.0} - -var variantTests = []VariantTest{ - { - in: map[string]interface{}{ - "type": "Point", - "coordinates": coords, - }, - result: true, - want: VariantPoint{ - Type: "Point", - Coordinates: []float64{1.0, 2.0}, - }, - }, - { - in: map[string]interface{}{ - "type": "Point", - "bogus": coords, - }, - result: true, - want: VariantPoint{ - Type: "Point", - }, - }, -} - -func TestVariantType(t *testing.T) { - for _, test := range variantTests { - if g := VariantType(test.in); g != test.want.Type { - t.Errorf("VariantType(%v): got %v, want %v", test.in, g, test.want.Type) - } - } -} - -func TestConvertVariant(t *testing.T) { - for _, test := range variantTests { - g := VariantPoint{} - r := ConvertVariant(test.in, &g) - if r != test.result { - t.Errorf("ConvertVariant(%v): got %v, want %v", test.in, r, test.result) - } - if !reflect.DeepEqual(g, test.want) { - t.Errorf("ConvertVariant(%v): got %v, want %v", test.in, g, test.want) - } - } -} - -type unexpectedReader struct{} - -func (unexpectedReader) Read([]byte) (int, error) { - return 0, fmt.Errorf("unexpected read in test.") -} - -var contentRangeRE = regexp.MustCompile(`^bytes (\d+)\-(\d+)/(\d+)$`) - -func (t *testTransport) RoundTrip(req *http.Request) (*http.Response, error) { - t.req = req - if rng := req.Header.Get("Content-Range"); rng != "" && !strings.HasPrefix(rng, "bytes */") { // Read the data - m := contentRangeRE.FindStringSubmatch(rng) - if len(m) != 4 { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - start, err := strconv.ParseInt(m[1], 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - end, err := strconv.ParseInt(m[2], 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - totalSize, err := strconv.ParseInt(m[3], 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - partialSize := end - start + 1 - t.buf, err = ioutil.ReadAll(req.Body) - if err != nil || int64(len(t.buf)) != partialSize { - return nil, fmt.Errorf("unable to read %v bytes from request data, n=%v: %v", partialSize, len(t.buf), err) - } - if totalSize == end+1 { - t.statusCode = 200 // signify completion of transfer - } - } - f := ioutil.NopCloser(unexpectedReader{}) - res := &http.Response{ - Body: f, - StatusCode: t.statusCode, - Header: http.Header{}, - } - if t.rangeVal != "" { - res.Header.Set("Range", t.rangeVal) - } - return res, nil -} - -type testTransport struct { - req *http.Request - statusCode int - rangeVal string - want int64 - buf []byte -} - -var statusTests = []*testTransport{ - &testTransport{statusCode: 308, want: 0}, - &testTransport{statusCode: 308, rangeVal: "bytes=0-0", want: 1}, - &testTransport{statusCode: 308, rangeVal: "bytes=0-42", want: 43}, -} - -func TestTransferStatus(t *testing.T) { - ctx := context.Background() - for _, tr := range statusTests { - rx := &ResumableUpload{ - Client: &http.Client{Transport: tr}, - } - g, _, err := rx.transferStatus(ctx) - if err != nil { - t.Error(err) - } - if g != tr.want { - t.Errorf("transferStatus got %v, want %v", g, tr.want) - } - } -} - -func (t *interruptedTransport) RoundTrip(req *http.Request) (*http.Response, error) { - t.req = req - if rng := req.Header.Get("Content-Range"); rng != "" && !strings.HasPrefix(rng, "bytes */") { - t.interruptCount += 1 - if t.interruptCount%7 == 0 { // Respond with a "service unavailable" error - res := &http.Response{ - StatusCode: http.StatusServiceUnavailable, - Header: http.Header{}, - } - t.rangeVal = fmt.Sprintf("bytes=0-%v", len(t.buf)-1) // Set the response for next time - return res, nil - } - m := contentRangeRE.FindStringSubmatch(rng) - if len(m) != 4 { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - start, err := strconv.ParseInt(m[1], 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - end, err := strconv.ParseInt(m[2], 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - totalSize, err := strconv.ParseInt(m[3], 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to parse content range: %v", rng) - } - partialSize := end - start + 1 - buf, err := ioutil.ReadAll(req.Body) - if err != nil || int64(len(buf)) != partialSize { - return nil, fmt.Errorf("unable to read %v bytes from request data, n=%v: %v", partialSize, len(buf), err) - } - t.buf = append(t.buf, buf...) - if totalSize == end+1 { - t.statusCode = 200 // signify completion of transfer - } - } - f := ioutil.NopCloser(unexpectedReader{}) - res := &http.Response{ - Body: f, - StatusCode: t.statusCode, - Header: http.Header{}, - } - if t.rangeVal != "" { - res.Header.Set("Range", t.rangeVal) - } - return res, nil -} - -type interruptedTransport struct { - req *http.Request - statusCode int - rangeVal string - interruptCount int - buf []byte - progressUpdates []int64 -} - -func (tr *interruptedTransport) ProgressUpdate(current int64) { - tr.progressUpdates = append(tr.progressUpdates, current) -} - -func TestInterruptedTransferChunks(t *testing.T) { - f, err := os.Open("googleapi.go") - if err != nil { - t.Fatalf("unable to open googleapi.go: %v", err) - } - defer f.Close() - slurp, err := ioutil.ReadAll(f) - if err != nil { - t.Fatalf("unable to slurp file: %v", err) - } - st, err := f.Stat() - if err != nil { - t.Fatalf("unable to stat googleapi.go: %v", err) - } - tr := &interruptedTransport{ - statusCode: 308, - buf: make([]byte, 0, st.Size()), - } - oldChunkSize := chunkSize - defer func() { chunkSize = oldChunkSize }() - chunkSize = 100 // override to process small chunks for test. - - sleep = func(time.Duration) {} // override time.Sleep - rx := &ResumableUpload{ - Client: &http.Client{Transport: tr}, - Media: f, - MediaType: "text/plain", - ContentLength: st.Size(), - Callback: tr.ProgressUpdate, - } - res, err := rx.Upload(context.Background()) - if err != nil || res == nil || res.StatusCode != http.StatusOK { - if res == nil { - t.Errorf("transferChunks not successful, res=nil: %v", err) - } else { - t.Errorf("transferChunks not successful, statusCode=%v: %v", res.StatusCode, err) - } - } - if len(tr.buf) != len(slurp) || bytes.Compare(tr.buf, slurp) != 0 { - t.Errorf("transferred file corrupted:\ngot %s\nwant %s", tr.buf, slurp) - } - want := []int64{} - for i := chunkSize; i <= st.Size(); i += chunkSize { - want = append(want, i) - } - if st.Size()%chunkSize != 0 { - want = append(want, st.Size()) - } - if !reflect.DeepEqual(tr.progressUpdates, want) { - t.Errorf("progress update error, got %v, want %v", tr.progressUpdates, want) - } -} - -func TestCancelUpload(t *testing.T) { - f, err := os.Open("googleapi.go") - if err != nil { - t.Fatalf("unable to open googleapi.go: %v", err) - } - defer f.Close() - st, err := f.Stat() - if err != nil { - t.Fatalf("unable to stat googleapi.go: %v", err) - } - tr := &interruptedTransport{ - statusCode: 308, - buf: make([]byte, 0, st.Size()), - } - oldChunkSize := chunkSize - defer func() { chunkSize = oldChunkSize }() - chunkSize = 100 // override to process small chunks for test. - - sleep = func(time.Duration) {} // override time.Sleep - rx := &ResumableUpload{ - Client: &http.Client{Transport: tr}, - Media: f, - MediaType: "text/plain", - ContentLength: st.Size(), - Callback: tr.ProgressUpdate, - } - ctx, cancelFunc := context.WithCancel(context.Background()) - cancelFunc() // stop the upload that hasn't started yet - res, err := rx.Upload(ctx) - if err == nil || res == nil || res.StatusCode != http.StatusRequestTimeout { - if res == nil { - t.Errorf("transferChunks not successful, got res=nil, err=%v, want StatusRequestTimeout", err) - } else { - t.Errorf("transferChunks not successful, got statusCode=%v, err=%v, want StatusRequestTimeout", res.StatusCode, err) - } - } -} diff --git a/Godeps/_workspace/src/google.golang.org/api/googleapi/transport/apikey.go b/Godeps/_workspace/src/google.golang.org/api/googleapi/transport/apikey.go deleted file mode 100644 index eca1ea250..000000000 --- a/Godeps/_workspace/src/google.golang.org/api/googleapi/transport/apikey.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package transport contains HTTP transports used to make -// authenticated API requests. -package transport - -import ( - "errors" - "net/http" -) - -// APIKey is an HTTP Transport which wraps an underlying transport and -// appends an API Key "key" parameter to the URL of outgoing requests. -type APIKey struct { - // Key is the API Key to set on requests. - Key string - - // Transport is the underlying HTTP transport. - // If nil, http.DefaultTransport is used. - Transport http.RoundTripper -} - -func (t *APIKey) RoundTrip(req *http.Request) (*http.Response, error) { - rt := t.Transport - if rt == nil { - rt = http.DefaultTransport - if rt == nil { - return nil, errors.New("googleapi/transport: no Transport specified or available") - } - } - newReq := *req - args := newReq.URL.Query() - args.Set("key", t.Key) - newReq.URL.RawQuery = args.Encode() - return rt.RoundTrip(&newReq) -} diff --git a/Godeps/_workspace/src/google.golang.org/api/googleapi/types_test.go b/Godeps/_workspace/src/google.golang.org/api/googleapi/types_test.go deleted file mode 100644 index a6b204515..000000000 --- a/Godeps/_workspace/src/google.golang.org/api/googleapi/types_test.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package googleapi - -import ( - "encoding/json" - "reflect" - "testing" -) - -func TestTypes(t *testing.T) { - type T struct { - I32 Int32s - I64 Int64s - U32 Uint32s - U64 Uint64s - F64 Float64s - } - v := &T{ - I32: Int32s{-1, 2, 3}, - I64: Int64s{-1, 2, 1 << 33}, - U32: Uint32s{1, 2}, - U64: Uint64s{1, 2, 1 << 33}, - F64: Float64s{1.5, 3.33}, - } - got, err := json.Marshal(v) - if err != nil { - t.Fatal(err) - } - want := `{"I32":["-1","2","3"],"I64":["-1","2","8589934592"],"U32":["1","2"],"U64":["1","2","8589934592"],"F64":["1.5","3.33"]}` - if string(got) != want { - t.Fatalf("Marshal mismatch.\n got: %s\nwant: %s\n", got, want) - } - - v2 := new(T) - if err := json.Unmarshal(got, v2); err != nil { - t.Fatalf("Unmarshal: %v", err) - } - if !reflect.DeepEqual(v, v2) { - t.Fatalf("Unmarshal didn't produce same results.\n got: %#v\nwant: %#v\n", v, v2) - } -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go b/Godeps/_workspace/src/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go deleted file mode 100644 index 9cb9be528..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/datastore/datastore_v1.pb.go +++ /dev/null @@ -1,1633 +0,0 @@ -// Code generated by protoc-gen-go. -// source: datastore_v1.proto -// DO NOT EDIT! - -/* -Package datastore is a generated protocol buffer package. - -It is generated from these files: - datastore_v1.proto - -It has these top-level messages: - PartitionId - Key - Value - Property - Entity - EntityResult - Query - KindExpression - PropertyReference - PropertyExpression - PropertyOrder - Filter - CompositeFilter - PropertyFilter - GqlQuery - GqlQueryArg - QueryResultBatch - Mutation - MutationResult - ReadOptions - LookupRequest - LookupResponse - RunQueryRequest - RunQueryResponse - BeginTransactionRequest - BeginTransactionResponse - RollbackRequest - RollbackResponse - CommitRequest - CommitResponse - AllocateIdsRequest - AllocateIdsResponse -*/ -package datastore - -import proto "github.com/golang/protobuf/proto" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = math.Inf - -// Specifies what data the 'entity' field contains. -// A ResultType is either implied (for example, in LookupResponse.found it -// is always FULL) or specified by context (for example, in message -// QueryResultBatch, field 'entity_result_type' specifies a ResultType -// for all the values in field 'entity_result'). -type EntityResult_ResultType int32 - -const ( - EntityResult_FULL EntityResult_ResultType = 1 - EntityResult_PROJECTION EntityResult_ResultType = 2 - // The entity may have no key. - // A property value may have meaning 18. - EntityResult_KEY_ONLY EntityResult_ResultType = 3 -) - -var EntityResult_ResultType_name = map[int32]string{ - 1: "FULL", - 2: "PROJECTION", - 3: "KEY_ONLY", -} -var EntityResult_ResultType_value = map[string]int32{ - "FULL": 1, - "PROJECTION": 2, - "KEY_ONLY": 3, -} - -func (x EntityResult_ResultType) Enum() *EntityResult_ResultType { - p := new(EntityResult_ResultType) - *p = x - return p -} -func (x EntityResult_ResultType) String() string { - return proto.EnumName(EntityResult_ResultType_name, int32(x)) -} -func (x *EntityResult_ResultType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(EntityResult_ResultType_value, data, "EntityResult_ResultType") - if err != nil { - return err - } - *x = EntityResult_ResultType(value) - return nil -} - -type PropertyExpression_AggregationFunction int32 - -const ( - PropertyExpression_FIRST PropertyExpression_AggregationFunction = 1 -) - -var PropertyExpression_AggregationFunction_name = map[int32]string{ - 1: "FIRST", -} -var PropertyExpression_AggregationFunction_value = map[string]int32{ - "FIRST": 1, -} - -func (x PropertyExpression_AggregationFunction) Enum() *PropertyExpression_AggregationFunction { - p := new(PropertyExpression_AggregationFunction) - *p = x - return p -} -func (x PropertyExpression_AggregationFunction) String() string { - return proto.EnumName(PropertyExpression_AggregationFunction_name, int32(x)) -} -func (x *PropertyExpression_AggregationFunction) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PropertyExpression_AggregationFunction_value, data, "PropertyExpression_AggregationFunction") - if err != nil { - return err - } - *x = PropertyExpression_AggregationFunction(value) - return nil -} - -type PropertyOrder_Direction int32 - -const ( - PropertyOrder_ASCENDING PropertyOrder_Direction = 1 - PropertyOrder_DESCENDING PropertyOrder_Direction = 2 -) - -var PropertyOrder_Direction_name = map[int32]string{ - 1: "ASCENDING", - 2: "DESCENDING", -} -var PropertyOrder_Direction_value = map[string]int32{ - "ASCENDING": 1, - "DESCENDING": 2, -} - -func (x PropertyOrder_Direction) Enum() *PropertyOrder_Direction { - p := new(PropertyOrder_Direction) - *p = x - return p -} -func (x PropertyOrder_Direction) String() string { - return proto.EnumName(PropertyOrder_Direction_name, int32(x)) -} -func (x *PropertyOrder_Direction) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PropertyOrder_Direction_value, data, "PropertyOrder_Direction") - if err != nil { - return err - } - *x = PropertyOrder_Direction(value) - return nil -} - -type CompositeFilter_Operator int32 - -const ( - CompositeFilter_AND CompositeFilter_Operator = 1 -) - -var CompositeFilter_Operator_name = map[int32]string{ - 1: "AND", -} -var CompositeFilter_Operator_value = map[string]int32{ - "AND": 1, -} - -func (x CompositeFilter_Operator) Enum() *CompositeFilter_Operator { - p := new(CompositeFilter_Operator) - *p = x - return p -} -func (x CompositeFilter_Operator) String() string { - return proto.EnumName(CompositeFilter_Operator_name, int32(x)) -} -func (x *CompositeFilter_Operator) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(CompositeFilter_Operator_value, data, "CompositeFilter_Operator") - if err != nil { - return err - } - *x = CompositeFilter_Operator(value) - return nil -} - -type PropertyFilter_Operator int32 - -const ( - PropertyFilter_LESS_THAN PropertyFilter_Operator = 1 - PropertyFilter_LESS_THAN_OR_EQUAL PropertyFilter_Operator = 2 - PropertyFilter_GREATER_THAN PropertyFilter_Operator = 3 - PropertyFilter_GREATER_THAN_OR_EQUAL PropertyFilter_Operator = 4 - PropertyFilter_EQUAL PropertyFilter_Operator = 5 - PropertyFilter_HAS_ANCESTOR PropertyFilter_Operator = 11 -) - -var PropertyFilter_Operator_name = map[int32]string{ - 1: "LESS_THAN", - 2: "LESS_THAN_OR_EQUAL", - 3: "GREATER_THAN", - 4: "GREATER_THAN_OR_EQUAL", - 5: "EQUAL", - 11: "HAS_ANCESTOR", -} -var PropertyFilter_Operator_value = map[string]int32{ - "LESS_THAN": 1, - "LESS_THAN_OR_EQUAL": 2, - "GREATER_THAN": 3, - "GREATER_THAN_OR_EQUAL": 4, - "EQUAL": 5, - "HAS_ANCESTOR": 11, -} - -func (x PropertyFilter_Operator) Enum() *PropertyFilter_Operator { - p := new(PropertyFilter_Operator) - *p = x - return p -} -func (x PropertyFilter_Operator) String() string { - return proto.EnumName(PropertyFilter_Operator_name, int32(x)) -} -func (x *PropertyFilter_Operator) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PropertyFilter_Operator_value, data, "PropertyFilter_Operator") - if err != nil { - return err - } - *x = PropertyFilter_Operator(value) - return nil -} - -// The possible values for the 'more_results' field. -type QueryResultBatch_MoreResultsType int32 - -const ( - QueryResultBatch_NOT_FINISHED QueryResultBatch_MoreResultsType = 1 - QueryResultBatch_MORE_RESULTS_AFTER_LIMIT QueryResultBatch_MoreResultsType = 2 - // results after the limit. - QueryResultBatch_NO_MORE_RESULTS QueryResultBatch_MoreResultsType = 3 -) - -var QueryResultBatch_MoreResultsType_name = map[int32]string{ - 1: "NOT_FINISHED", - 2: "MORE_RESULTS_AFTER_LIMIT", - 3: "NO_MORE_RESULTS", -} -var QueryResultBatch_MoreResultsType_value = map[string]int32{ - "NOT_FINISHED": 1, - "MORE_RESULTS_AFTER_LIMIT": 2, - "NO_MORE_RESULTS": 3, -} - -func (x QueryResultBatch_MoreResultsType) Enum() *QueryResultBatch_MoreResultsType { - p := new(QueryResultBatch_MoreResultsType) - *p = x - return p -} -func (x QueryResultBatch_MoreResultsType) String() string { - return proto.EnumName(QueryResultBatch_MoreResultsType_name, int32(x)) -} -func (x *QueryResultBatch_MoreResultsType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(QueryResultBatch_MoreResultsType_value, data, "QueryResultBatch_MoreResultsType") - if err != nil { - return err - } - *x = QueryResultBatch_MoreResultsType(value) - return nil -} - -type ReadOptions_ReadConsistency int32 - -const ( - ReadOptions_DEFAULT ReadOptions_ReadConsistency = 0 - ReadOptions_STRONG ReadOptions_ReadConsistency = 1 - ReadOptions_EVENTUAL ReadOptions_ReadConsistency = 2 -) - -var ReadOptions_ReadConsistency_name = map[int32]string{ - 0: "DEFAULT", - 1: "STRONG", - 2: "EVENTUAL", -} -var ReadOptions_ReadConsistency_value = map[string]int32{ - "DEFAULT": 0, - "STRONG": 1, - "EVENTUAL": 2, -} - -func (x ReadOptions_ReadConsistency) Enum() *ReadOptions_ReadConsistency { - p := new(ReadOptions_ReadConsistency) - *p = x - return p -} -func (x ReadOptions_ReadConsistency) String() string { - return proto.EnumName(ReadOptions_ReadConsistency_name, int32(x)) -} -func (x *ReadOptions_ReadConsistency) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(ReadOptions_ReadConsistency_value, data, "ReadOptions_ReadConsistency") - if err != nil { - return err - } - *x = ReadOptions_ReadConsistency(value) - return nil -} - -type BeginTransactionRequest_IsolationLevel int32 - -const ( - BeginTransactionRequest_SNAPSHOT BeginTransactionRequest_IsolationLevel = 0 - // conflict if their mutations conflict. For example: - // Read(A),Write(B) may not conflict with Read(B),Write(A), - // but Read(B),Write(B) does conflict with Read(B),Write(B). - BeginTransactionRequest_SERIALIZABLE BeginTransactionRequest_IsolationLevel = 1 -) - -var BeginTransactionRequest_IsolationLevel_name = map[int32]string{ - 0: "SNAPSHOT", - 1: "SERIALIZABLE", -} -var BeginTransactionRequest_IsolationLevel_value = map[string]int32{ - "SNAPSHOT": 0, - "SERIALIZABLE": 1, -} - -func (x BeginTransactionRequest_IsolationLevel) Enum() *BeginTransactionRequest_IsolationLevel { - p := new(BeginTransactionRequest_IsolationLevel) - *p = x - return p -} -func (x BeginTransactionRequest_IsolationLevel) String() string { - return proto.EnumName(BeginTransactionRequest_IsolationLevel_name, int32(x)) -} -func (x *BeginTransactionRequest_IsolationLevel) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(BeginTransactionRequest_IsolationLevel_value, data, "BeginTransactionRequest_IsolationLevel") - if err != nil { - return err - } - *x = BeginTransactionRequest_IsolationLevel(value) - return nil -} - -type CommitRequest_Mode int32 - -const ( - CommitRequest_TRANSACTIONAL CommitRequest_Mode = 1 - CommitRequest_NON_TRANSACTIONAL CommitRequest_Mode = 2 -) - -var CommitRequest_Mode_name = map[int32]string{ - 1: "TRANSACTIONAL", - 2: "NON_TRANSACTIONAL", -} -var CommitRequest_Mode_value = map[string]int32{ - "TRANSACTIONAL": 1, - "NON_TRANSACTIONAL": 2, -} - -func (x CommitRequest_Mode) Enum() *CommitRequest_Mode { - p := new(CommitRequest_Mode) - *p = x - return p -} -func (x CommitRequest_Mode) String() string { - return proto.EnumName(CommitRequest_Mode_name, int32(x)) -} -func (x *CommitRequest_Mode) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(CommitRequest_Mode_value, data, "CommitRequest_Mode") - if err != nil { - return err - } - *x = CommitRequest_Mode(value) - return nil -} - -// An identifier for a particular subset of entities. -// -// Entities are partitioned into various subsets, each used by different -// datasets and different namespaces within a dataset and so forth. -// -// All input partition IDs are normalized before use. -// A partition ID is normalized as follows: -// If the partition ID is unset or is set to an empty partition ID, replace it -// with the context partition ID. -// Otherwise, if the partition ID has no dataset ID, assign it the context -// partition ID's dataset ID. -// Unless otherwise documented, the context partition ID has the dataset ID set -// to the context dataset ID and no other partition dimension set. -// -// A partition ID is empty if all of its fields are unset. -// -// Partition dimension: -// A dimension may be unset. -// A dimension's value must never be "". -// A dimension's value must match [A-Za-z\d\.\-_]{1,100} -// If the value of any dimension matches regex "__.*__", -// the partition is reserved/read-only. -// A reserved/read-only partition ID is forbidden in certain documented contexts. -// -// Dataset ID: -// A dataset id's value must never be "". -// A dataset id's value must match -// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99} -type PartitionId struct { - // The dataset ID. - DatasetId *string `protobuf:"bytes,3,opt,name=dataset_id" json:"dataset_id,omitempty"` - // The namespace. - Namespace *string `protobuf:"bytes,4,opt,name=namespace" json:"namespace,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PartitionId) Reset() { *m = PartitionId{} } -func (m *PartitionId) String() string { return proto.CompactTextString(m) } -func (*PartitionId) ProtoMessage() {} - -func (m *PartitionId) GetDatasetId() string { - if m != nil && m.DatasetId != nil { - return *m.DatasetId - } - return "" -} - -func (m *PartitionId) GetNamespace() string { - if m != nil && m.Namespace != nil { - return *m.Namespace - } - return "" -} - -// A unique identifier for an entity. -// If a key's partition id or any of its path kinds or names are -// reserved/read-only, the key is reserved/read-only. -// A reserved/read-only key is forbidden in certain documented contexts. -type Key struct { - // Entities are partitioned into subsets, currently identified by a dataset - // (usually implicitly specified by the project) and namespace ID. - // Queries are scoped to a single partition. - PartitionId *PartitionId `protobuf:"bytes,1,opt,name=partition_id" json:"partition_id,omitempty"` - // The entity path. - // An entity path consists of one or more elements composed of a kind and a - // string or numerical identifier, which identify entities. The first - // element identifies a root entity, the second element identifies - // a child of the root entity, the third element a child of the - // second entity, and so forth. The entities identified by all prefixes of - // the path are called the element's ancestors. - // An entity path is always fully complete: ALL of the entity's ancestors - // are required to be in the path along with the entity identifier itself. - // The only exception is that in some documented cases, the identifier in the - // last path element (for the entity) itself may be omitted. A path can never - // be empty. - PathElement []*Key_PathElement `protobuf:"bytes,2,rep,name=path_element" json:"path_element,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Key) Reset() { *m = Key{} } -func (m *Key) String() string { return proto.CompactTextString(m) } -func (*Key) ProtoMessage() {} - -func (m *Key) GetPartitionId() *PartitionId { - if m != nil { - return m.PartitionId - } - return nil -} - -func (m *Key) GetPathElement() []*Key_PathElement { - if m != nil { - return m.PathElement - } - return nil -} - -// A (kind, ID/name) pair used to construct a key path. -// -// At most one of name or ID may be set. -// If either is set, the element is complete. -// If neither is set, the element is incomplete. -type Key_PathElement struct { - // The kind of the entity. - // A kind matching regex "__.*__" is reserved/read-only. - // A kind must not contain more than 500 characters. - // Cannot be "". - Kind *string `protobuf:"bytes,1,req,name=kind" json:"kind,omitempty"` - // The ID of the entity. - // Never equal to zero. Values less than zero are discouraged and will not - // be supported in the future. - Id *int64 `protobuf:"varint,2,opt,name=id" json:"id,omitempty"` - // The name of the entity. - // A name matching regex "__.*__" is reserved/read-only. - // A name must not be more than 500 characters. - // Cannot be "". - Name *string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Key_PathElement) Reset() { *m = Key_PathElement{} } -func (m *Key_PathElement) String() string { return proto.CompactTextString(m) } -func (*Key_PathElement) ProtoMessage() {} - -func (m *Key_PathElement) GetKind() string { - if m != nil && m.Kind != nil { - return *m.Kind - } - return "" -} - -func (m *Key_PathElement) GetId() int64 { - if m != nil && m.Id != nil { - return *m.Id - } - return 0 -} - -func (m *Key_PathElement) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// A message that can hold any of the supported value types and associated -// metadata. -// -// At most one of the Value fields may be set. -// If none are set the value is "null". -// -type Value struct { - // A boolean value. - BooleanValue *bool `protobuf:"varint,1,opt,name=boolean_value" json:"boolean_value,omitempty"` - // An integer value. - IntegerValue *int64 `protobuf:"varint,2,opt,name=integer_value" json:"integer_value,omitempty"` - // A double value. - DoubleValue *float64 `protobuf:"fixed64,3,opt,name=double_value" json:"double_value,omitempty"` - // A timestamp value. - TimestampMicrosecondsValue *int64 `protobuf:"varint,4,opt,name=timestamp_microseconds_value" json:"timestamp_microseconds_value,omitempty"` - // A key value. - KeyValue *Key `protobuf:"bytes,5,opt,name=key_value" json:"key_value,omitempty"` - // A blob key value. - BlobKeyValue *string `protobuf:"bytes,16,opt,name=blob_key_value" json:"blob_key_value,omitempty"` - // A UTF-8 encoded string value. - StringValue *string `protobuf:"bytes,17,opt,name=string_value" json:"string_value,omitempty"` - // A blob value. - BlobValue []byte `protobuf:"bytes,18,opt,name=blob_value" json:"blob_value,omitempty"` - // An entity value. - // May have no key. - // May have a key with an incomplete key path. - // May have a reserved/read-only key. - EntityValue *Entity `protobuf:"bytes,6,opt,name=entity_value" json:"entity_value,omitempty"` - // A list value. - // Cannot contain another list value. - // Cannot also have a meaning and indexing set. - ListValue []*Value `protobuf:"bytes,7,rep,name=list_value" json:"list_value,omitempty"` - // The meaning field is reserved and should not be used. - Meaning *int32 `protobuf:"varint,14,opt,name=meaning" json:"meaning,omitempty"` - // If the value should be indexed. - // - // The indexed property may be set for a - // null value. - // When indexed is true, stringValue - // is limited to 500 characters and the blob value is limited to 500 bytes. - // Exception: If meaning is set to 2, string_value is limited to 2038 - // characters regardless of indexed. - // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16 - // will be ignored on input (and will never be set on output). - // Input values by default have indexed set to - // true; however, you can explicitly set indexed to - // true if you want. (An output value never has - // indexed explicitly set to true.) If a value is - // itself an entity, it cannot have indexed set to - // true. - // Exception: An entity value with meaning 9, 20 or 21 may be indexed. - Indexed *bool `protobuf:"varint,15,opt,name=indexed,def=1" json:"indexed,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Value) Reset() { *m = Value{} } -func (m *Value) String() string { return proto.CompactTextString(m) } -func (*Value) ProtoMessage() {} - -const Default_Value_Indexed bool = true - -func (m *Value) GetBooleanValue() bool { - if m != nil && m.BooleanValue != nil { - return *m.BooleanValue - } - return false -} - -func (m *Value) GetIntegerValue() int64 { - if m != nil && m.IntegerValue != nil { - return *m.IntegerValue - } - return 0 -} - -func (m *Value) GetDoubleValue() float64 { - if m != nil && m.DoubleValue != nil { - return *m.DoubleValue - } - return 0 -} - -func (m *Value) GetTimestampMicrosecondsValue() int64 { - if m != nil && m.TimestampMicrosecondsValue != nil { - return *m.TimestampMicrosecondsValue - } - return 0 -} - -func (m *Value) GetKeyValue() *Key { - if m != nil { - return m.KeyValue - } - return nil -} - -func (m *Value) GetBlobKeyValue() string { - if m != nil && m.BlobKeyValue != nil { - return *m.BlobKeyValue - } - return "" -} - -func (m *Value) GetStringValue() string { - if m != nil && m.StringValue != nil { - return *m.StringValue - } - return "" -} - -func (m *Value) GetBlobValue() []byte { - if m != nil { - return m.BlobValue - } - return nil -} - -func (m *Value) GetEntityValue() *Entity { - if m != nil { - return m.EntityValue - } - return nil -} - -func (m *Value) GetListValue() []*Value { - if m != nil { - return m.ListValue - } - return nil -} - -func (m *Value) GetMeaning() int32 { - if m != nil && m.Meaning != nil { - return *m.Meaning - } - return 0 -} - -func (m *Value) GetIndexed() bool { - if m != nil && m.Indexed != nil { - return *m.Indexed - } - return Default_Value_Indexed -} - -// An entity property. -type Property struct { - // The name of the property. - // A property name matching regex "__.*__" is reserved. - // A reserved property name is forbidden in certain documented contexts. - // The name must not contain more than 500 characters. - // Cannot be "". - Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` - // The value(s) of the property. - // Each value can have only one value property populated. For example, - // you cannot have a values list of { value: { integerValue: 22, - // stringValue: "a" } }, but you can have { value: { listValue: - // [ { integerValue: 22 }, { stringValue: "a" } ] }. - Value *Value `protobuf:"bytes,4,req,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Property) Reset() { *m = Property{} } -func (m *Property) String() string { return proto.CompactTextString(m) } -func (*Property) ProtoMessage() {} - -func (m *Property) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *Property) GetValue() *Value { - if m != nil { - return m.Value - } - return nil -} - -// An entity. -// -// An entity is limited to 1 megabyte when stored. That roughly -// corresponds to a limit of 1 megabyte for the serialized form of this -// message. -type Entity struct { - // The entity's key. - // - // An entity must have a key, unless otherwise documented (for example, - // an entity in Value.entityValue may have no key). - // An entity's kind is its key's path's last element's kind, - // or null if it has no key. - Key *Key `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` - // The entity's properties. - // Each property's name must be unique for its entity. - Property []*Property `protobuf:"bytes,2,rep,name=property" json:"property,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Entity) Reset() { *m = Entity{} } -func (m *Entity) String() string { return proto.CompactTextString(m) } -func (*Entity) ProtoMessage() {} - -func (m *Entity) GetKey() *Key { - if m != nil { - return m.Key - } - return nil -} - -func (m *Entity) GetProperty() []*Property { - if m != nil { - return m.Property - } - return nil -} - -// The result of fetching an entity from the datastore. -type EntityResult struct { - // The resulting entity. - Entity *Entity `protobuf:"bytes,1,req,name=entity" json:"entity,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *EntityResult) Reset() { *m = EntityResult{} } -func (m *EntityResult) String() string { return proto.CompactTextString(m) } -func (*EntityResult) ProtoMessage() {} - -func (m *EntityResult) GetEntity() *Entity { - if m != nil { - return m.Entity - } - return nil -} - -// A query. -type Query struct { - // The projection to return. If not set the entire entity is returned. - Projection []*PropertyExpression `protobuf:"bytes,2,rep,name=projection" json:"projection,omitempty"` - // The kinds to query (if empty, returns entities from all kinds). - Kind []*KindExpression `protobuf:"bytes,3,rep,name=kind" json:"kind,omitempty"` - // The filter to apply (optional). - Filter *Filter `protobuf:"bytes,4,opt,name=filter" json:"filter,omitempty"` - // The order to apply to the query results (if empty, order is unspecified). - Order []*PropertyOrder `protobuf:"bytes,5,rep,name=order" json:"order,omitempty"` - // The properties to group by (if empty, no grouping is applied to the - // result set). - GroupBy []*PropertyReference `protobuf:"bytes,6,rep,name=group_by" json:"group_by,omitempty"` - // A starting point for the query results. Optional. Query cursors are - // returned in query result batches. - StartCursor []byte `protobuf:"bytes,7,opt,name=start_cursor" json:"start_cursor,omitempty"` - // An ending point for the query results. Optional. Query cursors are - // returned in query result batches. - EndCursor []byte `protobuf:"bytes,8,opt,name=end_cursor" json:"end_cursor,omitempty"` - // The number of results to skip. Applies before limit, but after all other - // constraints (optional, defaults to 0). - Offset *int32 `protobuf:"varint,10,opt,name=offset,def=0" json:"offset,omitempty"` - // The maximum number of results to return. Applies after all other - // constraints. Optional. - Limit *int32 `protobuf:"varint,11,opt,name=limit" json:"limit,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Query) Reset() { *m = Query{} } -func (m *Query) String() string { return proto.CompactTextString(m) } -func (*Query) ProtoMessage() {} - -const Default_Query_Offset int32 = 0 - -func (m *Query) GetProjection() []*PropertyExpression { - if m != nil { - return m.Projection - } - return nil -} - -func (m *Query) GetKind() []*KindExpression { - if m != nil { - return m.Kind - } - return nil -} - -func (m *Query) GetFilter() *Filter { - if m != nil { - return m.Filter - } - return nil -} - -func (m *Query) GetOrder() []*PropertyOrder { - if m != nil { - return m.Order - } - return nil -} - -func (m *Query) GetGroupBy() []*PropertyReference { - if m != nil { - return m.GroupBy - } - return nil -} - -func (m *Query) GetStartCursor() []byte { - if m != nil { - return m.StartCursor - } - return nil -} - -func (m *Query) GetEndCursor() []byte { - if m != nil { - return m.EndCursor - } - return nil -} - -func (m *Query) GetOffset() int32 { - if m != nil && m.Offset != nil { - return *m.Offset - } - return Default_Query_Offset -} - -func (m *Query) GetLimit() int32 { - if m != nil && m.Limit != nil { - return *m.Limit - } - return 0 -} - -// A representation of a kind. -type KindExpression struct { - // The name of the kind. - Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *KindExpression) Reset() { *m = KindExpression{} } -func (m *KindExpression) String() string { return proto.CompactTextString(m) } -func (*KindExpression) ProtoMessage() {} - -func (m *KindExpression) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// A reference to a property relative to the kind expressions. -// exactly. -type PropertyReference struct { - // The name of the property. - Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyReference) Reset() { *m = PropertyReference{} } -func (m *PropertyReference) String() string { return proto.CompactTextString(m) } -func (*PropertyReference) ProtoMessage() {} - -func (m *PropertyReference) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -// A representation of a property in a projection. -type PropertyExpression struct { - // The property to project. - Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` - // The aggregation function to apply to the property. Optional. - // Can only be used when grouping by at least one property. Must - // then be set on all properties in the projection that are not - // being grouped by. - AggregationFunction *PropertyExpression_AggregationFunction `protobuf:"varint,2,opt,name=aggregation_function,enum=datastore.PropertyExpression_AggregationFunction" json:"aggregation_function,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyExpression) Reset() { *m = PropertyExpression{} } -func (m *PropertyExpression) String() string { return proto.CompactTextString(m) } -func (*PropertyExpression) ProtoMessage() {} - -func (m *PropertyExpression) GetProperty() *PropertyReference { - if m != nil { - return m.Property - } - return nil -} - -func (m *PropertyExpression) GetAggregationFunction() PropertyExpression_AggregationFunction { - if m != nil && m.AggregationFunction != nil { - return *m.AggregationFunction - } - return PropertyExpression_FIRST -} - -// The desired order for a specific property. -type PropertyOrder struct { - // The property to order by. - Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` - // The direction to order by. - Direction *PropertyOrder_Direction `protobuf:"varint,2,opt,name=direction,enum=datastore.PropertyOrder_Direction,def=1" json:"direction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyOrder) Reset() { *m = PropertyOrder{} } -func (m *PropertyOrder) String() string { return proto.CompactTextString(m) } -func (*PropertyOrder) ProtoMessage() {} - -const Default_PropertyOrder_Direction PropertyOrder_Direction = PropertyOrder_ASCENDING - -func (m *PropertyOrder) GetProperty() *PropertyReference { - if m != nil { - return m.Property - } - return nil -} - -func (m *PropertyOrder) GetDirection() PropertyOrder_Direction { - if m != nil && m.Direction != nil { - return *m.Direction - } - return Default_PropertyOrder_Direction -} - -// A holder for any type of filter. Exactly one field should be specified. -type Filter struct { - // A composite filter. - CompositeFilter *CompositeFilter `protobuf:"bytes,1,opt,name=composite_filter" json:"composite_filter,omitempty"` - // A filter on a property. - PropertyFilter *PropertyFilter `protobuf:"bytes,2,opt,name=property_filter" json:"property_filter,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Filter) Reset() { *m = Filter{} } -func (m *Filter) String() string { return proto.CompactTextString(m) } -func (*Filter) ProtoMessage() {} - -func (m *Filter) GetCompositeFilter() *CompositeFilter { - if m != nil { - return m.CompositeFilter - } - return nil -} - -func (m *Filter) GetPropertyFilter() *PropertyFilter { - if m != nil { - return m.PropertyFilter - } - return nil -} - -// A filter that merges the multiple other filters using the given operation. -type CompositeFilter struct { - // The operator for combining multiple filters. - Operator *CompositeFilter_Operator `protobuf:"varint,1,req,name=operator,enum=datastore.CompositeFilter_Operator" json:"operator,omitempty"` - // The list of filters to combine. - // Must contain at least one filter. - Filter []*Filter `protobuf:"bytes,2,rep,name=filter" json:"filter,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CompositeFilter) Reset() { *m = CompositeFilter{} } -func (m *CompositeFilter) String() string { return proto.CompactTextString(m) } -func (*CompositeFilter) ProtoMessage() {} - -func (m *CompositeFilter) GetOperator() CompositeFilter_Operator { - if m != nil && m.Operator != nil { - return *m.Operator - } - return CompositeFilter_AND -} - -func (m *CompositeFilter) GetFilter() []*Filter { - if m != nil { - return m.Filter - } - return nil -} - -// A filter on a specific property. -type PropertyFilter struct { - // The property to filter by. - Property *PropertyReference `protobuf:"bytes,1,req,name=property" json:"property,omitempty"` - // The operator to filter by. - Operator *PropertyFilter_Operator `protobuf:"varint,2,req,name=operator,enum=datastore.PropertyFilter_Operator" json:"operator,omitempty"` - // The value to compare the property to. - Value *Value `protobuf:"bytes,3,req,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *PropertyFilter) Reset() { *m = PropertyFilter{} } -func (m *PropertyFilter) String() string { return proto.CompactTextString(m) } -func (*PropertyFilter) ProtoMessage() {} - -func (m *PropertyFilter) GetProperty() *PropertyReference { - if m != nil { - return m.Property - } - return nil -} - -func (m *PropertyFilter) GetOperator() PropertyFilter_Operator { - if m != nil && m.Operator != nil { - return *m.Operator - } - return PropertyFilter_LESS_THAN -} - -func (m *PropertyFilter) GetValue() *Value { - if m != nil { - return m.Value - } - return nil -} - -// A GQL query. -type GqlQuery struct { - QueryString *string `protobuf:"bytes,1,req,name=query_string" json:"query_string,omitempty"` - // When false, the query string must not contain a literal. - AllowLiteral *bool `protobuf:"varint,2,opt,name=allow_literal,def=0" json:"allow_literal,omitempty"` - // A named argument must set field GqlQueryArg.name. - // No two named arguments may have the same name. - // For each non-reserved named binding site in the query string, - // there must be a named argument with that name, - // but not necessarily the inverse. - NameArg []*GqlQueryArg `protobuf:"bytes,3,rep,name=name_arg" json:"name_arg,omitempty"` - // Numbered binding site @1 references the first numbered argument, - // effectively using 1-based indexing, rather than the usual 0. - // A numbered argument must NOT set field GqlQueryArg.name. - // For each binding site numbered i in query_string, - // there must be an ith numbered argument. - // The inverse must also be true. - NumberArg []*GqlQueryArg `protobuf:"bytes,4,rep,name=number_arg" json:"number_arg,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GqlQuery) Reset() { *m = GqlQuery{} } -func (m *GqlQuery) String() string { return proto.CompactTextString(m) } -func (*GqlQuery) ProtoMessage() {} - -const Default_GqlQuery_AllowLiteral bool = false - -func (m *GqlQuery) GetQueryString() string { - if m != nil && m.QueryString != nil { - return *m.QueryString - } - return "" -} - -func (m *GqlQuery) GetAllowLiteral() bool { - if m != nil && m.AllowLiteral != nil { - return *m.AllowLiteral - } - return Default_GqlQuery_AllowLiteral -} - -func (m *GqlQuery) GetNameArg() []*GqlQueryArg { - if m != nil { - return m.NameArg - } - return nil -} - -func (m *GqlQuery) GetNumberArg() []*GqlQueryArg { - if m != nil { - return m.NumberArg - } - return nil -} - -// A binding argument for a GQL query. -// Exactly one of fields value and cursor must be set. -type GqlQueryArg struct { - // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*". - // Must not match regex "__.*__". - // Must not be "". - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Value *Value `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - Cursor []byte `protobuf:"bytes,3,opt,name=cursor" json:"cursor,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *GqlQueryArg) Reset() { *m = GqlQueryArg{} } -func (m *GqlQueryArg) String() string { return proto.CompactTextString(m) } -func (*GqlQueryArg) ProtoMessage() {} - -func (m *GqlQueryArg) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *GqlQueryArg) GetValue() *Value { - if m != nil { - return m.Value - } - return nil -} - -func (m *GqlQueryArg) GetCursor() []byte { - if m != nil { - return m.Cursor - } - return nil -} - -// A batch of results produced by a query. -type QueryResultBatch struct { - // The result type for every entity in entityResults. - EntityResultType *EntityResult_ResultType `protobuf:"varint,1,req,name=entity_result_type,enum=datastore.EntityResult_ResultType" json:"entity_result_type,omitempty"` - // The results for this batch. - EntityResult []*EntityResult `protobuf:"bytes,2,rep,name=entity_result" json:"entity_result,omitempty"` - // A cursor that points to the position after the last result in the batch. - // May be absent. - EndCursor []byte `protobuf:"bytes,4,opt,name=end_cursor" json:"end_cursor,omitempty"` - // The state of the query after the current batch. - MoreResults *QueryResultBatch_MoreResultsType `protobuf:"varint,5,req,name=more_results,enum=datastore.QueryResultBatch_MoreResultsType" json:"more_results,omitempty"` - // The number of results skipped because of Query.offset. - SkippedResults *int32 `protobuf:"varint,6,opt,name=skipped_results" json:"skipped_results,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *QueryResultBatch) Reset() { *m = QueryResultBatch{} } -func (m *QueryResultBatch) String() string { return proto.CompactTextString(m) } -func (*QueryResultBatch) ProtoMessage() {} - -func (m *QueryResultBatch) GetEntityResultType() EntityResult_ResultType { - if m != nil && m.EntityResultType != nil { - return *m.EntityResultType - } - return EntityResult_FULL -} - -func (m *QueryResultBatch) GetEntityResult() []*EntityResult { - if m != nil { - return m.EntityResult - } - return nil -} - -func (m *QueryResultBatch) GetEndCursor() []byte { - if m != nil { - return m.EndCursor - } - return nil -} - -func (m *QueryResultBatch) GetMoreResults() QueryResultBatch_MoreResultsType { - if m != nil && m.MoreResults != nil { - return *m.MoreResults - } - return QueryResultBatch_NOT_FINISHED -} - -func (m *QueryResultBatch) GetSkippedResults() int32 { - if m != nil && m.SkippedResults != nil { - return *m.SkippedResults - } - return 0 -} - -// A set of changes to apply. -// -// No entity in this message may have a reserved property name, -// not even a property in an entity in a value. -// No value in this message may have meaning 18, -// not even a value in an entity in another value. -// -// If entities with duplicate keys are present, an arbitrary choice will -// be made as to which is written. -type Mutation struct { - // Entities to upsert. - // Each upserted entity's key must have a complete path and - // must not be reserved/read-only. - Upsert []*Entity `protobuf:"bytes,1,rep,name=upsert" json:"upsert,omitempty"` - // Entities to update. - // Each updated entity's key must have a complete path and - // must not be reserved/read-only. - Update []*Entity `protobuf:"bytes,2,rep,name=update" json:"update,omitempty"` - // Entities to insert. - // Each inserted entity's key must have a complete path and - // must not be reserved/read-only. - Insert []*Entity `protobuf:"bytes,3,rep,name=insert" json:"insert,omitempty"` - // Insert entities with a newly allocated ID. - // Each inserted entity's key must omit the final identifier in its path and - // must not be reserved/read-only. - InsertAutoId []*Entity `protobuf:"bytes,4,rep,name=insert_auto_id" json:"insert_auto_id,omitempty"` - // Keys of entities to delete. - // Each key must have a complete key path and must not be reserved/read-only. - Delete []*Key `protobuf:"bytes,5,rep,name=delete" json:"delete,omitempty"` - // Ignore a user specified read-only period. Optional. - Force *bool `protobuf:"varint,6,opt,name=force" json:"force,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *Mutation) Reset() { *m = Mutation{} } -func (m *Mutation) String() string { return proto.CompactTextString(m) } -func (*Mutation) ProtoMessage() {} - -func (m *Mutation) GetUpsert() []*Entity { - if m != nil { - return m.Upsert - } - return nil -} - -func (m *Mutation) GetUpdate() []*Entity { - if m != nil { - return m.Update - } - return nil -} - -func (m *Mutation) GetInsert() []*Entity { - if m != nil { - return m.Insert - } - return nil -} - -func (m *Mutation) GetInsertAutoId() []*Entity { - if m != nil { - return m.InsertAutoId - } - return nil -} - -func (m *Mutation) GetDelete() []*Key { - if m != nil { - return m.Delete - } - return nil -} - -func (m *Mutation) GetForce() bool { - if m != nil && m.Force != nil { - return *m.Force - } - return false -} - -// The result of applying a mutation. -type MutationResult struct { - // Number of index writes. - IndexUpdates *int32 `protobuf:"varint,1,req,name=index_updates" json:"index_updates,omitempty"` - // Keys for insertAutoId entities. One per entity from the - // request, in the same order. - InsertAutoIdKey []*Key `protobuf:"bytes,2,rep,name=insert_auto_id_key" json:"insert_auto_id_key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *MutationResult) Reset() { *m = MutationResult{} } -func (m *MutationResult) String() string { return proto.CompactTextString(m) } -func (*MutationResult) ProtoMessage() {} - -func (m *MutationResult) GetIndexUpdates() int32 { - if m != nil && m.IndexUpdates != nil { - return *m.IndexUpdates - } - return 0 -} - -func (m *MutationResult) GetInsertAutoIdKey() []*Key { - if m != nil { - return m.InsertAutoIdKey - } - return nil -} - -// Options shared by read requests. -type ReadOptions struct { - // The read consistency to use. - // Cannot be set when transaction is set. - // Lookup and ancestor queries default to STRONG, global queries default to - // EVENTUAL and cannot be set to STRONG. - ReadConsistency *ReadOptions_ReadConsistency `protobuf:"varint,1,opt,name=read_consistency,enum=datastore.ReadOptions_ReadConsistency,def=0" json:"read_consistency,omitempty"` - // The transaction to use. Optional. - Transaction []byte `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *ReadOptions) Reset() { *m = ReadOptions{} } -func (m *ReadOptions) String() string { return proto.CompactTextString(m) } -func (*ReadOptions) ProtoMessage() {} - -const Default_ReadOptions_ReadConsistency ReadOptions_ReadConsistency = ReadOptions_DEFAULT - -func (m *ReadOptions) GetReadConsistency() ReadOptions_ReadConsistency { - if m != nil && m.ReadConsistency != nil { - return *m.ReadConsistency - } - return Default_ReadOptions_ReadConsistency -} - -func (m *ReadOptions) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -// The request for Lookup. -type LookupRequest struct { - // Options for this lookup request. Optional. - ReadOptions *ReadOptions `protobuf:"bytes,1,opt,name=read_options" json:"read_options,omitempty"` - // Keys of entities to look up from the datastore. - Key []*Key `protobuf:"bytes,3,rep,name=key" json:"key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *LookupRequest) Reset() { *m = LookupRequest{} } -func (m *LookupRequest) String() string { return proto.CompactTextString(m) } -func (*LookupRequest) ProtoMessage() {} - -func (m *LookupRequest) GetReadOptions() *ReadOptions { - if m != nil { - return m.ReadOptions - } - return nil -} - -func (m *LookupRequest) GetKey() []*Key { - if m != nil { - return m.Key - } - return nil -} - -// The response for Lookup. -type LookupResponse struct { - // Entities found as ResultType.FULL entities. - Found []*EntityResult `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"` - // Entities not found as ResultType.KEY_ONLY entities. - Missing []*EntityResult `protobuf:"bytes,2,rep,name=missing" json:"missing,omitempty"` - // A list of keys that were not looked up due to resource constraints. - Deferred []*Key `protobuf:"bytes,3,rep,name=deferred" json:"deferred,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *LookupResponse) Reset() { *m = LookupResponse{} } -func (m *LookupResponse) String() string { return proto.CompactTextString(m) } -func (*LookupResponse) ProtoMessage() {} - -func (m *LookupResponse) GetFound() []*EntityResult { - if m != nil { - return m.Found - } - return nil -} - -func (m *LookupResponse) GetMissing() []*EntityResult { - if m != nil { - return m.Missing - } - return nil -} - -func (m *LookupResponse) GetDeferred() []*Key { - if m != nil { - return m.Deferred - } - return nil -} - -// The request for RunQuery. -type RunQueryRequest struct { - // The options for this query. - ReadOptions *ReadOptions `protobuf:"bytes,1,opt,name=read_options" json:"read_options,omitempty"` - // Entities are partitioned into subsets, identified by a dataset (usually - // implicitly specified by the project) and namespace ID. Queries are scoped - // to a single partition. - // This partition ID is normalized with the standard default context - // partition ID, but all other partition IDs in RunQueryRequest are - // normalized with this partition ID as the context partition ID. - PartitionId *PartitionId `protobuf:"bytes,2,opt,name=partition_id" json:"partition_id,omitempty"` - // The query to run. - // Either this field or field gql_query must be set, but not both. - Query *Query `protobuf:"bytes,3,opt,name=query" json:"query,omitempty"` - // The GQL query to run. - // Either this field or field query must be set, but not both. - GqlQuery *GqlQuery `protobuf:"bytes,7,opt,name=gql_query" json:"gql_query,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RunQueryRequest) Reset() { *m = RunQueryRequest{} } -func (m *RunQueryRequest) String() string { return proto.CompactTextString(m) } -func (*RunQueryRequest) ProtoMessage() {} - -func (m *RunQueryRequest) GetReadOptions() *ReadOptions { - if m != nil { - return m.ReadOptions - } - return nil -} - -func (m *RunQueryRequest) GetPartitionId() *PartitionId { - if m != nil { - return m.PartitionId - } - return nil -} - -func (m *RunQueryRequest) GetQuery() *Query { - if m != nil { - return m.Query - } - return nil -} - -func (m *RunQueryRequest) GetGqlQuery() *GqlQuery { - if m != nil { - return m.GqlQuery - } - return nil -} - -// The response for RunQuery. -type RunQueryResponse struct { - // A batch of query results (always present). - Batch *QueryResultBatch `protobuf:"bytes,1,opt,name=batch" json:"batch,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RunQueryResponse) Reset() { *m = RunQueryResponse{} } -func (m *RunQueryResponse) String() string { return proto.CompactTextString(m) } -func (*RunQueryResponse) ProtoMessage() {} - -func (m *RunQueryResponse) GetBatch() *QueryResultBatch { - if m != nil { - return m.Batch - } - return nil -} - -// The request for BeginTransaction. -type BeginTransactionRequest struct { - // The transaction isolation level. - IsolationLevel *BeginTransactionRequest_IsolationLevel `protobuf:"varint,1,opt,name=isolation_level,enum=datastore.BeginTransactionRequest_IsolationLevel,def=0" json:"isolation_level,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *BeginTransactionRequest) Reset() { *m = BeginTransactionRequest{} } -func (m *BeginTransactionRequest) String() string { return proto.CompactTextString(m) } -func (*BeginTransactionRequest) ProtoMessage() {} - -const Default_BeginTransactionRequest_IsolationLevel BeginTransactionRequest_IsolationLevel = BeginTransactionRequest_SNAPSHOT - -func (m *BeginTransactionRequest) GetIsolationLevel() BeginTransactionRequest_IsolationLevel { - if m != nil && m.IsolationLevel != nil { - return *m.IsolationLevel - } - return Default_BeginTransactionRequest_IsolationLevel -} - -// The response for BeginTransaction. -type BeginTransactionResponse struct { - // The transaction identifier (always present). - Transaction []byte `protobuf:"bytes,1,opt,name=transaction" json:"transaction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *BeginTransactionResponse) Reset() { *m = BeginTransactionResponse{} } -func (m *BeginTransactionResponse) String() string { return proto.CompactTextString(m) } -func (*BeginTransactionResponse) ProtoMessage() {} - -func (m *BeginTransactionResponse) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -// The request for Rollback. -type RollbackRequest struct { - // The transaction identifier, returned by a call to - // beginTransaction. - Transaction []byte `protobuf:"bytes,1,req,name=transaction" json:"transaction,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *RollbackRequest) Reset() { *m = RollbackRequest{} } -func (m *RollbackRequest) String() string { return proto.CompactTextString(m) } -func (*RollbackRequest) ProtoMessage() {} - -func (m *RollbackRequest) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -// The response for Rollback. -type RollbackResponse struct { - XXX_unrecognized []byte `json:"-"` -} - -func (m *RollbackResponse) Reset() { *m = RollbackResponse{} } -func (m *RollbackResponse) String() string { return proto.CompactTextString(m) } -func (*RollbackResponse) ProtoMessage() {} - -// The request for Commit. -type CommitRequest struct { - // The transaction identifier, returned by a call to - // beginTransaction. Must be set when mode is TRANSACTIONAL. - Transaction []byte `protobuf:"bytes,1,opt,name=transaction" json:"transaction,omitempty"` - // The mutation to perform. Optional. - Mutation *Mutation `protobuf:"bytes,2,opt,name=mutation" json:"mutation,omitempty"` - // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL. - Mode *CommitRequest_Mode `protobuf:"varint,5,opt,name=mode,enum=datastore.CommitRequest_Mode,def=1" json:"mode,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CommitRequest) Reset() { *m = CommitRequest{} } -func (m *CommitRequest) String() string { return proto.CompactTextString(m) } -func (*CommitRequest) ProtoMessage() {} - -const Default_CommitRequest_Mode CommitRequest_Mode = CommitRequest_TRANSACTIONAL - -func (m *CommitRequest) GetTransaction() []byte { - if m != nil { - return m.Transaction - } - return nil -} - -func (m *CommitRequest) GetMutation() *Mutation { - if m != nil { - return m.Mutation - } - return nil -} - -func (m *CommitRequest) GetMode() CommitRequest_Mode { - if m != nil && m.Mode != nil { - return *m.Mode - } - return Default_CommitRequest_Mode -} - -// The response for Commit. -type CommitResponse struct { - // The result of performing the mutation (if any). - MutationResult *MutationResult `protobuf:"bytes,1,opt,name=mutation_result" json:"mutation_result,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *CommitResponse) Reset() { *m = CommitResponse{} } -func (m *CommitResponse) String() string { return proto.CompactTextString(m) } -func (*CommitResponse) ProtoMessage() {} - -func (m *CommitResponse) GetMutationResult() *MutationResult { - if m != nil { - return m.MutationResult - } - return nil -} - -// The request for AllocateIds. -type AllocateIdsRequest struct { - // A list of keys with incomplete key paths to allocate IDs for. - // No key may be reserved/read-only. - Key []*Key `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *AllocateIdsRequest) Reset() { *m = AllocateIdsRequest{} } -func (m *AllocateIdsRequest) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsRequest) ProtoMessage() {} - -func (m *AllocateIdsRequest) GetKey() []*Key { - if m != nil { - return m.Key - } - return nil -} - -// The response for AllocateIds. -type AllocateIdsResponse struct { - // The keys specified in the request (in the same order), each with - // its key path completed with a newly allocated ID. - Key []*Key `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (m *AllocateIdsResponse) Reset() { *m = AllocateIdsResponse{} } -func (m *AllocateIdsResponse) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsResponse) ProtoMessage() {} - -func (m *AllocateIdsResponse) GetKey() []*Key { - if m != nil { - return m.Key - } - return nil -} - -func init() { - proto.RegisterEnum("datastore.EntityResult_ResultType", EntityResult_ResultType_name, EntityResult_ResultType_value) - proto.RegisterEnum("datastore.PropertyExpression_AggregationFunction", PropertyExpression_AggregationFunction_name, PropertyExpression_AggregationFunction_value) - proto.RegisterEnum("datastore.PropertyOrder_Direction", PropertyOrder_Direction_name, PropertyOrder_Direction_value) - proto.RegisterEnum("datastore.CompositeFilter_Operator", CompositeFilter_Operator_name, CompositeFilter_Operator_value) - proto.RegisterEnum("datastore.PropertyFilter_Operator", PropertyFilter_Operator_name, PropertyFilter_Operator_value) - proto.RegisterEnum("datastore.QueryResultBatch_MoreResultsType", QueryResultBatch_MoreResultsType_name, QueryResultBatch_MoreResultsType_value) - proto.RegisterEnum("datastore.ReadOptions_ReadConsistency", ReadOptions_ReadConsistency_name, ReadOptions_ReadConsistency_value) - proto.RegisterEnum("datastore.BeginTransactionRequest_IsolationLevel", BeginTransactionRequest_IsolationLevel_name, BeginTransactionRequest_IsolationLevel_value) - proto.RegisterEnum("datastore.CommitRequest_Mode", CommitRequest_Mode_name, CommitRequest_Mode_value) -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/datastore/datastore_v1.proto b/Godeps/_workspace/src/google.golang.org/cloud/internal/datastore/datastore_v1.proto deleted file mode 100644 index d752beaa5..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/datastore/datastore_v1.proto +++ /dev/null @@ -1,606 +0,0 @@ -// Copyright 2013 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. -// -// The datastore v1 service proto definitions - -syntax = "proto2"; - -package datastore; -option java_package = "com.google.api.services.datastore"; - - -// An identifier for a particular subset of entities. -// -// Entities are partitioned into various subsets, each used by different -// datasets and different namespaces within a dataset and so forth. -// -// All input partition IDs are normalized before use. -// A partition ID is normalized as follows: -// If the partition ID is unset or is set to an empty partition ID, replace it -// with the context partition ID. -// Otherwise, if the partition ID has no dataset ID, assign it the context -// partition ID's dataset ID. -// Unless otherwise documented, the context partition ID has the dataset ID set -// to the context dataset ID and no other partition dimension set. -// -// A partition ID is empty if all of its fields are unset. -// -// Partition dimension: -// A dimension may be unset. -// A dimension's value must never be "". -// A dimension's value must match [A-Za-z\d\.\-_]{1,100} -// If the value of any dimension matches regex "__.*__", -// the partition is reserved/read-only. -// A reserved/read-only partition ID is forbidden in certain documented contexts. -// -// Dataset ID: -// A dataset id's value must never be "". -// A dataset id's value must match -// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99} -message PartitionId { - // The dataset ID. - optional string dataset_id = 3; - // The namespace. - optional string namespace = 4; -} - -// A unique identifier for an entity. -// If a key's partition id or any of its path kinds or names are -// reserved/read-only, the key is reserved/read-only. -// A reserved/read-only key is forbidden in certain documented contexts. -message Key { - // Entities are partitioned into subsets, currently identified by a dataset - // (usually implicitly specified by the project) and namespace ID. - // Queries are scoped to a single partition. - optional PartitionId partition_id = 1; - - // A (kind, ID/name) pair used to construct a key path. - // - // At most one of name or ID may be set. - // If either is set, the element is complete. - // If neither is set, the element is incomplete. - message PathElement { - // The kind of the entity. - // A kind matching regex "__.*__" is reserved/read-only. - // A kind must not contain more than 500 characters. - // Cannot be "". - required string kind = 1; - // The ID of the entity. - // Never equal to zero. Values less than zero are discouraged and will not - // be supported in the future. - optional int64 id = 2; - // The name of the entity. - // A name matching regex "__.*__" is reserved/read-only. - // A name must not be more than 500 characters. - // Cannot be "". - optional string name = 3; - } - - // The entity path. - // An entity path consists of one or more elements composed of a kind and a - // string or numerical identifier, which identify entities. The first - // element identifies a root entity, the second element identifies - // a child of the root entity, the third element a child of the - // second entity, and so forth. The entities identified by all prefixes of - // the path are called the element's ancestors. - // An entity path is always fully complete: ALL of the entity's ancestors - // are required to be in the path along with the entity identifier itself. - // The only exception is that in some documented cases, the identifier in the - // last path element (for the entity) itself may be omitted. A path can never - // be empty. - repeated PathElement path_element = 2; -} - -// A message that can hold any of the supported value types and associated -// metadata. -// -// At most one of the Value fields may be set. -// If none are set the value is "null". -// -message Value { - // A boolean value. - optional bool boolean_value = 1; - // An integer value. - optional int64 integer_value = 2; - // A double value. - optional double double_value = 3; - // A timestamp value. - optional int64 timestamp_microseconds_value = 4; - // A key value. - optional Key key_value = 5; - // A blob key value. - optional string blob_key_value = 16; - // A UTF-8 encoded string value. - optional string string_value = 17; - // A blob value. - optional bytes blob_value = 18; - // An entity value. - // May have no key. - // May have a key with an incomplete key path. - // May have a reserved/read-only key. - optional Entity entity_value = 6; - // A list value. - // Cannot contain another list value. - // Cannot also have a meaning and indexing set. - repeated Value list_value = 7; - - // The meaning field is reserved and should not be used. - optional int32 meaning = 14; - - // If the value should be indexed. - // - // The indexed property may be set for a - // null value. - // When indexed is true, stringValue - // is limited to 500 characters and the blob value is limited to 500 bytes. - // Exception: If meaning is set to 2, string_value is limited to 2038 - // characters regardless of indexed. - // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16 - // will be ignored on input (and will never be set on output). - // Input values by default have indexed set to - // true; however, you can explicitly set indexed to - // true if you want. (An output value never has - // indexed explicitly set to true.) If a value is - // itself an entity, it cannot have indexed set to - // true. - // Exception: An entity value with meaning 9, 20 or 21 may be indexed. - optional bool indexed = 15 [default = true]; -} - -// An entity property. -message Property { - // The name of the property. - // A property name matching regex "__.*__" is reserved. - // A reserved property name is forbidden in certain documented contexts. - // The name must not contain more than 500 characters. - // Cannot be "". - required string name = 1; - - // The value(s) of the property. - // Each value can have only one value property populated. For example, - // you cannot have a values list of { value: { integerValue: 22, - // stringValue: "a" } }, but you can have { value: { listValue: - // [ { integerValue: 22 }, { stringValue: "a" } ] }. - required Value value = 4; -} - -// An entity. -// -// An entity is limited to 1 megabyte when stored. That roughly -// corresponds to a limit of 1 megabyte for the serialized form of this -// message. -message Entity { - // The entity's key. - // - // An entity must have a key, unless otherwise documented (for example, - // an entity in Value.entityValue may have no key). - // An entity's kind is its key's path's last element's kind, - // or null if it has no key. - optional Key key = 1; - // The entity's properties. - // Each property's name must be unique for its entity. - repeated Property property = 2; -} - -// The result of fetching an entity from the datastore. -message EntityResult { - // Specifies what data the 'entity' field contains. - // A ResultType is either implied (for example, in LookupResponse.found it - // is always FULL) or specified by context (for example, in message - // QueryResultBatch, field 'entity_result_type' specifies a ResultType - // for all the values in field 'entity_result'). - enum ResultType { - FULL = 1; // The entire entity. - PROJECTION = 2; // A projected subset of properties. - // The entity may have no key. - // A property value may have meaning 18. - KEY_ONLY = 3; // Only the key. - } - - // The resulting entity. - required Entity entity = 1; -} - -// A query. -message Query { - // The projection to return. If not set the entire entity is returned. - repeated PropertyExpression projection = 2; - - // The kinds to query (if empty, returns entities from all kinds). - repeated KindExpression kind = 3; - - // The filter to apply (optional). - optional Filter filter = 4; - - // The order to apply to the query results (if empty, order is unspecified). - repeated PropertyOrder order = 5; - - // The properties to group by (if empty, no grouping is applied to the - // result set). - repeated PropertyReference group_by = 6; - - // A starting point for the query results. Optional. Query cursors are - // returned in query result batches. - optional bytes /* serialized QueryCursor */ start_cursor = 7; - - // An ending point for the query results. Optional. Query cursors are - // returned in query result batches. - optional bytes /* serialized QueryCursor */ end_cursor = 8; - - // The number of results to skip. Applies before limit, but after all other - // constraints (optional, defaults to 0). - optional int32 offset = 10 [default=0]; - - // The maximum number of results to return. Applies after all other - // constraints. Optional. - optional int32 limit = 11; -} - -// A representation of a kind. -message KindExpression { - // The name of the kind. - required string name = 1; -} - -// A reference to a property relative to the kind expressions. -// exactly. -message PropertyReference { - // The name of the property. - required string name = 2; -} - -// A representation of a property in a projection. -message PropertyExpression { - enum AggregationFunction { - FIRST = 1; - } - // The property to project. - required PropertyReference property = 1; - // The aggregation function to apply to the property. Optional. - // Can only be used when grouping by at least one property. Must - // then be set on all properties in the projection that are not - // being grouped by. - optional AggregationFunction aggregation_function = 2; -} - -// The desired order for a specific property. -message PropertyOrder { - enum Direction { - ASCENDING = 1; - DESCENDING = 2; - } - // The property to order by. - required PropertyReference property = 1; - // The direction to order by. - optional Direction direction = 2 [default=ASCENDING]; -} - -// A holder for any type of filter. Exactly one field should be specified. -message Filter { - // A composite filter. - optional CompositeFilter composite_filter = 1; - // A filter on a property. - optional PropertyFilter property_filter = 2; -} - -// A filter that merges the multiple other filters using the given operation. -message CompositeFilter { - enum Operator { - AND = 1; - } - - // The operator for combining multiple filters. - required Operator operator = 1; - // The list of filters to combine. - // Must contain at least one filter. - repeated Filter filter = 2; -} - -// A filter on a specific property. -message PropertyFilter { - enum Operator { - LESS_THAN = 1; - LESS_THAN_OR_EQUAL = 2; - GREATER_THAN = 3; - GREATER_THAN_OR_EQUAL = 4; - EQUAL = 5; - - HAS_ANCESTOR = 11; - } - - // The property to filter by. - required PropertyReference property = 1; - // The operator to filter by. - required Operator operator = 2; - // The value to compare the property to. - required Value value = 3; -} - -// A GQL query. -message GqlQuery { - required string query_string = 1; - // When false, the query string must not contain a literal. - optional bool allow_literal = 2 [default = false]; - // A named argument must set field GqlQueryArg.name. - // No two named arguments may have the same name. - // For each non-reserved named binding site in the query string, - // there must be a named argument with that name, - // but not necessarily the inverse. - repeated GqlQueryArg name_arg = 3; - // Numbered binding site @1 references the first numbered argument, - // effectively using 1-based indexing, rather than the usual 0. - // A numbered argument must NOT set field GqlQueryArg.name. - // For each binding site numbered i in query_string, - // there must be an ith numbered argument. - // The inverse must also be true. - repeated GqlQueryArg number_arg = 4; -} - -// A binding argument for a GQL query. -// Exactly one of fields value and cursor must be set. -message GqlQueryArg { - // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*". - // Must not match regex "__.*__". - // Must not be "". - optional string name = 1; - optional Value value = 2; - optional bytes cursor = 3; -} - -// A batch of results produced by a query. -message QueryResultBatch { - // The possible values for the 'more_results' field. - enum MoreResultsType { - NOT_FINISHED = 1; // There are additional batches to fetch from this query. - MORE_RESULTS_AFTER_LIMIT = 2; // The query is finished, but there are more - // results after the limit. - NO_MORE_RESULTS = 3; // The query has been exhausted. - } - - // The result type for every entity in entityResults. - required EntityResult.ResultType entity_result_type = 1; - // The results for this batch. - repeated EntityResult entity_result = 2; - - // A cursor that points to the position after the last result in the batch. - // May be absent. - optional bytes /* serialized QueryCursor */ end_cursor = 4; - - // The state of the query after the current batch. - required MoreResultsType more_results = 5; - - // The number of results skipped because of Query.offset. - optional int32 skipped_results = 6; -} - -// A set of changes to apply. -// -// No entity in this message may have a reserved property name, -// not even a property in an entity in a value. -// No value in this message may have meaning 18, -// not even a value in an entity in another value. -// -// If entities with duplicate keys are present, an arbitrary choice will -// be made as to which is written. -message Mutation { - // Entities to upsert. - // Each upserted entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity upsert = 1; - // Entities to update. - // Each updated entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity update = 2; - // Entities to insert. - // Each inserted entity's key must have a complete path and - // must not be reserved/read-only. - repeated Entity insert = 3; - // Insert entities with a newly allocated ID. - // Each inserted entity's key must omit the final identifier in its path and - // must not be reserved/read-only. - repeated Entity insert_auto_id = 4; - // Keys of entities to delete. - // Each key must have a complete key path and must not be reserved/read-only. - repeated Key delete = 5; - // Ignore a user specified read-only period. Optional. - optional bool force = 6; -} - -// The result of applying a mutation. -message MutationResult { - // Number of index writes. - required int32 index_updates = 1; - // Keys for insertAutoId entities. One per entity from the - // request, in the same order. - repeated Key insert_auto_id_key = 2; -} - -// Options shared by read requests. -message ReadOptions { - enum ReadConsistency { - DEFAULT = 0; - STRONG = 1; - EVENTUAL = 2; - } - - // The read consistency to use. - // Cannot be set when transaction is set. - // Lookup and ancestor queries default to STRONG, global queries default to - // EVENTUAL and cannot be set to STRONG. - optional ReadConsistency read_consistency = 1 [default=DEFAULT]; - - // The transaction to use. Optional. - optional bytes /* serialized Transaction */ transaction = 2; -} - -// The request for Lookup. -message LookupRequest { - - // Options for this lookup request. Optional. - optional ReadOptions read_options = 1; - // Keys of entities to look up from the datastore. - repeated Key key = 3; -} - -// The response for Lookup. -message LookupResponse { - - // The order of results in these fields is undefined and has no relation to - // the order of the keys in the input. - - // Entities found as ResultType.FULL entities. - repeated EntityResult found = 1; - - // Entities not found as ResultType.KEY_ONLY entities. - repeated EntityResult missing = 2; - - // A list of keys that were not looked up due to resource constraints. - repeated Key deferred = 3; -} - - -// The request for RunQuery. -message RunQueryRequest { - - // The options for this query. - optional ReadOptions read_options = 1; - - // Entities are partitioned into subsets, identified by a dataset (usually - // implicitly specified by the project) and namespace ID. Queries are scoped - // to a single partition. - // This partition ID is normalized with the standard default context - // partition ID, but all other partition IDs in RunQueryRequest are - // normalized with this partition ID as the context partition ID. - optional PartitionId partition_id = 2; - - // The query to run. - // Either this field or field gql_query must be set, but not both. - optional Query query = 3; - // The GQL query to run. - // Either this field or field query must be set, but not both. - optional GqlQuery gql_query = 7; -} - -// The response for RunQuery. -message RunQueryResponse { - - // A batch of query results (always present). - optional QueryResultBatch batch = 1; - -} - -// The request for BeginTransaction. -message BeginTransactionRequest { - - enum IsolationLevel { - SNAPSHOT = 0; // Read from a consistent snapshot. Concurrent transactions - // conflict if their mutations conflict. For example: - // Read(A),Write(B) may not conflict with Read(B),Write(A), - // but Read(B),Write(B) does conflict with Read(B),Write(B). - SERIALIZABLE = 1; // Read from a consistent snapshot. Concurrent - // transactions conflict if they cannot be serialized. - // For example Read(A),Write(B) does conflict with - // Read(B),Write(A) but Read(A) may not conflict with - // Write(A). - } - - // The transaction isolation level. - optional IsolationLevel isolation_level = 1 [default=SNAPSHOT]; -} - -// The response for BeginTransaction. -message BeginTransactionResponse { - - // The transaction identifier (always present). - optional bytes /* serialized Transaction */ transaction = 1; -} - -// The request for Rollback. -message RollbackRequest { - - // The transaction identifier, returned by a call to - // beginTransaction. - required bytes /* serialized Transaction */ transaction = 1; -} - -// The response for Rollback. -message RollbackResponse { -// Empty -} - -// The request for Commit. -message CommitRequest { - - enum Mode { - TRANSACTIONAL = 1; - NON_TRANSACTIONAL = 2; - } - - // The transaction identifier, returned by a call to - // beginTransaction. Must be set when mode is TRANSACTIONAL. - optional bytes /* serialized Transaction */ transaction = 1; - // The mutation to perform. Optional. - optional Mutation mutation = 2; - // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL. - optional Mode mode = 5 [default=TRANSACTIONAL]; -} - -// The response for Commit. -message CommitResponse { - - // The result of performing the mutation (if any). - optional MutationResult mutation_result = 1; -} - -// The request for AllocateIds. -message AllocateIdsRequest { - - // A list of keys with incomplete key paths to allocate IDs for. - // No key may be reserved/read-only. - repeated Key key = 1; -} - -// The response for AllocateIds. -message AllocateIdsResponse { - - // The keys specified in the request (in the same order), each with - // its key path completed with a newly allocated ID. - repeated Key key = 1; -} - -// Each rpc normalizes the partition IDs of the keys in its input entities, -// and always returns entities with keys with normalized partition IDs. -// (Note that applies to all entities, including entities in values.) -service DatastoreService { - // Look up some entities by key. - rpc Lookup(LookupRequest) returns (LookupResponse) { - }; - // Query for entities. - rpc RunQuery(RunQueryRequest) returns (RunQueryResponse) { - }; - // Begin a new transaction. - rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) { - }; - // Commit a transaction, optionally creating, deleting or modifying some - // entities. - rpc Commit(CommitRequest) returns (CommitResponse) { - }; - // Roll back a transaction. - rpc Rollback(RollbackRequest) returns (RollbackResponse) { - }; - // Allocate IDs for incomplete keys (useful for referencing an entity before - // it is inserted). - rpc AllocateIds(AllocateIdsRequest) returns (AllocateIdsResponse) { - }; -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/opts/option.go b/Godeps/_workspace/src/google.golang.org/cloud/internal/opts/option.go deleted file mode 100644 index 844d31044..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/opts/option.go +++ /dev/null @@ -1,25 +0,0 @@ -// Package opts holds the DialOpts struct, configurable by -// cloud.ClientOptions to set up transports for cloud packages. -// -// This is a separate page to prevent cycles between the core -// cloud packages. -package opts - -import ( - "net/http" - - "golang.org/x/oauth2" - "google.golang.org/grpc" -) - -type DialOpt struct { - Endpoint string - Scopes []string - UserAgent string - - TokenSource oauth2.TokenSource - - HTTPClient *http.Client - GRPCClient *grpc.ClientConn - GRPCDialOpts []grpc.DialOption -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/testutil/context.go b/Godeps/_workspace/src/google.golang.org/cloud/internal/testutil/context.go deleted file mode 100644 index 34e605898..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/testutil/context.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 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 testutil contains helper functions for writing tests. -package testutil - -import ( - "io/ioutil" - "log" - "os" - - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" -) - -const ( - envProjID = "GCLOUD_TESTS_GOLANG_PROJECT_ID" - envPrivateKey = "GCLOUD_TESTS_GOLANG_KEY" -) - -// ProjID returns the project ID to use in integration tests, or the empty -// string if none is configured. -func ProjID() string { - projID := os.Getenv(envProjID) - if projID == "" { - return "" - } - return projID -} - -// TokenSource returns the OAuth2 token source to use in integration tests, -// or nil if none is configured. TokenSource will log.Fatal if the token -// source is specified but missing or invalid. -func TokenSource(ctx context.Context, scopes ...string) oauth2.TokenSource { - key := os.Getenv(envPrivateKey) - if key == "" { - return nil - } - jsonKey, err := ioutil.ReadFile(key) - if err != nil { - log.Fatalf("Cannot read the JSON key file, err: %v", err) - } - conf, err := google.JWTConfigFromJSON(jsonKey, scopes...) - if err != nil { - log.Fatalf("google.JWTConfigFromJSON: %v", err) - } - return conf.TokenSource(ctx) -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/cancelreq.go b/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/cancelreq.go deleted file mode 100644 index ddae71cce..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/cancelreq.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015 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. - -// +build go1.5 - -package transport - -import "net/http" - -// makeReqCancel returns a closure that cancels the given http.Request -// when called. -func makeReqCancel(req *http.Request) func(http.RoundTripper) { - c := make(chan struct{}) - req.Cancel = c - return func(http.RoundTripper) { - close(c) - } -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/cancelreq_legacy.go b/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/cancelreq_legacy.go deleted file mode 100644 index c11a4ddeb..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/cancelreq_legacy.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015 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. - -// +build !go1.5 - -package transport - -import "net/http" - -// makeReqCancel returns a closure that cancels the given http.Request -// when called. -func makeReqCancel(req *http.Request) func(http.RoundTripper) { - // Go 1.4 and prior do not have a reliable way of cancelling a request. - // Transport.CancelRequest will only work if the request is already in-flight. - return func(r http.RoundTripper) { - if t, ok := r.(*http.Transport); ok { - t.CancelRequest(req) - } - } -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/dial.go b/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/dial.go deleted file mode 100644 index ae2baf9fd..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/dial.go +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2015 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 transport - -import ( - "errors" - "fmt" - "net/http" - - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "google.golang.org/cloud" - "google.golang.org/cloud/internal/opts" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/credentials/oauth" -) - -// ErrHTTP is returned when on a non-200 HTTP response. -type ErrHTTP struct { - StatusCode int - Body []byte - err error -} - -func (e *ErrHTTP) Error() string { - if e.err == nil { - return fmt.Sprintf("error during call, http status code: %v %s", e.StatusCode, e.Body) - } - return e.err.Error() -} - -// NewHTTPClient returns an HTTP client for use communicating with a Google cloud -// service, configured with the given ClientOptions. It also returns the endpoint -// for the service as specified in the options. -func NewHTTPClient(ctx context.Context, opt ...cloud.ClientOption) (*http.Client, string, error) { - var o opts.DialOpt - for _, opt := range opt { - opt.Resolve(&o) - } - if o.GRPCClient != nil { - return nil, "", errors.New("unsupported GRPC base transport specified") - } - // TODO(djd): Wrap all http.Clients with appropriate internal version to add - // UserAgent header and prepend correct endpoint. - if o.HTTPClient != nil { - return o.HTTPClient, o.Endpoint, nil - } - if o.TokenSource == nil { - var err error - o.TokenSource, err = google.DefaultTokenSource(ctx, o.Scopes...) - if err != nil { - return nil, "", fmt.Errorf("google.DefaultTokenSource: %v", err) - } - } - return oauth2.NewClient(ctx, o.TokenSource), o.Endpoint, nil -} - -// NewProtoClient returns a ProtoClient for communicating with a Google cloud service, -// configured with the given ClientOptions. -func NewProtoClient(ctx context.Context, opt ...cloud.ClientOption) (*ProtoClient, error) { - var o opts.DialOpt - for _, opt := range opt { - opt.Resolve(&o) - } - if o.GRPCClient != nil { - return nil, errors.New("unsupported GRPC base transport specified") - } - var client *http.Client - switch { - case o.HTTPClient != nil: - if o.TokenSource != nil { - return nil, errors.New("at most one of WithTokenSource or WithBaseHTTP may be provided") - } - client = o.HTTPClient - case o.TokenSource != nil: - client = oauth2.NewClient(ctx, o.TokenSource) - default: - var err error - client, err = google.DefaultClient(ctx, o.Scopes...) - if err != nil { - return nil, err - } - } - - return &ProtoClient{ - client: client, - endpoint: o.Endpoint, - userAgent: o.UserAgent, - }, nil -} - -// DialGRPC returns a GRPC connection for use communicating with a Google cloud -// service, configured with the given ClientOptions. -func DialGRPC(ctx context.Context, opt ...cloud.ClientOption) (*grpc.ClientConn, error) { - var o opts.DialOpt - for _, opt := range opt { - opt.Resolve(&o) - } - if o.HTTPClient != nil { - return nil, errors.New("unsupported HTTP base transport specified") - } - if o.GRPCClient != nil { - return o.GRPCClient, nil - } - if o.TokenSource == nil { - var err error - o.TokenSource, err = google.DefaultTokenSource(ctx, o.Scopes...) - if err != nil { - return nil, fmt.Errorf("google.DefaultTokenSource: %v", err) - } - } - grpcOpts := []grpc.DialOption{ - grpc.WithPerRPCCredentials(oauth.TokenSource{o.TokenSource}), - grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, "")), - } - grpcOpts = append(grpcOpts, o.GRPCDialOpts...) - if o.UserAgent != "" { - grpcOpts = append(grpcOpts, grpc.WithUserAgent(o.UserAgent)) - } - return grpc.Dial(o.Endpoint, grpcOpts...) -} diff --git a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/proto.go b/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/proto.go deleted file mode 100644 index 05b11cde1..000000000 --- a/Godeps/_workspace/src/google.golang.org/cloud/internal/transport/proto.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2015 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 transport - -import ( - "bytes" - "io/ioutil" - "net/http" - - "github.com/golang/protobuf/proto" - "golang.org/x/net/context" -) - -type ProtoClient struct { - client *http.Client - endpoint string - userAgent string -} - -func (c *ProtoClient) Call(ctx context.Context, method string, req, resp proto.Message) error { - payload, err := proto.Marshal(req) - if err != nil { - return err - } - - httpReq, err := http.NewRequest("POST", c.endpoint+method, bytes.NewReader(payload)) - if err != nil { - return err - } - httpReq.Header.Set("Content-Type", "application/x-protobuf") - if ua := c.userAgent; ua != "" { - httpReq.Header.Set("User-Agent", ua) - } - - errc := make(chan error, 1) - cancel := makeReqCancel(httpReq) - - go func() { - r, err := c.client.Do(httpReq) - if err != nil { - errc <- err - return - } - defer r.Body.Close() - - body, err := ioutil.ReadAll(r.Body) - if r.StatusCode != http.StatusOK { - err = &ErrHTTP{ - StatusCode: r.StatusCode, - Body: body, - err: err, - } - } - if err != nil { - errc <- err - return - } - errc <- proto.Unmarshal(body, resp) - }() - - select { - case <-ctx.Done(): - cancel(c.client.Transport) // Cancel the HTTP request. - return ctx.Err() - case err := <-errc: - return err - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/example_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/example_test.go deleted file mode 100644 index 6fda72acd..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/example_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package gcfg_test - -import ( - "fmt" - "log" -) - -import "gopkg.in/gcfg.v1" - -func ExampleReadStringInto() { - cfgStr := `; Comment line -[section] -name=value # comment` - cfg := struct { - Section struct { - Name string - } - }{} - err := gcfg.ReadStringInto(&cfg, cfgStr) - if err != nil { - log.Fatalf("Failed to parse gcfg data: %s", err) - } - fmt.Println(cfg.Section.Name) - // Output: value -} - -func ExampleReadStringInto_bool() { - cfgStr := `; Comment line -[section] -switch=on` - cfg := struct { - Section struct { - Switch bool - } - }{} - err := gcfg.ReadStringInto(&cfg, cfgStr) - if err != nil { - log.Fatalf("Failed to parse gcfg data: %s", err) - } - fmt.Println(cfg.Section.Switch) - // Output: true -} - -func ExampleReadStringInto_hyphens() { - cfgStr := `; Comment line -[section-name] -variable-name=value # comment` - cfg := struct { - Section_Name struct { - Variable_Name string - } - }{} - err := gcfg.ReadStringInto(&cfg, cfgStr) - if err != nil { - log.Fatalf("Failed to parse gcfg data: %s", err) - } - fmt.Println(cfg.Section_Name.Variable_Name) - // Output: value -} - -func ExampleReadStringInto_tags() { - cfgStr := `; Comment line -[section] -var-name=value # comment` - cfg := struct { - Section struct { - FieldName string `gcfg:"var-name"` - } - }{} - err := gcfg.ReadStringInto(&cfg, cfgStr) - if err != nil { - log.Fatalf("Failed to parse gcfg data: %s", err) - } - fmt.Println(cfg.Section.FieldName) - // Output: value -} - -func ExampleReadStringInto_subsections() { - cfgStr := `; Comment line -[profile "A"] -color = white - -[profile "B"] -color = black -` - cfg := struct { - Profile map[string]*struct { - Color string - } - }{} - err := gcfg.ReadStringInto(&cfg, cfgStr) - if err != nil { - log.Fatalf("Failed to parse gcfg data: %s", err) - } - fmt.Printf("%s %s\n", cfg.Profile["A"].Color, cfg.Profile["B"].Color) - // Output: white black -} - -func ExampleReadStringInto_multivalue() { - cfgStr := `; Comment line -[section] -multi=value1 -multi=value2` - cfg := struct { - Section struct { - Multi []string - } - }{} - err := gcfg.ReadStringInto(&cfg, cfgStr) - if err != nil { - log.Fatalf("Failed to parse gcfg data: %s", err) - } - fmt.Println(cfg.Section.Multi) - // Output: [value1 value2] -} - -func ExampleReadStringInto_unicode() { - cfgStr := `; Comment line -[甲] -乙=丙 # comment` - cfg := struct { - X甲 struct { - X乙 string - } - }{} - err := gcfg.ReadStringInto(&cfg, cfgStr) - if err != nil { - log.Fatalf("Failed to parse gcfg data: %s", err) - } - fmt.Println(cfg.X甲.X乙) - // Output: 丙 -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/issues_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/issues_test.go deleted file mode 100644 index 796dd10b6..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/issues_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package gcfg - -import ( - "fmt" - "math/big" - "strings" - "testing" -) - -type Config1 struct { - Section struct { - Int int - BigInt big.Int - } -} - -var testsIssue1 = []struct { - cfg string - typename string -}{ - {"[section]\nint=X", "int"}, - {"[section]\nint=", "int"}, - {"[section]\nint=1A", "int"}, - {"[section]\nbigint=X", "big.Int"}, - {"[section]\nbigint=", "big.Int"}, - {"[section]\nbigint=1A", "big.Int"}, -} - -// Value parse error should: -// - include plain type name -// - not include reflect internals -func TestIssue1(t *testing.T) { - for i, tt := range testsIssue1 { - var c Config1 - err := ReadStringInto(&c, tt.cfg) - switch { - case err == nil: - t.Errorf("%d fail: got ok; wanted error", i) - case !strings.Contains(err.Error(), tt.typename): - t.Errorf("%d fail: error message doesn't contain type name %q: %v", - i, tt.typename, err) - case strings.Contains(err.Error(), "reflect"): - t.Errorf("%d fail: error message includes reflect internals: %v", - i, err) - default: - t.Logf("%d pass: %v", i, err) - } - } -} - -type confIssue2 struct{ Main struct{ Foo string } } - -var testsIssue2 = []readtest{ - {"[main]\n;\nfoo = bar\n", &confIssue2{struct{ Foo string }{"bar"}}, true}, - {"[main]\r\n;\r\nfoo = bar\r\n", &confIssue2{struct{ Foo string }{"bar"}}, true}, -} - -func TestIssue2(t *testing.T) { - for i, tt := range testsIssue2 { - id := fmt.Sprintf("issue2:%d", i) - testRead(t, id, tt) - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/read_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/read_test.go deleted file mode 100644 index 404d04dd9..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/read_test.go +++ /dev/null @@ -1,338 +0,0 @@ -package gcfg - -import ( - "fmt" - "math/big" - "os" - "reflect" - "testing" -) - -const ( - // 64 spaces - sp64 = " " - // 512 spaces - sp512 = sp64 + sp64 + sp64 + sp64 + sp64 + sp64 + sp64 + sp64 - // 4096 spaces - sp4096 = sp512 + sp512 + sp512 + sp512 + sp512 + sp512 + sp512 + sp512 -) - -type cBasic struct { - Section cBasicS1 - Hyphen_In_Section cBasicS2 - unexported cBasicS1 - Exported cBasicS3 - TagName cBasicS1 `gcfg:"tag-name"` -} -type cBasicS1 struct { - Name string - Int int - PName *string -} -type cBasicS2 struct { - Hyphen_In_Name string -} -type cBasicS3 struct { - unexported string -} - -type nonMulti []string - -type unmarshalable string - -func (u *unmarshalable) UnmarshalText(text []byte) error { - s := string(text) - if s == "error" { - return fmt.Errorf("%s", s) - } - *u = unmarshalable(s) - return nil -} - -var _ textUnmarshaler = new(unmarshalable) - -type cUni struct { - X甲 cUniS1 - XSection cUniS2 -} -type cUniS1 struct { - X乙 string -} -type cUniS2 struct { - XName string -} - -type cMulti struct { - M1 cMultiS1 - M2 cMultiS2 - M3 cMultiS3 -} -type cMultiS1 struct{ Multi []string } -type cMultiS2 struct{ NonMulti nonMulti } -type cMultiS3 struct{ PMulti *[]string } - -type cSubs struct{ Sub map[string]*cSubsS1 } -type cSubsS1 struct{ Name string } - -type cBool struct{ Section cBoolS1 } -type cBoolS1 struct{ Bool bool } - -type cTxUnm struct{ Section cTxUnmS1 } -type cTxUnmS1 struct{ Name unmarshalable } - -type cNum struct { - N1 cNumS1 - N2 cNumS2 - N3 cNumS3 -} -type cNumS1 struct { - Int int - IntDHO int `gcfg:",int=dho"` - Big *big.Int -} -type cNumS2 struct { - MultiInt []int - MultiBig []*big.Int -} -type cNumS3 struct{ FileMode os.FileMode } -type readtest struct { - gcfg string - exp interface{} - ok bool -} - -func newString(s string) *string { return &s } -func newStringSlice(s ...string) *[]string { return &s } - -var readtests = []struct { - group string - tests []readtest -}{{"scanning", []readtest{ - {"[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - // hyphen in name - {"[hyphen-in-section]\nhyphen-in-name=value", &cBasic{Hyphen_In_Section: cBasicS2{Hyphen_In_Name: "value"}}, true}, - // quoted string value - {"[section]\nname=\"\"", &cBasic{Section: cBasicS1{Name: ""}}, true}, - {"[section]\nname=\" \"", &cBasic{Section: cBasicS1{Name: " "}}, true}, - {"[section]\nname=\"value\"", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname=\" value \"", &cBasic{Section: cBasicS1{Name: " value "}}, true}, - {"\n[section]\nname=\"va ; lue\"", &cBasic{Section: cBasicS1{Name: "va ; lue"}}, true}, - {"[section]\nname=\"val\" \"ue\"", &cBasic{Section: cBasicS1{Name: "val ue"}}, true}, - {"[section]\nname=\"value", &cBasic{}, false}, - // escape sequences - {"[section]\nname=\"va\\\\lue\"", &cBasic{Section: cBasicS1{Name: "va\\lue"}}, true}, - {"[section]\nname=\"va\\\"lue\"", &cBasic{Section: cBasicS1{Name: "va\"lue"}}, true}, - {"[section]\nname=\"va\\nlue\"", &cBasic{Section: cBasicS1{Name: "va\nlue"}}, true}, - {"[section]\nname=\"va\\tlue\"", &cBasic{Section: cBasicS1{Name: "va\tlue"}}, true}, - {"\n[section]\nname=\\", &cBasic{}, false}, - {"\n[section]\nname=\\a", &cBasic{}, false}, - {"\n[section]\nname=\"val\\a\"", &cBasic{}, false}, - {"\n[section]\nname=val\\", &cBasic{}, false}, - {"\n[sub \"A\\\n\"]\nname=value", &cSubs{}, false}, - {"\n[sub \"A\\\t\"]\nname=value", &cSubs{}, false}, - // broken line - {"[section]\nname=value \\\n value", &cBasic{Section: cBasicS1{Name: "value value"}}, true}, - {"[section]\nname=\"value \\\n value\"", &cBasic{}, false}, -}}, {"scanning:whitespace", []readtest{ - {" \n[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {" [section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\t[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[ section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section ]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\n name=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname =value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname= value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname=value ", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\r\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\r\nname=value\r\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {";cmnt\r\n[section]\r\nname=value\r\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - // long lines - {sp4096 + "[section]\nname=value\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[" + sp4096 + "section]\nname=value\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section" + sp4096 + "]\nname=value\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]" + sp4096 + "\nname=value\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\n" + sp4096 + "name=value\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname" + sp4096 + "=value\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname=" + sp4096 + "value\n", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname=value\n" + sp4096, &cBasic{Section: cBasicS1{Name: "value"}}, true}, -}}, {"scanning:comments", []readtest{ - {"; cmnt\n[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"# cmnt\n[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {" ; cmnt\n[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\t; cmnt\n[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\n[section]; cmnt\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\n[section] ; cmnt\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\n[section]\nname=value; cmnt", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\n[section]\nname=value ; cmnt", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\n[section]\nname=\"value\" ; cmnt", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\n[section]\nname=value ; \"cmnt", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"\n[section]\nname=\"va ; lue\" ; cmnt", &cBasic{Section: cBasicS1{Name: "va ; lue"}}, true}, - {"\n[section]\nname=; cmnt", &cBasic{Section: cBasicS1{Name: ""}}, true}, -}}, {"scanning:subsections", []readtest{ - {"\n[sub \"A\"]\nname=value", &cSubs{map[string]*cSubsS1{"A": &cSubsS1{"value"}}}, true}, - {"\n[sub \"b\"]\nname=value", &cSubs{map[string]*cSubsS1{"b": &cSubsS1{"value"}}}, true}, - {"\n[sub \"A\\\\\"]\nname=value", &cSubs{map[string]*cSubsS1{"A\\": &cSubsS1{"value"}}}, true}, - {"\n[sub \"A\\\"\"]\nname=value", &cSubs{map[string]*cSubsS1{"A\"": &cSubsS1{"value"}}}, true}, -}}, {"syntax", []readtest{ - // invalid line - {"\n[section]\n=", &cBasic{}, false}, - // no section - {"name=value", &cBasic{}, false}, - // empty section - {"\n[]\nname=value", &cBasic{}, false}, - // empty subsection - {"\n[sub \"\"]\nname=value", &cSubs{}, false}, -}}, {"setting", []readtest{ - {"[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - // pointer - {"[section]", &cBasic{Section: cBasicS1{PName: nil}}, true}, - {"[section]\npname=value", &cBasic{Section: cBasicS1{PName: newString("value")}}, true}, - {"[m3]", &cMulti{M3: cMultiS3{PMulti: nil}}, true}, - {"[m3]\npmulti", &cMulti{M3: cMultiS3{PMulti: newStringSlice()}}, true}, - {"[m3]\npmulti=value", &cMulti{M3: cMultiS3{PMulti: newStringSlice("value")}}, true}, - {"[m3]\npmulti=value1\npmulti=value2", &cMulti{M3: cMultiS3{PMulti: newStringSlice("value1", "value2")}}, true}, - // section name not matched - {"\n[nonexistent]\nname=value", &cBasic{}, false}, - // subsection name not matched - {"\n[section \"nonexistent\"]\nname=value", &cBasic{}, false}, - // variable name not matched - {"\n[section]\nnonexistent=value", &cBasic{}, false}, - // hyphen in name - {"[hyphen-in-section]\nhyphen-in-name=value", &cBasic{Hyphen_In_Section: cBasicS2{Hyphen_In_Name: "value"}}, true}, - // ignore unexported fields - {"[unexported]\nname=value", &cBasic{}, false}, - {"[exported]\nunexported=value", &cBasic{}, false}, - // 'X' prefix for non-upper/lower-case letters - {"[甲]\n乙=丙", &cUni{X甲: cUniS1{X乙: "丙"}}, true}, - //{"[section]\nxname=value", &cBasic{XSection: cBasicS4{XName: "value"}}, false}, - //{"[xsection]\nname=value", &cBasic{XSection: cBasicS4{XName: "value"}}, false}, - // name specified as struct tag - {"[tag-name]\nname=value", &cBasic{TagName: cBasicS1{Name: "value"}}, true}, - // empty subsections - {"\n[sub \"A\"]\n[sub \"B\"]", &cSubs{map[string]*cSubsS1{"A": &cSubsS1{}, "B": &cSubsS1{}}}, true}, -}}, {"multivalue", []readtest{ - // unnamed slice type: treat as multi-value - {"\n[m1]", &cMulti{M1: cMultiS1{}}, true}, - {"\n[m1]\nmulti=value", &cMulti{M1: cMultiS1{[]string{"value"}}}, true}, - {"\n[m1]\nmulti=value1\nmulti=value2", &cMulti{M1: cMultiS1{[]string{"value1", "value2"}}}, true}, - // "blank" empties multi-valued slice -- here same result as above - {"\n[m1]\nmulti\nmulti=value1\nmulti=value2", &cMulti{M1: cMultiS1{[]string{"value1", "value2"}}}, true}, - // named slice type: do not treat as multi-value - {"\n[m2]", &cMulti{}, true}, - {"\n[m2]\nmulti=value", &cMulti{}, false}, - {"\n[m2]\nmulti=value1\nmulti=value2", &cMulti{}, false}, -}}, {"type:string", []readtest{ - {"[section]\nname=value", &cBasic{Section: cBasicS1{Name: "value"}}, true}, - {"[section]\nname=", &cBasic{Section: cBasicS1{Name: ""}}, true}, -}}, {"type:bool", []readtest{ - // explicit values - {"[section]\nbool=true", &cBool{cBoolS1{true}}, true}, - {"[section]\nbool=yes", &cBool{cBoolS1{true}}, true}, - {"[section]\nbool=on", &cBool{cBoolS1{true}}, true}, - {"[section]\nbool=1", &cBool{cBoolS1{true}}, true}, - {"[section]\nbool=tRuE", &cBool{cBoolS1{true}}, true}, - {"[section]\nbool=false", &cBool{cBoolS1{false}}, true}, - {"[section]\nbool=no", &cBool{cBoolS1{false}}, true}, - {"[section]\nbool=off", &cBool{cBoolS1{false}}, true}, - {"[section]\nbool=0", &cBool{cBoolS1{false}}, true}, - {"[section]\nbool=NO", &cBool{cBoolS1{false}}, true}, - // "blank" value handled as true - {"[section]\nbool", &cBool{cBoolS1{true}}, true}, - // bool parse errors - {"[section]\nbool=maybe", &cBool{}, false}, - {"[section]\nbool=t", &cBool{}, false}, - {"[section]\nbool=truer", &cBool{}, false}, - {"[section]\nbool=2", &cBool{}, false}, - {"[section]\nbool=-1", &cBool{}, false}, -}}, {"type:numeric", []readtest{ - {"[section]\nint=0", &cBasic{Section: cBasicS1{Int: 0}}, true}, - {"[section]\nint=1", &cBasic{Section: cBasicS1{Int: 1}}, true}, - {"[section]\nint=-1", &cBasic{Section: cBasicS1{Int: -1}}, true}, - {"[section]\nint=0.2", &cBasic{}, false}, - {"[section]\nint=1e3", &cBasic{}, false}, - // primitive [u]int(|8|16|32|64) and big.Int is parsed as dec or hex (not octal) - {"[n1]\nint=010", &cNum{N1: cNumS1{Int: 10}}, true}, - {"[n1]\nint=0x10", &cNum{N1: cNumS1{Int: 0x10}}, true}, - {"[n1]\nbig=1", &cNum{N1: cNumS1{Big: big.NewInt(1)}}, true}, - {"[n1]\nbig=0x10", &cNum{N1: cNumS1{Big: big.NewInt(0x10)}}, true}, - {"[n1]\nbig=010", &cNum{N1: cNumS1{Big: big.NewInt(10)}}, true}, - {"[n2]\nmultiint=010", &cNum{N2: cNumS2{MultiInt: []int{10}}}, true}, - {"[n2]\nmultibig=010", &cNum{N2: cNumS2{MultiBig: []*big.Int{big.NewInt(10)}}}, true}, - // set parse mode for int types via struct tag - {"[n1]\nintdho=010", &cNum{N1: cNumS1{IntDHO: 010}}, true}, - // octal allowed for named type - {"[n3]\nfilemode=0777", &cNum{N3: cNumS3{FileMode: 0777}}, true}, -}}, {"type:textUnmarshaler", []readtest{ - {"[section]\nname=value", &cTxUnm{Section: cTxUnmS1{Name: "value"}}, true}, - {"[section]\nname=error", &cTxUnm{}, false}, -}}, -} - -func TestReadStringInto(t *testing.T) { - for _, tg := range readtests { - for i, tt := range tg.tests { - id := fmt.Sprintf("%s:%d", tg.group, i) - testRead(t, id, tt) - } - } -} - -func TestReadStringIntoMultiBlankPreset(t *testing.T) { - tt := readtest{"\n[m1]\nmulti\nmulti=value1\nmulti=value2", &cMulti{M1: cMultiS1{[]string{"value1", "value2"}}}, true} - cfg := &cMulti{M1: cMultiS1{[]string{"preset1", "preset2"}}} - testReadInto(t, "multi:blank", tt, cfg) -} - -func testRead(t *testing.T, id string, tt readtest) { - // get the type of the expected result - restyp := reflect.TypeOf(tt.exp).Elem() - // create a new instance to hold the actual result - res := reflect.New(restyp).Interface() - testReadInto(t, id, tt, res) -} - -func testReadInto(t *testing.T, id string, tt readtest, res interface{}) { - err := ReadStringInto(res, tt.gcfg) - if tt.ok { - if err != nil { - t.Errorf("%s fail: got error %v, wanted ok", id, err) - return - } else if !reflect.DeepEqual(res, tt.exp) { - t.Errorf("%s fail: got value %#v, wanted value %#v", id, res, tt.exp) - return - } - if !testing.Short() { - t.Logf("%s pass: got value %#v", id, res) - } - } else { // !tt.ok - if err == nil { - t.Errorf("%s fail: got value %#v, wanted error", id, res) - return - } - if !testing.Short() { - t.Logf("%s pass: got error %v", id, err) - } - } -} - -func TestReadFileInto(t *testing.T) { - res := &struct{ Section struct{ Name string } }{} - err := ReadFileInto(res, "testdata/gcfg_test.gcfg") - if err != nil { - t.Errorf(err.Error()) - } - if "value" != res.Section.Name { - t.Errorf("got %q, wanted %q", res.Section.Name, "value") - } -} - -func TestReadFileIntoUnicode(t *testing.T) { - res := &struct{ X甲 struct{ X乙 string } }{} - err := ReadFileInto(res, "testdata/gcfg_unicode_test.gcfg") - if err != nil { - t.Errorf(err.Error()) - } - if "丙" != res.X甲.X乙 { - t.Errorf("got %q, wanted %q", res.X甲.X乙, "丙") - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/scanner/example_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/scanner/example_test.go deleted file mode 100644 index ce08e9ca9..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/scanner/example_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package scanner_test - -import ( - "fmt" -) - -import ( - "gopkg.in/gcfg.v1/scanner" - "gopkg.in/gcfg.v1/token" -) - -func ExampleScanner_Scan() { - // src is the input that we want to tokenize. - src := []byte(`[profile "A"] -color = blue ; Comment`) - - // Initialize the scanner. - var s scanner.Scanner - fset := token.NewFileSet() // positions are relative to fset - file := fset.AddFile("", fset.Base(), len(src)) // register input "file" - s.Init(file, src, nil /* no error handler */, scanner.ScanComments) - - // Repeated calls to Scan yield the token sequence found in the input. - for { - pos, tok, lit := s.Scan() - if tok == token.EOF { - break - } - fmt.Printf("%s\t%q\t%q\n", fset.Position(pos), tok, lit) - } - - // output: - // 1:1 "[" "" - // 1:2 "IDENT" "profile" - // 1:10 "STRING" "\"A\"" - // 1:13 "]" "" - // 1:14 "\n" "" - // 2:1 "IDENT" "color" - // 2:7 "=" "" - // 2:9 "STRING" "blue" - // 2:14 "COMMENT" "; Comment" -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/scanner/scanner_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/scanner/scanner_test.go deleted file mode 100644 index bef219d4c..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/scanner/scanner_test.go +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package scanner - -import ( - "os" - "strings" - "testing" -) - -import ( - "gopkg.in/gcfg.v1/token" -) - -var fset = token.NewFileSet() - -const /* class */ ( - special = iota - literal - operator -) - -func tokenclass(tok token.Token) int { - switch { - case tok.IsLiteral(): - return literal - case tok.IsOperator(): - return operator - } - return special -} - -type elt struct { - tok token.Token - lit string - class int - pre string - suf string -} - -var tokens = [...]elt{ - // Special tokens - {token.COMMENT, "; a comment", special, "", "\n"}, - {token.COMMENT, "# a comment", special, "", "\n"}, - - // Operators and delimiters - {token.ASSIGN, "=", operator, "", "value"}, - {token.LBRACK, "[", operator, "", ""}, - {token.RBRACK, "]", operator, "", ""}, - {token.EOL, "\n", operator, "", ""}, - - // Identifiers - {token.IDENT, "foobar", literal, "", ""}, - {token.IDENT, "a۰۱۸", literal, "", ""}, - {token.IDENT, "foo६४", literal, "", ""}, - {token.IDENT, "bar9876", literal, "", ""}, - {token.IDENT, "foo-bar", literal, "", ""}, - {token.IDENT, "foo", literal, ";\n", ""}, - // String literals (subsection names) - {token.STRING, `"foobar"`, literal, "", ""}, - {token.STRING, `"\""`, literal, "", ""}, - // String literals (values) - {token.STRING, `"\n"`, literal, "=", ""}, - {token.STRING, `"foobar"`, literal, "=", ""}, - {token.STRING, `"foo\nbar"`, literal, "=", ""}, - {token.STRING, `"foo\"bar"`, literal, "=", ""}, - {token.STRING, `"foo\\bar"`, literal, "=", ""}, - {token.STRING, `"foobar"`, literal, "=", ""}, - {token.STRING, `"foobar"`, literal, "= ", ""}, - {token.STRING, `"foobar"`, literal, "=", "\n"}, - {token.STRING, `"foobar"`, literal, "=", ";"}, - {token.STRING, `"foobar"`, literal, "=", " ;"}, - {token.STRING, `"foobar"`, literal, "=", "#"}, - {token.STRING, `"foobar"`, literal, "=", " #"}, - {token.STRING, "foobar", literal, "=", ""}, - {token.STRING, "foobar", literal, "= ", ""}, - {token.STRING, "foobar", literal, "=", " "}, - {token.STRING, `"foo" "bar"`, literal, "=", " "}, - {token.STRING, "foo\\\nbar", literal, "=", ""}, - {token.STRING, "foo\\\r\nbar", literal, "=", ""}, -} - -const whitespace = " \t \n\n\n" // to separate tokens - -var source = func() []byte { - var src []byte - for _, t := range tokens { - src = append(src, t.pre...) - src = append(src, t.lit...) - src = append(src, t.suf...) - src = append(src, whitespace...) - } - return src -}() - -func newlineCount(s string) int { - n := 0 - for i := 0; i < len(s); i++ { - if s[i] == '\n' { - n++ - } - } - return n -} - -func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) { - pos := fset.Position(p) - if pos.Filename != expected.Filename { - t.Errorf("bad filename for %q: got %s, expected %s", lit, pos.Filename, expected.Filename) - } - if pos.Offset != expected.Offset { - t.Errorf("bad position for %q: got %d, expected %d", lit, pos.Offset, expected.Offset) - } - if pos.Line != expected.Line { - t.Errorf("bad line for %q: got %d, expected %d", lit, pos.Line, expected.Line) - } - if pos.Column != expected.Column { - t.Errorf("bad column for %q: got %d, expected %d", lit, pos.Column, expected.Column) - } -} - -// Verify that calling Scan() provides the correct results. -func TestScan(t *testing.T) { - // make source - src_linecount := newlineCount(string(source)) - whitespace_linecount := newlineCount(whitespace) - - index := 0 - - // error handler - eh := func(_ token.Position, msg string) { - t.Errorf("%d: error handler called (msg = %s)", index, msg) - } - - // verify scan - var s Scanner - s.Init(fset.AddFile("", fset.Base(), len(source)), source, eh, ScanComments) - // epos is the expected position - epos := token.Position{ - Filename: "", - Offset: 0, - Line: 1, - Column: 1, - } - for { - pos, tok, lit := s.Scan() - if lit == "" { - // no literal value for non-literal tokens - lit = tok.String() - } - e := elt{token.EOF, "", special, "", ""} - if index < len(tokens) { - e = tokens[index] - } - if tok == token.EOF { - lit = "" - epos.Line = src_linecount - epos.Column = 2 - } - if e.pre != "" && strings.ContainsRune("=;#", rune(e.pre[0])) { - epos.Column = 1 - checkPos(t, lit, pos, epos) - var etok token.Token - if e.pre[0] == '=' { - etok = token.ASSIGN - } else { - etok = token.COMMENT - } - if tok != etok { - t.Errorf("bad token for %q: got %q, expected %q", lit, tok, etok) - } - pos, tok, lit = s.Scan() - } - epos.Offset += len(e.pre) - if tok != token.EOF { - epos.Column = 1 + len(e.pre) - } - if e.pre != "" && e.pre[len(e.pre)-1] == '\n' { - epos.Offset-- - epos.Column-- - checkPos(t, lit, pos, epos) - if tok != token.EOL { - t.Errorf("bad token for %q: got %q, expected %q", lit, tok, token.EOL) - } - epos.Line++ - epos.Offset++ - epos.Column = 1 - pos, tok, lit = s.Scan() - } - checkPos(t, lit, pos, epos) - if tok != e.tok { - t.Errorf("bad token for %q: got %q, expected %q", lit, tok, e.tok) - } - if e.tok.IsLiteral() { - // no CRs in value string literals - elit := e.lit - if strings.ContainsRune(e.pre, '=') { - elit = string(stripCR([]byte(elit))) - epos.Offset += len(e.lit) - len(lit) // correct position - } - if lit != elit { - t.Errorf("bad literal for %q: got %q, expected %q", lit, lit, elit) - } - } - if tokenclass(tok) != e.class { - t.Errorf("bad class for %q: got %d, expected %d", lit, tokenclass(tok), e.class) - } - epos.Offset += len(lit) + len(e.suf) + len(whitespace) - epos.Line += newlineCount(lit) + newlineCount(e.suf) + whitespace_linecount - index++ - if tok == token.EOF { - break - } - if e.suf == "value" { - pos, tok, lit = s.Scan() - if tok != token.STRING { - t.Errorf("bad token for %q: got %q, expected %q", lit, tok, token.STRING) - } - } else if strings.ContainsRune(e.suf, ';') || strings.ContainsRune(e.suf, '#') { - pos, tok, lit = s.Scan() - if tok != token.COMMENT { - t.Errorf("bad token for %q: got %q, expected %q", lit, tok, token.COMMENT) - } - } - // skip EOLs - for i := 0; i < whitespace_linecount+newlineCount(e.suf); i++ { - pos, tok, lit = s.Scan() - if tok != token.EOL { - t.Errorf("bad token for %q: got %q, expected %q", lit, tok, token.EOL) - } - } - } - if s.ErrorCount != 0 { - t.Errorf("found %d errors", s.ErrorCount) - } -} - -func TestScanValStringEOF(t *testing.T) { - var s Scanner - src := "= value" - f := fset.AddFile("src", fset.Base(), len(src)) - s.Init(f, []byte(src), nil, 0) - s.Scan() // = - s.Scan() // value - _, tok, _ := s.Scan() // EOF - if tok != token.EOF { - t.Errorf("bad token: got %s, expected %s", tok, token.EOF) - } - if s.ErrorCount > 0 { - t.Error("scanning error") - } -} - -// Verify that initializing the same scanner more then once works correctly. -func TestInit(t *testing.T) { - var s Scanner - - // 1st init - src1 := "\nname = value" - f1 := fset.AddFile("src1", fset.Base(), len(src1)) - s.Init(f1, []byte(src1), nil, 0) - if f1.Size() != len(src1) { - t.Errorf("bad file size: got %d, expected %d", f1.Size(), len(src1)) - } - s.Scan() // \n - s.Scan() // name - _, tok, _ := s.Scan() // = - if tok != token.ASSIGN { - t.Errorf("bad token: got %s, expected %s", tok, token.ASSIGN) - } - - // 2nd init - src2 := "[section]" - f2 := fset.AddFile("src2", fset.Base(), len(src2)) - s.Init(f2, []byte(src2), nil, 0) - if f2.Size() != len(src2) { - t.Errorf("bad file size: got %d, expected %d", f2.Size(), len(src2)) - } - _, tok, _ = s.Scan() // [ - if tok != token.LBRACK { - t.Errorf("bad token: got %s, expected %s", tok, token.LBRACK) - } - - if s.ErrorCount != 0 { - t.Errorf("found %d errors", s.ErrorCount) - } -} - -func TestStdErrorHandler(t *testing.T) { - const src = "@\n" + // illegal character, cause an error - "@ @\n" // two errors on the same line - - var list ErrorList - eh := func(pos token.Position, msg string) { list.Add(pos, msg) } - - var s Scanner - s.Init(fset.AddFile("File1", fset.Base(), len(src)), []byte(src), eh, 0) - for { - if _, tok, _ := s.Scan(); tok == token.EOF { - break - } - } - - if len(list) != s.ErrorCount { - t.Errorf("found %d errors, expected %d", len(list), s.ErrorCount) - } - - if len(list) != 3 { - t.Errorf("found %d raw errors, expected 3", len(list)) - PrintError(os.Stderr, list) - } - - list.Sort() - if len(list) != 3 { - t.Errorf("found %d sorted errors, expected 3", len(list)) - PrintError(os.Stderr, list) - } - - list.RemoveMultiples() - if len(list) != 2 { - t.Errorf("found %d one-per-line errors, expected 2", len(list)) - PrintError(os.Stderr, list) - } -} - -type errorCollector struct { - cnt int // number of errors encountered - msg string // last error message encountered - pos token.Position // last error position encountered -} - -func checkError(t *testing.T, src string, tok token.Token, pos int, err string) { - var s Scanner - var h errorCollector - eh := func(pos token.Position, msg string) { - h.cnt++ - h.msg = msg - h.pos = pos - } - s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), eh, ScanComments) - if src[0] == '=' { - _, _, _ = s.Scan() - } - _, tok0, _ := s.Scan() - _, tok1, _ := s.Scan() - if tok0 != tok { - t.Errorf("%q: got %s, expected %s", src, tok0, tok) - } - if tok1 != token.EOF { - t.Errorf("%q: got %s, expected EOF", src, tok1) - } - cnt := 0 - if err != "" { - cnt = 1 - } - if h.cnt != cnt { - t.Errorf("%q: got cnt %d, expected %d", src, h.cnt, cnt) - } - if h.msg != err { - t.Errorf("%q: got msg %q, expected %q", src, h.msg, err) - } - if h.pos.Offset != pos { - t.Errorf("%q: got offset %d, expected %d", src, h.pos.Offset, pos) - } -} - -var errors = []struct { - src string - tok token.Token - pos int - err string -}{ - {"\a", token.ILLEGAL, 0, "illegal character U+0007"}, - {"/", token.ILLEGAL, 0, "illegal character U+002F '/'"}, - {"_", token.ILLEGAL, 0, "illegal character U+005F '_'"}, - {`…`, token.ILLEGAL, 0, "illegal character U+2026 '…'"}, - {`""`, token.STRING, 0, ""}, - {`"`, token.STRING, 0, "string not terminated"}, - {"\"\n", token.STRING, 0, "string not terminated"}, - {`="`, token.STRING, 1, "string not terminated"}, - {"=\"\n", token.STRING, 1, "string not terminated"}, - {"=\\", token.STRING, 1, "unquoted '\\' must be followed by new line"}, - {"=\\\r", token.STRING, 1, "unquoted '\\' must be followed by new line"}, - {`"\z"`, token.STRING, 2, "unknown escape sequence"}, - {`"\a"`, token.STRING, 2, "unknown escape sequence"}, - {`"\b"`, token.STRING, 2, "unknown escape sequence"}, - {`"\f"`, token.STRING, 2, "unknown escape sequence"}, - {`"\r"`, token.STRING, 2, "unknown escape sequence"}, - {`"\t"`, token.STRING, 2, "unknown escape sequence"}, - {`"\v"`, token.STRING, 2, "unknown escape sequence"}, - {`"\0"`, token.STRING, 2, "unknown escape sequence"}, -} - -func TestScanErrors(t *testing.T) { - for _, e := range errors { - checkError(t, e.src, e.tok, e.pos, e.err) - } -} - -func BenchmarkScan(b *testing.B) { - b.StopTimer() - fset := token.NewFileSet() - file := fset.AddFile("", fset.Base(), len(source)) - var s Scanner - b.StartTimer() - for i := b.N - 1; i >= 0; i-- { - s.Init(file, source, nil, ScanComments) - for { - _, tok, _ := s.Scan() - if tok == token.EOF { - break - } - } - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/testdata/gcfg_test.gcfg b/Godeps/_workspace/src/gopkg.in/gcfg.v1/testdata/gcfg_test.gcfg deleted file mode 100644 index cddff29ab..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/testdata/gcfg_test.gcfg +++ /dev/null @@ -1,3 +0,0 @@ -; Comment line -[section] -name=value # comment diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/testdata/gcfg_unicode_test.gcfg b/Godeps/_workspace/src/gopkg.in/gcfg.v1/testdata/gcfg_unicode_test.gcfg deleted file mode 100644 index 3762a201e..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/testdata/gcfg_unicode_test.gcfg +++ /dev/null @@ -1,3 +0,0 @@ -; Comment line -[甲] -乙=丙 # comment diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/token/position_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/token/position_test.go deleted file mode 100644 index 160107df4..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/token/position_test.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package token - -import ( - "fmt" - "testing" -) - -func checkPos(t *testing.T, msg string, p, q Position) { - if p.Filename != q.Filename { - t.Errorf("%s: expected filename = %q; got %q", msg, q.Filename, p.Filename) - } - if p.Offset != q.Offset { - t.Errorf("%s: expected offset = %d; got %d", msg, q.Offset, p.Offset) - } - if p.Line != q.Line { - t.Errorf("%s: expected line = %d; got %d", msg, q.Line, p.Line) - } - if p.Column != q.Column { - t.Errorf("%s: expected column = %d; got %d", msg, q.Column, p.Column) - } -} - -func TestNoPos(t *testing.T) { - if NoPos.IsValid() { - t.Errorf("NoPos should not be valid") - } - var fset *FileSet - checkPos(t, "nil NoPos", fset.Position(NoPos), Position{}) - fset = NewFileSet() - checkPos(t, "fset NoPos", fset.Position(NoPos), Position{}) -} - -var tests = []struct { - filename string - source []byte // may be nil - size int - lines []int -}{ - {"a", []byte{}, 0, []int{}}, - {"b", []byte("01234"), 5, []int{0}}, - {"c", []byte("\n\n\n\n\n\n\n\n\n"), 9, []int{0, 1, 2, 3, 4, 5, 6, 7, 8}}, - {"d", nil, 100, []int{0, 5, 10, 20, 30, 70, 71, 72, 80, 85, 90, 99}}, - {"e", nil, 777, []int{0, 80, 100, 120, 130, 180, 267, 455, 500, 567, 620}}, - {"f", []byte("package p\n\nimport \"fmt\""), 23, []int{0, 10, 11}}, - {"g", []byte("package p\n\nimport \"fmt\"\n"), 24, []int{0, 10, 11}}, - {"h", []byte("package p\n\nimport \"fmt\"\n "), 25, []int{0, 10, 11, 24}}, -} - -func linecol(lines []int, offs int) (int, int) { - prevLineOffs := 0 - for line, lineOffs := range lines { - if offs < lineOffs { - return line, offs - prevLineOffs + 1 - } - prevLineOffs = lineOffs - } - return len(lines), offs - prevLineOffs + 1 -} - -func verifyPositions(t *testing.T, fset *FileSet, f *File, lines []int) { - for offs := 0; offs < f.Size(); offs++ { - p := f.Pos(offs) - offs2 := f.Offset(p) - if offs2 != offs { - t.Errorf("%s, Offset: expected offset %d; got %d", f.Name(), offs, offs2) - } - line, col := linecol(lines, offs) - msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p) - checkPos(t, msg, f.Position(f.Pos(offs)), Position{f.Name(), offs, line, col}) - checkPos(t, msg, fset.Position(p), Position{f.Name(), offs, line, col}) - } -} - -func makeTestSource(size int, lines []int) []byte { - src := make([]byte, size) - for _, offs := range lines { - if offs > 0 { - src[offs-1] = '\n' - } - } - return src -} - -func TestPositions(t *testing.T) { - const delta = 7 // a non-zero base offset increment - fset := NewFileSet() - for _, test := range tests { - // verify consistency of test case - if test.source != nil && len(test.source) != test.size { - t.Errorf("%s: inconsistent test case: expected file size %d; got %d", test.filename, test.size, len(test.source)) - } - - // add file and verify name and size - f := fset.AddFile(test.filename, fset.Base()+delta, test.size) - if f.Name() != test.filename { - t.Errorf("expected filename %q; got %q", test.filename, f.Name()) - } - if f.Size() != test.size { - t.Errorf("%s: expected file size %d; got %d", f.Name(), test.size, f.Size()) - } - if fset.File(f.Pos(0)) != f { - t.Errorf("%s: f.Pos(0) was not found in f", f.Name()) - } - - // add lines individually and verify all positions - for i, offset := range test.lines { - f.AddLine(offset) - if f.LineCount() != i+1 { - t.Errorf("%s, AddLine: expected line count %d; got %d", f.Name(), i+1, f.LineCount()) - } - // adding the same offset again should be ignored - f.AddLine(offset) - if f.LineCount() != i+1 { - t.Errorf("%s, AddLine: expected unchanged line count %d; got %d", f.Name(), i+1, f.LineCount()) - } - verifyPositions(t, fset, f, test.lines[0:i+1]) - } - - // add lines with SetLines and verify all positions - if ok := f.SetLines(test.lines); !ok { - t.Errorf("%s: SetLines failed", f.Name()) - } - if f.LineCount() != len(test.lines) { - t.Errorf("%s, SetLines: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount()) - } - verifyPositions(t, fset, f, test.lines) - - // add lines with SetLinesForContent and verify all positions - src := test.source - if src == nil { - // no test source available - create one from scratch - src = makeTestSource(test.size, test.lines) - } - f.SetLinesForContent(src) - if f.LineCount() != len(test.lines) { - t.Errorf("%s, SetLinesForContent: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount()) - } - verifyPositions(t, fset, f, test.lines) - } -} - -func TestLineInfo(t *testing.T) { - fset := NewFileSet() - f := fset.AddFile("foo", fset.Base(), 500) - lines := []int{0, 42, 77, 100, 210, 220, 277, 300, 333, 401} - // add lines individually and provide alternative line information - for _, offs := range lines { - f.AddLine(offs) - f.AddLineInfo(offs, "bar", 42) - } - // verify positions for all offsets - for offs := 0; offs <= f.Size(); offs++ { - p := f.Pos(offs) - _, col := linecol(lines, offs) - msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p) - checkPos(t, msg, f.Position(f.Pos(offs)), Position{"bar", offs, 42, col}) - checkPos(t, msg, fset.Position(p), Position{"bar", offs, 42, col}) - } -} - -func TestFiles(t *testing.T) { - fset := NewFileSet() - for i, test := range tests { - fset.AddFile(test.filename, fset.Base(), test.size) - j := 0 - fset.Iterate(func(f *File) bool { - if f.Name() != tests[j].filename { - t.Errorf("expected filename = %s; got %s", tests[j].filename, f.Name()) - } - j++ - return true - }) - if j != i+1 { - t.Errorf("expected %d files; got %d", i+1, j) - } - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/token/serialize_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/token/serialize_test.go deleted file mode 100644 index 4e925adb6..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/token/serialize_test.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package token - -import ( - "bytes" - "encoding/gob" - "fmt" - "testing" -) - -// equal returns nil if p and q describe the same file set; -// otherwise it returns an error describing the discrepancy. -func equal(p, q *FileSet) error { - if p == q { - // avoid deadlock if p == q - return nil - } - - // not strictly needed for the test - p.mutex.Lock() - q.mutex.Lock() - defer q.mutex.Unlock() - defer p.mutex.Unlock() - - if p.base != q.base { - return fmt.Errorf("different bases: %d != %d", p.base, q.base) - } - - if len(p.files) != len(q.files) { - return fmt.Errorf("different number of files: %d != %d", len(p.files), len(q.files)) - } - - for i, f := range p.files { - g := q.files[i] - if f.set != p { - return fmt.Errorf("wrong fileset for %q", f.name) - } - if g.set != q { - return fmt.Errorf("wrong fileset for %q", g.name) - } - if f.name != g.name { - return fmt.Errorf("different filenames: %q != %q", f.name, g.name) - } - if f.base != g.base { - return fmt.Errorf("different base for %q: %d != %d", f.name, f.base, g.base) - } - if f.size != g.size { - return fmt.Errorf("different size for %q: %d != %d", f.name, f.size, g.size) - } - for j, l := range f.lines { - m := g.lines[j] - if l != m { - return fmt.Errorf("different offsets for %q", f.name) - } - } - for j, l := range f.infos { - m := g.infos[j] - if l.Offset != m.Offset || l.Filename != m.Filename || l.Line != m.Line { - return fmt.Errorf("different infos for %q", f.name) - } - } - } - - // we don't care about .last - it's just a cache - return nil -} - -func checkSerialize(t *testing.T, p *FileSet) { - var buf bytes.Buffer - encode := func(x interface{}) error { - return gob.NewEncoder(&buf).Encode(x) - } - if err := p.Write(encode); err != nil { - t.Errorf("writing fileset failed: %s", err) - return - } - q := NewFileSet() - decode := func(x interface{}) error { - return gob.NewDecoder(&buf).Decode(x) - } - if err := q.Read(decode); err != nil { - t.Errorf("reading fileset failed: %s", err) - return - } - if err := equal(p, q); err != nil { - t.Errorf("filesets not identical: %s", err) - } -} - -func TestSerialization(t *testing.T) { - p := NewFileSet() - checkSerialize(t, p) - // add some files - for i := 0; i < 10; i++ { - f := p.AddFile(fmt.Sprintf("file%d", i), p.Base()+i, i*100) - checkSerialize(t, p) - // add some lines and alternative file infos - line := 1000 - for offs := 0; offs < f.Size(); offs += 40 + i { - f.AddLine(offs) - if offs%7 == 0 { - f.AddLineInfo(offs, fmt.Sprintf("file%d", offs), line) - line += 33 - } - } - checkSerialize(t, p) - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/enum_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/enum_test.go deleted file mode 100644 index 4bf135e67..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/enum_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package types - -import ( - "testing" -) - -func TestEnumParserBool(t *testing.T) { - for _, tt := range []struct { - val string - res bool - ok bool - }{ - {val: "tRuE", res: true, ok: true}, - {val: "False", res: false, ok: true}, - {val: "t", ok: false}, - } { - b, err := ParseBool(tt.val) - switch { - case tt.ok && err != nil: - t.Errorf("%q: got error %v, want %v", tt.val, err, tt.res) - case !tt.ok && err == nil: - t.Errorf("%q: got %v, want error", tt.val, b) - case tt.ok && b != tt.res: - t.Errorf("%q: got %v, want %v", tt.val, b, tt.res) - default: - t.Logf("%q: got %v, %v", tt.val, b, err) - } - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/int_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/int_test.go deleted file mode 100644 index b63dbcbae..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/int_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package types - -import ( - "reflect" - "testing" -) - -func elem(p interface{}) interface{} { - return reflect.ValueOf(p).Elem().Interface() -} - -func TestParseInt(t *testing.T) { - for _, tt := range []struct { - val string - mode IntMode - exp interface{} - ok bool - }{ - {"0", Dec, int(0), true}, - {"10", Dec, int(10), true}, - {"-10", Dec, int(-10), true}, - {"x", Dec, int(0), false}, - {"0xa", Hex, int(0xa), true}, - {"a", Hex, int(0xa), true}, - {"10", Hex, int(0x10), true}, - {"-0xa", Hex, int(-0xa), true}, - {"0x", Hex, int(0x0), true}, // Scanf doesn't require digit behind 0x - {"-0x", Hex, int(0x0), true}, // Scanf doesn't require digit behind 0x - {"-a", Hex, int(-0xa), true}, - {"-10", Hex, int(-0x10), true}, - {"x", Hex, int(0), false}, - {"10", Oct, int(010), true}, - {"010", Oct, int(010), true}, - {"-10", Oct, int(-010), true}, - {"-010", Oct, int(-010), true}, - {"10", Dec | Hex, int(10), true}, - {"010", Dec | Hex, int(10), true}, - {"0x10", Dec | Hex, int(0x10), true}, - {"10", Dec | Oct, int(10), true}, - {"010", Dec | Oct, int(010), true}, - {"0x10", Dec | Oct, int(0), false}, - {"10", Hex | Oct, int(0), false}, // need prefix to distinguish Hex/Oct - {"010", Hex | Oct, int(010), true}, - {"0x10", Hex | Oct, int(0x10), true}, - {"10", Dec | Hex | Oct, int(10), true}, - {"010", Dec | Hex | Oct, int(010), true}, - {"0x10", Dec | Hex | Oct, int(0x10), true}, - } { - typ := reflect.TypeOf(tt.exp) - res := reflect.New(typ).Interface() - err := ParseInt(res, tt.val, tt.mode) - switch { - case tt.ok && err != nil: - t.Errorf("ParseInt(%v, %#v, %v): fail; got error %v, want ok", - typ, tt.val, tt.mode, err) - case !tt.ok && err == nil: - t.Errorf("ParseInt(%v, %#v, %v): fail; got %v, want error", - typ, tt.val, tt.mode, elem(res)) - case tt.ok && !reflect.DeepEqual(elem(res), tt.exp): - t.Errorf("ParseInt(%v, %#v, %v): fail; got %v, want %v", - typ, tt.val, tt.mode, elem(res), tt.exp) - default: - t.Logf("ParseInt(%v, %#v, %s): pass; got %v, error %v", - typ, tt.val, tt.mode, elem(res), err) - } - } -} diff --git a/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/scan_test.go b/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/scan_test.go deleted file mode 100644 index a8083e04f..000000000 --- a/Godeps/_workspace/src/gopkg.in/gcfg.v1/types/scan_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package types - -import ( - "reflect" - "testing" -) - -func TestScanFully(t *testing.T) { - for _, tt := range []struct { - val string - verb byte - res interface{} - ok bool - }{ - {"a", 'v', int(0), false}, - {"0x", 'v', int(0), true}, - {"0x", 'd', int(0), false}, - } { - d := reflect.New(reflect.TypeOf(tt.res)).Interface() - err := ScanFully(d, tt.val, tt.verb) - switch { - case tt.ok && err != nil: - t.Errorf("ScanFully(%T, %q, '%c'): want ok, got error %v", - d, tt.val, tt.verb, err) - case !tt.ok && err == nil: - t.Errorf("ScanFully(%T, %q, '%c'): want error, got %v", - d, tt.val, tt.verb, elem(d)) - case tt.ok && err == nil && !reflect.DeepEqual(tt.res, elem(d)): - t.Errorf("ScanFully(%T, %q, '%c'): want %v, got %v", - d, tt.val, tt.verb, tt.res, elem(d)) - default: - t.Logf("ScanFully(%T, %q, '%c') = %v; *ptr==%v", - d, tt.val, tt.verb, err, elem(d)) - } - } -} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go deleted file mode 100644 index c159760b6..000000000 --- a/Godeps/_workspace/src/gopkg.in/yaml.v2/decode_test.go +++ /dev/null @@ -1,988 +0,0 @@ -package yaml_test - -import ( - "errors" - . "gopkg.in/check.v1" - "gopkg.in/yaml.v2" - "math" - "net" - "reflect" - "strings" - "time" -) - -var unmarshalIntTest = 123 - -var unmarshalTests = []struct { - data string - value interface{} -}{ - { - "", - &struct{}{}, - }, { - "{}", &struct{}{}, - }, { - "v: hi", - map[string]string{"v": "hi"}, - }, { - "v: hi", map[string]interface{}{"v": "hi"}, - }, { - "v: true", - map[string]string{"v": "true"}, - }, { - "v: true", - map[string]interface{}{"v": true}, - }, { - "v: 10", - map[string]interface{}{"v": 10}, - }, { - "v: 0b10", - map[string]interface{}{"v": 2}, - }, { - "v: 0xA", - map[string]interface{}{"v": 10}, - }, { - "v: 4294967296", - map[string]int64{"v": 4294967296}, - }, { - "v: 0.1", - map[string]interface{}{"v": 0.1}, - }, { - "v: .1", - map[string]interface{}{"v": 0.1}, - }, { - "v: .Inf", - map[string]interface{}{"v": math.Inf(+1)}, - }, { - "v: -.Inf", - map[string]interface{}{"v": math.Inf(-1)}, - }, { - "v: -10", - map[string]interface{}{"v": -10}, - }, { - "v: -.1", - map[string]interface{}{"v": -0.1}, - }, - - // Simple values. - { - "123", - &unmarshalIntTest, - }, - - // Floats from spec - { - "canonical: 6.8523e+5", - map[string]interface{}{"canonical": 6.8523e+5}, - }, { - "expo: 685.230_15e+03", - map[string]interface{}{"expo": 685.23015e+03}, - }, { - "fixed: 685_230.15", - map[string]interface{}{"fixed": 685230.15}, - }, { - "neginf: -.inf", - map[string]interface{}{"neginf": math.Inf(-1)}, - }, { - "fixed: 685_230.15", - map[string]float64{"fixed": 685230.15}, - }, - //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported - //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. - - // Bools from spec - { - "canonical: y", - map[string]interface{}{"canonical": true}, - }, { - "answer: NO", - map[string]interface{}{"answer": false}, - }, { - "logical: True", - map[string]interface{}{"logical": true}, - }, { - "option: on", - map[string]interface{}{"option": true}, - }, { - "option: on", - map[string]bool{"option": true}, - }, - // Ints from spec - { - "canonical: 685230", - map[string]interface{}{"canonical": 685230}, - }, { - "decimal: +685_230", - map[string]interface{}{"decimal": 685230}, - }, { - "octal: 02472256", - map[string]interface{}{"octal": 685230}, - }, { - "hexa: 0x_0A_74_AE", - map[string]interface{}{"hexa": 685230}, - }, { - "bin: 0b1010_0111_0100_1010_1110", - map[string]interface{}{"bin": 685230}, - }, { - "bin: -0b101010", - map[string]interface{}{"bin": -42}, - }, { - "decimal: +685_230", - map[string]int{"decimal": 685230}, - }, - - //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported - - // Nulls from spec - { - "empty:", - map[string]interface{}{"empty": nil}, - }, { - "canonical: ~", - map[string]interface{}{"canonical": nil}, - }, { - "english: null", - map[string]interface{}{"english": nil}, - }, { - "~: null key", - map[interface{}]string{nil: "null key"}, - }, { - "empty:", - map[string]*bool{"empty": nil}, - }, - - // Flow sequence - { - "seq: [A,B]", - map[string]interface{}{"seq": []interface{}{"A", "B"}}, - }, { - "seq: [A,B,C,]", - map[string][]string{"seq": []string{"A", "B", "C"}}, - }, { - "seq: [A,1,C]", - map[string][]string{"seq": []string{"A", "1", "C"}}, - }, { - "seq: [A,1,C]", - map[string][]int{"seq": []int{1}}, - }, { - "seq: [A,1,C]", - map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, - }, - // Block sequence - { - "seq:\n - A\n - B", - map[string]interface{}{"seq": []interface{}{"A", "B"}}, - }, { - "seq:\n - A\n - B\n - C", - map[string][]string{"seq": []string{"A", "B", "C"}}, - }, { - "seq:\n - A\n - 1\n - C", - map[string][]string{"seq": []string{"A", "1", "C"}}, - }, { - "seq:\n - A\n - 1\n - C", - map[string][]int{"seq": []int{1}}, - }, { - "seq:\n - A\n - 1\n - C", - map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, - }, - - // Literal block scalar - { - "scalar: | # Comment\n\n literal\n\n \ttext\n\n", - map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, - }, - - // Folded block scalar - { - "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", - map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, - }, - - // Map inside interface with no type hints. - { - "a: {b: c}", - map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, - }, - - // Structs and type conversions. - { - "hello: world", - &struct{ Hello string }{"world"}, - }, { - "a: {b: c}", - &struct{ A struct{ B string } }{struct{ B string }{"c"}}, - }, { - "a: {b: c}", - &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, - }, { - "a: {b: c}", - &struct{ A map[string]string }{map[string]string{"b": "c"}}, - }, { - "a: {b: c}", - &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, - }, { - "a:", - &struct{ A map[string]string }{}, - }, { - "a: 1", - &struct{ A int }{1}, - }, { - "a: 1", - &struct{ A float64 }{1}, - }, { - "a: 1.0", - &struct{ A int }{1}, - }, { - "a: 1.0", - &struct{ A uint }{1}, - }, { - "a: [1, 2]", - &struct{ A []int }{[]int{1, 2}}, - }, { - "a: 1", - &struct{ B int }{0}, - }, { - "a: 1", - &struct { - B int "a" - }{1}, - }, { - "a: y", - &struct{ A bool }{true}, - }, - - // Some cross type conversions - { - "v: 42", - map[string]uint{"v": 42}, - }, { - "v: -42", - map[string]uint{}, - }, { - "v: 4294967296", - map[string]uint64{"v": 4294967296}, - }, { - "v: -4294967296", - map[string]uint64{}, - }, - - // int - { - "int_max: 2147483647", - map[string]int{"int_max": math.MaxInt32}, - }, - { - "int_min: -2147483648", - map[string]int{"int_min": math.MinInt32}, - }, - { - "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 - map[string]int{}, - }, - - // int64 - { - "int64_max: 9223372036854775807", - map[string]int64{"int64_max": math.MaxInt64}, - }, - { - "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", - map[string]int64{"int64_max_base2": math.MaxInt64}, - }, - { - "int64_min: -9223372036854775808", - map[string]int64{"int64_min": math.MinInt64}, - }, - { - "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", - map[string]int64{"int64_neg_base2": -math.MaxInt64}, - }, - { - "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 - map[string]int64{}, - }, - - // uint - { - "uint_min: 0", - map[string]uint{"uint_min": 0}, - }, - { - "uint_max: 4294967295", - map[string]uint{"uint_max": math.MaxUint32}, - }, - { - "uint_underflow: -1", - map[string]uint{}, - }, - - // uint64 - { - "uint64_min: 0", - map[string]uint{"uint64_min": 0}, - }, - { - "uint64_max: 18446744073709551615", - map[string]uint64{"uint64_max": math.MaxUint64}, - }, - { - "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", - map[string]uint64{"uint64_max_base2": math.MaxUint64}, - }, - { - "uint64_maxint64: 9223372036854775807", - map[string]uint64{"uint64_maxint64": math.MaxInt64}, - }, - { - "uint64_underflow: -1", - map[string]uint64{}, - }, - - // float32 - { - "float32_max: 3.40282346638528859811704183484516925440e+38", - map[string]float32{"float32_max": math.MaxFloat32}, - }, - { - "float32_nonzero: 1.401298464324817070923729583289916131280e-45", - map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32}, - }, - { - "float32_maxuint64: 18446744073709551615", - map[string]float32{"float32_maxuint64": float32(math.MaxUint64)}, - }, - { - "float32_maxuint64+1: 18446744073709551616", - map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)}, - }, - - // float64 - { - "float64_max: 1.797693134862315708145274237317043567981e+308", - map[string]float64{"float64_max": math.MaxFloat64}, - }, - { - "float64_nonzero: 4.940656458412465441765687928682213723651e-324", - map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64}, - }, - { - "float64_maxuint64: 18446744073709551615", - map[string]float64{"float64_maxuint64": float64(math.MaxUint64)}, - }, - { - "float64_maxuint64+1: 18446744073709551616", - map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)}, - }, - - // Overflow cases. - { - "v: 4294967297", - map[string]int32{}, - }, { - "v: 128", - map[string]int8{}, - }, - - // Quoted values. - { - "'1': '\"2\"'", - map[interface{}]interface{}{"1": "\"2\""}, - }, { - "v:\n- A\n- 'B\n\n C'\n", - map[string][]string{"v": []string{"A", "B\nC"}}, - }, - - // Explicit tags. - { - "v: !!float '1.1'", - map[string]interface{}{"v": 1.1}, - }, { - "v: !!null ''", - map[string]interface{}{"v": nil}, - }, { - "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", - map[string]interface{}{"v": 1}, - }, - - // Anchors and aliases. - { - "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", - &struct{ A, B, C, D int }{1, 2, 1, 2}, - }, { - "a: &a {c: 1}\nb: *a", - &struct { - A, B struct { - C int - } - }{struct{ C int }{1}, struct{ C int }{1}}, - }, { - "a: &a [1, 2]\nb: *a", - &struct{ B []int }{[]int{1, 2}}, - }, { - "b: *a\na: &a {c: 1}", - &struct { - A, B struct { - C int - } - }{struct{ C int }{1}, struct{ C int }{1}}, - }, - - // Bug #1133337 - { - "foo: ''", - map[string]*string{"foo": new(string)}, - }, { - "foo: null", - map[string]string{"foo": ""}, - }, { - "foo: null", - map[string]interface{}{"foo": nil}, - }, - - // Ignored field - { - "a: 1\nb: 2\n", - &struct { - A int - B int "-" - }{1, 0}, - }, - - // Bug #1191981 - { - "" + - "%YAML 1.1\n" + - "--- !!str\n" + - `"Generic line break (no glyph)\n\` + "\n" + - ` Generic line break (glyphed)\n\` + "\n" + - ` Line separator\u2028\` + "\n" + - ` Paragraph separator\u2029"` + "\n", - "" + - "Generic line break (no glyph)\n" + - "Generic line break (glyphed)\n" + - "Line separator\u2028Paragraph separator\u2029", - }, - - // Struct inlining - { - "a: 1\nb: 2\nc: 3\n", - &struct { - A int - C inlineB `yaml:",inline"` - }{1, inlineB{2, inlineC{3}}}, - }, - - // Map inlining - { - "a: 1\nb: 2\nc: 3\n", - &struct { - A int - C map[string]int `yaml:",inline"` - }{1, map[string]int{"b": 2, "c": 3}}, - }, - - // bug 1243827 - { - "a: -b_c", - map[string]interface{}{"a": "-b_c"}, - }, - { - "a: +b_c", - map[string]interface{}{"a": "+b_c"}, - }, - { - "a: 50cent_of_dollar", - map[string]interface{}{"a": "50cent_of_dollar"}, - }, - - // Duration - { - "a: 3s", - map[string]time.Duration{"a": 3 * time.Second}, - }, - - // Issue #24. - { - "a: ", - map[string]string{"a": ""}, - }, - - // Base 60 floats are obsolete and unsupported. - { - "a: 1:1\n", - map[string]string{"a": "1:1"}, - }, - - // Binary data. - { - "a: !!binary gIGC\n", - map[string]string{"a": "\x80\x81\x82"}, - }, { - "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", - map[string]string{"a": strings.Repeat("\x90", 54)}, - }, { - "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", - map[string]string{"a": strings.Repeat("\x00", 52)}, - }, - - // Ordered maps. - { - "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}", - &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, - }, - - // Issue #39. - { - "a:\n b:\n c: d\n", - map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}}, - }, - - // Custom map type. - { - "a: {b: c}", - M{"a": M{"b": "c"}}, - }, - - // Support encoding.TextUnmarshaler. - { - "a: 1.2.3.4\n", - map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, - }, - { - "a: 2015-02-24T18:19:39Z\n", - map[string]time.Time{"a": time.Unix(1424801979, 0)}, - }, - - // Encode empty lists as zero-length slices. - { - "a: []", - &struct{ A []int }{[]int{}}, - }, - - // UTF-16-LE - { - "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00", - M{"ñoño": "very yes"}, - }, - // UTF-16-LE with surrogate. - { - "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00", - M{"ñoño": "very yes 🟔"}, - }, - - // UTF-16-BE - { - "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n", - M{"ñoño": "very yes"}, - }, - // UTF-16-BE with surrogate. - { - "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n", - M{"ñoño": "very yes 🟔"}, - }, -} - -type M map[interface{}]interface{} - -type inlineB struct { - B int - inlineC `yaml:",inline"` -} - -type inlineC struct { - C int -} - -func (s *S) TestUnmarshal(c *C) { - for _, item := range unmarshalTests { - t := reflect.ValueOf(item.value).Type() - var value interface{} - switch t.Kind() { - case reflect.Map: - value = reflect.MakeMap(t).Interface() - case reflect.String: - value = reflect.New(t).Interface() - case reflect.Ptr: - value = reflect.New(t.Elem()).Interface() - default: - c.Fatalf("missing case for %s", t) - } - err := yaml.Unmarshal([]byte(item.data), value) - if _, ok := err.(*yaml.TypeError); !ok { - c.Assert(err, IsNil) - } - if t.Kind() == reflect.String { - c.Assert(*value.(*string), Equals, item.value) - } else { - c.Assert(value, DeepEquals, item.value) - } - } -} - -func (s *S) TestUnmarshalNaN(c *C) { - value := map[string]interface{}{} - err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) - c.Assert(err, IsNil) - c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) -} - -var unmarshalErrorTests = []struct { - data, error string -}{ - {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, - {"v: [A,", "yaml: line 1: did not find expected node content"}, - {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, - {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, - {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, - {"value: -", "yaml: block sequence entries are not allowed in this context"}, - {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, - {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, - {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, -} - -func (s *S) TestUnmarshalErrors(c *C) { - for _, item := range unmarshalErrorTests { - var value interface{} - err := yaml.Unmarshal([]byte(item.data), &value) - c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) - } -} - -var unmarshalerTests = []struct { - data, tag string - value interface{} -}{ - {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, - {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, - {"_: 10", "!!int", 10}, - {"_: null", "!!null", nil}, - {`_: BAR!`, "!!str", "BAR!"}, - {`_: "BAR!"`, "!!str", "BAR!"}, - {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, -} - -var unmarshalerResult = map[int]error{} - -type unmarshalerType struct { - value interface{} -} - -func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { - if err := unmarshal(&o.value); err != nil { - return err - } - if i, ok := o.value.(int); ok { - if result, ok := unmarshalerResult[i]; ok { - return result - } - } - return nil -} - -type unmarshalerPointer struct { - Field *unmarshalerType "_" -} - -type unmarshalerValue struct { - Field unmarshalerType "_" -} - -func (s *S) TestUnmarshalerPointerField(c *C) { - for _, item := range unmarshalerTests { - obj := &unmarshalerPointer{} - err := yaml.Unmarshal([]byte(item.data), obj) - c.Assert(err, IsNil) - if item.value == nil { - c.Assert(obj.Field, IsNil) - } else { - c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) - c.Assert(obj.Field.value, DeepEquals, item.value) - } - } -} - -func (s *S) TestUnmarshalerValueField(c *C) { - for _, item := range unmarshalerTests { - obj := &unmarshalerValue{} - err := yaml.Unmarshal([]byte(item.data), obj) - c.Assert(err, IsNil) - c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) - c.Assert(obj.Field.value, DeepEquals, item.value) - } -} - -func (s *S) TestUnmarshalerWholeDocument(c *C) { - obj := &unmarshalerType{} - err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) - c.Assert(err, IsNil) - value, ok := obj.value.(map[interface{}]interface{}) - c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) - c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) -} - -func (s *S) TestUnmarshalerTypeError(c *C) { - unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} - unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} - defer func() { - delete(unmarshalerResult, 2) - delete(unmarshalerResult, 4) - }() - - type T struct { - Before int - After int - M map[string]*unmarshalerType - } - var v T - data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` - err := yaml.Unmarshal([]byte(data), &v) - c.Assert(err, ErrorMatches, ""+ - "yaml: unmarshal errors:\n"+ - " line 1: cannot unmarshal !!str `A` into int\n"+ - " foo\n"+ - " bar\n"+ - " line 1: cannot unmarshal !!str `B` into int") - c.Assert(v.M["abc"], NotNil) - c.Assert(v.M["def"], IsNil) - c.Assert(v.M["ghi"], NotNil) - c.Assert(v.M["jkl"], IsNil) - - c.Assert(v.M["abc"].value, Equals, 1) - c.Assert(v.M["ghi"].value, Equals, 3) -} - -type proxyTypeError struct{} - -func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { - var s string - var a int32 - var b int64 - if err := unmarshal(&s); err != nil { - panic(err) - } - if s == "a" { - if err := unmarshal(&b); err == nil { - panic("should have failed") - } - return unmarshal(&a) - } - if err := unmarshal(&a); err == nil { - panic("should have failed") - } - return unmarshal(&b) -} - -func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { - type T struct { - Before int - After int - M map[string]*proxyTypeError - } - var v T - data := `{before: A, m: {abc: a, def: b}, after: B}` - err := yaml.Unmarshal([]byte(data), &v) - c.Assert(err, ErrorMatches, ""+ - "yaml: unmarshal errors:\n"+ - " line 1: cannot unmarshal !!str `A` into int\n"+ - " line 1: cannot unmarshal !!str `a` into int32\n"+ - " line 1: cannot unmarshal !!str `b` into int64\n"+ - " line 1: cannot unmarshal !!str `B` into int") -} - -type failingUnmarshaler struct{} - -var failingErr = errors.New("failingErr") - -func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { - return failingErr -} - -func (s *S) TestUnmarshalerError(c *C) { - err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) - c.Assert(err, Equals, failingErr) -} - -type sliceUnmarshaler []int - -func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { - var slice []int - err := unmarshal(&slice) - if err == nil { - *su = slice - return nil - } - - var intVal int - err = unmarshal(&intVal) - if err == nil { - *su = []int{intVal} - return nil - } - - return err -} - -func (s *S) TestUnmarshalerRetry(c *C) { - var su sliceUnmarshaler - err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) - c.Assert(err, IsNil) - c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) - - err = yaml.Unmarshal([]byte("1"), &su) - c.Assert(err, IsNil) - c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) -} - -// From http://yaml.org/type/merge.html -var mergeTests = ` -anchors: - list: - - &CENTER { "x": 1, "y": 2 } - - &LEFT { "x": 0, "y": 2 } - - &BIG { "r": 10 } - - &SMALL { "r": 1 } - -# All the following maps are equal: - -plain: - # Explicit keys - "x": 1 - "y": 2 - "r": 10 - label: center/big - -mergeOne: - # Merge one map - << : *CENTER - "r": 10 - label: center/big - -mergeMultiple: - # Merge multiple maps - << : [ *CENTER, *BIG ] - label: center/big - -override: - # Override - << : [ *BIG, *LEFT, *SMALL ] - "x": 1 - label: center/big - -shortTag: - # Explicit short merge tag - !!merge "<<" : [ *CENTER, *BIG ] - label: center/big - -longTag: - # Explicit merge long tag - ! "<<" : [ *CENTER, *BIG ] - label: center/big - -inlineMap: - # Inlined map - << : {"x": 1, "y": 2, "r": 10} - label: center/big - -inlineSequenceMap: - # Inlined map in sequence - << : [ *CENTER, {"r": 10} ] - label: center/big -` - -func (s *S) TestMerge(c *C) { - var want = map[interface{}]interface{}{ - "x": 1, - "y": 2, - "r": 10, - "label": "center/big", - } - - var m map[interface{}]interface{} - err := yaml.Unmarshal([]byte(mergeTests), &m) - c.Assert(err, IsNil) - for name, test := range m { - if name == "anchors" { - continue - } - c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) - } -} - -func (s *S) TestMergeStruct(c *C) { - type Data struct { - X, Y, R int - Label string - } - want := Data{1, 2, 10, "center/big"} - - var m map[string]Data - err := yaml.Unmarshal([]byte(mergeTests), &m) - c.Assert(err, IsNil) - for name, test := range m { - if name == "anchors" { - continue - } - c.Assert(test, Equals, want, Commentf("test %q failed", name)) - } -} - -var unmarshalNullTests = []func() interface{}{ - func() interface{} { var v interface{}; v = "v"; return &v }, - func() interface{} { var s = "s"; return &s }, - func() interface{} { var s = "s"; sptr := &s; return &sptr }, - func() interface{} { var i = 1; return &i }, - func() interface{} { var i = 1; iptr := &i; return &iptr }, - func() interface{} { m := map[string]int{"s": 1}; return &m }, - func() interface{} { m := map[string]int{"s": 1}; return m }, -} - -func (s *S) TestUnmarshalNull(c *C) { - for _, test := range unmarshalNullTests { - item := test() - zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() - err := yaml.Unmarshal([]byte("null"), item) - c.Assert(err, IsNil) - if reflect.TypeOf(item).Kind() == reflect.Map { - c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) - } else { - c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) - } - } -} - -func (s *S) TestUnmarshalSliceOnPreset(c *C) { - // Issue #48. - v := struct{ A []int }{[]int{1}} - yaml.Unmarshal([]byte("a: [2]"), &v) - c.Assert(v.A, DeepEquals, []int{2}) -} - -//var data []byte -//func init() { -// var err error -// data, err = ioutil.ReadFile("/tmp/file.yaml") -// if err != nil { -// panic(err) -// } -//} -// -//func (s *S) BenchmarkUnmarshal(c *C) { -// var err error -// for i := 0; i < c.N; i++ { -// var v map[string]interface{} -// err = yaml.Unmarshal(data, &v) -// } -// if err != nil { -// panic(err) -// } -//} -// -//func (s *S) BenchmarkMarshal(c *C) { -// var v map[string]interface{} -// yaml.Unmarshal(data, &v) -// c.ResetTimer() -// for i := 0; i < c.N; i++ { -// yaml.Marshal(&v) -// } -//} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go deleted file mode 100644 index 84099bd38..000000000 --- a/Godeps/_workspace/src/gopkg.in/yaml.v2/encode_test.go +++ /dev/null @@ -1,501 +0,0 @@ -package yaml_test - -import ( - "fmt" - "math" - "strconv" - "strings" - "time" - - . "gopkg.in/check.v1" - "gopkg.in/yaml.v2" - "net" - "os" -) - -var marshalIntTest = 123 - -var marshalTests = []struct { - value interface{} - data string -}{ - { - nil, - "null\n", - }, { - &struct{}{}, - "{}\n", - }, { - map[string]string{"v": "hi"}, - "v: hi\n", - }, { - map[string]interface{}{"v": "hi"}, - "v: hi\n", - }, { - map[string]string{"v": "true"}, - "v: \"true\"\n", - }, { - map[string]string{"v": "false"}, - "v: \"false\"\n", - }, { - map[string]interface{}{"v": true}, - "v: true\n", - }, { - map[string]interface{}{"v": false}, - "v: false\n", - }, { - map[string]interface{}{"v": 10}, - "v: 10\n", - }, { - map[string]interface{}{"v": -10}, - "v: -10\n", - }, { - map[string]uint{"v": 42}, - "v: 42\n", - }, { - map[string]interface{}{"v": int64(4294967296)}, - "v: 4294967296\n", - }, { - map[string]int64{"v": int64(4294967296)}, - "v: 4294967296\n", - }, { - map[string]uint64{"v": 4294967296}, - "v: 4294967296\n", - }, { - map[string]interface{}{"v": "10"}, - "v: \"10\"\n", - }, { - map[string]interface{}{"v": 0.1}, - "v: 0.1\n", - }, { - map[string]interface{}{"v": float64(0.1)}, - "v: 0.1\n", - }, { - map[string]interface{}{"v": -0.1}, - "v: -0.1\n", - }, { - map[string]interface{}{"v": math.Inf(+1)}, - "v: .inf\n", - }, { - map[string]interface{}{"v": math.Inf(-1)}, - "v: -.inf\n", - }, { - map[string]interface{}{"v": math.NaN()}, - "v: .nan\n", - }, { - map[string]interface{}{"v": nil}, - "v: null\n", - }, { - map[string]interface{}{"v": ""}, - "v: \"\"\n", - }, { - map[string][]string{"v": []string{"A", "B"}}, - "v:\n- A\n- B\n", - }, { - map[string][]string{"v": []string{"A", "B\nC"}}, - "v:\n- A\n- |-\n B\n C\n", - }, { - map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, - "v:\n- A\n- 1\n- B:\n - 2\n - 3\n", - }, { - map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, - "a:\n b: c\n", - }, { - map[string]interface{}{"a": "-"}, - "a: '-'\n", - }, - - // Simple values. - { - &marshalIntTest, - "123\n", - }, - - // Structures - { - &struct{ Hello string }{"world"}, - "hello: world\n", - }, { - &struct { - A struct { - B string - } - }{struct{ B string }{"c"}}, - "a:\n b: c\n", - }, { - &struct { - A *struct { - B string - } - }{&struct{ B string }{"c"}}, - "a:\n b: c\n", - }, { - &struct { - A *struct { - B string - } - }{}, - "a: null\n", - }, { - &struct{ A int }{1}, - "a: 1\n", - }, { - &struct{ A []int }{[]int{1, 2}}, - "a:\n- 1\n- 2\n", - }, { - &struct { - B int "a" - }{1}, - "a: 1\n", - }, { - &struct{ A bool }{true}, - "a: true\n", - }, - - // Conditional flag - { - &struct { - A int "a,omitempty" - B int "b,omitempty" - }{1, 0}, - "a: 1\n", - }, { - &struct { - A int "a,omitempty" - B int "b,omitempty" - }{0, 0}, - "{}\n", - }, { - &struct { - A *struct{ X, y int } "a,omitempty,flow" - }{&struct{ X, y int }{1, 2}}, - "a: {x: 1}\n", - }, { - &struct { - A *struct{ X, y int } "a,omitempty,flow" - }{nil}, - "{}\n", - }, { - &struct { - A *struct{ X, y int } "a,omitempty,flow" - }{&struct{ X, y int }{}}, - "a: {x: 0}\n", - }, { - &struct { - A struct{ X, y int } "a,omitempty,flow" - }{struct{ X, y int }{1, 2}}, - "a: {x: 1}\n", - }, { - &struct { - A struct{ X, y int } "a,omitempty,flow" - }{struct{ X, y int }{0, 1}}, - "{}\n", - }, { - &struct { - A float64 "a,omitempty" - B float64 "b,omitempty" - }{1, 0}, - "a: 1\n", - }, - - // Flow flag - { - &struct { - A []int "a,flow" - }{[]int{1, 2}}, - "a: [1, 2]\n", - }, { - &struct { - A map[string]string "a,flow" - }{map[string]string{"b": "c", "d": "e"}}, - "a: {b: c, d: e}\n", - }, { - &struct { - A struct { - B, D string - } "a,flow" - }{struct{ B, D string }{"c", "e"}}, - "a: {b: c, d: e}\n", - }, - - // Unexported field - { - &struct { - u int - A int - }{0, 1}, - "a: 1\n", - }, - - // Ignored field - { - &struct { - A int - B int "-" - }{1, 2}, - "a: 1\n", - }, - - // Struct inlining - { - &struct { - A int - C inlineB `yaml:",inline"` - }{1, inlineB{2, inlineC{3}}}, - "a: 1\nb: 2\nc: 3\n", - }, - - // Map inlining - { - &struct { - A int - C map[string]int `yaml:",inline"` - }{1, map[string]int{"b": 2, "c": 3}}, - "a: 1\nb: 2\nc: 3\n", - }, - - // Duration - { - map[string]time.Duration{"a": 3 * time.Second}, - "a: 3s\n", - }, - - // Issue #24: bug in map merging logic. - { - map[string]string{"a": ""}, - "a: \n", - }, - - // Issue #34: marshal unsupported base 60 floats quoted for compatibility - // with old YAML 1.1 parsers. - { - map[string]string{"a": "1:1"}, - "a: \"1:1\"\n", - }, - - // Binary data. - { - map[string]string{"a": "\x00"}, - "a: \"\\0\"\n", - }, { - map[string]string{"a": "\x80\x81\x82"}, - "a: !!binary gIGC\n", - }, { - map[string]string{"a": strings.Repeat("\x90", 54)}, - "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", - }, - - // Ordered maps. - { - &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, - "b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n", - }, - - // Encode unicode as utf-8 rather than in escaped form. - { - map[string]string{"a": "你好"}, - "a: 你好\n", - }, - - // Support encoding.TextMarshaler. - { - map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, - "a: 1.2.3.4\n", - }, - { - map[string]time.Time{"a": time.Unix(1424801979, 0)}, - "a: 2015-02-24T18:19:39Z\n", - }, - - // Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible). - { - map[string]string{"a": "b: c"}, - "a: 'b: c'\n", - }, - - // Containing hash mark ('#') in string should be quoted - { - map[string]string{"a": "Hello #comment"}, - "a: 'Hello #comment'\n", - }, - { - map[string]string{"a": "你好 #comment"}, - "a: '你好 #comment'\n", - }, -} - -func (s *S) TestMarshal(c *C) { - defer os.Setenv("TZ", os.Getenv("TZ")) - os.Setenv("TZ", "UTC") - for _, item := range marshalTests { - data, err := yaml.Marshal(item.value) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, item.data) - } -} - -var marshalErrorTests = []struct { - value interface{} - error string - panic string -}{{ - value: &struct { - B int - inlineB ",inline" - }{1, inlineB{2, inlineC{3}}}, - panic: `Duplicated key 'b' in struct struct \{ B int; .*`, -}, { - value: &struct { - A int - B map[string]int ",inline" - }{1, map[string]int{"a": 2}}, - panic: `Can't have key "a" in inlined map; conflicts with struct field`, -}} - -func (s *S) TestMarshalErrors(c *C) { - for _, item := range marshalErrorTests { - if item.panic != "" { - c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) - } else { - _, err := yaml.Marshal(item.value) - c.Assert(err, ErrorMatches, item.error) - } - } -} - -func (s *S) TestMarshalTypeCache(c *C) { - var data []byte - var err error - func() { - type T struct{ A int } - data, err = yaml.Marshal(&T{}) - c.Assert(err, IsNil) - }() - func() { - type T struct{ B int } - data, err = yaml.Marshal(&T{}) - c.Assert(err, IsNil) - }() - c.Assert(string(data), Equals, "b: 0\n") -} - -var marshalerTests = []struct { - data string - value interface{} -}{ - {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}}, - {"_:\n- 1\n- A\n", []interface{}{1, "A"}}, - {"_: 10\n", 10}, - {"_: null\n", nil}, - {"_: BAR!\n", "BAR!"}, -} - -type marshalerType struct { - value interface{} -} - -func (o marshalerType) MarshalText() ([]byte, error) { - panic("MarshalText called on type with MarshalYAML") -} - -func (o marshalerType) MarshalYAML() (interface{}, error) { - return o.value, nil -} - -type marshalerValue struct { - Field marshalerType "_" -} - -func (s *S) TestMarshaler(c *C) { - for _, item := range marshalerTests { - obj := &marshalerValue{} - obj.Field.value = item.value - data, err := yaml.Marshal(obj) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, string(item.data)) - } -} - -func (s *S) TestMarshalerWholeDocument(c *C) { - obj := &marshalerType{} - obj.value = map[string]string{"hello": "world!"} - data, err := yaml.Marshal(obj) - c.Assert(err, IsNil) - c.Assert(string(data), Equals, "hello: world!\n") -} - -type failingMarshaler struct{} - -func (ft *failingMarshaler) MarshalYAML() (interface{}, error) { - return nil, failingErr -} - -func (s *S) TestMarshalerError(c *C) { - _, err := yaml.Marshal(&failingMarshaler{}) - c.Assert(err, Equals, failingErr) -} - -func (s *S) TestSortedOutput(c *C) { - order := []interface{}{ - false, - true, - 1, - uint(1), - 1.0, - 1.1, - 1.2, - 2, - uint(2), - 2.0, - 2.1, - "", - ".1", - ".2", - ".a", - "1", - "2", - "a!10", - "a/2", - "a/10", - "a~10", - "ab/1", - "b/1", - "b/01", - "b/2", - "b/02", - "b/3", - "b/03", - "b1", - "b01", - "b3", - "c2.10", - "c10.2", - "d1", - "d12", - "d12a", - } - m := make(map[interface{}]int) - for _, k := range order { - m[k] = 1 - } - data, err := yaml.Marshal(m) - c.Assert(err, IsNil) - out := "\n" + string(data) - last := 0 - for i, k := range order { - repr := fmt.Sprint(k) - if s, ok := k.(string); ok { - if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { - repr = `"` + repr + `"` - } - } - index := strings.Index(out, "\n"+repr+":") - if index == -1 { - c.Fatalf("%#v is not in the output: %#v", k, out) - } - if index < last { - c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) - } - last = index - } -} diff --git a/Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go b/Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go deleted file mode 100644 index c5cf1ed4f..000000000 --- a/Godeps/_workspace/src/gopkg.in/yaml.v2/suite_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package yaml_test - -import ( - . "gopkg.in/check.v1" - "testing" -) - -func Test(t *testing.T) { TestingT(t) } - -type S struct{} - -var _ = Suite(&S{}) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/install/install_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/install/install_test.go deleted file mode 100644 index 87f1ef65d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/install/install_test.go +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 install - -import ( - "encoding/json" - "testing" - - "k8s.io/kubernetes/federation/apis/federation" - "k8s.io/kubernetes/federation/apis/federation/v1alpha1" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestResourceVersioner(t *testing.T) { - cluster := federation.Cluster{ObjectMeta: api.ObjectMeta{ResourceVersion: "10"}} - version, err := accessor.ResourceVersion(&cluster) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != "10" { - t.Errorf("unexpected version %v", version) - } - - clusterList := federation.ClusterList{ListMeta: unversioned.ListMeta{ResourceVersion: "10"}} - version, err = accessor.ResourceVersion(&clusterList) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != "10" { - t.Errorf("unexpected version %v", version) - } -} - -func TestCodec(t *testing.T) { - cluster := federation.Cluster{} - // We do want to use package registered rather than testapi here, because we - // want to test if the package install and package registered work as expected. - data, err := runtime.Encode(api.Codecs.LegacyCodec(registered.GroupOrDie(federation.GroupName).GroupVersion), &cluster) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - other := federation.Cluster{} - if err := json.Unmarshal(data, &other); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if other.APIVersion != registered.GroupOrDie(federation.GroupName).GroupVersion.String() || other.Kind != "Cluster" { - t.Errorf("unexpected unmarshalled object %#v", other) - } -} - -func TestInterfacesFor(t *testing.T) { - if _, err := registered.GroupOrDie(federation.GroupName).InterfacesFor(federation.SchemeGroupVersion); err == nil { - t.Fatalf("unexpected non-error: %v", err) - } - for i, version := range registered.GroupOrDie(federation.GroupName).GroupVersions { - if vi, err := registered.GroupOrDie(federation.GroupName).InterfacesFor(version); err != nil || vi == nil { - t.Fatalf("%d: unexpected result: %v", i, err) - } - } -} - -func TestRESTMapper(t *testing.T) { - gv := v1alpha1.SchemeGroupVersion - clusterGVK := gv.WithKind("Cluster") - - if gvk, err := registered.GroupOrDie(federation.GroupName).RESTMapper.KindFor(gv.WithResource("clusters")); err != nil || gvk != clusterGVK { - t.Errorf("unexpected version mapping: %v %v", gvk, err) - } - - if m, err := registered.GroupOrDie(federation.GroupName).RESTMapper.RESTMapping(clusterGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != clusterGVK || m.Resource != "clusters" { - t.Errorf("unexpected version mapping: %#v %v", m, err) - } - - for _, version := range registered.GroupOrDie(federation.GroupName).GroupVersions { - mapping, err := registered.GroupOrDie(federation.GroupName).RESTMapper.RESTMapping(clusterGVK.GroupKind(), version.Version) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if mapping.Resource != "clusters" { - t.Errorf("incorrect resource name: %#v", mapping) - } - if mapping.GroupVersionKind.GroupVersion() != version { - t.Errorf("incorrect groupVersion: %v", mapping) - } - - interfaces, _ := registered.GroupOrDie(federation.GroupName).InterfacesFor(version) - if mapping.ObjectConvertor != interfaces.ObjectConvertor { - t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces) - } - - rc := &federation.Cluster{ObjectMeta: api.ObjectMeta{Name: "foo"}} - name, err := mapping.MetadataAccessor.Name(rc) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if name != "foo" { - t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/validation/validation.go b/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/validation/validation.go deleted file mode 100644 index f6f3dac48..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/validation/validation.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "k8s.io/kubernetes/federation/apis/federation" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func ValidateClusterName(name string, prefix bool) (bool, string) { - return validation.NameIsDNSSubdomain(name, prefix) -} - -func ValidateClusterSpec(spec *federation.ClusterSpec, fieldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - // address is required. - if len(spec.ServerAddressByClientCIDRs) == 0 { - allErrs = append(allErrs, field.Required(fieldPath.Child("serverAddressByClientCIDRs"), "")) - } - return allErrs -} - -func ValidateCluster(cluster *federation.Cluster) field.ErrorList { - allErrs := validation.ValidateObjectMeta(&cluster.ObjectMeta, false, ValidateClusterName, field.NewPath("metadata")) - allErrs = append(allErrs, ValidateClusterSpec(&cluster.Spec, field.NewPath("spec"))...) - return allErrs -} - -func ValidateClusterUpdate(cluster, oldCluster *federation.Cluster) field.ErrorList { - allErrs := validation.ValidateObjectMetaUpdate(&cluster.ObjectMeta, &oldCluster.ObjectMeta, field.NewPath("metadata")) - if cluster.Name != oldCluster.Name { - allErrs = append(allErrs, field.Invalid(field.NewPath("meta", "name"), - cluster.Name+" != "+oldCluster.Name, "cannot change cluster name")) - } - return allErrs -} - -func ValidateClusterStatusUpdate(cluster, oldCluster *federation.Cluster) field.ErrorList { - allErrs := validation.ValidateObjectMetaUpdate(&cluster.ObjectMeta, &oldCluster.ObjectMeta, field.NewPath("metadata")) - return allErrs -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/validation/validation_test.go deleted file mode 100644 index d68883675..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/federation/apis/federation/validation/validation_test.go +++ /dev/null @@ -1,206 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "testing" - - "k8s.io/kubernetes/federation/apis/federation" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -func TestValidateCluster(t *testing.T) { - successCases := []federation.Cluster{ - { - ObjectMeta: api.ObjectMeta{Name: "cluster-s"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{ - { - ClientCIDR: "0.0.0.0/0", - ServerAddress: "localhost:8888", - }, - }, - }, - }, - } - for _, successCase := range successCases { - errs := ValidateCluster(&successCase) - if len(errs) != 0 { - t.Errorf("expect success: %v", errs) - } - } - - errorCases := map[string]federation.Cluster{ - "missing cluster addresses": { - ObjectMeta: api.ObjectMeta{Name: "cluster-f"}, - }, - "empty cluster addresses": { - ObjectMeta: api.ObjectMeta{Name: "cluster-f"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{}, - }}, - "invalid_label": { - ObjectMeta: api.ObjectMeta{ - Name: "cluster-f", - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - }, - } - for testName, errorCase := range errorCases { - errs := ValidateCluster(&errorCase) - if len(errs) == 0 { - t.Errorf("expected failur for %s", testName) - } - } -} - -func TestValidateClusterUpdate(t *testing.T) { - type clusterUpdateTest struct { - old federation.Cluster - update federation.Cluster - } - successCases := []clusterUpdateTest{ - { - old: federation.Cluster{ - ObjectMeta: api.ObjectMeta{Name: "cluster-s"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{ - { - ClientCIDR: "0.0.0.0/0", - ServerAddress: "localhost:8888", - }, - }, - }, - }, - update: federation.Cluster{ - ObjectMeta: api.ObjectMeta{Name: "cluster-s"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{ - { - ClientCIDR: "0.0.0.0/0", - ServerAddress: "localhost:8888", - }, - }, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - errs := ValidateClusterUpdate(&successCase.update, &successCase.old) - if len(errs) != 0 { - t.Errorf("expect success: %v", errs) - } - } - - errorCases := map[string]clusterUpdateTest{ - "cluster name changed": { - old: federation.Cluster{ - ObjectMeta: api.ObjectMeta{Name: "cluster-s"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{ - { - ClientCIDR: "0.0.0.0/0", - ServerAddress: "localhost:8888", - }, - }, - }, - }, - update: federation.Cluster{ - ObjectMeta: api.ObjectMeta{Name: "cluster-newname"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{ - { - ClientCIDR: "0.0.0.0/0", - ServerAddress: "localhost:8888", - }, - }, - }, - }, - }, - } - for testName, errorCase := range errorCases { - errs := ValidateClusterUpdate(&errorCase.update, &errorCase.old) - if len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } -} - -func TestValidateClusterStatusUpdate(t *testing.T) { - type clusterUpdateTest struct { - old federation.Cluster - update federation.Cluster - } - successCases := []clusterUpdateTest{ - { - old: federation.Cluster{ - ObjectMeta: api.ObjectMeta{Name: "cluster-s"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{ - { - ClientCIDR: "0.0.0.0/0", - ServerAddress: "localhost:8888", - }, - }, - }, - Status: federation.ClusterStatus{ - Conditions: []federation.ClusterCondition{ - {Type: federation.ClusterReady, Status: api.ConditionTrue}, - }, - }, - }, - update: federation.Cluster{ - ObjectMeta: api.ObjectMeta{Name: "cluster-s"}, - Spec: federation.ClusterSpec{ - ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{ - { - ClientCIDR: "0.0.0.0/0", - ServerAddress: "localhost:8888", - }, - }, - }, - Status: federation.ClusterStatus{ - Conditions: []federation.ClusterCondition{ - {Type: federation.ClusterReady, Status: api.ConditionTrue}, - {Type: federation.ClusterOffline, Status: api.ConditionTrue}, - }, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - errs := ValidateClusterUpdate(&successCase.update, &successCase.old) - if len(errs) != 0 { - t.Errorf("expect success: %v", errs) - } - } - - errorCases := map[string]clusterUpdateTest{} - for testName, errorCase := range errorCases { - errs := ValidateClusterStatusUpdate(&errorCase.update, &errorCase.old) - if len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/context_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/context_test.go deleted file mode 100644 index c384999ff..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/context_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 api_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -// TestNamespaceContext validates that a namespace can be get/set on a context object -func TestNamespaceContext(t *testing.T) { - ctx := api.NewDefaultContext() - result, ok := api.NamespaceFrom(ctx) - if !ok { - t.Errorf("Error getting namespace") - } - if api.NamespaceDefault != result { - t.Errorf("Expected: %v, Actual: %v", api.NamespaceDefault, result) - } - - ctx = api.NewContext() - result, ok = api.NamespaceFrom(ctx) - if ok { - t.Errorf("Should not be ok because there is no namespace on the context") - } -} - -// TestValidNamespace validates that namespace rules are enforced on a resource prior to create or update -func TestValidNamespace(t *testing.T) { - ctx := api.NewDefaultContext() - namespace, _ := api.NamespaceFrom(ctx) - resource := api.ReplicationController{} - if !api.ValidNamespace(ctx, &resource.ObjectMeta) { - t.Errorf("expected success") - } - if namespace != resource.Namespace { - t.Errorf("expected resource to have the default namespace assigned during validation") - } - resource = api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: "other"}} - if api.ValidNamespace(ctx, &resource.ObjectMeta) { - t.Errorf("Expected error that resource and context errors do not match because resource has different namespace") - } - ctx = api.NewContext() - if api.ValidNamespace(ctx, &resource.ObjectMeta) { - t.Errorf("Expected error that resource and context errors do not match since context has no namespace") - } - - ctx = api.NewContext() - ns := api.NamespaceValue(ctx) - if ns != "" { - t.Errorf("Expected the empty string") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/conversion_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/conversion_test.go deleted file mode 100644 index 2a91f0aec..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/conversion_test.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 api_test - -import ( - "io/ioutil" - "math/rand" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/runtime" -) - -func BenchmarkPodConversion(b *testing.B) { - apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) - items := make([]api.Pod, 4) - for i := range items { - apiObjectFuzzer.Fuzz(&items[i]) - } - - // add a fixed item - data, err := ioutil.ReadFile("pod_example.json") - if err != nil { - b.Fatalf("Unexpected error while reading file: %v", err) - } - var pod api.Pod - if err := runtime.DecodeInto(testapi.Default.Codec(), data, &pod); err != nil { - b.Fatalf("Unexpected error decoding pod: %v", err) - } - items = append(items, pod) - width := len(items) - - scheme := api.Scheme - var result *api.Pod - for i := 0; i < b.N; i++ { - pod := &items[i%width] - versionedObj, err := scheme.ConvertToVersion(pod, testapi.Default.GroupVersion().String()) - if err != nil { - b.Fatalf("Conversion error: %v", err) - } - obj, err := scheme.ConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion().String()) - if err != nil { - b.Fatalf("Conversion error: %v", err) - } - result = obj.(*api.Pod) - } - b.Log(result) -} - -func BenchmarkNodeConversion(b *testing.B) { - data, err := ioutil.ReadFile("node_example.json") - if err != nil { - b.Fatalf("Unexpected error while reading file: %v", err) - } - var node api.Node - if err := runtime.DecodeInto(testapi.Default.Codec(), data, &node); err != nil { - b.Fatalf("Unexpected error decoding node: %v", err) - } - - scheme := api.Scheme - var result *api.Node - for i := 0; i < b.N; i++ { - versionedObj, err := scheme.ConvertToVersion(&node, testapi.Default.GroupVersion().String()) - if err != nil { - b.Fatalf("Conversion error: %v", err) - } - obj, err := scheme.ConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion().String()) - if err != nil { - b.Fatalf("Conversion error: %v", err) - } - result = obj.(*api.Node) - } - if !api.Semantic.DeepDerivative(node, *result) { - b.Fatalf("Incorrect conversion: expected %v, got %v", node, *result) - } -} - -func BenchmarkReplicationControllerConversion(b *testing.B) { - data, err := ioutil.ReadFile("replication_controller_example.json") - if err != nil { - b.Fatalf("Unexpected error while reading file: %v", err) - } - var replicationController api.ReplicationController - if err := runtime.DecodeInto(testapi.Default.Codec(), data, &replicationController); err != nil { - b.Fatalf("Unexpected error decoding node: %v", err) - } - - scheme := api.Scheme - var result *api.ReplicationController - for i := 0; i < b.N; i++ { - versionedObj, err := scheme.ConvertToVersion(&replicationController, testapi.Default.GroupVersion().String()) - if err != nil { - b.Fatalf("Conversion error: %v", err) - } - obj, err := scheme.ConvertToVersion(versionedObj, testapi.Default.InternalGroupVersion().String()) - if err != nil { - b.Fatalf("Conversion error: %v", err) - } - result = obj.(*api.ReplicationController) - } - if !api.Semantic.DeepDerivative(replicationController, *result) { - b.Fatalf("Incorrect conversion: expected %v, got %v", replicationController, *result) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/copy_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/copy_test.go deleted file mode 100644 index af81d0273..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/copy_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 api_test - -import ( - "math/rand" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/util/diff" - - "github.com/google/gofuzz" -) - -func TestDeepCopyApiObjects(t *testing.T) { - for i := 0; i < *fuzzIters; i++ { - for _, version := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { - f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) - for kind := range api.Scheme.KnownTypes(version) { - doDeepCopyTest(t, version.WithKind(kind), f) - } - } - } -} - -func doDeepCopyTest(t *testing.T, kind unversioned.GroupVersionKind, f *fuzz.Fuzzer) { - item, err := api.Scheme.New(kind) - if err != nil { - t.Fatalf("Could not create a %v: %s", kind, err) - } - f.Fuzz(item) - itemCopy, err := api.Scheme.DeepCopy(item) - if err != nil { - t.Errorf("Could not deep copy a %v: %s", kind, err) - return - } - - if !reflect.DeepEqual(item, itemCopy) { - t.Errorf("\nexpected: %#v\n\ngot: %#v\n\ndiff: %v", item, itemCopy, diff.ObjectGoPrintSideBySide(item, itemCopy)) - } -} - -func TestDeepCopySingleType(t *testing.T) { - for i := 0; i < *fuzzIters; i++ { - for _, version := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { - f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) - doDeepCopyTest(t, version.WithKind("Pod"), f) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/deep_copy_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/deep_copy_test.go deleted file mode 100644 index a251623a0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/deep_copy_test.go +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 api_test - -import ( - "io/ioutil" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/runtime" -) - -func BenchmarkPodCopy(b *testing.B) { - data, err := ioutil.ReadFile("pod_example.json") - if err != nil { - b.Fatalf("Unexpected error while reading file: %v", err) - } - var pod api.Pod - if err := runtime.DecodeInto(testapi.Default.Codec(), data, &pod); err != nil { - b.Fatalf("Unexpected error decoding pod: %v", err) - } - - var result *api.Pod - for i := 0; i < b.N; i++ { - obj, err := api.Scheme.DeepCopy(&pod) - if err != nil { - b.Fatalf("Unexpected error copying pod: %v", err) - } - result = obj.(*api.Pod) - } - if !api.Semantic.DeepEqual(pod, *result) { - b.Fatalf("Incorrect copy: expected %v, got %v", pod, *result) - } -} - -func BenchmarkNodeCopy(b *testing.B) { - data, err := ioutil.ReadFile("node_example.json") - if err != nil { - b.Fatalf("Unexpected error while reading file: %v", err) - } - var node api.Node - if err := runtime.DecodeInto(testapi.Default.Codec(), data, &node); err != nil { - b.Fatalf("Unexpected error decoding node: %v", err) - } - - var result *api.Node - for i := 0; i < b.N; i++ { - obj, err := api.Scheme.DeepCopy(&node) - if err != nil { - b.Fatalf("Unexpected error copying node: %v", err) - } - result = obj.(*api.Node) - } - if !api.Semantic.DeepEqual(node, *result) { - b.Fatalf("Incorrect copy: expected %v, got %v", node, *result) - } -} - -func BenchmarkReplicationControllerCopy(b *testing.B) { - data, err := ioutil.ReadFile("replication_controller_example.json") - if err != nil { - b.Fatalf("Unexpected error while reading file: %v", err) - } - var replicationController api.ReplicationController - if err := runtime.DecodeInto(testapi.Default.Codec(), data, &replicationController); err != nil { - b.Fatalf("Unexpected error decoding node: %v", err) - } - - var result *api.ReplicationController - for i := 0; i < b.N; i++ { - obj, err := api.Scheme.DeepCopy(&replicationController) - if err != nil { - b.Fatalf("Unexpected error copying replication controller: %v", err) - } - result = obj.(*api.ReplicationController) - } - if !api.Semantic.DeepEqual(replicationController, *result) { - b.Fatalf("Incorrect copy: expected %v, got %v", replicationController, *result) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/endpoints/util_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/endpoints/util_test.go deleted file mode 100644 index a2f960317..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/endpoints/util_test.go +++ /dev/null @@ -1,444 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 endpoints - -import ( - "reflect" - "testing" - - "github.com/davecgh/go-spew/spew" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/types" -) - -func podRef(uid string) *api.ObjectReference { - ref := api.ObjectReference{UID: types.UID(uid)} - return &ref -} - -func TestPackSubsets(t *testing.T) { - // The downside of table-driven tests is that some things have to live outside the table. - fooObjRef := api.ObjectReference{Name: "foo"} - barObjRef := api.ObjectReference{Name: "bar"} - - testCases := []struct { - name string - given []api.EndpointSubset - expect []api.EndpointSubset - }{ - { - name: "empty everything", - given: []api.EndpointSubset{{Addresses: []api.EndpointAddress{}, Ports: []api.EndpointPort{}}}, - expect: []api.EndpointSubset{}, - }, { - name: "empty addresses", - given: []api.EndpointSubset{{Addresses: []api.EndpointAddress{}, Ports: []api.EndpointPort{{Port: 111}}}}, - expect: []api.EndpointSubset{}, - }, { - name: "empty ports", - given: []api.EndpointSubset{{Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []api.EndpointPort{}}}, - expect: []api.EndpointSubset{}, - }, { - name: "empty ports", - given: []api.EndpointSubset{{NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []api.EndpointPort{}}}, - expect: []api.EndpointSubset{}, - }, { - name: "one set, one ip, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, one notReady ip, one port", - given: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, one ip, one UID, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, one notReady ip, one UID, one port", - given: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, one ip, empty UID, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, one notReady ip, empty UID, one port", - given: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, two ips, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, two mixed ips, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - NotReadyAddresses: []api.EndpointAddress{{IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - NotReadyAddresses: []api.EndpointAddress{{IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, two duplicate ips, one port, notReady is covered by ready", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, one ip, two ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}, {Port: 222}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}, {Port: 222}}, - }}, - }, { - name: "one set, dup ips, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, dup ips with target-refs, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "1.2.3.4", TargetRef: &fooObjRef}, - {IP: "1.2.3.4", TargetRef: &barObjRef}, - }, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, dup mixed ips with target-refs, one port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "1.2.3.4", TargetRef: &fooObjRef}, - }, - NotReadyAddresses: []api.EndpointAddress{ - {IP: "1.2.3.4", TargetRef: &barObjRef}, - }, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - // finding the same address twice is considered an error on input, only the first address+port - // reference is preserved - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &fooObjRef}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "one set, one ip, dup ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}, {Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two sets, dup ip, dup port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two sets, dup mixed ip, dup port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two sets, dup ip, two ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 222}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}, {Port: 222}}, - }}, - }, { - name: "two sets, dup ip, dup uids, two ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 222}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}, {Port: 222}}, - }}, - }, { - name: "two sets, dup mixed ip, dup uids, two ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 222}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 222}}, - }}, - }, { - name: "two sets, two ips, dup port", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two set, dup ip, two uids, dup ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "1.2.3.4", TargetRef: podRef("uid-1")}, - {IP: "1.2.3.4", TargetRef: podRef("uid-2")}, - }, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two set, dup ip, with and without uid, dup ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-2")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "1.2.3.4"}, - {IP: "1.2.3.4", TargetRef: podRef("uid-2")}, - }, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two sets, two ips, two dup ip with uid, dup port, wrong order", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "1.2.3.4"}, - {IP: "1.2.3.4", TargetRef: podRef("uid-1")}, - {IP: "5.6.7.8"}, - {IP: "5.6.7.8", TargetRef: podRef("uid-1")}, - }, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two sets, two mixed ips, two dup ip with uid, dup port, wrong order, ends up with split addresses", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "5.6.7.8", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: podRef("uid-1")}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "5.6.7.8"}, - }, - NotReadyAddresses: []api.EndpointAddress{ - {IP: "1.2.3.4"}, - {IP: "1.2.3.4", TargetRef: podRef("uid-1")}, - {IP: "5.6.7.8", TargetRef: podRef("uid-1")}, - }, - Ports: []api.EndpointPort{{Port: 111}}, - }}, - }, { - name: "two sets, two ips, two ports", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 222}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "5.6.7.8"}}, - Ports: []api.EndpointPort{{Port: 222}}, - }}, - }, { - name: "four sets, three ips, three ports, jumbled", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.5"}}, - Ports: []api.EndpointPort{{Port: 222}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.6"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.5"}}, - Ports: []api.EndpointPort{{Port: 333}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.5"}}, - Ports: []api.EndpointPort{{Port: 222}, {Port: 333}}, - }}, - }, { - name: "four sets, three mixed ips, three ports, jumbled", - given: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5"}}, - Ports: []api.EndpointPort{{Port: 222}}, - }, { - Addresses: []api.EndpointAddress{{IP: "1.2.3.6"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5"}}, - Ports: []api.EndpointPort{{Port: 333}}, - }}, - expect: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "1.2.3.6"}}, - Ports: []api.EndpointPort{{Port: 111}}, - }, { - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5"}}, - Ports: []api.EndpointPort{{Port: 222}, {Port: 333}}, - }}, - }, - } - - for _, tc := range testCases { - result := RepackSubsets(tc.given) - if !reflect.DeepEqual(result, SortSubsets(tc.expect)) { - t.Errorf("case %q: expected %s, got %s", tc.name, spew.Sprintf("%#v", SortSubsets(tc.expect)), spew.Sprintf("%#v", result)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/errors_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/errors_test.go deleted file mode 100644 index 066bb25f2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/errors_test.go +++ /dev/null @@ -1,189 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 errors - -import ( - "errors" - "fmt" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func TestErrorNew(t *testing.T) { - err := NewAlreadyExists(api.Resource("tests"), "1") - if !IsAlreadyExists(err) { - t.Errorf("expected to be %s", unversioned.StatusReasonAlreadyExists) - } - if IsConflict(err) { - t.Errorf("expected to not be %s", unversioned.StatusReasonConflict) - } - if IsNotFound(err) { - t.Errorf(fmt.Sprintf("expected to not be %s", unversioned.StatusReasonNotFound)) - } - if IsInvalid(err) { - t.Errorf("expected to not be %s", unversioned.StatusReasonInvalid) - } - if IsBadRequest(err) { - t.Errorf("expected to not be %s", unversioned.StatusReasonBadRequest) - } - if IsForbidden(err) { - t.Errorf("expected to not be %s", unversioned.StatusReasonForbidden) - } - if IsServerTimeout(err) { - t.Errorf("expected to not be %s", unversioned.StatusReasonServerTimeout) - } - if IsMethodNotSupported(err) { - t.Errorf("expected to not be %s", unversioned.StatusReasonMethodNotAllowed) - } - - if !IsConflict(NewConflict(api.Resource("tests"), "2", errors.New("message"))) { - t.Errorf("expected to be conflict") - } - if !IsNotFound(NewNotFound(api.Resource("tests"), "3")) { - t.Errorf("expected to be %s", unversioned.StatusReasonNotFound) - } - if !IsInvalid(NewInvalid(api.Kind("Test"), "2", nil)) { - t.Errorf("expected to be %s", unversioned.StatusReasonInvalid) - } - if !IsBadRequest(NewBadRequest("reason")) { - t.Errorf("expected to be %s", unversioned.StatusReasonBadRequest) - } - if !IsForbidden(NewForbidden(api.Resource("tests"), "2", errors.New("reason"))) { - t.Errorf("expected to be %s", unversioned.StatusReasonForbidden) - } - if !IsUnauthorized(NewUnauthorized("reason")) { - t.Errorf("expected to be %s", unversioned.StatusReasonUnauthorized) - } - if !IsServerTimeout(NewServerTimeout(api.Resource("tests"), "reason", 0)) { - t.Errorf("expected to be %s", unversioned.StatusReasonServerTimeout) - } - if time, ok := SuggestsClientDelay(NewServerTimeout(api.Resource("tests"), "doing something", 10)); time != 10 || !ok { - t.Errorf("expected to be %s", unversioned.StatusReasonServerTimeout) - } - if time, ok := SuggestsClientDelay(NewTimeoutError("test reason", 10)); time != 10 || !ok { - t.Errorf("expected to be %s", unversioned.StatusReasonTimeout) - } - if !IsMethodNotSupported(NewMethodNotSupported(api.Resource("foos"), "delete")) { - t.Errorf("expected to be %s", unversioned.StatusReasonMethodNotAllowed) - } -} - -func TestNewInvalid(t *testing.T) { - testCases := []struct { - Err *field.Error - Details *unversioned.StatusDetails - }{ - { - field.Duplicate(field.NewPath("field[0].name"), "bar"), - &unversioned.StatusDetails{ - Kind: "Kind", - Name: "name", - Causes: []unversioned.StatusCause{{ - Type: unversioned.CauseTypeFieldValueDuplicate, - Field: "field[0].name", - }}, - }, - }, - { - field.Invalid(field.NewPath("field[0].name"), "bar", "detail"), - &unversioned.StatusDetails{ - Kind: "Kind", - Name: "name", - Causes: []unversioned.StatusCause{{ - Type: unversioned.CauseTypeFieldValueInvalid, - Field: "field[0].name", - }}, - }, - }, - { - field.NotFound(field.NewPath("field[0].name"), "bar"), - &unversioned.StatusDetails{ - Kind: "Kind", - Name: "name", - Causes: []unversioned.StatusCause{{ - Type: unversioned.CauseTypeFieldValueNotFound, - Field: "field[0].name", - }}, - }, - }, - { - field.NotSupported(field.NewPath("field[0].name"), "bar", nil), - &unversioned.StatusDetails{ - Kind: "Kind", - Name: "name", - Causes: []unversioned.StatusCause{{ - Type: unversioned.CauseTypeFieldValueNotSupported, - Field: "field[0].name", - }}, - }, - }, - { - field.Required(field.NewPath("field[0].name"), ""), - &unversioned.StatusDetails{ - Kind: "Kind", - Name: "name", - Causes: []unversioned.StatusCause{{ - Type: unversioned.CauseTypeFieldValueRequired, - Field: "field[0].name", - }}, - }, - }, - } - for i, testCase := range testCases { - vErr, expected := testCase.Err, testCase.Details - expected.Causes[0].Message = vErr.ErrorBody() - err := NewInvalid(api.Kind("Kind"), "name", field.ErrorList{vErr}) - status := err.(*StatusError).ErrStatus - if status.Code != 422 || status.Reason != unversioned.StatusReasonInvalid { - t.Errorf("%d: unexpected status: %#v", i, status) - } - if !reflect.DeepEqual(expected, status.Details) { - t.Errorf("%d: expected %#v, got %#v", i, expected, status.Details) - } - } -} - -func Test_reasonForError(t *testing.T) { - if e, a := unversioned.StatusReasonUnknown, reasonForError(nil); e != a { - t.Errorf("unexpected reason type: %#v", a) - } -} - -type TestType struct{} - -func (obj *TestType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -func TestFromObject(t *testing.T) { - table := []struct { - obj runtime.Object - message string - }{ - {&unversioned.Status{Message: "foobar"}, "foobar"}, - {&TestType{}, "unexpected object: &{}"}, - } - - for _, item := range table { - if e, a := item.message, FromObject(item.obj).Error(); e != a { - t.Errorf("Expected %v, got %v", e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/storage/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/storage/doc.go deleted file mode 100644 index a2a550526..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/storage/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd provides conversion of etcd errors to API errors. -package storage diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/storage/storage.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/storage/storage.go deleted file mode 100644 index 2a22b4f17..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/errors/storage/storage.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 storage - -import ( - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/storage" -) - -// InterpretListError converts a generic error on a retrieval -// operation into the appropriate API error. -func InterpretListError(err error, qualifiedResource unversioned.GroupResource) error { - switch { - case storage.IsNotFound(err): - return errors.NewNotFound(qualifiedResource, "") - case storage.IsUnreachable(err): - return errors.NewServerTimeout(qualifiedResource, "list", 2) // TODO: make configurable or handled at a higher level - default: - return err - } -} - -// InterpretGetError converts a generic error on a retrieval -// operation into the appropriate API error. -func InterpretGetError(err error, qualifiedResource unversioned.GroupResource, name string) error { - switch { - case storage.IsNotFound(err): - return errors.NewNotFound(qualifiedResource, name) - case storage.IsUnreachable(err): - return errors.NewServerTimeout(qualifiedResource, "get", 2) // TODO: make configurable or handled at a higher level - default: - return err - } -} - -// InterpretCreateError converts a generic error on a create -// operation into the appropriate API error. -func InterpretCreateError(err error, qualifiedResource unversioned.GroupResource, name string) error { - switch { - case storage.IsNodeExist(err): - return errors.NewAlreadyExists(qualifiedResource, name) - case storage.IsUnreachable(err): - return errors.NewServerTimeout(qualifiedResource, "create", 2) // TODO: make configurable or handled at a higher level - default: - return err - } -} - -// InterpretUpdateError converts a generic error on a update -// operation into the appropriate API error. -func InterpretUpdateError(err error, qualifiedResource unversioned.GroupResource, name string) error { - switch { - case storage.IsTestFailed(err), storage.IsNodeExist(err): - return errors.NewConflict(qualifiedResource, name, err) - case storage.IsUnreachable(err): - return errors.NewServerTimeout(qualifiedResource, "update", 2) // TODO: make configurable or handled at a higher level - case storage.IsNotFound(err): - return errors.NewNotFound(qualifiedResource, name) - case storage.IsInternalError(err): - return errors.NewInternalError(err) - default: - return err - } -} - -// InterpretDeleteError converts a generic error on a delete -// operation into the appropriate API error. -func InterpretDeleteError(err error, qualifiedResource unversioned.GroupResource, name string) error { - switch { - case storage.IsNotFound(err): - return errors.NewNotFound(qualifiedResource, name) - case storage.IsUnreachable(err): - return errors.NewServerTimeout(qualifiedResource, "delete", 2) // TODO: make configurable or handled at a higher level - case storage.IsTestFailed(err), storage.IsNodeExist(err): - return errors.NewConflict(qualifiedResource, name, err) - case storage.IsInternalError(err): - return errors.NewInternalError(err) - default: - return err - } -} - -// InterpretWatchError converts a generic error on a watch -// operation into the appropriate API error. -func InterpretWatchError(err error, resource unversioned.GroupResource, name string) error { - switch { - case storage.IsInvalidError(err): - invalidError, _ := err.(storage.InvalidError) - return errors.NewInvalid(unversioned.GroupKind{Group: resource.Group, Kind: resource.Resource}, name, invalidError.Errs) - default: - return err - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/generate_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/generate_test.go deleted file mode 100644 index fe3cf812b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/generate_test.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 api - -import ( - "strings" - "testing" -) - -type nameGeneratorFunc func(base string) string - -func (fn nameGeneratorFunc) GenerateName(base string) string { - return fn(base) -} - -func TestGenerateName(t *testing.T) { - testCases := []struct { - meta ObjectMeta - - base string - returned string - }{ - { - returned: "", - }, - { - meta: ObjectMeta{ - GenerateName: "test", - }, - base: "test", - returned: "test", - }, - { - meta: ObjectMeta{ - Name: "foo", - GenerateName: "test", - }, - base: "test", - returned: "foo", - }, - } - - for i, testCase := range testCases { - GenerateName(nameGeneratorFunc(func(base string) string { - if base != testCase.base { - t.Errorf("%d: unexpected call with base", i) - } - return "test" - }), &testCase.meta) - expect := testCase.returned - if expect != testCase.meta.Name { - t.Errorf("%d: unexpected name: %#v", i, testCase.meta) - } - } -} - -func TestSimpleNameGenerator(t *testing.T) { - meta := &ObjectMeta{ - GenerateName: "foo", - } - GenerateName(SimpleNameGenerator, meta) - if !strings.HasPrefix(meta.Name, "foo") || meta.Name == "foo" { - t.Errorf("unexpected name: %#v", meta) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/helpers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/helpers_test.go deleted file mode 100644 index 2d6bd488f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/helpers_test.go +++ /dev/null @@ -1,299 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 api - -import ( - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/labels" - - "speter.net/go/exp/math/dec/inf" -) - -func TestConversionError(t *testing.T) { - var i int - var s string - i = 3 - s = "foo" - c := ConversionError{ - In: &i, Out: &s, - Message: "Can't make x into y, silly", - } - var e error - e = &c // ensure it implements error - msg := e.Error() - t.Logf("Message is %v", msg) - for _, part := range []string{"3", "int", "string", "Can't"} { - if !strings.Contains(msg, part) { - t.Errorf("didn't find %v", part) - } - } -} - -func TestSemantic(t *testing.T) { - table := []struct { - a, b interface{} - shouldEqual bool - }{ - {resource.MustParse("0"), resource.Quantity{}, true}, - {resource.Quantity{}, resource.MustParse("0"), true}, - {resource.Quantity{}, resource.MustParse("1m"), false}, - { - resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.BinarySI}, - resource.Quantity{Amount: inf.NewDec(5, 0), Format: resource.DecimalSI}, - true, - }, - {resource.MustParse("2m"), resource.MustParse("1m"), false}, - } - - for index, item := range table { - if e, a := item.shouldEqual, Semantic.DeepEqual(item.a, item.b); e != a { - t.Errorf("case[%d], expected %v, got %v.", index, e, a) - } - } -} - -func TestIsStandardResource(t *testing.T) { - testCases := []struct { - input string - output bool - }{ - {"cpu", true}, - {"memory", true}, - {"disk", false}, - {"blah", false}, - {"x.y.z", false}, - } - for i, tc := range testCases { - if IsStandardResourceName(tc.input) != tc.output { - t.Errorf("case[%d], expected: %t, got: %t", i, tc.output, !tc.output) - } - } -} - -func TestAddToNodeAddresses(t *testing.T) { - testCases := []struct { - existing []NodeAddress - toAdd []NodeAddress - expected []NodeAddress - }{ - { - existing: []NodeAddress{}, - toAdd: []NodeAddress{}, - expected: []NodeAddress{}, - }, - { - existing: []NodeAddress{}, - toAdd: []NodeAddress{ - {Type: NodeExternalIP, Address: "1.1.1.1"}, - {Type: NodeHostName, Address: "localhost"}, - }, - expected: []NodeAddress{ - {Type: NodeExternalIP, Address: "1.1.1.1"}, - {Type: NodeHostName, Address: "localhost"}, - }, - }, - { - existing: []NodeAddress{}, - toAdd: []NodeAddress{ - {Type: NodeExternalIP, Address: "1.1.1.1"}, - {Type: NodeExternalIP, Address: "1.1.1.1"}, - }, - expected: []NodeAddress{ - {Type: NodeExternalIP, Address: "1.1.1.1"}, - }, - }, - { - existing: []NodeAddress{ - {Type: NodeExternalIP, Address: "1.1.1.1"}, - {Type: NodeInternalIP, Address: "10.1.1.1"}, - }, - toAdd: []NodeAddress{ - {Type: NodeExternalIP, Address: "1.1.1.1"}, - {Type: NodeHostName, Address: "localhost"}, - }, - expected: []NodeAddress{ - {Type: NodeExternalIP, Address: "1.1.1.1"}, - {Type: NodeInternalIP, Address: "10.1.1.1"}, - {Type: NodeHostName, Address: "localhost"}, - }, - }, - } - - for i, tc := range testCases { - AddToNodeAddresses(&tc.existing, tc.toAdd...) - if !Semantic.DeepEqual(tc.expected, tc.existing) { - t.Errorf("case[%d], expected: %v, got: %v", i, tc.expected, tc.existing) - } - } -} - -func TestGetAccessModesFromString(t *testing.T) { - modes := GetAccessModesFromString("ROX") - if !containsAccessMode(modes, ReadOnlyMany) { - t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes) - } - - modes = GetAccessModesFromString("ROX,RWX") - if !containsAccessMode(modes, ReadOnlyMany) { - t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes) - } - if !containsAccessMode(modes, ReadWriteMany) { - t.Errorf("Expected mode %s, but got %+v", ReadWriteMany, modes) - } - - modes = GetAccessModesFromString("RWO,ROX,RWX") - if !containsAccessMode(modes, ReadOnlyMany) { - t.Errorf("Expected mode %s, but got %+v", ReadOnlyMany, modes) - } - if !containsAccessMode(modes, ReadWriteMany) { - t.Errorf("Expected mode %s, but got %+v", ReadWriteMany, modes) - } -} - -func TestRemoveDuplicateAccessModes(t *testing.T) { - modes := []PersistentVolumeAccessMode{ - ReadWriteOnce, ReadOnlyMany, ReadOnlyMany, ReadOnlyMany, - } - modes = removeDuplicateAccessModes(modes) - if len(modes) != 2 { - t.Errorf("Expected 2 distinct modes in set but found %v", len(modes)) - } -} - -func TestNodeSelectorRequirementsAsSelector(t *testing.T) { - matchExpressions := []NodeSelectorRequirement{{ - Key: "foo", - Operator: NodeSelectorOpIn, - Values: []string{"bar", "baz"}, - }} - mustParse := func(s string) labels.Selector { - out, e := labels.Parse(s) - if e != nil { - panic(e) - } - return out - } - tc := []struct { - in []NodeSelectorRequirement - out labels.Selector - expectErr bool - }{ - {in: nil, out: labels.Nothing()}, - {in: []NodeSelectorRequirement{}, out: labels.Nothing()}, - { - in: matchExpressions, - out: mustParse("foo in (baz,bar)"), - }, - { - in: []NodeSelectorRequirement{{ - Key: "foo", - Operator: NodeSelectorOpExists, - Values: []string{"bar", "baz"}, - }}, - expectErr: true, - }, - { - in: []NodeSelectorRequirement{{ - Key: "foo", - Operator: NodeSelectorOpGt, - Values: []string{"1.1"}, - }}, - out: mustParse("foo>1.1"), - }, - { - in: []NodeSelectorRequirement{{ - Key: "bar", - Operator: NodeSelectorOpLt, - Values: []string{"7.1"}, - }}, - out: mustParse("bar<7.1"), - }, - } - - for i, tc := range tc { - out, err := NodeSelectorRequirementsAsSelector(tc.in) - if err == nil && tc.expectErr { - t.Errorf("[%v]expected error but got none.", i) - } - if err != nil && !tc.expectErr { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } - if !reflect.DeepEqual(out, tc.out) { - t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out) - } - } -} - -func TestGetAffinityFromPod(t *testing.T) { - testCases := []struct { - pod *Pod - expectErr bool - }{ - { - pod: &Pod{}, - expectErr: false, - }, - { - pod: &Pod{ - ObjectMeta: ObjectMeta{ - Annotations: map[string]string{ - AffinityAnnotationKey: ` - {"nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [{ - "matchExpressions": [{ - "key": "foo", - "operator": "In", - "values": ["value1", "value2"] - }] - }] - }}}`, - }, - }, - }, - expectErr: false, - }, - { - pod: &Pod{ - ObjectMeta: ObjectMeta{ - Annotations: map[string]string{ - AffinityAnnotationKey: ` - {"nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [{ - "matchExpressions": [{ - "key": "foo", - `, - }, - }, - }, - expectErr: true, - }, - } - - for i, tc := range testCases { - _, err := GetAffinityFromPodAnnotations(tc.pod.Annotations) - if err == nil && tc.expectErr { - t.Errorf("[%v]expected error but got none.", i) - } - if err != nil && !tc.expectErr { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/install/install_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/install/install_test.go deleted file mode 100644 index 07c7f5d51..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/install/install_test.go +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 install - -import ( - "encoding/json" - "reflect" - "testing" - - internal "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestResourceVersioner(t *testing.T) { - pod := internal.Pod{ObjectMeta: internal.ObjectMeta{ResourceVersion: "10"}} - version, err := accessor.ResourceVersion(&pod) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != "10" { - t.Errorf("unexpected version %v", version) - } - - podList := internal.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "10"}} - version, err = accessor.ResourceVersion(&podList) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != "10" { - t.Errorf("unexpected version %v", version) - } -} - -func TestCodec(t *testing.T) { - pod := internal.Pod{} - // We do want to use package registered rather than testapi here, because we - // want to test if the package install and package registered work as expected. - data, err := runtime.Encode(internal.Codecs.LegacyCodec(registered.GroupOrDie(internal.GroupName).GroupVersion), &pod) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - other := internal.Pod{} - if err := json.Unmarshal(data, &other); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if other.APIVersion != registered.GroupOrDie(internal.GroupName).GroupVersion.Version || other.Kind != "Pod" { - t.Errorf("unexpected unmarshalled object %#v", other) - } -} - -func TestInterfacesFor(t *testing.T) { - if _, err := registered.GroupOrDie(internal.GroupName).InterfacesFor(internal.SchemeGroupVersion); err == nil { - t.Fatalf("unexpected non-error: %v", err) - } - for i, version := range registered.GroupOrDie(internal.GroupName).GroupVersions { - if vi, err := registered.GroupOrDie(internal.GroupName).InterfacesFor(version); err != nil || vi == nil { - t.Fatalf("%d: unexpected result: %v", i, err) - } - } -} - -func TestRESTMapper(t *testing.T) { - gv := unversioned.GroupVersion{Group: "", Version: "v1"} - rcGVK := gv.WithKind("ReplicationController") - podTemplateGVK := gv.WithKind("PodTemplate") - - if gvk, err := registered.RESTMapper().KindFor(internal.SchemeGroupVersion.WithResource("replicationcontrollers")); err != nil || gvk != rcGVK { - t.Errorf("unexpected version mapping: %v %v", gvk, err) - } - - if m, err := registered.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(podTemplateGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != podTemplateGVK || m.Resource != "podtemplates" { - t.Errorf("unexpected version mapping: %#v %v", m, err) - } - - for _, version := range registered.GroupOrDie(internal.GroupName).GroupVersions { - mapping, err := registered.GroupOrDie(internal.GroupName).RESTMapper.RESTMapping(rcGVK.GroupKind(), version.Version) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if mapping.Resource != "replicationControllers" && mapping.Resource != "replicationcontrollers" { - t.Errorf("incorrect resource name: %#v", mapping) - } - if mapping.GroupVersionKind.GroupVersion() != version { - t.Errorf("incorrect version: %v", mapping) - } - - interfaces, _ := registered.GroupOrDie(internal.GroupName).InterfacesFor(version) - if mapping.ObjectConvertor != interfaces.ObjectConvertor { - t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces) - } - - rc := &internal.ReplicationController{ObjectMeta: internal.ObjectMeta{Name: "foo"}} - name, err := mapping.MetadataAccessor.Name(rc) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if name != "foo" { - t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor) - } - } -} - -func TestUnversioned(t *testing.T) { - for _, obj := range []runtime.Object{ - &unversioned.Status{}, - &unversioned.ExportOptions{}, - } { - if unversioned, ok := internal.Scheme.IsUnversioned(obj); !unversioned || !ok { - t.Errorf("%v is expected to be unversioned", reflect.TypeOf(obj)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/help_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/help_test.go deleted file mode 100644 index 85ba2cbf6..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/help_test.go +++ /dev/null @@ -1,253 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 meta_test - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/diff" - - "github.com/google/gofuzz" -) - -func TestIsList(t *testing.T) { - tests := []struct { - obj runtime.Object - isList bool - }{ - {&api.PodList{}, true}, - {&api.Pod{}, false}, - } - for _, item := range tests { - if e, a := item.isList, meta.IsListType(item.obj); e != a { - t.Errorf("%v: Expected %v, got %v", reflect.TypeOf(item.obj), e, a) - } - } -} - -func TestExtractList(t *testing.T) { - pl := &api.PodList{ - Items: []api.Pod{ - {ObjectMeta: api.ObjectMeta{Name: "1"}}, - {ObjectMeta: api.ObjectMeta{Name: "2"}}, - {ObjectMeta: api.ObjectMeta{Name: "3"}}, - }, - } - list, err := meta.ExtractList(pl) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if e, a := len(list), len(pl.Items); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - for i := range list { - if e, a := list[i].(*api.Pod).Name, pl.Items[i].Name; e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - } -} - -func TestExtractListV1(t *testing.T) { - pl := &v1.PodList{ - Items: []v1.Pod{ - {ObjectMeta: v1.ObjectMeta{Name: "1"}}, - {ObjectMeta: v1.ObjectMeta{Name: "2"}}, - {ObjectMeta: v1.ObjectMeta{Name: "3"}}, - }, - } - list, err := meta.ExtractList(pl) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if e, a := len(list), len(pl.Items); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - for i := range list { - if e, a := list[i].(*v1.Pod).Name, pl.Items[i].Name; e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - } -} - -func TestExtractListGeneric(t *testing.T) { - pl := &api.List{ - Items: []runtime.Object{ - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, - &api.Service{ObjectMeta: api.ObjectMeta{Name: "2"}}, - }, - } - list, err := meta.ExtractList(pl) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if e, a := len(list), len(pl.Items); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - if obj, ok := list[0].(*api.Pod); !ok { - t.Fatalf("Expected list[0] to be *api.Pod, it is %#v", obj) - } - if obj, ok := list[1].(*api.Service); !ok { - t.Fatalf("Expected list[1] to be *api.Service, it is %#v", obj) - } -} - -func TestExtractListGenericV1(t *testing.T) { - pl := &v1.List{ - Items: []runtime.RawExtension{ - {Raw: []byte("foo")}, - {Raw: []byte("bar")}, - {Object: &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "other"}}}, - }, - } - list, err := meta.ExtractList(pl) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if e, a := len(list), len(pl.Items); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - if obj, ok := list[0].(*runtime.Unknown); !ok { - t.Fatalf("Expected list[0] to be *runtime.Unknown, it is %#v", obj) - } - if obj, ok := list[1].(*runtime.Unknown); !ok { - t.Fatalf("Expected list[1] to be *runtime.Unknown, it is %#v", obj) - } - if obj, ok := list[2].(*v1.Pod); !ok { - t.Fatalf("Expected list[2] to be *runtime.Unknown, it is %#v", obj) - } -} - -type fakePtrInterfaceList struct { - Items *[]runtime.Object -} - -func (obj fakePtrInterfaceList) GetObjectKind() unversioned.ObjectKind { - return unversioned.EmptyObjectKind -} - -func TestExtractListOfInterfacePtrs(t *testing.T) { - pl := &fakePtrInterfaceList{ - Items: &[]runtime.Object{}, - } - list, err := meta.ExtractList(pl) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if len(list) > 0 { - t.Fatalf("Expected empty list, got %#v", list) - } -} - -type fakePtrValueList struct { - Items []*api.Pod -} - -func (obj fakePtrValueList) GetObjectKind() unversioned.ObjectKind { - return unversioned.EmptyObjectKind -} - -func TestExtractListOfValuePtrs(t *testing.T) { - pl := &fakePtrValueList{ - Items: []*api.Pod{ - {ObjectMeta: api.ObjectMeta{Name: "1"}}, - {ObjectMeta: api.ObjectMeta{Name: "2"}}, - }, - } - list, err := meta.ExtractList(pl) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if e, a := len(list), len(pl.Items); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - for i := range list { - if obj, ok := list[i].(*api.Pod); !ok { - t.Fatalf("Expected list[%d] to be *api.Pod, it is %#v", i, obj) - } - } -} - -func TestSetList(t *testing.T) { - pl := &api.PodList{} - list := []runtime.Object{ - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}}, - } - err := meta.SetList(pl, list) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if e, a := len(list), len(pl.Items); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - for i := range list { - if e, a := list[i].(*api.Pod).Name, pl.Items[i].Name; e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - } -} - -func TestSetListToRuntimeObjectArray(t *testing.T) { - pl := &api.List{} - list := []runtime.Object{ - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "2"}}, - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "3"}}, - } - err := meta.SetList(pl, list) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - if e, a := len(list), len(pl.Items); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - for i := range list { - if e, a := list[i], pl.Items[i]; e != a { - t.Fatalf("%d: unmatched: %s", i, diff.ObjectDiff(e, a)) - } - } -} - -func TestSetExtractListRoundTrip(t *testing.T) { - fuzzer := fuzz.New().NilChance(0).NumElements(1, 5) - for i := 0; i < 5; i++ { - start := &api.PodList{} - fuzzer.Fuzz(&start.Items) - - list, err := meta.ExtractList(start) - if err != nil { - t.Errorf("Unexpected error %v", err) - continue - } - got := &api.PodList{} - err = meta.SetList(got, list) - if err != nil { - t.Errorf("Unexpected error %v", err) - continue - } - if e, a := start, got; !reflect.DeepEqual(e, a) { - t.Fatalf("Expected %#v, got %#v", e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/meta_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/meta_test.go deleted file mode 100644 index 5b6c35230..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/meta_test.go +++ /dev/null @@ -1,778 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 meta_test - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/types" -) - -func TestAPIObjectMeta(t *testing.T) { - j := &api.Pod{ - TypeMeta: unversioned.TypeMeta{APIVersion: "/a", Kind: "b"}, - ObjectMeta: api.ObjectMeta{ - Namespace: "bar", - Name: "foo", - GenerateName: "prefix", - UID: "uid", - ResourceVersion: "1", - SelfLink: "some/place/only/we/know", - Labels: map[string]string{"foo": "bar"}, - Annotations: map[string]string{"x": "y"}, - }, - } - var _ meta.Object = &j.ObjectMeta - var _ meta.ObjectMetaAccessor = j - accessor, err := meta.Accessor(j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if accessor != meta.Object(&j.ObjectMeta) { - t.Fatalf("should have returned the same pointer: %#v %#v", accessor, j) - } - if e, a := "bar", accessor.GetNamespace(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "foo", accessor.GetName(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "prefix", accessor.GetGenerateName(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "uid", string(accessor.GetUID()); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "1", accessor.GetResourceVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - typeAccessor, err := meta.TypeAccessor(j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := "a", typeAccessor.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "b", typeAccessor.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - accessor.SetNamespace("baz") - accessor.SetName("bar") - accessor.SetGenerateName("generate") - accessor.SetUID("other") - typeAccessor.SetAPIVersion("c") - typeAccessor.SetKind("d") - accessor.SetResourceVersion("2") - accessor.SetSelfLink("google.com") - - // Prove that accessor changes the original object. - if e, a := "baz", j.Namespace; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "bar", j.Name; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "generate", j.GenerateName; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := types.UID("other"), j.UID; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "c", j.APIVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "d", j.Kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "2", j.ResourceVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "google.com", j.SelfLink; e != a { - t.Errorf("expected %v, got %v", e, a) - } - - typeAccessor.SetAPIVersion("d") - typeAccessor.SetKind("e") - if e, a := "d", j.APIVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "e", j.Kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGenericTypeMeta(t *testing.T) { - type TypeMeta struct { - Kind string `json:"kind,omitempty"` - Namespace string `json:"namespace,omitempty"` - Name string `json:"name,omitempty"` - GenerateName string `json:"generateName,omitempty"` - UID string `json:"uid,omitempty"` - CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"` - SelfLink string `json:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty"` - APIVersion string `json:"apiVersion,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` - } - type Object struct { - TypeMeta `json:",inline"` - } - j := Object{ - TypeMeta{ - Namespace: "bar", - Name: "foo", - GenerateName: "prefix", - UID: "uid", - APIVersion: "a", - Kind: "b", - ResourceVersion: "1", - SelfLink: "some/place/only/we/know", - Labels: map[string]string{"foo": "bar"}, - Annotations: map[string]string{"x": "y"}, - }, - } - accessor, err := meta.Accessor(&j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := "bar", accessor.GetNamespace(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "foo", accessor.GetName(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "prefix", accessor.GetGenerateName(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "uid", string(accessor.GetUID()); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "1", accessor.GetResourceVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - typeAccessor, err := meta.TypeAccessor(&j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := "a", typeAccessor.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "b", typeAccessor.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - accessor.SetNamespace("baz") - accessor.SetName("bar") - accessor.SetGenerateName("generate") - accessor.SetUID("other") - typeAccessor.SetAPIVersion("c") - typeAccessor.SetKind("d") - accessor.SetResourceVersion("2") - accessor.SetSelfLink("google.com") - - // Prove that accessor changes the original object. - if e, a := "baz", j.Namespace; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "bar", j.Name; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "generate", j.GenerateName; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "other", j.UID; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "c", j.APIVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "d", j.Kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "2", j.ResourceVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "google.com", j.SelfLink; e != a { - t.Errorf("expected %v, got %v", e, a) - } - - typeAccessor.SetAPIVersion("d") - typeAccessor.SetKind("e") - if e, a := "d", j.APIVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "e", j.Kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -type InternalTypeMeta struct { - Kind string `json:"kind,omitempty"` - Namespace string `json:"namespace,omitempty"` - Name string `json:"name,omitempty"` - GenerateName string `json:"generateName,omitempty"` - UID string `json:"uid,omitempty"` - CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"` - SelfLink string `json:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty"` - APIVersion string `json:"apiVersion,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` -} -type InternalObject struct { - TypeMeta InternalTypeMeta `json:",inline"` -} - -func (obj *InternalObject) GetObjectKind() unversioned.ObjectKind { return obj } -func (obj *InternalObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { - obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() -} -func (obj *InternalObject) GroupVersionKind() *unversioned.GroupVersionKind { - return unversioned.FromAPIVersionAndKind(obj.TypeMeta.APIVersion, obj.TypeMeta.Kind) -} - -func TestGenericTypeMetaAccessor(t *testing.T) { - j := &InternalObject{ - InternalTypeMeta{ - Namespace: "bar", - Name: "foo", - GenerateName: "prefix", - UID: "uid", - APIVersion: "/a", - Kind: "b", - ResourceVersion: "1", - SelfLink: "some/place/only/we/know", - Labels: map[string]string{"foo": "bar"}, - Annotations: map[string]string{"x": "y"}, - }, - } - accessor := meta.NewAccessor() - namespace, err := accessor.Namespace(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "bar", namespace; e != a { - t.Errorf("expected %v, got %v", e, a) - } - name, err := accessor.Name(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "foo", name; e != a { - t.Errorf("expected %v, got %v", e, a) - } - generateName, err := accessor.GenerateName(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "prefix", generateName; e != a { - t.Errorf("expected %v, got %v", e, a) - } - uid, err := accessor.UID(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "uid", string(uid); e != a { - t.Errorf("expected %v, got %v", e, a) - } - apiVersion, err := accessor.APIVersion(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "a", apiVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - kind, err := accessor.Kind(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "b", kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } - rv, err := accessor.ResourceVersion(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "1", rv; e != a { - t.Errorf("expected %v, got %v", e, a) - } - selfLink, err := accessor.SelfLink(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := "some/place/only/we/know", selfLink; e != a { - t.Errorf("expected %v, got %v", e, a) - } - labels, err := accessor.Labels(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := 1, len(labels); e != a { - t.Errorf("expected %v, got %v", e, a) - } - annotations, err := accessor.Annotations(j) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := 1, len(annotations); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - if err := accessor.SetNamespace(j, "baz"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetName(j, "bar"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetGenerateName(j, "generate"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetUID(j, "other"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetAPIVersion(j, "c"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetKind(j, "d"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetResourceVersion(j, "2"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetSelfLink(j, "google.com"); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := accessor.SetLabels(j, map[string]string{}); err != nil { - t.Errorf("unexpected error: %v", err) - } - var nilMap map[string]string - if err := accessor.SetAnnotations(j, nilMap); err != nil { - t.Errorf("unexpected error: %v", err) - } - - // Prove that accessor changes the original object. - if e, a := "baz", j.TypeMeta.Namespace; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "bar", j.TypeMeta.Name; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "generate", j.TypeMeta.GenerateName; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "other", j.TypeMeta.UID; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "c", j.TypeMeta.APIVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "d", j.TypeMeta.Kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "2", j.TypeMeta.ResourceVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "google.com", j.TypeMeta.SelfLink; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := map[string]string{}, j.TypeMeta.Labels; !reflect.DeepEqual(e, a) { - t.Errorf("expected %#v, got %#v", e, a) - } - if e, a := nilMap, j.TypeMeta.Annotations; !reflect.DeepEqual(e, a) { - t.Errorf("expected %#v, got %#v", e, a) - } -} - -func TestGenericObjectMeta(t *testing.T) { - type TypeMeta struct { - Kind string `json:"kind,omitempty"` - APIVersion string `json:"apiVersion,omitempty"` - } - type ObjectMeta struct { - Namespace string `json:"namespace,omitempty"` - Name string `json:"name,omitempty"` - GenerateName string `json:"generateName,omitempty"` - UID string `json:"uid,omitempty"` - CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"` - SelfLink string `json:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` - } - type Object struct { - TypeMeta `json:",inline"` - ObjectMeta `json:"metadata"` - } - j := Object{ - TypeMeta{ - APIVersion: "a", - Kind: "b", - }, - ObjectMeta{ - Namespace: "bar", - Name: "foo", - GenerateName: "prefix", - UID: "uid", - ResourceVersion: "1", - SelfLink: "some/place/only/we/know", - Labels: map[string]string{"foo": "bar"}, - Annotations: map[string]string{"a": "b"}, - }, - } - accessor, err := meta.Accessor(&j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := "bar", accessor.GetNamespace(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "foo", accessor.GetName(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "prefix", accessor.GetGenerateName(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "uid", string(accessor.GetUID()); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "1", accessor.GetResourceVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := 1, len(accessor.GetLabels()); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := 1, len(accessor.GetAnnotations()); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - typeAccessor, err := meta.TypeAccessor(&j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := "a", typeAccessor.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "b", typeAccessor.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - accessor.SetNamespace("baz") - accessor.SetName("bar") - accessor.SetGenerateName("generate") - accessor.SetUID("other") - typeAccessor.SetAPIVersion("c") - typeAccessor.SetKind("d") - accessor.SetResourceVersion("2") - accessor.SetSelfLink("google.com") - accessor.SetLabels(map[string]string{"other": "label"}) - accessor.SetAnnotations(map[string]string{"c": "d"}) - - // Prove that accessor changes the original object. - if e, a := "baz", j.Namespace; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "bar", j.Name; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "generate", j.GenerateName; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "other", j.UID; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "c", j.APIVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "d", j.Kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "2", j.ResourceVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "google.com", j.SelfLink; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := map[string]string{"other": "label"}, j.Labels; !reflect.DeepEqual(e, a) { - t.Errorf("expected %#v, got %#v", e, a) - } - if e, a := map[string]string{"c": "d"}, j.Annotations; !reflect.DeepEqual(e, a) { - t.Errorf("expected %#v, got %#v", e, a) - } -} - -func TestGenericListMeta(t *testing.T) { - type TypeMeta struct { - Kind string `json:"kind,omitempty"` - APIVersion string `json:"apiVersion,omitempty"` - } - type ListMeta struct { - SelfLink string `json:"selfLink,omitempty"` - ResourceVersion string `json:"resourceVersion,omitempty"` - } - type Object struct { - TypeMeta `json:",inline"` - ListMeta `json:"metadata"` - } - j := Object{ - TypeMeta{ - APIVersion: "a", - Kind: "b", - }, - ListMeta{ - ResourceVersion: "1", - SelfLink: "some/place/only/we/know", - }, - } - accessor, err := meta.Accessor(&j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := "", accessor.GetName(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "", string(accessor.GetUID()); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "1", accessor.GetResourceVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - typeAccessor, err := meta.TypeAccessor(&j) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := "a", typeAccessor.GetAPIVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "b", typeAccessor.GetKind(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - - accessor.SetName("bar") - accessor.SetUID("other") - typeAccessor.SetAPIVersion("c") - typeAccessor.SetKind("d") - accessor.SetResourceVersion("2") - accessor.SetSelfLink("google.com") - - // Prove that accessor changes the original object. - if e, a := "c", j.APIVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "d", j.Kind; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "2", j.ResourceVersion; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "google.com", j.SelfLink; e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -type MyAPIObject struct { - TypeMeta InternalTypeMeta `json:",inline"` -} - -func (obj *MyAPIObject) GetObjectKind() unversioned.ObjectKind { return obj } -func (obj *MyAPIObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { - obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind() -} -func (obj *MyAPIObject) GroupVersionKind() *unversioned.GroupVersionKind { - return unversioned.FromAPIVersionAndKind(obj.TypeMeta.APIVersion, obj.TypeMeta.Kind) -} - -type MyIncorrectlyMarkedAsAPIObject struct{} - -func (obj *MyIncorrectlyMarkedAsAPIObject) GetObjectKind() unversioned.ObjectKind { - return unversioned.EmptyObjectKind -} - -func TestResourceVersionerOfAPI(t *testing.T) { - type T struct { - runtime.Object - Expected string - } - testCases := map[string]T{ - "empty api object": {&MyAPIObject{}, ""}, - "api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"}, - "pointer to api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"}, - } - versioning := meta.NewAccessor() - for key, testCase := range testCases { - actual, err := versioning.ResourceVersion(testCase.Object) - if err != nil { - t.Errorf("%s: unexpected error %#v", key, err) - } - if actual != testCase.Expected { - t.Errorf("%s: expected %v, got %v", key, testCase.Expected, actual) - } - } - - failingCases := map[string]struct { - runtime.Object - Expected string - }{ - "not a valid object to try": {&MyIncorrectlyMarkedAsAPIObject{}, "1"}, - } - for key, testCase := range failingCases { - _, err := versioning.ResourceVersion(testCase.Object) - if err == nil { - t.Errorf("%s: expected error, got nil", key) - } - } - - setCases := map[string]struct { - runtime.Object - Expected string - }{ - "pointer to api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"}, - } - for key, testCase := range setCases { - if err := versioning.SetResourceVersion(testCase.Object, "5"); err != nil { - t.Errorf("%s: unexpected error %#v", key, err) - } - actual, err := versioning.ResourceVersion(testCase.Object) - if err != nil { - t.Errorf("%s: unexpected error %#v", key, err) - } - if actual != "5" { - t.Errorf("%s: expected %v, got %v", key, "5", actual) - } - } -} - -func TestTypeMetaSelfLinker(t *testing.T) { - table := map[string]struct { - obj runtime.Object - expect string - try string - succeed bool - }{ - "normal": { - obj: &MyAPIObject{TypeMeta: InternalTypeMeta{SelfLink: "foobar"}}, - expect: "foobar", - try: "newbar", - succeed: true, - }, - "fail": { - obj: &MyIncorrectlyMarkedAsAPIObject{}, - succeed: false, - }, - } - - linker := runtime.SelfLinker(meta.NewAccessor()) - for name, item := range table { - got, err := linker.SelfLink(item.obj) - if e, a := item.succeed, err == nil; e != a { - t.Errorf("%v: expected %v, got %v", name, e, a) - } - if e, a := item.expect, got; item.succeed && e != a { - t.Errorf("%v: expected %v, got %v", name, e, a) - } - - err = linker.SetSelfLink(item.obj, item.try) - if e, a := item.succeed, err == nil; e != a { - t.Errorf("%v: expected %v, got %v", name, e, a) - } - if item.succeed { - got, err := linker.SelfLink(item.obj) - if err != nil { - t.Errorf("%v: expected no err, got %v", name, err) - } - if e, a := item.try, got; e != a { - t.Errorf("%v: expected %v, got %v", name, e, a) - } - } - } -} - -// BenchmarkAccessorSetFastPath shows the interface fast path -func BenchmarkAccessorSetFastPath(b *testing.B) { - obj := &api.Pod{ - TypeMeta: unversioned.TypeMeta{APIVersion: "/a", Kind: "b"}, - ObjectMeta: api.ObjectMeta{ - Namespace: "bar", - Name: "foo", - GenerateName: "prefix", - UID: "uid", - ResourceVersion: "1", - SelfLink: "some/place/only/we/know", - Labels: map[string]string{"foo": "bar"}, - Annotations: map[string]string{"x": "y"}, - }, - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - acc, err := meta.Accessor(obj) - if err != nil { - b.Fatal(err) - } - acc.SetNamespace("something") - } - b.StopTimer() -} - -// BenchmarkAccessorSetReflection provides a baseline for accessor performance -func BenchmarkAccessorSetReflection(b *testing.B) { - obj := &InternalObject{ - InternalTypeMeta{ - Namespace: "bar", - Name: "foo", - GenerateName: "prefix", - UID: "uid", - APIVersion: "a", - Kind: "b", - ResourceVersion: "1", - SelfLink: "some/place/only/we/know", - Labels: map[string]string{"foo": "bar"}, - Annotations: map[string]string{"x": "y"}, - }, - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - acc, err := meta.Accessor(obj) - if err != nil { - b.Fatal(err) - } - acc.SetNamespace("something") - } - b.StopTimer() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/multirestmapper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/multirestmapper_test.go deleted file mode 100644 index 1b3685e85..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/multirestmapper_test.go +++ /dev/null @@ -1,298 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 meta - -import ( - "errors" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" -) - -func TestMultiRESTMapperResourceFor(t *testing.T) { - tcs := []struct { - name string - - mapper MultiRESTMapper - input unversioned.GroupVersionResource - result unversioned.GroupVersionResource - err error - }{ - { - name: "empty", - mapper: MultiRESTMapper{}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: unversioned.GroupVersionResource{}, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "ignore not found", - mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: unversioned.GroupVersionResource{}, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "accept first failure", - mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "unused"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: unversioned.GroupVersionResource{}, - err: errors.New("fail on this"), - }, - } - - for _, tc := range tcs { - actualResult, actualErr := tc.mapper.ResourceFor(tc.input) - if e, a := tc.result, actualResult; e != a { - t.Errorf("%s: expected %v, got %v", tc.name, e, a) - } - switch { - case tc.err == nil && actualErr == nil: - case tc.err == nil: - t.Errorf("%s: unexpected error: %v", tc.name, actualErr) - case actualErr == nil: - t.Errorf("%s: expected error: %v got nil", tc.name, tc.err) - case tc.err.Error() != actualErr.Error(): - t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr) - } - } -} - -func TestMultiRESTMapperResourcesFor(t *testing.T) { - tcs := []struct { - name string - - mapper MultiRESTMapper - input unversioned.GroupVersionResource - result []unversioned.GroupVersionResource - err error - }{ - { - name: "empty", - mapper: MultiRESTMapper{}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: nil, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "ignore not found", - mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: nil, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "accept first failure", - mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "unused"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: nil, - err: errors.New("fail on this"), - }, - { - name: "union and dedup", - mapper: MultiRESTMapper{ - fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "dupe"}, {Resource: "first"}}}, - fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "dupe"}, {Resource: "second"}}}, - }, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: []unversioned.GroupVersionResource{{Resource: "dupe"}, {Resource: "first"}, {Resource: "second"}}, - }, - { - name: "skip not and continue", - mapper: MultiRESTMapper{ - fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}, - fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "first"}, {Resource: "second"}}}, - }, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: []unversioned.GroupVersionResource{{Resource: "first"}, {Resource: "second"}}, - }, - } - - for _, tc := range tcs { - actualResult, actualErr := tc.mapper.ResourcesFor(tc.input) - if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) { - t.Errorf("%s: expected %v, got %v", tc.name, e, a) - } - switch { - case tc.err == nil && actualErr == nil: - case tc.err == nil: - t.Errorf("%s: unexpected error: %v", tc.name, actualErr) - case actualErr == nil: - t.Errorf("%s: expected error: %v got nil", tc.name, tc.err) - case tc.err.Error() != actualErr.Error(): - t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr) - } - } -} - -func TestMultiRESTMapperKindsFor(t *testing.T) { - tcs := []struct { - name string - - mapper MultiRESTMapper - input unversioned.GroupVersionResource - result []unversioned.GroupVersionKind - err error - }{ - { - name: "empty", - mapper: MultiRESTMapper{}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: nil, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "ignore not found", - mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: nil, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "accept first failure", - mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "unused"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: nil, - err: errors.New("fail on this"), - }, - { - name: "union and dedup", - mapper: MultiRESTMapper{ - fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "dupe"}, {Kind: "first"}}}, - fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "dupe"}, {Kind: "second"}}}, - }, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: []unversioned.GroupVersionKind{{Kind: "dupe"}, {Kind: "first"}, {Kind: "second"}}, - }, - { - name: "skip not and continue", - mapper: MultiRESTMapper{ - fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}, - fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "first"}, {Kind: "second"}}}, - }, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: []unversioned.GroupVersionKind{{Kind: "first"}, {Kind: "second"}}, - }, - } - - for _, tc := range tcs { - actualResult, actualErr := tc.mapper.KindsFor(tc.input) - if e, a := tc.result, actualResult; !reflect.DeepEqual(e, a) { - t.Errorf("%s: expected %v, got %v", tc.name, e, a) - } - switch { - case tc.err == nil && actualErr == nil: - case tc.err == nil: - t.Errorf("%s: unexpected error: %v", tc.name, actualErr) - case actualErr == nil: - t.Errorf("%s: expected error: %v got nil", tc.name, tc.err) - case tc.err.Error() != actualErr.Error(): - t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr) - } - } -} - -func TestMultiRESTMapperKindFor(t *testing.T) { - tcs := []struct { - name string - - mapper MultiRESTMapper - input unversioned.GroupVersionResource - result unversioned.GroupVersionKind - err error - }{ - { - name: "empty", - mapper: MultiRESTMapper{}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: unversioned.GroupVersionKind{}, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "ignore not found", - mapper: MultiRESTMapper{fixedRESTMapper{err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "IGNORE_THIS"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: unversioned.GroupVersionKind{}, - err: &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - }, - { - name: "accept first failure", - mapper: MultiRESTMapper{fixedRESTMapper{err: errors.New("fail on this")}, fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "unused"}}}}, - input: unversioned.GroupVersionResource{Resource: "foo"}, - result: unversioned.GroupVersionKind{}, - err: errors.New("fail on this"), - }, - } - - for _, tc := range tcs { - actualResult, actualErr := tc.mapper.KindFor(tc.input) - if e, a := tc.result, actualResult; e != a { - t.Errorf("%s: expected %v, got %v", tc.name, e, a) - } - switch { - case tc.err == nil && actualErr == nil: - case tc.err == nil: - t.Errorf("%s: unexpected error: %v", tc.name, actualErr) - case actualErr == nil: - t.Errorf("%s: expected error: %v got nil", tc.name, tc.err) - case tc.err.Error() != actualErr.Error(): - t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr) - } - } -} - -type fixedRESTMapper struct { - resourcesFor []unversioned.GroupVersionResource - kindsFor []unversioned.GroupVersionKind - resourceFor unversioned.GroupVersionResource - kindFor unversioned.GroupVersionKind - - err error -} - -func (m fixedRESTMapper) ResourceSingularizer(resource string) (singular string, err error) { - return "", m.err -} - -func (m fixedRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) { - return m.resourcesFor, m.err -} - -func (m fixedRESTMapper) KindsFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) { - return m.kindsFor, m.err -} - -func (m fixedRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) { - return m.resourceFor, m.err -} - -func (m fixedRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) { - return m.kindFor, m.err -} - -func (m fixedRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (mapping *RESTMapping, err error) { - return nil, m.err -} - -func (m fixedRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) { - return nil, false -} - -func (m fixedRESTMapper) ResourceIsValid(resource unversioned.GroupVersionResource) bool { - return false -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/priority_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/priority_test.go deleted file mode 100644 index ea2d24b37..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/priority_test.go +++ /dev/null @@ -1,206 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 meta - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" -) - -func TestPriorityRESTMapperResourceForErrorHandling(t *testing.T) { - tcs := []struct { - name string - - delegate RESTMapper - resourcePatterns []unversioned.GroupVersionResource - result unversioned.GroupVersionResource - err string - }{ - { - name: "single hit", - delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{{Resource: "single-hit"}}}, - result: unversioned.GroupVersionResource{Resource: "single-hit"}, - }, - { - name: "ambiguous match", - delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{ - {Group: "one", Version: "a", Resource: "first"}, - {Group: "two", Version: "b", Resource: "second"}, - }}, - err: "matches multiple resources", - }, - { - name: "group selection", - delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{ - {Group: "one", Version: "a", Resource: "first"}, - {Group: "two", Version: "b", Resource: "second"}, - }}, - resourcePatterns: []unversioned.GroupVersionResource{ - {Group: "one", Version: AnyVersion, Resource: AnyResource}, - }, - result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "first"}, - }, - { - name: "empty match continues", - delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{ - {Group: "one", Version: "a", Resource: "first"}, - {Group: "two", Version: "b", Resource: "second"}, - }}, - resourcePatterns: []unversioned.GroupVersionResource{ - {Group: "fail", Version: AnyVersion, Resource: AnyResource}, - {Group: "one", Version: AnyVersion, Resource: AnyResource}, - }, - result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "first"}, - }, - { - name: "group followed by version selection", - delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{ - {Group: "one", Version: "a", Resource: "first"}, - {Group: "two", Version: "b", Resource: "second"}, - {Group: "one", Version: "c", Resource: "third"}, - }}, - resourcePatterns: []unversioned.GroupVersionResource{ - {Group: "one", Version: AnyVersion, Resource: AnyResource}, - {Group: AnyGroup, Version: "a", Resource: AnyResource}, - }, - result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "first"}, - }, - { - name: "resource selection", - delegate: fixedRESTMapper{resourcesFor: []unversioned.GroupVersionResource{ - {Group: "one", Version: "a", Resource: "first"}, - {Group: "one", Version: "a", Resource: "second"}, - }}, - resourcePatterns: []unversioned.GroupVersionResource{ - {Group: AnyGroup, Version: AnyVersion, Resource: "second"}, - }, - result: unversioned.GroupVersionResource{Group: "one", Version: "a", Resource: "second"}, - }, - } - - for _, tc := range tcs { - mapper := PriorityRESTMapper{Delegate: tc.delegate, ResourcePriority: tc.resourcePatterns} - - actualResult, actualErr := mapper.ResourceFor(unversioned.GroupVersionResource{}) - if e, a := tc.result, actualResult; e != a { - t.Errorf("%s: expected %v, got %v", tc.name, e, a) - } - if len(tc.err) == 0 && actualErr == nil { - continue - } - if len(tc.err) > 0 && actualErr == nil { - t.Errorf("%s: missing expected err: %v", tc.name, tc.err) - continue - } - if !strings.Contains(actualErr.Error(), tc.err) { - t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr) - } - } -} - -func TestPriorityRESTMapperKindForErrorHandling(t *testing.T) { - tcs := []struct { - name string - - delegate RESTMapper - kindPatterns []unversioned.GroupVersionKind - result unversioned.GroupVersionKind - err string - }{ - { - name: "single hit", - delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{{Kind: "single-hit"}}}, - result: unversioned.GroupVersionKind{Kind: "single-hit"}, - }, - { - name: "ambiguous match", - delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{ - {Group: "one", Version: "a", Kind: "first"}, - {Group: "two", Version: "b", Kind: "second"}, - }}, - err: "matches multiple kinds", - }, - { - name: "group selection", - delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{ - {Group: "one", Version: "a", Kind: "first"}, - {Group: "two", Version: "b", Kind: "second"}, - }}, - kindPatterns: []unversioned.GroupVersionKind{ - {Group: "one", Version: AnyVersion, Kind: AnyKind}, - }, - result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "first"}, - }, - { - name: "empty match continues", - delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{ - {Group: "one", Version: "a", Kind: "first"}, - {Group: "two", Version: "b", Kind: "second"}, - }}, - kindPatterns: []unversioned.GroupVersionKind{ - {Group: "fail", Version: AnyVersion, Kind: AnyKind}, - {Group: "one", Version: AnyVersion, Kind: AnyKind}, - }, - result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "first"}, - }, - { - name: "group followed by version selection", - delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{ - {Group: "one", Version: "a", Kind: "first"}, - {Group: "two", Version: "b", Kind: "second"}, - {Group: "one", Version: "c", Kind: "third"}, - }}, - kindPatterns: []unversioned.GroupVersionKind{ - {Group: "one", Version: AnyVersion, Kind: AnyKind}, - {Group: AnyGroup, Version: "a", Kind: AnyKind}, - }, - result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "first"}, - }, - { - name: "kind selection", - delegate: fixedRESTMapper{kindsFor: []unversioned.GroupVersionKind{ - {Group: "one", Version: "a", Kind: "first"}, - {Group: "one", Version: "a", Kind: "second"}, - }}, - kindPatterns: []unversioned.GroupVersionKind{ - {Group: AnyGroup, Version: AnyVersion, Kind: "second"}, - }, - result: unversioned.GroupVersionKind{Group: "one", Version: "a", Kind: "second"}, - }, - } - - for _, tc := range tcs { - mapper := PriorityRESTMapper{Delegate: tc.delegate, KindPriority: tc.kindPatterns} - - actualResult, actualErr := mapper.KindFor(unversioned.GroupVersionResource{}) - if e, a := tc.result, actualResult; e != a { - t.Errorf("%s: expected %v, got %v", tc.name, e, a) - } - if len(tc.err) == 0 && actualErr == nil { - continue - } - if len(tc.err) > 0 && actualErr == nil { - t.Errorf("%s: missing expected err: %v", tc.name, tc.err) - continue - } - if !strings.Contains(actualErr.Error(), tc.err) { - t.Errorf("%s: expected %v, got %v", tc.name, tc.err, actualErr) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/restmapper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/restmapper_test.go deleted file mode 100644 index 8f494d0a6..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta/restmapper_test.go +++ /dev/null @@ -1,550 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 meta - -import ( - "errors" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" -) - -type fakeConvertor struct{} - -func (fakeConvertor) Convert(in, out interface{}) error { - return nil -} - -func (fakeConvertor) ConvertToVersion(in runtime.Object, _ string) (runtime.Object, error) { - return in, nil -} - -func (fakeConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - return label, value, nil -} - -var validAccessor = resourceAccessor{} -var validConvertor = fakeConvertor{} - -func fakeInterfaces(version unversioned.GroupVersion) (*VersionInterfaces, error) { - return &VersionInterfaces{ObjectConvertor: validConvertor, MetadataAccessor: validAccessor}, nil -} - -var unmatchedErr = errors.New("no version") - -func unmatchedVersionInterfaces(version unversioned.GroupVersion) (*VersionInterfaces, error) { - return nil, unmatchedErr -} - -func TestRESTMapperVersionAndKindForResource(t *testing.T) { - testGroup := "test.group" - testVersion := "test" - testGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: testVersion} - - testCases := []struct { - Resource unversioned.GroupVersionResource - GroupVersionToRegister unversioned.GroupVersion - ExpectedGVK unversioned.GroupVersionKind - Err bool - }{ - {Resource: unversioned.GroupVersionResource{Resource: "internalobjec"}, Err: true}, - {Resource: unversioned.GroupVersionResource{Resource: "internalObjec"}, Err: true}, - - {Resource: unversioned.GroupVersionResource{Resource: "internalobject"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - {Resource: unversioned.GroupVersionResource{Resource: "internalobjects"}, ExpectedGVK: testGroupVersion.WithKind("InternalObject")}, - } - for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces) - if len(testCase.ExpectedGVK.Kind) != 0 { - mapper.Add(testCase.ExpectedGVK, RESTScopeNamespace) - } - actualGVK, err := mapper.KindFor(testCase.Resource) - - hasErr := err != nil - if hasErr != testCase.Err { - t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err) - continue - } - if err != nil { - continue - } - - if actualGVK != testCase.ExpectedGVK { - t.Errorf("%d: unexpected version and kind: e=%s a=%s", i, testCase.ExpectedGVK, actualGVK) - } - } -} - -func TestRESTMapperGroupForResource(t *testing.T) { - testCases := []struct { - Resource unversioned.GroupVersionResource - GroupVersionKind unversioned.GroupVersionKind - Err bool - }{ - {Resource: unversioned.GroupVersionResource{Resource: "myObject"}, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, - {Resource: unversioned.GroupVersionResource{Resource: "myobject"}, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi2", Version: "test", Kind: "MyObject"}}, - {Resource: unversioned.GroupVersionResource{Resource: "myObje"}, Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, - {Resource: unversioned.GroupVersionResource{Resource: "myobje"}, Err: true, GroupVersionKind: unversioned.GroupVersionKind{Group: "testapi", Version: "test", Kind: "MyObject"}}, - } - for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testCase.GroupVersionKind.GroupVersion()}, fakeInterfaces) - mapper.Add(testCase.GroupVersionKind, RESTScopeNamespace) - - actualGVK, err := mapper.KindFor(testCase.Resource) - if testCase.Err { - if err == nil { - t.Errorf("%d: expected error", i) - } - } else if err != nil { - t.Errorf("%d: unexpected error: %v", i, err) - } else if actualGVK != testCase.GroupVersionKind { - t.Errorf("%d: expected group %q, got %q", i, testCase.GroupVersionKind, actualGVK) - } - } -} - -func TestRESTMapperKindsFor(t *testing.T) { - testCases := []struct { - Name string - PreferredOrder []unversioned.GroupVersion - KindsToRegister []unversioned.GroupVersionKind - PartialResourceToRequest unversioned.GroupVersionResource - - ExpectedKinds []unversioned.GroupVersionKind - ExpectedKindErr string - }{ - { - Name: "ambiguous groups, with preference order", - PreferredOrder: []unversioned.GroupVersion{ - {Group: "second-group", Version: "first-version"}, - {Group: "first-group", Version: "first-version"}, - }, - KindsToRegister: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - {Group: "first-group", Version: "first-version", Kind: "your-kind"}, - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - {Group: "second-group", Version: "first-version", Kind: "your-kind"}, - }, - PartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kinds"}, - - ExpectedKinds: []unversioned.GroupVersionKind{ - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - }, - ExpectedKindErr: " matches multiple kinds ", - }, - - { - Name: "ambiguous groups, with explicit group match", - PreferredOrder: []unversioned.GroupVersion{ - {Group: "second-group", Version: "first-version"}, - {Group: "first-group", Version: "first-version"}, - }, - KindsToRegister: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - {Group: "first-group", Version: "first-version", Kind: "your-kind"}, - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - {Group: "second-group", Version: "first-version", Kind: "your-kind"}, - }, - PartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kinds"}, - - ExpectedKinds: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - }, - }, - - { - Name: "ambiguous groups, with ambiguous version match", - PreferredOrder: []unversioned.GroupVersion{ - {Group: "first-group", Version: "first-version"}, - {Group: "second-group", Version: "first-version"}, - }, - KindsToRegister: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - {Group: "first-group", Version: "first-version", Kind: "your-kind"}, - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - {Group: "second-group", Version: "first-version", Kind: "your-kind"}, - }, - PartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kinds"}, - - ExpectedKinds: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - }, - ExpectedKindErr: " matches multiple kinds ", - }, - } - for _, testCase := range testCases { - tcName := testCase.Name - mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) - for _, kind := range testCase.KindsToRegister { - mapper.Add(kind, RESTScopeNamespace) - } - - actualKinds, err := mapper.KindsFor(testCase.PartialResourceToRequest) - if err != nil { - t.Errorf("%s: unexpected error: %v", tcName, err) - continue - } - if !reflect.DeepEqual(testCase.ExpectedKinds, actualKinds) { - t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds, actualKinds) - } - - singleKind, err := mapper.KindFor(testCase.PartialResourceToRequest) - if err == nil && len(testCase.ExpectedKindErr) != 0 { - t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedKindErr) - continue - } - if err != nil { - if len(testCase.ExpectedKindErr) == 0 { - t.Errorf("%s: unexpected error: %v", tcName, err) - continue - } else { - if !strings.Contains(err.Error(), testCase.ExpectedKindErr) { - t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKindErr, err) - continue - } - } - - } else { - if testCase.ExpectedKinds[0] != singleKind { - t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedKinds[0], singleKind) - } - - } - } -} - -func TestRESTMapperResourcesFor(t *testing.T) { - testCases := []struct { - Name string - PreferredOrder []unversioned.GroupVersion - KindsToRegister []unversioned.GroupVersionKind - PluralPartialResourceToRequest unversioned.GroupVersionResource - SingularPartialResourceToRequest unversioned.GroupVersionResource - - ExpectedResources []unversioned.GroupVersionResource - ExpectedResourceErr string - }{ - { - Name: "ambiguous groups, with preference order", - PreferredOrder: []unversioned.GroupVersion{ - {Group: "second-group", Version: "first-version"}, - {Group: "first-group", Version: "first-version"}, - }, - KindsToRegister: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - {Group: "first-group", Version: "first-version", Kind: "your-kind"}, - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - {Group: "second-group", Version: "first-version", Kind: "your-kind"}, - }, - PluralPartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kinds"}, - SingularPartialResourceToRequest: unversioned.GroupVersionResource{Resource: "my-kind"}, - - ExpectedResources: []unversioned.GroupVersionResource{ - {Group: "second-group", Version: "first-version", Resource: "my-kinds"}, - {Group: "first-group", Version: "first-version", Resource: "my-kinds"}, - }, - ExpectedResourceErr: " matches multiple resources ", - }, - - { - Name: "ambiguous groups, with explicit group match", - PreferredOrder: []unversioned.GroupVersion{ - {Group: "second-group", Version: "first-version"}, - {Group: "first-group", Version: "first-version"}, - }, - KindsToRegister: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - {Group: "first-group", Version: "first-version", Kind: "your-kind"}, - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - {Group: "second-group", Version: "first-version", Kind: "your-kind"}, - }, - PluralPartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kinds"}, - SingularPartialResourceToRequest: unversioned.GroupVersionResource{Group: "first-group", Resource: "my-kind"}, - - ExpectedResources: []unversioned.GroupVersionResource{ - {Group: "first-group", Version: "first-version", Resource: "my-kinds"}, - }, - }, - - { - Name: "ambiguous groups, with ambiguous version match", - PreferredOrder: []unversioned.GroupVersion{ - {Group: "first-group", Version: "first-version"}, - {Group: "second-group", Version: "first-version"}, - }, - KindsToRegister: []unversioned.GroupVersionKind{ - {Group: "first-group", Version: "first-version", Kind: "my-kind"}, - {Group: "first-group", Version: "first-version", Kind: "your-kind"}, - {Group: "second-group", Version: "first-version", Kind: "my-kind"}, - {Group: "second-group", Version: "first-version", Kind: "your-kind"}, - }, - PluralPartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kinds"}, - SingularPartialResourceToRequest: unversioned.GroupVersionResource{Version: "first-version", Resource: "my-kind"}, - - ExpectedResources: []unversioned.GroupVersionResource{ - {Group: "first-group", Version: "first-version", Resource: "my-kinds"}, - {Group: "second-group", Version: "first-version", Resource: "my-kinds"}, - }, - ExpectedResourceErr: " matches multiple resources ", - }, - } - for _, testCase := range testCases { - tcName := testCase.Name - - for _, partialResource := range []unversioned.GroupVersionResource{testCase.PluralPartialResourceToRequest, testCase.SingularPartialResourceToRequest} { - mapper := NewDefaultRESTMapper(testCase.PreferredOrder, fakeInterfaces) - for _, kind := range testCase.KindsToRegister { - mapper.Add(kind, RESTScopeNamespace) - } - - actualResources, err := mapper.ResourcesFor(partialResource) - if err != nil { - t.Errorf("%s: unexpected error: %v", tcName, err) - continue - } - if !reflect.DeepEqual(testCase.ExpectedResources, actualResources) { - t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources, actualResources) - } - - singleResource, err := mapper.ResourceFor(partialResource) - if err == nil && len(testCase.ExpectedResourceErr) != 0 { - t.Errorf("%s: expected error: %v", tcName, testCase.ExpectedResourceErr) - continue - } - if err != nil { - if len(testCase.ExpectedResourceErr) == 0 { - t.Errorf("%s: unexpected error: %v", tcName, err) - continue - } else { - if !strings.Contains(err.Error(), testCase.ExpectedResourceErr) { - t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResourceErr, err) - continue - } - } - - } else { - if testCase.ExpectedResources[0] != singleResource { - t.Errorf("%s: expected %v, got %v", tcName, testCase.ExpectedResources[0], singleResource) - } - - } - } - } -} - -func TestKindToResource(t *testing.T) { - testCases := []struct { - Kind string - Plural, Singular string - }{ - {Kind: "Pod", Plural: "pods", Singular: "pod"}, - - {Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"}, - - // Add "ies" when ending with "y" - {Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"}, - // Add "es" when ending with "s" - {Kind: "miss", Plural: "misses", Singular: "miss"}, - // Add "s" otherwise - {Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"}, - } - for i, testCase := range testCases { - version := unversioned.GroupVersion{} - - plural, singular := KindToResource(version.WithKind(testCase.Kind)) - if singular != version.WithResource(testCase.Singular) || plural != version.WithResource(testCase.Plural) { - t.Errorf("%d: unexpected plural and singular: %v %v", i, plural, singular) - } - } -} - -func TestRESTMapperResourceSingularizer(t *testing.T) { - testGroupVersion := unversioned.GroupVersion{Group: "tgroup", Version: "test"} - - testCases := []struct { - Kind string - Plural string - Singular string - }{ - {Kind: "Pod", Plural: "pods", Singular: "pod"}, - {Kind: "ReplicationController", Plural: "replicationcontrollers", Singular: "replicationcontroller"}, - {Kind: "ImageRepository", Plural: "imagerepositories", Singular: "imagerepository"}, - {Kind: "Status", Plural: "statuses", Singular: "status"}, - - {Kind: "lowercase", Plural: "lowercases", Singular: "lowercase"}, - // TODO this test is broken. This updates to reflect actual behavior. Kinds are expected to be singular - // old (incorrect), coment: Don't add extra s if the original object is already plural - {Kind: "lowercases", Plural: "lowercaseses", Singular: "lowercases"}, - } - for i, testCase := range testCases { - mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{testGroupVersion}, fakeInterfaces) - // create singular/plural mapping - mapper.Add(testGroupVersion.WithKind(testCase.Kind), RESTScopeNamespace) - - singular, err := mapper.ResourceSingularizer(testCase.Plural) - if err != nil { - t.Errorf("%d: unexpected error: %v", i, err) - } - if singular != testCase.Singular { - t.Errorf("%d: mismatched singular: got %v, expected %v", i, singular, testCase.Singular) - } - } -} - -func TestRESTMapperRESTMapping(t *testing.T) { - testGroup := "tgroup" - testGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: "test"} - internalGroupVersion := unversioned.GroupVersion{Group: testGroup, Version: "test"} - - testCases := []struct { - Kind string - APIGroupVersions []unversioned.GroupVersion - DefaultVersions []unversioned.GroupVersion - - Resource string - ExpectedGroupVersion *unversioned.GroupVersion - Err bool - }{ - {Kind: "Unknown", Err: true}, - {Kind: "InternalObject", Err: true}, - - {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "Unknown", Err: true}, - - {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - - {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - - {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{}, Resource: "internalobjects", ExpectedGroupVersion: &unversioned.GroupVersion{Group: testGroup, Version: "test"}}, - - {DefaultVersions: []unversioned.GroupVersion{testGroupVersion}, Kind: "InternalObject", APIGroupVersions: []unversioned.GroupVersion{{Group: testGroup, Version: "test"}}, Resource: "internalobjects"}, - - // TODO: add test for a resource that exists in one version but not another - } - for i, testCase := range testCases { - mapper := NewDefaultRESTMapper(testCase.DefaultVersions, fakeInterfaces) - mapper.Add(internalGroupVersion.WithKind("InternalObject"), RESTScopeNamespace) - - preferredVersions := []string{} - for _, gv := range testCase.APIGroupVersions { - preferredVersions = append(preferredVersions, gv.Version) - } - gk := unversioned.GroupKind{Group: testGroup, Kind: testCase.Kind} - - mapping, err := mapper.RESTMapping(gk, preferredVersions...) - hasErr := err != nil - if hasErr != testCase.Err { - t.Errorf("%d: unexpected error behavior %t: %v", i, testCase.Err, err) - } - if hasErr { - continue - } - if mapping.Resource != testCase.Resource { - t.Errorf("%d: unexpected resource: %#v", i, mapping) - } - - if mapping.MetadataAccessor == nil || mapping.ObjectConvertor == nil { - t.Errorf("%d: missing codec and accessor: %#v", i, mapping) - } - - groupVersion := testCase.ExpectedGroupVersion - if groupVersion == nil { - groupVersion = &testCase.APIGroupVersions[0] - } - if mapping.GroupVersionKind.GroupVersion() != *groupVersion { - t.Errorf("%d: unexpected version: %#v", i, mapping) - } - - } -} - -func TestRESTMapperRESTMappingSelectsVersion(t *testing.T) { - expectedGroupVersion1 := unversioned.GroupVersion{Group: "tgroup", Version: "test1"} - expectedGroupVersion2 := unversioned.GroupVersion{Group: "tgroup", Version: "test2"} - expectedGroupVersion3 := unversioned.GroupVersion{Group: "tgroup", Version: "test3"} - internalObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "InternalObject"} - otherObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "OtherObject"} - - mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, fakeInterfaces) - mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) - mapper.Add(expectedGroupVersion2.WithKind("OtherObject"), RESTScopeNamespace) - - // pick default matching object kind based on search order - mapping, err := mapper.RESTMapping(otherObjectGK) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { - t.Errorf("unexpected mapping: %#v", mapping) - } - - mapping, err = mapper.RESTMapping(internalObjectGK) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if mapping.Resource != "internalobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion1 { - t.Errorf("unexpected mapping: %#v", mapping) - } - - // mismatch of version - mapping, err = mapper.RESTMapping(internalObjectGK, expectedGroupVersion2.Version) - if err == nil { - t.Errorf("unexpected non-error") - } - mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion1.Version) - if err == nil { - t.Errorf("unexpected non-error") - } - - // not in the search versions - mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version) - if err == nil { - t.Errorf("unexpected non-error") - } - - // explicit search order - mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version, expectedGroupVersion1.Version) - if err == nil { - t.Errorf("unexpected non-error") - } - - mapping, err = mapper.RESTMapping(otherObjectGK, expectedGroupVersion3.Version, expectedGroupVersion2.Version) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if mapping.Resource != "otherobjects" || mapping.GroupVersionKind.GroupVersion() != expectedGroupVersion2 { - t.Errorf("unexpected mapping: %#v", mapping) - } -} - -func TestRESTMapperReportsErrorOnBadVersion(t *testing.T) { - expectedGroupVersion1 := unversioned.GroupVersion{Group: "tgroup", Version: "test1"} - expectedGroupVersion2 := unversioned.GroupVersion{Group: "tgroup", Version: "test2"} - internalObjectGK := unversioned.GroupKind{Group: "tgroup", Kind: "InternalObject"} - - mapper := NewDefaultRESTMapper([]unversioned.GroupVersion{expectedGroupVersion1, expectedGroupVersion2}, unmatchedVersionInterfaces) - mapper.Add(expectedGroupVersion1.WithKind("InternalObject"), RESTScopeNamespace) - _, err := mapper.RESTMapping(internalObjectGK, expectedGroupVersion1.Version) - if err == nil { - t.Errorf("unexpected non-error") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta_test.go deleted file mode 100644 index e4a9657a0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/meta_test.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 api_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" -) - -var _ meta.Object = &api.ObjectMeta{} - -// TestFillObjectMetaSystemFields validates that system populated fields are set on an object -func TestFillObjectMetaSystemFields(t *testing.T) { - ctx := api.NewDefaultContext() - resource := api.ObjectMeta{} - api.FillObjectMetaSystemFields(ctx, &resource) - if resource.CreationTimestamp.Time.IsZero() { - t.Errorf("resource.CreationTimestamp is zero") - } else if len(resource.UID) == 0 { - t.Errorf("resource.UID missing") - } -} - -// TestHasObjectMetaSystemFieldValues validates that true is returned if and only if all fields are populated -func TestHasObjectMetaSystemFieldValues(t *testing.T) { - ctx := api.NewDefaultContext() - resource := api.ObjectMeta{} - if api.HasObjectMetaSystemFieldValues(&resource) { - t.Errorf("the resource does not have all fields yet populated, but incorrectly reports it does") - } - api.FillObjectMetaSystemFields(ctx, &resource) - if !api.HasObjectMetaSystemFieldValues(&resource) { - t.Errorf("the resource does have all fields populated, but incorrectly reports it does not") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/pod/util_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/pod/util_test.go deleted file mode 100644 index 428f2bdcd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/pod/util_test.go +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 pod - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func TestFindPort(t *testing.T) { - testCases := []struct { - name string - containers []api.Container - port intstr.IntOrString - expected int - pass bool - }{{ - name: "valid int, no ports", - containers: []api.Container{{}}, - port: intstr.FromInt(93), - expected: 93, - pass: true, - }, { - name: "valid int, with ports", - containers: []api.Container{{Ports: []api.ContainerPort{{ - Name: "", - ContainerPort: 11, - Protocol: "TCP", - }, { - Name: "p", - ContainerPort: 22, - Protocol: "TCP", - }}}}, - port: intstr.FromInt(93), - expected: 93, - pass: true, - }, { - name: "valid str, no ports", - containers: []api.Container{{}}, - port: intstr.FromString("p"), - expected: 0, - pass: false, - }, { - name: "valid str, one ctr with ports", - containers: []api.Container{{Ports: []api.ContainerPort{{ - Name: "", - ContainerPort: 11, - Protocol: "UDP", - }, { - Name: "p", - ContainerPort: 22, - Protocol: "TCP", - }, { - Name: "q", - ContainerPort: 33, - Protocol: "TCP", - }}}}, - port: intstr.FromString("q"), - expected: 33, - pass: true, - }, { - name: "valid str, two ctr with ports", - containers: []api.Container{{}, {Ports: []api.ContainerPort{{ - Name: "", - ContainerPort: 11, - Protocol: "UDP", - }, { - Name: "p", - ContainerPort: 22, - Protocol: "TCP", - }, { - Name: "q", - ContainerPort: 33, - Protocol: "TCP", - }}}}, - port: intstr.FromString("q"), - expected: 33, - pass: true, - }} - - for _, tc := range testCases { - port, err := FindPort(&api.Pod{Spec: api.PodSpec{Containers: tc.containers}}, - &api.ServicePort{Protocol: "TCP", TargetPort: tc.port}) - if err != nil && tc.pass { - t.Errorf("unexpected error for %s: %v", tc.name, err) - } - if err == nil && !tc.pass { - t.Errorf("unexpected non-error for %s: %d", tc.name, port) - } - if port != tc.expected { - t.Errorf("wrong result for %s: expected %d, got %d", tc.name, tc.expected, port) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/ref_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/ref_test.go deleted file mode 100644 index dbde7a01f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/ref_test.go +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 api - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" -) - -type FakeAPIObject struct{} - -func (obj *FakeAPIObject) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -type ExtensionAPIObject struct { - unversioned.TypeMeta - ObjectMeta -} - -func (obj *ExtensionAPIObject) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } - -func TestGetReference(t *testing.T) { - - // when vendoring kube, if you don't force the set of registered versions (like this hack/test-go.sh does) - // then you run into trouble because the types aren't registered in the scheme by anything. This does the - // register manually to allow unit test execution - if _, err := Scheme.ObjectKind(&Pod{}); err != nil { - AddToScheme(Scheme) - } - - table := map[string]struct { - obj runtime.Object - ref *ObjectReference - fieldPath string - shouldErr bool - }{ - "pod": { - obj: &Pod{ - ObjectMeta: ObjectMeta{ - Name: "foo", - UID: "bar", - ResourceVersion: "42", - SelfLink: "/api/version1/pods/foo", - }, - }, - fieldPath: ".desiredState.containers[0]", - ref: &ObjectReference{ - Kind: "Pod", - APIVersion: "version1", - Name: "foo", - UID: "bar", - ResourceVersion: "42", - FieldPath: ".desiredState.containers[0]", - }, - }, - "serviceList": { - obj: &ServiceList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "42", - SelfLink: "/api/version2/services", - }, - }, - ref: &ObjectReference{ - Kind: "ServiceList", - APIVersion: "version2", - ResourceVersion: "42", - }, - }, - "extensionAPIObject": { - obj: &ExtensionAPIObject{ - TypeMeta: unversioned.TypeMeta{ - Kind: "ExtensionAPIObject", - }, - ObjectMeta: ObjectMeta{ - Name: "foo", - UID: "bar", - ResourceVersion: "42", - SelfLink: "/custom_prefix/version1/extensions/foo", - }, - }, - ref: &ObjectReference{ - Kind: "ExtensionAPIObject", - APIVersion: "version1", - Name: "foo", - UID: "bar", - ResourceVersion: "42", - }, - }, - "badSelfLink": { - obj: &ServiceList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "42", - SelfLink: "version2/services", - }, - }, - shouldErr: true, - }, - "error": { - obj: &FakeAPIObject{}, - ref: nil, - shouldErr: true, - }, - "errorNil": { - obj: nil, - ref: nil, - shouldErr: true, - }, - } - - for name, item := range table { - ref, err := GetPartialReference(item.obj, item.fieldPath) - if e, a := item.shouldErr, (err != nil); e != a { - t.Errorf("%v: expected %v, got %v, err %v", name, e, a, err) - continue - } - if e, a := item.ref, ref; !reflect.DeepEqual(e, a) { - t.Errorf("%v: expected %#v, got %#v", name, e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_example_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_example_test.go deleted file mode 100644 index 48c3d2555..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_example_test.go +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 resource_test - -import ( - "fmt" - - "k8s.io/kubernetes/pkg/api/resource" -) - -func ExampleFormat() { - memorySize := resource.NewQuantity(5*1024*1024*1024, resource.BinarySI) - fmt.Printf("memorySize = %v\n", memorySize) - - diskSize := resource.NewQuantity(5*1000*1000*1000, resource.DecimalSI) - fmt.Printf("diskSize = %v\n", diskSize) - - cores := resource.NewMilliQuantity(5300, resource.DecimalSI) - fmt.Printf("cores = %v\n", cores) - - // Output: - // memorySize = 5Gi - // diskSize = 5G - // cores = 5300m -} - -func ExampleMustParse() { - memorySize := resource.MustParse("5Gi") - fmt.Printf("memorySize = %v (%v)\n", memorySize.Value(), memorySize.Format) - - diskSize := resource.MustParse("5G") - fmt.Printf("diskSize = %v (%v)\n", diskSize.Value(), diskSize.Format) - - cores := resource.MustParse("5300m") - fmt.Printf("milliCores = %v (%v)\n", cores.MilliValue(), cores.Format) - - cores2 := resource.MustParse("5.4") - fmt.Printf("milliCores = %v (%v)\n", cores2.MilliValue(), cores2.Format) - - // Output: - // memorySize = 5368709120 (BinarySI) - // diskSize = 5000000000 (DecimalSI) - // milliCores = 5300 (DecimalSI) - // milliCores = 5400 (DecimalSI) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_test.go deleted file mode 100644 index 68806b749..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/quantity_test.go +++ /dev/null @@ -1,930 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 resource - -import ( - //"reflect" - "encoding/json" - "testing" - - fuzz "github.com/google/gofuzz" - "github.com/spf13/pflag" - "speter.net/go/exp/math/dec/inf" -) - -var ( - testQuantityFlag = QuantityFlag("quantityFlag", "1M", "dummy flag for testing the quantity flag mechanism") -) - -func dec(i int64, exponent int) *inf.Dec { - // See the below test-- scale is the negative of an exponent. - return inf.NewDec(i, inf.Scale(-exponent)) -} - -func TestDec(t *testing.T) { - table := []struct { - got *inf.Dec - expect string - }{ - {dec(1, 0), "1"}, - {dec(1, 1), "10"}, - {dec(5, 2), "500"}, - {dec(8, 3), "8000"}, - {dec(2, 0), "2"}, - {dec(1, -1), "0.1"}, - {dec(3, -2), "0.03"}, - {dec(4, -3), "0.004"}, - } - - for _, item := range table { - if e, a := item.expect, item.got.String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - } -} - -// TestQuantityParseZero ensures that when a 0 quantity is passed, its string value is 0 -func TestQuantityParseZero(t *testing.T) { - zero := MustParse("0") - if expected, actual := "0", zero.String(); expected != actual { - t.Errorf("Expected %v, actual %v", expected, actual) - } -} - -// TestQuantityAddZeroPreservesSuffix verifies that a suffix is preserved -// independent of the order of operations when adding a zero and non-zero val -func TestQuantityAddZeroPreservesSuffix(t *testing.T) { - testValues := []string{"100m", "1Gi"} - zero := MustParse("0") - for _, testValue := range testValues { - value := MustParse(testValue) - v1 := *value.Copy() - // ensure non-zero + zero = non-zero (suffix preserved) - err := v1.Add(zero) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - // ensure zero + non-zero = non-zero (suffix preserved) - v2 := *zero.Copy() - err = v2.Add(value) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - // ensure we preserved the input value - if v1.String() != testValue { - t.Errorf("Expected %v, actual %v", testValue, v1.String()) - } - if v2.String() != testValue { - t.Errorf("Expected %v, actual %v", testValue, v2.String()) - } - } -} - -// TestQuantitySubZeroPreservesSuffix verifies that a suffix is preserved -// independent of the order of operations when subtracting a zero and non-zero val -func TestQuantitySubZeroPreservesSuffix(t *testing.T) { - testValues := []string{"100m", "1Gi"} - zero := MustParse("0") - for _, testValue := range testValues { - value := MustParse(testValue) - v1 := *value.Copy() - // ensure non-zero - zero = non-zero (suffix preserved) - err := v1.Sub(zero) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - // ensure we preserved the input value - if v1.String() != testValue { - t.Errorf("Expected %v, actual %v", testValue, v1.String()) - } - - // ensure zero - non-zero = -non-zero (suffix preserved) - v2 := *zero.Copy() - err = v2.Sub(value) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - negVal := *value.Copy() - err = negVal.Neg(negVal) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - if v2.String() != negVal.String() { - t.Errorf("Expected %v, actual %v", negVal.String(), v2.String()) - } - } -} - -// Verifies that you get 0 as canonical value if internal value is 0, and not 0 -func TestQuantityCanocicalizeZero(t *testing.T) { - val := MustParse("1000m") - x := val.Amount - y := dec(1, 0) - z := val.Amount.Sub(x, y) - zero := Quantity{z, DecimalSI} - if expected, actual := "0", zero.String(); expected != actual { - t.Errorf("Expected %v, actual %v", expected, actual) - } -} - -func TestQuantityCmp(t *testing.T) { - table := []struct { - x string - y string - expect int - }{ - {"0", "0", 0}, - {"100m", "50m", 1}, - {"50m", "100m", -1}, - {"10000T", "100Gi", 1}, - } - for _, testCase := range table { - q1 := MustParse(testCase.x) - q2 := MustParse(testCase.y) - if result := q1.Cmp(q2); result != testCase.expect { - t.Errorf("X: %v, Y: %v, Expected: %v, Actual: %v", testCase.x, testCase.y, testCase.expect, result) - } - } - - nils := []struct { - x *inf.Dec - y *inf.Dec - expect int - }{ - {dec(0, 0), dec(0, 0), 0}, - {nil, dec(0, 0), 0}, - {dec(0, 0), nil, 0}, - {nil, nil, 0}, - {nil, dec(10, 0), -1}, - {nil, dec(-10, 0), 1}, - {dec(10, 0), nil, 1}, - {dec(-10, 0), nil, -1}, - } - for _, nilCase := range nils { - q1 := Quantity{nilCase.x, DecimalSI} - q2 := Quantity{nilCase.y, DecimalSI} - if result := q1.Cmp(q2); result != nilCase.expect { - t.Errorf("X: %v, Y: %v, Expected: %v, Actual: %v", nilCase.x, nilCase.y, nilCase.expect, result) - } - } -} - -func TestQuantityParse(t *testing.T) { - table := []struct { - input string - expect Quantity - }{ - {"0", Quantity{dec(0, 0), DecimalSI}}, - {"0n", Quantity{dec(0, 0), DecimalSI}}, - {"0u", Quantity{dec(0, 0), DecimalSI}}, - {"0m", Quantity{dec(0, 0), DecimalSI}}, - {"0Ki", Quantity{dec(0, 0), BinarySI}}, - {"0k", Quantity{dec(0, 0), DecimalSI}}, - {"0Mi", Quantity{dec(0, 0), BinarySI}}, - {"0M", Quantity{dec(0, 0), DecimalSI}}, - {"0Gi", Quantity{dec(0, 0), BinarySI}}, - {"0G", Quantity{dec(0, 0), DecimalSI}}, - {"0Ti", Quantity{dec(0, 0), BinarySI}}, - {"0T", Quantity{dec(0, 0), DecimalSI}}, - - // Binary suffixes - {"1Ki", Quantity{dec(1024, 0), BinarySI}}, - {"8Ki", Quantity{dec(8*1024, 0), BinarySI}}, - {"7Mi", Quantity{dec(7*1024*1024, 0), BinarySI}}, - {"6Gi", Quantity{dec(6*1024*1024*1024, 0), BinarySI}}, - {"5Ti", Quantity{dec(5*1024*1024*1024*1024, 0), BinarySI}}, - {"4Pi", Quantity{dec(4*1024*1024*1024*1024*1024, 0), BinarySI}}, - {"3Ei", Quantity{dec(3*1024*1024*1024*1024*1024*1024, 0), BinarySI}}, - - {"10Ti", Quantity{dec(10*1024*1024*1024*1024, 0), BinarySI}}, - {"100Ti", Quantity{dec(100*1024*1024*1024*1024, 0), BinarySI}}, - - // Decimal suffixes - {"5n", Quantity{dec(5, -9), DecimalSI}}, - {"4u", Quantity{dec(4, -6), DecimalSI}}, - {"3m", Quantity{dec(3, -3), DecimalSI}}, - {"9", Quantity{dec(9, 0), DecimalSI}}, - {"8k", Quantity{dec(8, 3), DecimalSI}}, - {"7M", Quantity{dec(7, 6), DecimalSI}}, - {"6G", Quantity{dec(6, 9), DecimalSI}}, - {"5T", Quantity{dec(5, 12), DecimalSI}}, - {"40T", Quantity{dec(4, 13), DecimalSI}}, - {"300T", Quantity{dec(3, 14), DecimalSI}}, - {"2P", Quantity{dec(2, 15), DecimalSI}}, - {"1E", Quantity{dec(1, 18), DecimalSI}}, - - // Decimal exponents - {"1E-3", Quantity{dec(1, -3), DecimalExponent}}, - {"1e3", Quantity{dec(1, 3), DecimalExponent}}, - {"1E6", Quantity{dec(1, 6), DecimalExponent}}, - {"1e9", Quantity{dec(1, 9), DecimalExponent}}, - {"1E12", Quantity{dec(1, 12), DecimalExponent}}, - {"1e15", Quantity{dec(1, 15), DecimalExponent}}, - {"1E18", Quantity{dec(1, 18), DecimalExponent}}, - - // Nonstandard but still parsable - {"1e14", Quantity{dec(1, 14), DecimalExponent}}, - {"1e13", Quantity{dec(1, 13), DecimalExponent}}, - {"1e3", Quantity{dec(1, 3), DecimalExponent}}, - {"100.035k", Quantity{dec(100035, 0), DecimalSI}}, - - // Things that look like floating point - {"0.001", Quantity{dec(1, -3), DecimalSI}}, - {"0.0005k", Quantity{dec(5, -1), DecimalSI}}, - {"0.005", Quantity{dec(5, -3), DecimalSI}}, - {"0.05", Quantity{dec(5, -2), DecimalSI}}, - {"0.5", Quantity{dec(5, -1), DecimalSI}}, - {"0.00050k", Quantity{dec(5, -1), DecimalSI}}, - {"0.00500", Quantity{dec(5, -3), DecimalSI}}, - {"0.05000", Quantity{dec(5, -2), DecimalSI}}, - {"0.50000", Quantity{dec(5, -1), DecimalSI}}, - {"0.5e0", Quantity{dec(5, -1), DecimalExponent}}, - {"0.5e-1", Quantity{dec(5, -2), DecimalExponent}}, - {"0.5e-2", Quantity{dec(5, -3), DecimalExponent}}, - {"0.5e0", Quantity{dec(5, -1), DecimalExponent}}, - {"10.035M", Quantity{dec(10035, 3), DecimalSI}}, - - {"1.2e3", Quantity{dec(12, 2), DecimalExponent}}, - {"1.3E+6", Quantity{dec(13, 5), DecimalExponent}}, - {"1.40e9", Quantity{dec(14, 8), DecimalExponent}}, - {"1.53E12", Quantity{dec(153, 10), DecimalExponent}}, - {"1.6e15", Quantity{dec(16, 14), DecimalExponent}}, - {"1.7E18", Quantity{dec(17, 17), DecimalExponent}}, - - {"9.01", Quantity{dec(901, -2), DecimalSI}}, - {"8.1k", Quantity{dec(81, 2), DecimalSI}}, - {"7.123456M", Quantity{dec(7123456, 0), DecimalSI}}, - {"6.987654321G", Quantity{dec(6987654321, 0), DecimalSI}}, - {"5.444T", Quantity{dec(5444, 9), DecimalSI}}, - {"40.1T", Quantity{dec(401, 11), DecimalSI}}, - {"300.2T", Quantity{dec(3002, 11), DecimalSI}}, - {"2.5P", Quantity{dec(25, 14), DecimalSI}}, - {"1.01E", Quantity{dec(101, 16), DecimalSI}}, - - // Things that saturate/round - {"3.001n", Quantity{dec(4, -9), DecimalSI}}, - {"1.1E-9", Quantity{dec(2, -9), DecimalExponent}}, - {"0.0000000001", Quantity{dec(1, -9), DecimalSI}}, - {"0.0000000005", Quantity{dec(1, -9), DecimalSI}}, - {"0.00000000050", Quantity{dec(1, -9), DecimalSI}}, - {"0.5e-9", Quantity{dec(1, -9), DecimalExponent}}, - {"0.9n", Quantity{dec(1, -9), DecimalSI}}, - {"0.00000012345", Quantity{dec(124, -9), DecimalSI}}, - {"0.00000012354", Quantity{dec(124, -9), DecimalSI}}, - {"9Ei", Quantity{maxAllowed, BinarySI}}, - {"9223372036854775807Ki", Quantity{maxAllowed, BinarySI}}, - {"12E", Quantity{maxAllowed, DecimalSI}}, - - // We'll accept fractional binary stuff, too. - {"100.035Ki", Quantity{dec(10243584, -2), BinarySI}}, - {"0.5Mi", Quantity{dec(.5*1024*1024, 0), BinarySI}}, - {"0.05Gi", Quantity{dec(536870912, -1), BinarySI}}, - {"0.025Ti", Quantity{dec(274877906944, -1), BinarySI}}, - - // Things written by trolls - {"0.000000000001Ki", Quantity{dec(2, -9), DecimalSI}}, // rounds up, changes format - {".001", Quantity{dec(1, -3), DecimalSI}}, - {".0001k", Quantity{dec(100, -3), DecimalSI}}, - {"1.", Quantity{dec(1, 0), DecimalSI}}, - {"1.G", Quantity{dec(1, 9), DecimalSI}}, - } - - for _, item := range table { - got, err := ParseQuantity(item.input) - if err != nil { - t.Errorf("%v: unexpected error: %v", item.input, err) - continue - } - if e, a := item.expect.Amount, got.Amount; e.Cmp(a) != 0 { - t.Errorf("%v: expected %v, got %v", item.input, e, a) - } - if e, a := item.expect.Format, got.Format; e != a { - t.Errorf("%v: expected %#v, got %#v", item.input, e, a) - } - } - - // Try the negative version of everything - desired := &inf.Dec{} - for _, item := range table { - got, err := ParseQuantity("-" + item.input) - if err != nil { - t.Errorf("-%v: unexpected error: %v", item.input, err) - continue - } - desired.Neg(item.expect.Amount) - if e, a := desired, got.Amount; e.Cmp(a) != 0 { - t.Errorf("%v: expected %v, got %v", item.input, e, a) - } - if e, a := item.expect.Format, got.Format; e != a { - t.Errorf("%v: expected %#v, got %#v", item.input, e, a) - } - } - - // Try everything with an explicit + - for _, item := range table { - got, err := ParseQuantity("+" + item.input) - if err != nil { - t.Errorf("-%v: unexpected error: %v", item.input, err) - continue - } - if e, a := item.expect.Amount, got.Amount; e.Cmp(a) != 0 { - t.Errorf("%v: expected %v, got %v", item.input, e, a) - } - if e, a := item.expect.Format, got.Format; e != a { - t.Errorf("%v: expected %#v, got %#v", item.input, e, a) - } - } - - invalid := []string{ - "1.1.M", - "1+1.0M", - "0.1mi", - "0.1am", - "aoeu", - ".5i", - "1i", - "-3.01i", - } - for _, item := range invalid { - _, err := ParseQuantity(item) - if err == nil { - t.Errorf("%v parsed unexpectedly", item) - } - } -} - -func TestQuantityString(t *testing.T) { - table := []struct { - in Quantity - expect string - }{ - {Quantity{dec(1024*1024*1024, 0), BinarySI}, "1Gi"}, - {Quantity{dec(300*1024*1024, 0), BinarySI}, "300Mi"}, - {Quantity{dec(6*1024, 0), BinarySI}, "6Ki"}, - {Quantity{dec(1001*1024*1024*1024, 0), BinarySI}, "1001Gi"}, - {Quantity{dec(1024*1024*1024*1024, 0), BinarySI}, "1Ti"}, - {Quantity{dec(5, 0), BinarySI}, "5"}, - {Quantity{dec(500, -3), BinarySI}, "500m"}, - {Quantity{dec(1, 9), DecimalSI}, "1G"}, - {Quantity{dec(1000, 6), DecimalSI}, "1G"}, - {Quantity{dec(1000000, 3), DecimalSI}, "1G"}, - {Quantity{dec(1000000000, 0), DecimalSI}, "1G"}, - {Quantity{dec(1, -3), DecimalSI}, "1m"}, - {Quantity{dec(80, -3), DecimalSI}, "80m"}, - {Quantity{dec(1080, -3), DecimalSI}, "1080m"}, - {Quantity{dec(108, -2), DecimalSI}, "1080m"}, - {Quantity{dec(10800, -4), DecimalSI}, "1080m"}, - {Quantity{dec(300, 6), DecimalSI}, "300M"}, - {Quantity{dec(1, 12), DecimalSI}, "1T"}, - {Quantity{dec(1234567, 6), DecimalSI}, "1234567M"}, - {Quantity{dec(1234567, -3), BinarySI}, "1234567m"}, - {Quantity{dec(3, 3), DecimalSI}, "3k"}, - {Quantity{dec(1025, 0), BinarySI}, "1025"}, - {Quantity{dec(0, 0), DecimalSI}, "0"}, - {Quantity{dec(0, 0), BinarySI}, "0"}, - {Quantity{dec(1, 9), DecimalExponent}, "1e9"}, - {Quantity{dec(1, -3), DecimalExponent}, "1e-3"}, - {Quantity{dec(1, -9), DecimalExponent}, "1e-9"}, - {Quantity{dec(80, -3), DecimalExponent}, "80e-3"}, - {Quantity{dec(300, 6), DecimalExponent}, "300e6"}, - {Quantity{dec(1, 12), DecimalExponent}, "1e12"}, - {Quantity{dec(1, 3), DecimalExponent}, "1e3"}, - {Quantity{dec(3, 3), DecimalExponent}, "3e3"}, - {Quantity{dec(3, 3), DecimalSI}, "3k"}, - {Quantity{dec(0, 0), DecimalExponent}, "0"}, - {Quantity{dec(1, -9), DecimalSI}, "1n"}, - {Quantity{dec(80, -9), DecimalSI}, "80n"}, - {Quantity{dec(1080, -9), DecimalSI}, "1080n"}, - {Quantity{dec(108, -8), DecimalSI}, "1080n"}, - {Quantity{dec(10800, -10), DecimalSI}, "1080n"}, - {Quantity{dec(1, -6), DecimalSI}, "1u"}, - {Quantity{dec(80, -6), DecimalSI}, "80u"}, - {Quantity{dec(1080, -6), DecimalSI}, "1080u"}, - } - for _, item := range table { - got := item.in.String() - if e, a := item.expect, got; e != a { - t.Errorf("%#v: expected %v, got %v", item.in, e, a) - } - } - desired := &inf.Dec{} // Avoid modifying the values in the table. - for _, item := range table { - if item.in.Amount.Cmp(decZero) == 0 { - // Don't expect it to print "-0" ever - continue - } - q := item.in - q.Amount = desired.Neg(q.Amount) - if e, a := "-"+item.expect, q.String(); e != a { - t.Errorf("%#v: expected %v, got %v", item.in, e, a) - } - } -} - -func TestQuantityParseEmit(t *testing.T) { - table := []struct { - in string - expect string - }{ - {"1Ki", "1Ki"}, - {"1Mi", "1Mi"}, - {"1Gi", "1Gi"}, - {"1024Mi", "1Gi"}, - {"1000M", "1G"}, - {".001Ki", "1024m"}, - {".000001Ki", "1024u"}, - {".000000001Ki", "1024n"}, - {".000000000001Ki", "2n"}, - } - - for _, item := range table { - q, err := ParseQuantity(item.in) - if err != nil { - t.Errorf("Couldn't parse %v", item.in) - continue - } - if e, a := item.expect, q.String(); e != a { - t.Errorf("%#v: expected %v, got %v", item.in, e, a) - } - } - for _, item := range table { - q, err := ParseQuantity("-" + item.in) - if err != nil { - t.Errorf("Couldn't parse %v", item.in) - continue - } - if q.Amount.Cmp(decZero) == 0 { - continue - } - if e, a := "-"+item.expect, q.String(); e != a { - t.Errorf("%#v: expected %v, got %v", item.in, e, a) - } - } -} - -var fuzzer = fuzz.New().Funcs( - func(q *Quantity, c fuzz.Continue) { - q.Amount = &inf.Dec{} - if c.RandBool() { - q.Format = BinarySI - if c.RandBool() { - q.Amount.SetScale(0) - q.Amount.SetUnscaled(c.Int63()) - return - } - // Be sure to test cases like 1Mi - q.Amount.SetScale(0) - q.Amount.SetUnscaled(c.Int63n(1024) << uint(10*c.Intn(5))) - return - } - if c.RandBool() { - q.Format = DecimalSI - } else { - q.Format = DecimalExponent - } - if c.RandBool() { - q.Amount.SetScale(inf.Scale(c.Intn(4))) - q.Amount.SetUnscaled(c.Int63()) - return - } - // Be sure to test cases like 1M - q.Amount.SetScale(inf.Scale(3 - c.Intn(15))) - q.Amount.SetUnscaled(c.Int63n(1000)) - }, -) - -func TestJSON(t *testing.T) { - for i := 0; i < 500; i++ { - q := &Quantity{} - fuzzer.Fuzz(q) - b, err := json.Marshal(q) - if err != nil { - t.Errorf("error encoding %v", q) - } - q2 := &Quantity{} - err = json.Unmarshal(b, q2) - if err != nil { - t.Errorf("%v: error decoding %v", q, string(b)) - } - if q2.Amount.Cmp(q.Amount) != 0 { - t.Errorf("Expected equal: %v, %v (json was '%v')", q, q2, string(b)) - } - } -} - -func TestMilliNewSet(t *testing.T) { - table := []struct { - value int64 - format Format - expect string - exact bool - }{ - {1, DecimalSI, "1m", true}, - {1000, DecimalSI, "1", true}, - {1234000, DecimalSI, "1234", true}, - {1024, BinarySI, "1024m", false}, // Format changes - {1000000, "invalidFormatDefaultsToExponent", "1e3", true}, - {1024 * 1024, BinarySI, "1048576m", false}, // Format changes - } - - for _, item := range table { - q := NewMilliQuantity(item.value, item.format) - if e, a := item.expect, q.String(); e != a { - t.Errorf("Expected %v, got %v; %#v", e, a, q) - } - if !item.exact { - continue - } - q2, err := ParseQuantity(q.String()) - if err != nil { - t.Errorf("Round trip failed on %v", q) - } - if e, a := item.value, q2.MilliValue(); e != a { - t.Errorf("Expected %v, got %v", e, a) - } - } - - for _, item := range table { - q := NewQuantity(0, item.format) - q.SetMilli(item.value) - if e, a := item.expect, q.String(); e != a { - t.Errorf("Set: Expected %v, got %v; %#v", e, a, q) - } - } -} - -func TestNewSet(t *testing.T) { - table := []struct { - value int64 - format Format - expect string - }{ - {1, DecimalSI, "1"}, - {1000, DecimalSI, "1k"}, - {1234000, DecimalSI, "1234k"}, - {1024, BinarySI, "1Ki"}, - {1000000, "invalidFormatDefaultsToExponent", "1e6"}, - {1024 * 1024, BinarySI, "1Mi"}, - } - - for _, item := range table { - q := NewQuantity(item.value, item.format) - if e, a := item.expect, q.String(); e != a { - t.Errorf("Expected %v, got %v; %#v", e, a, q) - } - q2, err := ParseQuantity(q.String()) - if err != nil { - t.Errorf("Round trip failed on %v", q) - } - if e, a := item.value, q2.Value(); e != a { - t.Errorf("Expected %v, got %v", e, a) - } - } - - for _, item := range table { - q := NewQuantity(0, item.format) - q.Set(item.value) - if e, a := item.expect, q.String(); e != a { - t.Errorf("Set: Expected %v, got %v; %#v", e, a, q) - } - } -} - -func TestNewScaledSet(t *testing.T) { - table := []struct { - value int64 - scale Scale - expect string - }{ - {1, Nano, "1n"}, - {1000, Nano, "1u"}, - {1, Micro, "1u"}, - {1000, Micro, "1m"}, - {1, Milli, "1m"}, - {1000, Milli, "1"}, - {1, 0, "1"}, - {0, Nano, "0"}, - {0, Micro, "0"}, - {0, Milli, "0"}, - {0, 0, "0"}, - } - - for _, item := range table { - q := NewScaledQuantity(item.value, item.scale) - if e, a := item.expect, q.String(); e != a { - t.Errorf("Expected %v, got %v; %#v", e, a, q) - } - q2, err := ParseQuantity(q.String()) - if err != nil { - t.Errorf("Round trip failed on %v", q) - } - if e, a := item.value, q2.ScaledValue(item.scale); e != a { - t.Errorf("Expected %v, got %v", e, a) - } - q3 := NewQuantity(0, DecimalSI) - q3.SetScaled(item.value, item.scale) - if q.Cmp(*q3) != 0 { - t.Errorf("Expected %v and %v to be equal", q, q3) - } - } -} - -func TestScaledValue(t *testing.T) { - table := []struct { - fromScale Scale - toScale Scale - expected int64 - }{ - {Nano, Nano, 1}, - {Nano, Micro, 1}, - {Nano, Milli, 1}, - {Nano, 0, 1}, - {Micro, Nano, 1000}, - {Micro, Micro, 1}, - {Micro, Milli, 1}, - {Micro, 0, 1}, - {Milli, Nano, 1000 * 1000}, - {Milli, Micro, 1000}, - {Milli, Milli, 1}, - {Milli, 0, 1}, - {0, Nano, 1000 * 1000 * 1000}, - {0, Micro, 1000 * 1000}, - {0, Milli, 1000}, - {0, 0, 1}, - } - - for _, item := range table { - q := NewScaledQuantity(1, item.fromScale) - if e, a := item.expected, q.ScaledValue(item.toScale); e != a { - t.Errorf("%v to %v: Expected %v, got %v", item.fromScale, item.toScale, e, a) - } - } -} - -func TestUninitializedNoCrash(t *testing.T) { - var q Quantity - - q.Value() - q.MilliValue() - q.Copy() - _ = q.String() - q.MarshalJSON() -} - -func TestCopy(t *testing.T) { - q := NewQuantity(5, DecimalSI) - c := q.Copy() - c.Set(6) - if q.Value() == 6 { - t.Errorf("Copy didn't") - } -} - -func TestQFlagSet(t *testing.T) { - qf := qFlag{&Quantity{}} - qf.Set("1Ki") - if e, a := "1Ki", qf.String(); e != a { - t.Errorf("Unexpected result %v != %v", e, a) - } -} - -func TestQFlagIsPFlag(t *testing.T) { - var pfv pflag.Value = qFlag{} - if e, a := "quantity", pfv.Type(); e != a { - t.Errorf("Unexpected result %v != %v", e, a) - } -} - -func TestSub(t *testing.T) { - tests := []struct { - a Quantity - b Quantity - expected Quantity - }{ - {Quantity{dec(10, 0), DecimalSI}, Quantity{dec(1, 1), DecimalSI}, Quantity{dec(0, 0), DecimalSI}}, - {Quantity{dec(10, 0), DecimalSI}, Quantity{dec(1, 0), BinarySI}, Quantity{dec(9, 0), DecimalSI}}, - {Quantity{dec(10, 0), BinarySI}, Quantity{dec(1, 0), DecimalSI}, Quantity{dec(9, 0), BinarySI}}, - {Quantity{nil, DecimalSI}, Quantity{dec(50, 0), DecimalSI}, Quantity{dec(-50, 0), DecimalSI}}, - {Quantity{dec(50, 0), DecimalSI}, Quantity{nil, DecimalSI}, Quantity{dec(50, 0), DecimalSI}}, - {Quantity{nil, DecimalSI}, Quantity{nil, DecimalSI}, Quantity{dec(0, 0), DecimalSI}}, - } - - for i, test := range tests { - test.a.Sub(test.b) - if test.a.Cmp(test.expected) != 0 { - t.Errorf("[%d] Expected %q, got %q", i, test.expected.String(), test.a.String()) - } - } -} - -func TestNeg(t *testing.T) { - tests := []struct { - a Quantity - b Quantity - expected Quantity - }{ - { - a: Quantity{dec(0, 0), DecimalSI}, - b: Quantity{dec(10, 0), DecimalSI}, - expected: Quantity{dec(-10, 0), DecimalSI}, - }, - { - a: Quantity{dec(0, 0), DecimalSI}, - b: Quantity{dec(-10, 0), DecimalSI}, - expected: Quantity{dec(10, 0), DecimalSI}, - }, - { - a: Quantity{dec(0, 0), DecimalSI}, - b: Quantity{dec(10, 0), BinarySI}, - expected: Quantity{dec(-10, 0), BinarySI}, - }, - { - a: Quantity{dec(0, 0), DecimalSI}, - b: Quantity{dec(0, 0), BinarySI}, - expected: Quantity{dec(0, 0), BinarySI}, - }, - { - a: Quantity{}, - b: Quantity{dec(10, 0), BinarySI}, - expected: Quantity{dec(-10, 0), BinarySI}, - }, - { - a: Quantity{dec(10, 0), BinarySI}, - b: Quantity{}, - expected: Quantity{}, - }, - { - a: Quantity{dec(10, 0), BinarySI}, - b: Quantity{Format: DecimalSI}, - expected: Quantity{dec(0, 0), DecimalSI}, - }, - } - - for i, test := range tests { - test.a.Neg(test.b) - // ensure value is same - if test.a.Cmp(test.expected) != 0 { - t.Errorf("[%d] Expected %q, got %q", i, test.expected.String(), test.a.String()) - } - // ensure format is updated - if test.a.Format != test.expected.Format { - t.Errorf("[%d] Expected format %v, got format %v", i, test.expected.Format, test.a.Format) - } - } -} - -func TestAdd(t *testing.T) { - tests := []struct { - a Quantity - b Quantity - expected Quantity - }{ - {Quantity{dec(10, 0), DecimalSI}, Quantity{dec(1, 1), DecimalSI}, Quantity{dec(20, 0), DecimalSI}}, - {Quantity{dec(10, 0), DecimalSI}, Quantity{dec(1, 0), BinarySI}, Quantity{dec(11, 0), DecimalSI}}, - {Quantity{dec(10, 0), BinarySI}, Quantity{dec(1, 0), DecimalSI}, Quantity{dec(11, 0), BinarySI}}, - {Quantity{nil, DecimalSI}, Quantity{dec(50, 0), DecimalSI}, Quantity{dec(50, 0), DecimalSI}}, - {Quantity{dec(50, 0), DecimalSI}, Quantity{nil, DecimalSI}, Quantity{dec(50, 0), DecimalSI}}, - {Quantity{nil, DecimalSI}, Quantity{nil, DecimalSI}, Quantity{dec(0, 0), DecimalSI}}, - } - - for i, test := range tests { - test.a.Add(test.b) - if test.a.Cmp(test.expected) != 0 { - t.Errorf("[%d] Expected %q, got %q", i, test.expected.String(), test.a.String()) - } - } -} - -func benchmarkQuantities() []Quantity { - return []Quantity{ - {dec(1024*1024*1024, 0), BinarySI}, - {dec(1024*1024*1024*1024, 0), BinarySI}, - {dec(1000000, 3), DecimalSI}, - {dec(1000000000, 0), DecimalSI}, - {dec(1, -3), DecimalSI}, - {dec(80, -3), DecimalSI}, - {dec(1080, -3), DecimalSI}, - {dec(0, 0), BinarySI}, - {dec(1, 9), DecimalExponent}, - {dec(1, -9), DecimalSI}, - } -} - -func BenchmarkQuantityString(b *testing.B) { - values := benchmarkQuantities() - b.ResetTimer() - var s string - for i := 0; i < b.N; i++ { - s = values[i%len(values)].String() - } - b.StopTimer() - if len(s) == 0 { - b.Fatal(s) - } -} - -func BenchmarkQuantityMarshalJSON(b *testing.B) { - values := benchmarkQuantities() - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := values[i%len(values)].MarshalJSON(); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkQuantityUnmarshalJSON(b *testing.B) { - values := benchmarkQuantities() - var json [][]byte - for _, v := range values { - data, _ := v.MarshalJSON() - json = append(json, data) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - var q Quantity - if err := q.UnmarshalJSON(json[i%len(values)]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkParseQuantity(b *testing.B) { - values := benchmarkQuantities() - var strings []string - for _, v := range values { - strings = append(strings, v.String()) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := ParseQuantity(strings[i%len(values)]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkCanonicalize(b *testing.B) { - values := benchmarkQuantities() - b.ResetTimer() - for i := 0; i < b.N; i++ { - s, _ := values[i%len(values)].Canonicalize() - if len(s) == 0 { - b.Fatal(s) - } - } - b.StopTimer() -} - -func BenchmarkQuantityCopy(b *testing.B) { - values := benchmarkQuantities() - b.ResetTimer() - for i := 0; i < b.N; i++ { - q := values[i%len(values)].Copy() - if q.Amount == nil { - b.Fatal(q) - } - } - b.StopTimer() -} - -func BenchmarkQuantityAdd(b *testing.B) { - values := benchmarkQuantities() - b.ResetTimer() - for i := 0; i < b.N; i++ { - q := values[i%len(values)] - if err := q.Add(q); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkQuantityRound(b *testing.B) { - values := benchmarkQuantities() - b.ResetTimer() - for i := 0; i < b.N; i++ { - q := values[i%len(values)] - if q.Cmp(q) != 0 { - b.Fatal(q) - } - } - b.StopTimer() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/scale_int_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/scale_int_test.go deleted file mode 100644 index 1b4390e55..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource/scale_int_test.go +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 resource - -import ( - "math" - "math/big" - "testing" -) - -func TestScaledValueInternal(t *testing.T) { - tests := []struct { - unscaled *big.Int - scale int - newScale int - - want int64 - }{ - // remain scale - {big.NewInt(1000), 0, 0, 1000}, - - // scale down - {big.NewInt(1000), 0, -3, 1}, - {big.NewInt(1000), 3, 0, 1}, - {big.NewInt(0), 3, 0, 0}, - - // always round up - {big.NewInt(999), 3, 0, 1}, - {big.NewInt(500), 3, 0, 1}, - {big.NewInt(499), 3, 0, 1}, - {big.NewInt(1), 3, 0, 1}, - // large scaled value does not lose precision - {big.NewInt(0).Sub(maxInt64, bigOne), 1, 0, (math.MaxInt64-1)/10 + 1}, - // large intermidiate result. - {big.NewInt(1).Exp(big.NewInt(10), big.NewInt(100), nil), 100, 0, 1}, - - // scale up - {big.NewInt(0), 0, 3, 0}, - {big.NewInt(1), 0, 3, 1000}, - {big.NewInt(1), -3, 0, 1000}, - {big.NewInt(1000), -3, 2, 100000000}, - {big.NewInt(0).Div(big.NewInt(math.MaxInt64), bigThousand), 0, 3, - (math.MaxInt64 / 1000) * 1000}, - } - - for i, tt := range tests { - old := (&big.Int{}).Set(tt.unscaled) - got := scaledValue(tt.unscaled, tt.scale, tt.newScale) - if got != tt.want { - t.Errorf("#%d: got = %v, want %v", i, got, tt.want) - } - if tt.unscaled.Cmp(old) != 0 { - t.Errorf("#%d: unscaled = %v, want %v", i, tt.unscaled, old) - } - } -} - -func BenchmarkScaledValueSmall(b *testing.B) { - s := big.NewInt(1000) - for i := 0; i < b.N; i++ { - scaledValue(s, 3, 0) - } -} - -func BenchmarkScaledValueLarge(b *testing.B) { - s := big.NewInt(math.MaxInt64) - s.Mul(s, big.NewInt(1000)) - for i := 0; i < b.N; i++ { - scaledValue(s, 10, 0) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource_helpers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource_helpers_test.go deleted file mode 100644 index 12c0ce7db..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/resource_helpers_test.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 api - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api/resource" -) - -func TestResourceHelpers(t *testing.T) { - cpuLimit := resource.MustParse("10") - memoryLimit := resource.MustParse("10G") - resourceSpec := ResourceRequirements{ - Limits: ResourceList{ - "cpu": cpuLimit, - "memory": memoryLimit, - "kube.io/storage": memoryLimit, - }, - } - if res := resourceSpec.Limits.Cpu(); *res != cpuLimit { - t.Errorf("expected cpulimit %v, got %v", cpuLimit, res) - } - if res := resourceSpec.Limits.Memory(); *res != memoryLimit { - t.Errorf("expected memorylimit %v, got %v", memoryLimit, res) - } - resourceSpec = ResourceRequirements{ - Limits: ResourceList{ - "memory": memoryLimit, - "kube.io/storage": memoryLimit, - }, - } - if res := resourceSpec.Limits.Cpu(); res.Value() != 0 { - t.Errorf("expected cpulimit %v, got %v", 0, res) - } - if res := resourceSpec.Limits.Memory(); *res != memoryLimit { - t.Errorf("expected memorylimit %v, got %v", memoryLimit, res) - } -} - -func TestDefaultResourceHelpers(t *testing.T) { - resourceList := ResourceList{} - if resourceList.Cpu().Format != resource.DecimalSI { - t.Errorf("expected %v, actual %v", resource.DecimalSI, resourceList.Cpu().Format) - } - if resourceList.Memory().Format != resource.BinarySI { - t.Errorf("expected %v, actual %v", resource.BinarySI, resourceList.Memory().Format) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/rest/resttest/resttest.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/rest/resttest/resttest.go deleted file mode 100644 index bd0a36475..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/rest/resttest/resttest.go +++ /dev/null @@ -1,1064 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 resttest - -import ( - "fmt" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/rest" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/wait" -) - -type Tester struct { - *testing.T - storage rest.Storage - clusterScope bool - createOnUpdate bool - generatesName bool - returnDeletedObject bool -} - -func New(t *testing.T, storage rest.Storage) *Tester { - return &Tester{ - T: t, - storage: storage, - } -} - -func (t *Tester) ClusterScope() *Tester { - t.clusterScope = true - return t -} - -func (t *Tester) AllowCreateOnUpdate() *Tester { - t.createOnUpdate = true - return t -} - -func (t *Tester) GeneratesName() *Tester { - t.generatesName = true - return t -} - -func (t *Tester) ReturnDeletedObject() *Tester { - t.returnDeletedObject = true - return t -} - -// TestNamespace returns the namespace that will be used when creating contexts. -// Returns NamespaceNone for cluster-scoped objects. -func (t *Tester) TestNamespace() string { - if t.clusterScope { - return api.NamespaceNone - } - return "test" -} - -// TestContext returns a namespaced context that will be used when making storage calls. -// Namespace is determined by TestNamespace() -func (t *Tester) TestContext() api.Context { - if t.clusterScope { - return api.NewContext() - } - return api.WithNamespace(api.NewContext(), t.TestNamespace()) -} - -func (t *Tester) getObjectMetaOrFail(obj runtime.Object) *api.ObjectMeta { - meta, err := api.ObjectMetaFor(obj) - if err != nil { - t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj) - } - return meta -} - -func (t *Tester) setObjectMeta(obj runtime.Object, name string) { - meta := t.getObjectMetaOrFail(obj) - meta.Name = name - if t.clusterScope { - meta.Namespace = api.NamespaceNone - } else { - meta.Namespace = api.NamespaceValue(t.TestContext()) - } - meta.GenerateName = "" -} - -func copyOrDie(obj runtime.Object) runtime.Object { - out, err := api.Scheme.Copy(obj) - if err != nil { - panic(err) - } - return out -} - -type AssignFunc func([]runtime.Object) []runtime.Object -type EmitFunc func(runtime.Object, string) error -type GetFunc func(api.Context, runtime.Object) (runtime.Object, error) -type InitWatchFunc func() -type InjectErrFunc func(err error) -type IsErrorFunc func(err error) bool -type CreateFunc func(api.Context, runtime.Object) error -type SetRVFunc func(uint64) -type UpdateFunc func(runtime.Object) runtime.Object - -// Test creating an object. -func (t *Tester) TestCreate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, invalid ...runtime.Object) { - t.testCreateHasMetadata(copyOrDie(valid)) - if !t.generatesName { - t.testCreateGeneratesName(copyOrDie(valid)) - } - t.testCreateEquals(copyOrDie(valid), getFn) - t.testCreateAlreadyExisting(copyOrDie(valid), createFn) - if t.clusterScope { - t.testCreateDiscardsObjectNamespace(copyOrDie(valid)) - t.testCreateIgnoresContextNamespace(copyOrDie(valid)) - t.testCreateIgnoresMismatchedNamespace(copyOrDie(valid)) - } else { - t.testCreateRejectsMismatchedNamespace(copyOrDie(valid)) - } - t.testCreateInvokesValidation(invalid...) - t.testCreateValidatesNames(copyOrDie(valid)) -} - -// Test updating an object. -func (t *Tester) TestUpdate(valid runtime.Object, createFn CreateFunc, getFn GetFunc, updateFn UpdateFunc, invalidUpdateFn ...UpdateFunc) { - t.testUpdateEquals(copyOrDie(valid), createFn, getFn, updateFn) - t.testUpdateFailsOnVersionTooOld(copyOrDie(valid), createFn, getFn) - t.testUpdateOnNotFound(copyOrDie(valid)) - if !t.clusterScope { - t.testUpdateRejectsMismatchedNamespace(copyOrDie(valid), createFn) - } - t.testUpdateInvokesValidation(copyOrDie(valid), createFn, invalidUpdateFn...) - t.testUpdateWithWrongUID(copyOrDie(valid), createFn, getFn) -} - -// Test deleting an object. -func (t *Tester) TestDelete(valid runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) { - t.testDeleteNonExist(copyOrDie(valid)) - t.testDeleteNoGraceful(copyOrDie(valid), createFn, getFn, isNotFoundFn) - t.testDeleteWithUID(copyOrDie(valid), createFn, getFn, isNotFoundFn) -} - -// Test gracefully deleting an object. -func (t *Tester) TestDeleteGraceful(valid runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) { - t.testDeleteGracefulHasDefault(copyOrDie(valid), createFn, getFn, expectedGrace) - t.testDeleteGracefulWithValue(copyOrDie(valid), createFn, getFn, expectedGrace) - t.testDeleteGracefulUsesZeroOnNil(copyOrDie(valid), createFn, expectedGrace) - t.testDeleteGracefulExtend(copyOrDie(valid), createFn, getFn, expectedGrace) - t.testDeleteGracefulImmediate(copyOrDie(valid), createFn, getFn, expectedGrace) -} - -// Test getting object. -func (t *Tester) TestGet(valid runtime.Object) { - t.testGetFound(copyOrDie(valid)) - t.testGetNotFound(copyOrDie(valid)) - t.testGetMimatchedNamespace(copyOrDie(valid)) - if !t.clusterScope { - t.testGetDifferentNamespace(copyOrDie(valid)) - } -} - -// Test listing objects. -func (t *Tester) TestList(valid runtime.Object, assignFn AssignFunc) { - t.testListNotFound(assignFn) - t.testListFound(copyOrDie(valid), assignFn) - t.testListMatchLabels(copyOrDie(valid), assignFn) -} - -// Test watching objects. -func (t *Tester) TestWatch( - valid runtime.Object, emitFn EmitFunc, - labelsPass, labelsFail []labels.Set, fieldsPass, fieldsFail []fields.Set, actions []string) { - t.testWatchLabels(copyOrDie(valid), emitFn, labelsPass, labelsFail, actions) - t.testWatchFields(copyOrDie(valid), emitFn, fieldsPass, fieldsFail, actions) -} - -// ============================================================================= -// Creation tests. - -func (t *Tester) testCreateAlreadyExisting(obj runtime.Object, createFn CreateFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo1") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - - _, err := t.storage.(rest.Creater).Create(ctx, foo) - if !errors.IsAlreadyExists(err) { - t.Errorf("expected already exists err, got %v", err) - } -} - -func (t *Tester) testCreateEquals(obj runtime.Object, getFn GetFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo2") - - created, err := t.storage.(rest.Creater).Create(ctx, foo) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - got, err := getFn(ctx, foo) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - // Set resource version which might be unset in created object. - createdMeta := t.getObjectMetaOrFail(created) - gotMeta := t.getObjectMetaOrFail(got) - createdMeta.ResourceVersion = gotMeta.ResourceVersion - - if e, a := created, got; !api.Semantic.DeepEqual(e, a) { - t.Errorf("unexpected obj: %#v, expected %#v", e, a) - } -} - -func (t *Tester) testCreateDiscardsObjectNamespace(valid runtime.Object) { - objectMeta := t.getObjectMetaOrFail(valid) - - // Ignore non-empty namespace in object meta - objectMeta.Namespace = "not-default" - - // Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted - created, err := t.storage.(rest.Creater).Create(t.TestContext(), copyOrDie(valid)) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - createdObjectMeta := t.getObjectMetaOrFail(created) - if createdObjectMeta.Namespace != api.NamespaceNone { - t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace) - } -} - -func (t *Tester) testCreateGeneratesName(valid runtime.Object) { - objectMeta := t.getObjectMetaOrFail(valid) - objectMeta.Name = "" - objectMeta.GenerateName = "test-" - - _, err := t.storage.(rest.Creater).Create(t.TestContext(), valid) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if objectMeta.Name == "test-" || !strings.HasPrefix(objectMeta.Name, "test-") { - t.Errorf("unexpected name: %#v", valid) - } -} - -func (t *Tester) testCreateHasMetadata(valid runtime.Object) { - objectMeta := t.getObjectMetaOrFail(valid) - objectMeta.Name = "" - objectMeta.GenerateName = "test-" - objectMeta.Namespace = t.TestNamespace() - - obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if obj == nil { - t.Fatalf("Unexpected object from result: %#v", obj) - } - if !api.HasObjectMetaSystemFieldValues(objectMeta) { - t.Errorf("storage did not populate object meta field values") - } -} - -func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object) { - // Ignore non-empty namespace in context - ctx := api.WithNamespace(api.NewContext(), "not-default2") - - // Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted - created, err := t.storage.(rest.Creater).Create(ctx, copyOrDie(valid)) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - createdObjectMeta := t.getObjectMetaOrFail(created) - if createdObjectMeta.Namespace != api.NamespaceNone { - t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace) - } -} - -func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object) { - objectMeta := t.getObjectMetaOrFail(valid) - - // Ignore non-empty namespace in object meta - objectMeta.Namespace = "not-default" - ctx := api.WithNamespace(api.NewContext(), "not-default2") - - // Ideally, we'd get an error back here, but at least verify the namespace wasn't persisted - created, err := t.storage.(rest.Creater).Create(ctx, copyOrDie(valid)) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - createdObjectMeta := t.getObjectMetaOrFail(created) - if createdObjectMeta.Namespace != api.NamespaceNone { - t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace) - } -} - -func (t *Tester) testCreateValidatesNames(valid runtime.Object) { - for _, invalidName := range validation.NameMayNotBe { - objCopy := copyOrDie(valid) - objCopyMeta := t.getObjectMetaOrFail(objCopy) - objCopyMeta.Name = invalidName - - ctx := t.TestContext() - _, err := t.storage.(rest.Creater).Create(ctx, objCopy) - if !errors.IsInvalid(err) { - t.Errorf("%s: Expected to get an invalid resource error, got %v", invalidName, err) - } - } - - for _, invalidSuffix := range validation.NameMayNotContain { - objCopy := copyOrDie(valid) - objCopyMeta := t.getObjectMetaOrFail(objCopy) - objCopyMeta.Name += invalidSuffix - - ctx := t.TestContext() - _, err := t.storage.(rest.Creater).Create(ctx, objCopy) - if !errors.IsInvalid(err) { - t.Errorf("%s: Expected to get an invalid resource error, got %v", invalidSuffix, err) - } - } -} - -func (t *Tester) testCreateInvokesValidation(invalid ...runtime.Object) { - for i, obj := range invalid { - ctx := t.TestContext() - _, err := t.storage.(rest.Creater).Create(ctx, obj) - if !errors.IsInvalid(err) { - t.Errorf("%d: Expected to get an invalid resource error, got %v", i, err) - } - } -} - -func (t *Tester) testCreateRejectsMismatchedNamespace(valid runtime.Object) { - objectMeta := t.getObjectMetaOrFail(valid) - objectMeta.Namespace = "not-default" - - _, err := t.storage.(rest.Creater).Create(t.TestContext(), valid) - if err == nil { - t.Errorf("Expected an error, but we didn't get one") - } else if !strings.Contains(err.Error(), "does not match the namespace sent on the request") { - t.Errorf("Expected 'does not match the namespace sent on the request' error, got '%v'", err.Error()) - } -} - -func (t *Tester) testCreateResetsUserData(valid runtime.Object) { - objectMeta := t.getObjectMetaOrFail(valid) - now := unversioned.Now() - objectMeta.UID = "bad-uid" - objectMeta.CreationTimestamp = now - - obj, err := t.storage.(rest.Creater).Create(t.TestContext(), valid) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if obj == nil { - t.Fatalf("Unexpected object from result: %#v", obj) - } - if objectMeta.UID == "bad-uid" || objectMeta.CreationTimestamp == now { - t.Errorf("ObjectMeta did not reset basic fields: %#v", objectMeta) - } -} - -// ============================================================================= -// Update tests. - -func (t *Tester) testUpdateEquals(obj runtime.Object, createFn CreateFunc, getFn GetFunc, updateFn UpdateFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo2") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - - toUpdate, err := getFn(ctx, foo) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - toUpdate = updateFn(toUpdate) - updated, created, err := t.storage.(rest.Updater).Update(ctx, toUpdate) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if created { - t.Errorf("unexpected creation") - } - got, err := getFn(ctx, foo) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - // Set resource version which might be unset in created object. - updatedMeta := t.getObjectMetaOrFail(updated) - gotMeta := t.getObjectMetaOrFail(got) - updatedMeta.ResourceVersion = gotMeta.ResourceVersion - - if e, a := updated, got; !api.Semantic.DeepEqual(e, a) { - t.Errorf("unexpected obj: %#v, expected %#v", e, a) - } -} - -func (t *Tester) testUpdateFailsOnVersionTooOld(obj runtime.Object, createFn CreateFunc, getFn GetFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo3") - - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - - storedFoo, err := getFn(ctx, foo) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - older := copyOrDie(storedFoo) - olderMeta := t.getObjectMetaOrFail(older) - olderMeta.ResourceVersion = "1" - - _, _, err = t.storage.(rest.Updater).Update(t.TestContext(), older) - if err == nil { - t.Errorf("Expected an error, but we didn't get one") - } else if !errors.IsConflict(err) { - t.Errorf("Expected Conflict error, got '%v'", err) - } -} - -func (t *Tester) testUpdateInvokesValidation(obj runtime.Object, createFn CreateFunc, invalidUpdateFn ...UpdateFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo4") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - - for _, update := range invalidUpdateFn { - toUpdate := update(copyOrDie(foo)) - got, created, err := t.storage.(rest.Updater).Update(t.TestContext(), toUpdate) - if got != nil || created { - t.Errorf("expected nil object and no creation for object: %v", toUpdate) - } - if !errors.IsInvalid(err) && !errors.IsBadRequest(err) { - t.Errorf("expected invalid or bad request error, got %v", err) - } - } -} - -func (t *Tester) testUpdateWithWrongUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc) { - ctx := t.TestContext() - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo5") - objectMeta := t.getObjectMetaOrFail(foo) - objectMeta.UID = types.UID("UID0000") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - objectMeta.UID = types.UID("UID1111") - - obj, created, err := t.storage.(rest.Updater).Update(ctx, foo) - if created || obj != nil { - t.Errorf("expected nil object and no creation for object: %v", foo) - } - if err == nil || !errors.IsConflict(err) { - t.Errorf("unexpected error: %v", err) - } -} - -func (t *Tester) testUpdateOnNotFound(obj runtime.Object) { - t.setObjectMeta(obj, "foo") - _, created, err := t.storage.(rest.Updater).Update(t.TestContext(), obj) - if t.createOnUpdate { - if err != nil { - t.Errorf("creation allowed on updated, but got an error: %v", err) - } - if !created { - t.Errorf("creation allowed on update, but object not created") - } - } else { - if err == nil { - t.Errorf("Expected an error, but we didn't get one") - } else if !errors.IsNotFound(err) { - t.Errorf("Expected NotFound error, got '%v'", err) - } - } -} - -func (t *Tester) testUpdateRejectsMismatchedNamespace(obj runtime.Object, createFn CreateFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo1") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - - objectMeta := t.getObjectMetaOrFail(obj) - objectMeta.Name = "foo1" - objectMeta.Namespace = "not-default" - - obj, updated, err := t.storage.(rest.Updater).Update(t.TestContext(), obj) - if obj != nil || updated { - t.Errorf("expected nil object and not updated") - } - if err == nil { - t.Errorf("expected an error, but didn't get one") - } else if !strings.Contains(err.Error(), "does not match the namespace sent on the request") { - t.Errorf("expected 'does not match the namespace sent on the request' error, got '%v'", err.Error()) - } -} - -// ============================================================================= -// Deletion tests. - -func (t *Tester) testDeleteNoGraceful(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo1") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - objectMeta := t.getObjectMetaOrFail(foo) - obj, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(10)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !t.returnDeletedObject { - if status, ok := obj.(*unversioned.Status); !ok { - t.Errorf("expected status of delete, got %v", status) - } else if status.Status != unversioned.StatusSuccess { - t.Errorf("expected success, got: %v", status.Status) - } - } - - _, err = getFn(ctx, foo) - if err == nil || !isNotFoundFn(err) { - t.Errorf("unexpected error: %v", err) - } -} - -func (t *Tester) testDeleteNonExist(obj runtime.Object) { - objectMeta := t.getObjectMetaOrFail(obj) - - _, err := t.storage.(rest.GracefulDeleter).Delete(t.TestContext(), objectMeta.Name, nil) - if err == nil || !errors.IsNotFound(err) { - t.Errorf("unexpected error: %v", err) - } - -} - -// This test the fast-fail path. We test that the precondition gets verified -// again before deleting the object in tests of pkg/storage/etcd. -func (t *Tester) testDeleteWithUID(obj runtime.Object, createFn CreateFunc, getFn GetFunc, isNotFoundFn IsErrorFunc) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo1") - objectMeta := t.getObjectMetaOrFail(foo) - objectMeta.UID = types.UID("UID0000") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - obj, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewPreconditionDeleteOptions("UID1111")) - if err == nil || !errors.IsConflict(err) { - t.Errorf("unexpected error: %v", err) - } - - obj, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewPreconditionDeleteOptions("UID0000")) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if !t.returnDeletedObject { - if status, ok := obj.(*unversioned.Status); !ok { - t.Errorf("expected status of delete, got %v", status) - } else if status.Status != unversioned.StatusSuccess { - t.Errorf("expected success, got: %v", status.Status) - } - } - - _, err = getFn(ctx, foo) - if err == nil || !isNotFoundFn(err) { - t.Errorf("unexpected error: %v", err) - } -} - -// ============================================================================= -// Graceful Deletion tests. - -func (t *Tester) testDeleteGracefulHasDefault(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo1") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - objectMeta := t.getObjectMetaOrFail(foo) - _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, &api.DeleteOptions{}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if _, err := getFn(ctx, foo); err != nil { - t.Fatalf("did not gracefully delete resource: %v", err) - } - - object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name) - if err != nil { - t.Fatalf("unexpected error, object should exist: %v", err) - } - objectMeta = t.getObjectMetaOrFail(object) - if objectMeta.DeletionTimestamp == nil || objectMeta.DeletionGracePeriodSeconds == nil || *objectMeta.DeletionGracePeriodSeconds != expectedGrace { - t.Errorf("unexpected deleted meta: %#v", objectMeta) - } -} - -func (t *Tester) testDeleteGracefulWithValue(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo2") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - objectMeta := t.getObjectMetaOrFail(foo) - _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace+2)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if _, err := getFn(ctx, foo); err != nil { - t.Fatalf("did not gracefully delete resource: %v", err) - } - - object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name) - if err != nil { - t.Errorf("unexpected error, object should exist: %v", err) - } - objectMeta = t.getObjectMetaOrFail(object) - if objectMeta.DeletionTimestamp == nil || objectMeta.DeletionGracePeriodSeconds == nil || *objectMeta.DeletionGracePeriodSeconds != expectedGrace+2 { - t.Errorf("unexpected deleted meta: %#v", objectMeta) - } -} - -func (t *Tester) testDeleteGracefulExtend(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo3") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - objectMeta := t.getObjectMetaOrFail(foo) - _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if _, err := getFn(ctx, foo); err != nil { - t.Fatalf("did not gracefully delete resource: %v", err) - } - - // second delete duration is ignored - _, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace+2)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - object, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name) - if err != nil { - t.Errorf("unexpected error, object should exist: %v", err) - } - objectMeta = t.getObjectMetaOrFail(object) - if objectMeta.DeletionTimestamp == nil || objectMeta.DeletionGracePeriodSeconds == nil || *objectMeta.DeletionGracePeriodSeconds != expectedGrace { - t.Errorf("unexpected deleted meta: %#v", objectMeta) - } -} - -func (t *Tester) testDeleteGracefulImmediate(obj runtime.Object, createFn CreateFunc, getFn GetFunc, expectedGrace int64) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo4") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - objectMeta := t.getObjectMetaOrFail(foo) - _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if _, err := getFn(ctx, foo); err != nil { - t.Fatalf("did not gracefully delete resource: %v", err) - } - - // second delete is immediate, resource is deleted - out, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(0)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - _, err = t.storage.(rest.Getter).Get(ctx, objectMeta.Name) - if !errors.IsNotFound(err) { - t.Errorf("unexpected error, object should be deleted immediately: %v", err) - } - objectMeta = t.getObjectMetaOrFail(out) - // the second delete shouldn't update the object, so the objectMeta.DeletionGracePeriodSeconds should eqaul to the value set in the first delete. - if objectMeta.DeletionTimestamp == nil || objectMeta.DeletionGracePeriodSeconds == nil || *objectMeta.DeletionGracePeriodSeconds != 0 { - t.Errorf("unexpected deleted meta: %#v", objectMeta) - } -} - -func (t *Tester) testDeleteGracefulUsesZeroOnNil(obj runtime.Object, createFn CreateFunc, expectedGrace int64) { - ctx := t.TestContext() - - foo := copyOrDie(obj) - t.setObjectMeta(foo, "foo5") - if err := createFn(ctx, foo); err != nil { - t.Errorf("unexpected error: %v", err) - } - objectMeta := t.getObjectMetaOrFail(foo) - _, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, nil) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if _, err := t.storage.(rest.Getter).Get(ctx, objectMeta.Name); !errors.IsNotFound(err) { - t.Errorf("unexpected error, object should not exist: %v", err) - } -} - -// ============================================================================= -// Get tests. - -// testGetDifferentNamespace ensures same-name objects in different namespaces do not clash -func (t *Tester) testGetDifferentNamespace(obj runtime.Object) { - if t.clusterScope { - t.Fatalf("the test does not work in in cluster-scope") - } - - objMeta := t.getObjectMetaOrFail(obj) - objMeta.Name = "foo5" - - ctx1 := api.WithNamespace(api.NewContext(), "bar3") - objMeta.Namespace = api.NamespaceValue(ctx1) - _, err := t.storage.(rest.Creater).Create(ctx1, obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - ctx2 := api.WithNamespace(api.NewContext(), "bar4") - objMeta.Namespace = api.NamespaceValue(ctx2) - _, err = t.storage.(rest.Creater).Create(ctx2, obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - got1, err := t.storage.(rest.Getter).Get(ctx1, objMeta.Name) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - got1Meta := t.getObjectMetaOrFail(got1) - if got1Meta.Name != objMeta.Name { - t.Errorf("unexpected name of object: %#v, expected: %s", got1, objMeta.Name) - } - if got1Meta.Namespace != api.NamespaceValue(ctx1) { - t.Errorf("unexpected namespace of object: %#v, expected: %s", got1, api.NamespaceValue(ctx1)) - } - - got2, err := t.storage.(rest.Getter).Get(ctx2, objMeta.Name) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - got2Meta := t.getObjectMetaOrFail(got2) - if got2Meta.Name != objMeta.Name { - t.Errorf("unexpected name of object: %#v, expected: %s", got2, objMeta.Name) - } - if got2Meta.Namespace != api.NamespaceValue(ctx2) { - t.Errorf("unexpected namespace of object: %#v, expected: %s", got2, api.NamespaceValue(ctx2)) - } -} - -func (t *Tester) testGetFound(obj runtime.Object) { - ctx := t.TestContext() - t.setObjectMeta(obj, "foo1") - - existing, err := t.storage.(rest.Creater).Create(ctx, obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - existingMeta := t.getObjectMetaOrFail(existing) - - got, err := t.storage.(rest.Getter).Get(ctx, "foo1") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - gotMeta := t.getObjectMetaOrFail(got) - gotMeta.ResourceVersion = existingMeta.ResourceVersion - if e, a := existing, got; !api.Semantic.DeepEqual(e, a) { - t.Errorf("unexpected obj: %#v, expected %#v", e, a) - } -} - -func (t *Tester) testGetMimatchedNamespace(obj runtime.Object) { - ctx1 := api.WithNamespace(api.NewContext(), "bar1") - ctx2 := api.WithNamespace(api.NewContext(), "bar2") - objMeta := t.getObjectMetaOrFail(obj) - objMeta.Name = "foo4" - objMeta.Namespace = api.NamespaceValue(ctx1) - _, err := t.storage.(rest.Creater).Create(ctx1, obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - _, err = t.storage.(rest.Getter).Get(ctx2, "foo4") - if t.clusterScope { - if err != nil { - t.Errorf("unexpected error: %v", err) - } - } else { - if !errors.IsNotFound(err) { - t.Errorf("unexpected error returned: %#v", err) - } - } -} - -func (t *Tester) testGetNotFound(obj runtime.Object) { - ctx := t.TestContext() - t.setObjectMeta(obj, "foo2") - _, err := t.storage.(rest.Creater).Create(ctx, obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - _, err = t.storage.(rest.Getter).Get(ctx, "foo3") - if !errors.IsNotFound(err) { - t.Errorf("unexpected error returned: %#v", err) - } -} - -// ============================================================================= -// List tests. - -func listToItems(listObj runtime.Object) ([]runtime.Object, error) { - v, err := conversion.EnforcePtr(listObj) - if err != nil { - return nil, fmt.Errorf("unexpected error: %v", err) - } - items := v.FieldByName("Items") - if !items.IsValid() { - return nil, fmt.Errorf("unexpected Items field in %v", listObj) - } - if items.Type().Kind() != reflect.Slice { - return nil, fmt.Errorf("unexpected Items field type: %v", items.Type().Kind()) - } - result := make([]runtime.Object, items.Len()) - for i := 0; i < items.Len(); i++ { - result[i] = items.Index(i).Addr().Interface().(runtime.Object) - } - return result, nil -} - -func (t *Tester) testListFound(obj runtime.Object, assignFn AssignFunc) { - ctx := t.TestContext() - - foo1 := copyOrDie(obj) - t.setObjectMeta(foo1, "foo1") - foo2 := copyOrDie(obj) - t.setObjectMeta(foo2, "foo2") - - existing := assignFn([]runtime.Object{foo1, foo2}) - - listObj, err := t.storage.(rest.Lister).List(ctx, nil) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - items, err := listToItems(listObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(items) != len(existing) { - t.Errorf("unexpected number of items: %v", len(items)) - } - if !api.Semantic.DeepEqual(existing, items) { - t.Errorf("expected: %#v, got: %#v", existing, items) - } -} - -func (t *Tester) testListMatchLabels(obj runtime.Object, assignFn AssignFunc) { - ctx := t.TestContext() - testLabels := map[string]string{"key": "value"} - - foo3 := copyOrDie(obj) - t.setObjectMeta(foo3, "foo3") - foo4 := copyOrDie(obj) - foo4Meta := t.getObjectMetaOrFail(foo4) - foo4Meta.Name = "foo4" - foo4Meta.Namespace = api.NamespaceValue(ctx) - foo4Meta.Labels = testLabels - - objs := ([]runtime.Object{foo3, foo4}) - - assignFn(objs) - filtered := []runtime.Object{objs[1]} - - selector := labels.SelectorFromSet(labels.Set(testLabels)) - options := &api.ListOptions{LabelSelector: selector} - listObj, err := t.storage.(rest.Lister).List(ctx, options) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - items, err := listToItems(listObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(items) != len(filtered) { - t.Errorf("unexpected number of items: %v", len(items)) - } - if !api.Semantic.DeepEqual(filtered, items) { - t.Errorf("expected: %#v, got: %#v", filtered, items) - } -} - -func (t *Tester) testListNotFound(assignFn AssignFunc) { - ctx := t.TestContext() - _ = assignFn([]runtime.Object{}) - - listObj, err := t.storage.(rest.Lister).List(ctx, nil) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - items, err := listToItems(listObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(items) != 0 { - t.Errorf("unexpected items: %#v", items) - } -} - -// ============================================================================= -// Watching tests. - -func (t *Tester) testWatchFields(obj runtime.Object, emitFn EmitFunc, fieldsPass, fieldsFail []fields.Set, actions []string) { - ctx := t.TestContext() - - for _, field := range fieldsPass { - for _, action := range actions { - options := &api.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"} - watcher, err := t.storage.(rest.Watcher).Watch(ctx, options) - if err != nil { - t.Errorf("unexpected error: %v, %v", err, action) - } - - if err := emitFn(obj, action); err != nil { - t.Errorf("unexpected error: %v", err) - } - - select { - case _, ok := <-watcher.ResultChan(): - if !ok { - t.Errorf("watch channel should be open") - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("unexpected timeout from result channel") - } - watcher.Stop() - } - } - - for _, field := range fieldsFail { - for _, action := range actions { - options := &api.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"} - watcher, err := t.storage.(rest.Watcher).Watch(ctx, options) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := emitFn(obj, action); err != nil { - t.Errorf("unexpected error: %v", err) - } - - select { - case <-watcher.ResultChan(): - t.Errorf("unexpected result from result channel") - case <-time.After(time.Millisecond * 500): - // expected case - } - watcher.Stop() - } - } -} - -func (t *Tester) testWatchLabels(obj runtime.Object, emitFn EmitFunc, labelsPass, labelsFail []labels.Set, actions []string) { - ctx := t.TestContext() - - for _, label := range labelsPass { - for _, action := range actions { - options := &api.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"} - watcher, err := t.storage.(rest.Watcher).Watch(ctx, options) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := emitFn(obj, action); err != nil { - t.Errorf("unexpected error: %v", err) - } - - select { - case _, ok := <-watcher.ResultChan(): - if !ok { - t.Errorf("watch channel should be open") - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("unexpected timeout from result channel") - } - watcher.Stop() - } - } - - for _, label := range labelsFail { - for _, action := range actions { - options := &api.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"} - watcher, err := t.storage.(rest.Watcher).Watch(ctx, options) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := emitFn(obj, action); err != nil { - t.Errorf("unexpected error: %v", err) - } - - select { - case <-watcher.ResultChan(): - t.Errorf("unexpected result from result channel") - case <-time.After(time.Millisecond * 500): - // expected case - } - watcher.Stop() - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/serialization_proto_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/serialization_proto_test.go deleted file mode 100644 index e35708340..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/serialization_proto_test.go +++ /dev/null @@ -1,182 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 api_test - -import ( - "bytes" - "encoding/hex" - "math/rand" - "testing" - - "github.com/gogo/protobuf/proto" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - _ "k8s.io/kubernetes/pkg/apis/extensions" - _ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/protobuf" - "k8s.io/kubernetes/pkg/util/diff" -) - -func init() { - codecsToTest = append(codecsToTest, func(version unversioned.GroupVersion, item runtime.Object) (runtime.Codec, error) { - s := protobuf.NewSerializer(api.Scheme, runtime.ObjectTyperToTyper(api.Scheme), "application/arbitrary.content.type") - return api.Codecs.CodecForVersions(s, s, testapi.ExternalGroupVersions(), nil), nil - }) -} - -func TestUniversalDeserializer(t *testing.T) { - expected := &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "test"}} - d := api.Codecs.UniversalDeserializer() - for _, mediaType := range []string{"application/json", "application/yaml", "application/vnd.kubernetes.protobuf"} { - e, ok := api.Codecs.SerializerForMediaType(mediaType, nil) - if !ok { - t.Fatal(mediaType) - } - buf := &bytes.Buffer{} - if err := e.EncodeToStream(expected, buf); err != nil { - t.Fatalf("%s: %v", mediaType, err) - } - obj, _, err := d.Decode(buf.Bytes(), &unversioned.GroupVersionKind{Kind: "Pod", Version: "v1"}, nil) - if err != nil { - t.Fatalf("%s: %v", mediaType, err) - } - if !api.Semantic.DeepEqual(expected, obj) { - t.Fatalf("%s: %#v", mediaType, obj) - } - } -} - -func TestProtobufRoundTrip(t *testing.T) { - obj := &v1.Pod{} - apitesting.FuzzerFor(t, v1.SchemeGroupVersion, rand.NewSource(benchmarkSeed)).Fuzz(obj) - data, err := obj.Marshal() - if err != nil { - t.Fatal(err) - } - out := &v1.Pod{} - if err := out.Unmarshal(data); err != nil { - t.Fatal(err) - } - if !api.Semantic.Equalities.DeepEqual(out, obj) { - t.Logf("marshal\n%s", hex.Dump(data)) - t.Fatalf("Unmarshal is unequal\n%s", diff.ObjectGoPrintSideBySide(out, obj)) - } -} - -// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes -// reflection (to clear APIVersion and Kind) -func BenchmarkEncodeCodecProtobuf(b *testing.B) { - items := benchmarkItems() - width := len(items) - s := protobuf.NewSerializer(nil, nil, "application/arbitrary.content.type") - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := runtime.Encode(s, &items[i%width]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -// BenchmarkEncodeCodecFromInternalProtobuf measures the cost of performing a codec encode, -// including conversions and any type setting. This is a "full" encode. -func BenchmarkEncodeCodecFromInternalProtobuf(b *testing.B) { - items := benchmarkItems() - width := len(items) - encodable := make([]api.Pod, width) - for i := range items { - if err := api.Scheme.Convert(&items[i], &encodable[i]); err != nil { - b.Fatal(err) - } - } - s := protobuf.NewSerializer(nil, nil, "application/arbitrary.content.type") - codec := api.Codecs.EncoderForVersion(s, v1.SchemeGroupVersion) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := runtime.Encode(codec, &encodable[i%width]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkEncodeProtobufGeneratedMarshal(b *testing.B) { - items := benchmarkItems() - width := len(items) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := items[i%width].Marshal(); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -// BenchmarkDecodeCodecToInternalProtobuf measures the cost of performing a codec decode, -// including conversions and any type setting. This is a "full" decode. -func BenchmarkDecodeCodecToInternalProtobuf(b *testing.B) { - items := benchmarkItems() - width := len(items) - s := protobuf.NewSerializer(api.Scheme, runtime.ObjectTyperToTyper(api.Scheme), "application/arbitrary.content.type") - encoder := api.Codecs.EncoderForVersion(s, v1.SchemeGroupVersion) - var encoded [][]byte - for i := range items { - data, err := runtime.Encode(encoder, &items[i]) - if err != nil { - b.Fatal(err) - } - encoded = append(encoded, data) - } - - decoder := api.Codecs.DecoderToVersion(s, api.SchemeGroupVersion) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := runtime.Decode(decoder, encoded[i%width]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance -func BenchmarkDecodeIntoProtobuf(b *testing.B) { - items := benchmarkItems() - width := len(items) - encoded := make([][]byte, width) - for i := range items { - data, err := (&items[i]).Marshal() - if err != nil { - b.Fatal(err) - } - encoded[i] = data - validate := &v1.Pod{} - if err := proto.Unmarshal(data, validate); err != nil { - b.Fatalf("Failed to unmarshal %d: %v\n%#v", i, err, items[i]) - } - } - - for i := 0; i < b.N; i++ { - obj := v1.Pod{} - if err := proto.Unmarshal(encoded[i%width], &obj); err != nil { - b.Fatal(err) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/serialization_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/serialization_test.go deleted file mode 100644 index e52e965bd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/serialization_test.go +++ /dev/null @@ -1,532 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 api_test - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "io/ioutil" - "math/rand" - "reflect" - "strings" - "testing" - - "github.com/davecgh/go-spew/spew" - proto "github.com/golang/protobuf/proto" - flag "github.com/spf13/pflag" - "github.com/ugorji/go/codec" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/streaming" - "k8s.io/kubernetes/pkg/util/diff" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/watch" - "k8s.io/kubernetes/pkg/watch/versioned" -) - -var fuzzIters = flag.Int("fuzz-iters", 20, "How many fuzzing iterations to do.") - -var codecsToTest = []func(version unversioned.GroupVersion, item runtime.Object) (runtime.Codec, error){ - func(version unversioned.GroupVersion, item runtime.Object) (runtime.Codec, error) { - return testapi.GetCodecForObject(item) - }, -} - -func fuzzInternalObject(t *testing.T, forVersion unversioned.GroupVersion, item runtime.Object, seed int64) runtime.Object { - apitesting.FuzzerFor(t, forVersion, rand.NewSource(seed)).Fuzz(item) - - j, err := meta.TypeAccessor(item) - if err != nil { - t.Fatalf("Unexpected error %v for %#v", err, item) - } - j.SetKind("") - j.SetAPIVersion("") - - return item -} - -func dataAsString(data []byte) string { - dataString := string(data) - if !strings.HasPrefix(dataString, "{") { - dataString = "\n" + hex.Dump(data) - proto.NewBuffer(make([]byte, 0, 1024)).DebugPrint("decoded object", data) - } - return dataString -} - -func roundTrip(t *testing.T, codec runtime.Codec, item runtime.Object) { - printer := spew.ConfigState{DisableMethods: true} - - name := reflect.TypeOf(item).Elem().Name() - data, err := runtime.Encode(codec, item) - if err != nil { - t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", item)) - return - } - - obj2, err := runtime.Decode(codec, data) - if err != nil { - t.Errorf("0: %v: %v\nCodec: %v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), printer.Sprintf("%#v", item)) - panic("failed") - } - if !api.Semantic.DeepEqual(item, obj2) { - t.Errorf("\n1: %v: diff: %v\nCodec: %v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectGoPrintDiff(item, obj2), codec, printer.Sprintf("%#v", item), dataAsString(data), printer.Sprintf("%#v", obj2)) - return - } - - obj3 := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) - if err := runtime.DecodeInto(codec, data, obj3); err != nil { - t.Errorf("2: %v: %v", name, err) - return - } - if !api.Semantic.DeepEqual(item, obj3) { - t.Errorf("3: %v: diff: %v\nCodec: %v", name, diff.ObjectDiff(item, obj3), codec) - return - } -} - -// roundTripSame verifies the same source object is tested in all API versions. -func roundTripSame(t *testing.T, group testapi.TestGroup, item runtime.Object, except ...string) { - set := sets.NewString(except...) - seed := rand.Int63() - fuzzInternalObject(t, group.InternalGroupVersion(), item, seed) - - version := *group.GroupVersion() - codecs := []runtime.Codec{} - for _, fn := range codecsToTest { - codec, err := fn(version, item) - if err != nil { - t.Errorf("unable to get codec: %v", err) - return - } - codecs = append(codecs, codec) - } - - if !set.Has(version.String()) { - fuzzInternalObject(t, version, item, seed) - for _, codec := range codecs { - roundTrip(t, codec, item) - } - } -} - -// For debugging problems -func TestSpecificKind(t *testing.T) { - kind := "DaemonSet" - for i := 0; i < *fuzzIters; i++ { - doRoundTripTest(testapi.Groups["extensions"], kind, t) - if t.Failed() { - break - } - } -} - -func TestList(t *testing.T) { - kind := "List" - item, err := api.Scheme.New(api.SchemeGroupVersion.WithKind(kind)) - if err != nil { - t.Errorf("Couldn't make a %v? %v", kind, err) - return - } - roundTripSame(t, testapi.Default, item) -} - -var nonRoundTrippableTypes = sets.NewString( - "ExportOptions", - // WatchEvent does not include kind and version and can only be deserialized - // implicitly (if the caller expects the specific object). The watch call defines - // the schema by content type, rather than via kind/version included in each - // object. - "WatchEvent", -) - -var nonInternalRoundTrippableTypes = sets.NewString("List", "ListOptions", "ExportOptions") -var nonRoundTrippableTypesByVersion = map[string][]string{} - -func TestRoundTripTypes(t *testing.T) { - for groupKey, group := range testapi.Groups { - for kind := range group.InternalTypes() { - t.Logf("working on %v in %v", kind, groupKey) - if nonRoundTrippableTypes.Has(kind) { - continue - } - // Try a few times, since runTest uses random values. - for i := 0; i < *fuzzIters; i++ { - doRoundTripTest(group, kind, t) - if t.Failed() { - break - } - } - } - } -} - -func doRoundTripTest(group testapi.TestGroup, kind string, t *testing.T) { - item, err := api.Scheme.New(group.InternalGroupVersion().WithKind(kind)) - if err != nil { - t.Fatalf("Couldn't make a %v? %v", kind, err) - } - if _, err := meta.TypeAccessor(item); err != nil { - t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) - } - if api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { - roundTripSame(t, group, item, nonRoundTrippableTypesByVersion[kind]...) - } - if !nonInternalRoundTrippableTypes.Has(kind) && api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { - roundTrip(t, group.Codec(), fuzzInternalObject(t, group.InternalGroupVersion(), item, rand.Int63())) - } -} - -func TestEncode_Ptr(t *testing.T) { - grace := int64(30) - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"name": "foo"}, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - - TerminationGracePeriodSeconds: &grace, - - SecurityContext: &api.PodSecurityContext{}, - }, - } - obj := runtime.Object(pod) - data, err := runtime.Encode(testapi.Default.Codec(), obj) - obj2, err2 := runtime.Decode(testapi.Default.Codec(), data) - if err != nil || err2 != nil { - t.Fatalf("Failure: '%v' '%v'", err, err2) - } - if _, ok := obj2.(*api.Pod); !ok { - t.Fatalf("Got wrong type") - } - if !api.Semantic.DeepEqual(obj2, pod) { - t.Errorf("\nExpected:\n\n %#v,\n\nGot:\n\n %#vDiff: %v\n\n", pod, obj2, diff.ObjectDiff(obj2, pod)) - - } -} - -func TestBadJSONRejection(t *testing.T) { - badJSONMissingKind := []byte(`{ }`) - if _, err := runtime.Decode(testapi.Default.Codec(), badJSONMissingKind); err == nil { - t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind) - } - badJSONUnknownType := []byte(`{"kind": "bar"}`) - if _, err1 := runtime.Decode(testapi.Default.Codec(), badJSONUnknownType); err1 == nil { - t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType) - } - /*badJSONKindMismatch := []byte(`{"kind": "Pod"}`) - if err2 := DecodeInto(badJSONKindMismatch, &Minion{}); err2 == nil { - t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch) - }*/ -} - -func TestUnversionedTypes(t *testing.T) { - testcases := []runtime.Object{ - &unversioned.Status{Status: "Failure", Message: "something went wrong"}, - &unversioned.APIVersions{Versions: []string{"A", "B", "C"}}, - &unversioned.APIGroupList{Groups: []unversioned.APIGroup{{Name: "mygroup"}}}, - &unversioned.APIGroup{Name: "mygroup"}, - &unversioned.APIResourceList{GroupVersion: "mygroup/myversion"}, - } - - for _, obj := range testcases { - // Make sure the unversioned codec can encode - unversionedJSON, err := runtime.Encode(testapi.Default.Codec(), obj) - if err != nil { - t.Errorf("%v: unexpected error: %v", obj, err) - continue - } - - // Make sure the versioned codec under test can decode - versionDecodedObject, err := runtime.Decode(testapi.Default.Codec(), unversionedJSON) - if err != nil { - t.Errorf("%v: unexpected error: %v", obj, err) - continue - } - // Make sure it decodes correctly - if !reflect.DeepEqual(obj, versionDecodedObject) { - t.Errorf("%v: expected %#v, got %#v", obj, obj, versionDecodedObject) - continue - } - } -} - -func TestObjectWatchFraming(t *testing.T) { - f := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) - secret := &api.Secret{} - f.Fuzz(secret) - secret.Data["binary"] = []byte{0x00, 0x10, 0x30, 0x55, 0xff, 0x00} - secret.Data["utf8"] = []byte("a string with \u0345 characters") - secret.Data["long"] = bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x00}, 1000) - converted, _ := api.Scheme.ConvertToVersion(secret, "v1") - v1secret := converted.(*v1.Secret) - for _, streamingMediaType := range api.Codecs.SupportedStreamingMediaTypes() { - s, _ := api.Codecs.StreamingSerializerForMediaType(streamingMediaType, nil) - framer := s.Framer - embedded := s.Embedded.Serializer - if embedded == nil { - t.Errorf("no embedded serializer for %s", streamingMediaType) - continue - } - innerDecode := api.Codecs.DecoderToVersion(embedded, api.SchemeGroupVersion) - - // write a single object through the framer and back out - obj := &bytes.Buffer{} - if err := s.EncodeToStream(v1secret, obj); err != nil { - t.Fatal(err) - } - out := &bytes.Buffer{} - w := framer.NewFrameWriter(out) - if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) { - t.Fatal(err) - } - sr := streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s) - resultSecret := &v1.Secret{} - res, _, err := sr.Decode(nil, resultSecret) - if err != nil { - t.Fatalf("%v:\n%s", err, hex.Dump(obj.Bytes())) - } - resultSecret.Kind = "Secret" - resultSecret.APIVersion = "v1" - if !api.Semantic.DeepEqual(v1secret, res) { - t.Fatalf("objects did not match: %s", diff.ObjectGoPrintDiff(v1secret, res)) - } - - // write a watch event through and back out - obj = &bytes.Buffer{} - if err := embedded.EncodeToStream(v1secret, obj); err != nil { - t.Fatal(err) - } - event := &versioned.Event{Type: string(watch.Added)} - event.Object.Raw = obj.Bytes() - obj = &bytes.Buffer{} - if err := s.EncodeToStream(event, obj); err != nil { - t.Fatal(err) - } - out = &bytes.Buffer{} - w = framer.NewFrameWriter(out) - if n, err := w.Write(obj.Bytes()); err != nil || n != len(obj.Bytes()) { - t.Fatal(err) - } - sr = streaming.NewDecoder(framer.NewFrameReader(ioutil.NopCloser(out)), s) - outEvent := &versioned.Event{} - res, _, err = sr.Decode(nil, outEvent) - if err != nil || outEvent.Type != string(watch.Added) { - t.Fatalf("%v: %#v", err, outEvent) - } - if outEvent.Object.Object == nil && outEvent.Object.Raw != nil { - outEvent.Object.Object, err = runtime.Decode(innerDecode, outEvent.Object.Raw) - if err != nil { - t.Fatalf("%v:\n%s", err, hex.Dump(outEvent.Object.Raw)) - } - } - - if !api.Semantic.DeepEqual(secret, outEvent.Object.Object) { - t.Fatalf("%s: did not match after frame decoding: %s", streamingMediaType, diff.ObjectGoPrintDiff(secret, outEvent.Object.Object)) - } - } -} - -const benchmarkSeed = 100 - -func benchmarkItems() []v1.Pod { - apiObjectFuzzer := apitesting.FuzzerFor(nil, api.SchemeGroupVersion, rand.NewSource(benchmarkSeed)) - items := make([]v1.Pod, 2) - for i := range items { - var pod api.Pod - apiObjectFuzzer.Fuzz(&pod) - out, err := api.Scheme.ConvertToVersion(&pod, "v1") - if err != nil { - panic(err) - } - items[i] = *out.(*v1.Pod) - } - return items -} - -// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes -// reflection (to clear APIVersion and Kind) -func BenchmarkEncodeCodec(b *testing.B) { - items := benchmarkItems() - width := len(items) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := runtime.Encode(testapi.Default.Codec(), &items[i%width]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -// BenchmarkEncodeCodecFromInternal measures the cost of performing a codec encode, -// including conversions. -func BenchmarkEncodeCodecFromInternal(b *testing.B) { - items := benchmarkItems() - width := len(items) - encodable := make([]api.Pod, width) - for i := range items { - if err := api.Scheme.Convert(&items[i], &encodable[i]); err != nil { - b.Fatal(err) - } - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := runtime.Encode(testapi.Default.Codec(), &encodable[i%width]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -// BenchmarkEncodeJSONMarshal provides a baseline for regular JSON encode performance -func BenchmarkEncodeJSONMarshal(b *testing.B) { - items := benchmarkItems() - width := len(items) - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := json.Marshal(&items[i%width]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkDecodeCodec(b *testing.B) { - codec := testapi.Default.Codec() - items := benchmarkItems() - width := len(items) - encoded := make([][]byte, width) - for i := range items { - data, err := runtime.Encode(codec, &items[i]) - if err != nil { - b.Fatal(err) - } - encoded[i] = data - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - if _, err := runtime.Decode(codec, encoded[i%width]); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkDecodeIntoExternalCodec(b *testing.B) { - codec := testapi.Default.Codec() - items := benchmarkItems() - width := len(items) - encoded := make([][]byte, width) - for i := range items { - data, err := runtime.Encode(codec, &items[i]) - if err != nil { - b.Fatal(err) - } - encoded[i] = data - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - obj := v1.Pod{} - if err := runtime.DecodeInto(codec, encoded[i%width], &obj); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -func BenchmarkDecodeIntoInternalCodec(b *testing.B) { - codec := testapi.Default.Codec() - items := benchmarkItems() - width := len(items) - encoded := make([][]byte, width) - for i := range items { - data, err := runtime.Encode(codec, &items[i]) - if err != nil { - b.Fatal(err) - } - encoded[i] = data - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - obj := api.Pod{} - if err := runtime.DecodeInto(codec, encoded[i%width], &obj); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -// BenchmarkDecodeJSON provides a baseline for regular JSON decode performance -func BenchmarkDecodeIntoJSON(b *testing.B) { - codec := testapi.Default.Codec() - items := benchmarkItems() - width := len(items) - encoded := make([][]byte, width) - for i := range items { - data, err := runtime.Encode(codec, &items[i]) - if err != nil { - b.Fatal(err) - } - encoded[i] = data - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - obj := v1.Pod{} - if err := json.Unmarshal(encoded[i%width], &obj); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} - -// BenchmarkDecodeJSON provides a baseline for codecgen JSON decode performance -func BenchmarkDecodeIntoJSONCodecGen(b *testing.B) { - kcodec := testapi.Default.Codec() - items := benchmarkItems() - width := len(items) - encoded := make([][]byte, width) - for i := range items { - data, err := runtime.Encode(kcodec, &items[i]) - if err != nil { - b.Fatal(err) - } - encoded[i] = data - } - handler := &codec.JsonHandle{} - - b.ResetTimer() - for i := 0; i < b.N; i++ { - obj := v1.Pod{} - if err := codec.NewDecoderBytes(encoded[i%width], handler).Decode(&obj); err != nil { - b.Fatal(err) - } - } - b.StopTimer() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/service/util_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/service/util_test.go deleted file mode 100644 index c77d4f259..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/service/util_test.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 service - -import ( - "testing" - - netsets "k8s.io/kubernetes/pkg/util/net/sets" -) - -func TestGetLoadBalancerSourceRanges(t *testing.T) { - checkError := func(v string) { - annotations := make(map[string]string) - annotations[AnnotationLoadBalancerSourceRangesKey] = v - _, err := GetLoadBalancerSourceRanges(annotations) - if err == nil { - t.Errorf("Expected error parsing: %q", v) - } - } - checkError("10.0.0.1/33") - checkError("foo.bar") - checkError("10.0.0.1/32,*") - checkError("10.0.0.1/32,") - checkError("10.0.0.1/32, ") - checkError("10.0.0.1") - - checkOK := func(v string) netsets.IPNet { - annotations := make(map[string]string) - annotations[AnnotationLoadBalancerSourceRangesKey] = v - cidrs, err := GetLoadBalancerSourceRanges(annotations) - if err != nil { - t.Errorf("Unexpected error parsing: %q", v) - } - return cidrs - } - cidrs := checkOK("192.168.0.1/32") - if len(cidrs) != 1 { - t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice()) - } - cidrs = checkOK("192.168.0.1/32,192.168.0.1/32") - if len(cidrs) != 1 { - t.Errorf("Expected exactly one CIDR (after de-dup): %v", cidrs.StringSlice()) - } - cidrs = checkOK("192.168.0.1/32,192.168.0.2/32") - if len(cidrs) != 2 { - t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice()) - } - cidrs = checkOK(" 192.168.0.1/32 , 192.168.0.2/32 ") - if len(cidrs) != 2 { - t.Errorf("Expected two CIDRs: %v", cidrs.StringSlice()) - } - cidrs = checkOK("") - if len(cidrs) != 1 { - t.Errorf("Expected exactly one CIDR: %v", cidrs.StringSlice()) - } - if !IsAllowAll(cidrs) { - t.Errorf("Expected default to be allow-all: %v", cidrs.StringSlice()) - } -} - -func TestAllowAll(t *testing.T) { - checkAllowAll := func(allowAll bool, cidrs ...string) { - ipnets, err := netsets.ParseIPNets(cidrs...) - if err != nil { - t.Errorf("Unexpected error parsing cidrs: %v", cidrs) - } - if allowAll != IsAllowAll(ipnets) { - t.Errorf("IsAllowAll did not return expected value for %v", cidrs) - } - } - checkAllowAll(false, "10.0.0.1/32") - checkAllowAll(false, "10.0.0.1/32", "10.0.0.2/32") - checkAllowAll(false, "10.0.0.1/32", "10.0.0.1/32") - - checkAllowAll(true, "0.0.0.0/0") - checkAllowAll(true, "192.168.0.0/0") - checkAllowAll(true, "192.168.0.1/32", "0.0.0.0/0") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testapi/testapi_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testapi/testapi_test.go deleted file mode 100644 index aa049f91d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testapi/testapi_test.go +++ /dev/null @@ -1,137 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testapi - -import ( - "encoding/json" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" -) - -// TODO these tests don't add much value for testing things that have groups - -func TestResourcePathWithPrefix(t *testing.T) { - testCases := []struct { - prefix string - resource string - namespace string - name string - expected string - }{ - {"prefix", "resource", "mynamespace", "myresource", "/api/" + Default.GroupVersion().Version + "/prefix/namespaces/mynamespace/resource/myresource"}, - {"prefix", "resource", "", "myresource", "/api/" + Default.GroupVersion().Version + "/prefix/resource/myresource"}, - {"prefix", "resource", "mynamespace", "", "/api/" + Default.GroupVersion().Version + "/prefix/namespaces/mynamespace/resource"}, - {"prefix", "resource", "", "", "/api/" + Default.GroupVersion().Version + "/prefix/resource"}, - {"", "resource", "mynamespace", "myresource", "/api/" + Default.GroupVersion().Version + "/namespaces/mynamespace/resource/myresource"}, - } - for _, item := range testCases { - if actual := Default.ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name) - } - } -} - -func TestResourcePath(t *testing.T) { - testCases := []struct { - resource string - namespace string - name string - expected string - }{ - {"resource", "mynamespace", "myresource", "/api/" + Default.GroupVersion().Version + "/namespaces/mynamespace/resource/myresource"}, - {"resource", "", "myresource", "/api/" + Default.GroupVersion().Version + "/resource/myresource"}, - {"resource", "mynamespace", "", "/api/" + Default.GroupVersion().Version + "/namespaces/mynamespace/resource"}, - {"resource", "", "", "/api/" + Default.GroupVersion().Version + "/resource"}, - } - for _, item := range testCases { - if actual := Default.ResourcePath(item.resource, item.namespace, item.name); actual != item.expected { - t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name) - } - } -} - -var status = &unversioned.Status{ - Status: unversioned.StatusFailure, - Code: 200, - Reason: unversioned.StatusReasonUnknown, - Message: "", -} - -func TestV1EncodeDecodeStatus(t *testing.T) { - v1Codec := Default.Codec() - - encoded, err := runtime.Encode(v1Codec, status) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - typeMeta := unversioned.TypeMeta{} - if err := json.Unmarshal(encoded, &typeMeta); err != nil { - t.Errorf("unexpected error: %v", err) - } - if typeMeta.Kind != "Status" { - t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) - } - if typeMeta.APIVersion != "v1" { - t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) - } - decoded, err := runtime.Decode(v1Codec, encoded) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(status, decoded) { - t.Errorf("expected: %#v, got: %#v", status, decoded) - } -} - -func testEncodeDecodeStatus(t *testing.T, codec runtime.Codec) { - encoded, err := runtime.Encode(codec, status) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - typeMeta := unversioned.TypeMeta{} - if err := json.Unmarshal(encoded, &typeMeta); err != nil { - t.Errorf("unexpected error: %v", err) - } - if typeMeta.Kind != "Status" { - t.Errorf("Kind is not set to \"Status\". Got %s", encoded) - } - if typeMeta.APIVersion != "v1" { - t.Errorf("APIVersion is not set to \"\". Got %s", encoded) - } - decoded, err := runtime.Decode(codec, encoded) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(status, decoded) { - t.Errorf("expected: %v, got: %v", status, decoded) - } -} - -func TestAutoscalingEncodeDecodeStatus(t *testing.T) { - testEncodeDecodeStatus(t, Autoscaling.Codec()) -} - -func TestBatchEncodeDecodeStatus(t *testing.T) { - testEncodeDecodeStatus(t, Batch.Codec()) -} - -func TestExperimentalEncodeDecodeStatus(t *testing.T) { - testEncodeDecodeStatus(t, Extensions.Codec()) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go deleted file mode 100644 index 82f165a33..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/compat/compatibility_tester.go +++ /dev/null @@ -1,144 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 compat - -import ( - "encoding/json" - "fmt" - "os" - "reflect" - "regexp" - "strconv" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -// Based on: https://github.com/openshift/origin/blob/master/pkg/api/compatibility_test.go -// -// TestCompatibility reencodes the input using the codec for the given -// version and checks for the presence of the expected keys and absent -// keys in the resulting JSON. -func TestCompatibility( - t *testing.T, - version unversioned.GroupVersion, - input []byte, - validator func(obj runtime.Object) field.ErrorList, - expectedKeys map[string]string, - absentKeys []string, -) { - - // Decode - codec := api.Codecs.LegacyCodec(version) - obj, err := runtime.Decode(codec, input) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - // Validate - errs := validator(obj) - if len(errs) != 0 { - t.Fatalf("Unexpected validation errors: %v", errs) - } - - // Encode - output, err := runtime.Encode(codec, obj) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - // Validate old and new fields are encoded - generic := map[string]interface{}{} - if err := json.Unmarshal(output, &generic); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - hasError := false - for k, expectedValue := range expectedKeys { - keys := strings.Split(k, ".") - if actualValue, ok, err := getJSONValue(generic, keys...); err != nil || !ok { - t.Errorf("Unexpected error for %s: %v", k, err) - hasError = true - } else if !reflect.DeepEqual(expectedValue, fmt.Sprintf("%v", actualValue)) { - hasError = true - t.Errorf("Unexpected value for %v: expected %v, got %v", k, expectedValue, actualValue) - } - } - - for _, absentKey := range absentKeys { - keys := strings.Split(absentKey, ".") - actualValue, ok, err := getJSONValue(generic, keys...) - if err == nil || ok { - t.Errorf("Unexpected value found for for key %s: %v", absentKey, actualValue) - hasError = true - } - } - - if hasError { - printer := new(kubectl.JSONPrinter) - printer.PrintObj(obj, os.Stdout) - t.Logf("2: Encoded value: %#v", string(output)) - } -} - -func getJSONValue(data map[string]interface{}, keys ...string) (interface{}, bool, error) { - // No keys, current value is it - if len(keys) == 0 { - return data, true, nil - } - - // Get the key (and optional index) - key := keys[0] - index := -1 - if matches := regexp.MustCompile(`^(.*)\[(\d+)\]$`).FindStringSubmatch(key); len(matches) > 0 { - key = matches[1] - index, _ = strconv.Atoi(matches[2]) - } - - // Look up the value - value, ok := data[key] - if !ok { - return nil, false, fmt.Errorf("No key %s found", key) - } - - // Get the indexed value if an index is specified - if index >= 0 { - valueSlice, ok := value.([]interface{}) - if !ok { - return nil, false, fmt.Errorf("Key %s did not hold a slice", key) - } - if index >= len(valueSlice) { - return nil, false, fmt.Errorf("Index %d out of bounds for slice at key: %v", index, key) - } - value = valueSlice[index] - } - - if len(keys) == 1 { - return value, true, nil - } - - childData, ok := value.(map[string]interface{}) - if !ok { - return nil, false, fmt.Errorf("Key %s did not hold a map", keys[0]) - } - return getJSONValue(childData, keys[1:]...) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/conversion.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/conversion.go deleted file mode 100644 index 6f91427e7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/conversion.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/labels" -) - -// TestSelectableFieldLabelConversions verifies that given resource have field -// label conversion defined for each its selectable field. -// fields contains selectable fields of the resource. -// labelMap maps deprecated labels to their canonical names. -func TestSelectableFieldLabelConversionsOfKind(t *testing.T, apiVersion string, kind string, fields labels.Set, labelMap map[string]string) { - badFieldLabels := []string{ - "name", - ".name", - "bad", - "metadata", - "foo.bar", - } - - value := "value" - - if len(fields) == 0 { - t.Logf("no selectable fields for kind %q, skipping", kind) - } - for label := range fields { - if label == "name" { - t.Logf("FIXME: \"name\" is deprecated by \"metadata.name\", it should be removed from selectable fields of kind=%s", kind) - continue - } - newLabel, newValue, err := api.Scheme.ConvertFieldLabel(apiVersion, kind, label, value) - if err != nil { - t.Errorf("kind=%s label=%s: got unexpected error: %v", kind, label, err) - } else { - expectedLabel := label - if l, exists := labelMap[label]; exists { - expectedLabel = l - } - if newLabel != expectedLabel { - t.Errorf("kind=%s label=%s: got unexpected label name (%q != %q)", kind, label, newLabel, expectedLabel) - } - if newValue != value { - t.Errorf("kind=%s label=%s: got unexpected new value (%q != %q)", kind, label, newValue, value) - } - } - } - - for _, label := range badFieldLabels { - _, _, err := api.Scheme.ConvertFieldLabel(apiVersion, kind, label, "value") - if err == nil { - t.Errorf("kind=%s label=%s: got unexpected non-error", kind, label) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/fuzzer.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/fuzzer.go deleted file mode 100644 index 052ce3f49..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/fuzzer.go +++ /dev/null @@ -1,424 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import ( - "fmt" - "math/rand" - "reflect" - "strconv" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/intstr" - - "github.com/google/gofuzz" -) - -// FuzzerFor can randomly populate api objects that are destined for version. -func FuzzerFor(t *testing.T, version unversioned.GroupVersion, src rand.Source) *fuzz.Fuzzer { - f := fuzz.New().NilChance(.5).NumElements(1, 1) - if src != nil { - f.RandSource(src) - } - f.Funcs( - func(j *int, c fuzz.Continue) { - *j = int(c.Int31()) - }, - func(j **int, c fuzz.Continue) { - if c.RandBool() { - i := int(c.Int31()) - *j = &i - } else { - *j = nil - } - }, - func(q *resource.Quantity, c fuzz.Continue) { - *q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent) - }, - func(j *runtime.TypeMeta, c fuzz.Continue) { - // We have to customize the randomization of TypeMetas because their - // APIVersion and Kind must remain blank in memory. - j.APIVersion = "" - j.Kind = "" - }, - func(j *unversioned.TypeMeta, c fuzz.Continue) { - // We have to customize the randomization of TypeMetas because their - // APIVersion and Kind must remain blank in memory. - j.APIVersion = "" - j.Kind = "" - }, - func(j *api.ObjectMeta, c fuzz.Continue) { - j.Name = c.RandString() - j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) - j.SelfLink = c.RandString() - j.UID = types.UID(c.RandString()) - j.GenerateName = c.RandString() - - var sec, nsec int64 - c.Fuzz(&sec) - c.Fuzz(&nsec) - j.CreationTimestamp = unversioned.Unix(sec, nsec).Rfc3339Copy() - }, - func(j *api.ObjectReference, c fuzz.Continue) { - // We have to customize the randomization of TypeMetas because their - // APIVersion and Kind must remain blank in memory. - j.APIVersion = c.RandString() - j.Kind = c.RandString() - j.Namespace = c.RandString() - j.Name = c.RandString() - j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) - j.FieldPath = c.RandString() - }, - func(j *unversioned.ListMeta, c fuzz.Continue) { - j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10) - j.SelfLink = c.RandString() - }, - func(j *api.ListOptions, c fuzz.Continue) { - label, _ := labels.Parse("a=b") - j.LabelSelector = label - field, _ := fields.ParseSelector("a=b") - j.FieldSelector = field - }, - func(j *api.PodExecOptions, c fuzz.Continue) { - j.Stdout = true - j.Stderr = true - }, - func(j *api.PodAttachOptions, c fuzz.Continue) { - j.Stdout = true - j.Stderr = true - }, - func(s *api.PodSpec, c fuzz.Continue) { - c.FuzzNoCustom(s) - // has a default value - ttl := int64(30) - if c.RandBool() { - ttl = int64(c.Uint32()) - } - s.TerminationGracePeriodSeconds = &ttl - - c.Fuzz(s.SecurityContext) - - if s.SecurityContext == nil { - s.SecurityContext = new(api.PodSecurityContext) - } - }, - func(j *api.PodPhase, c fuzz.Continue) { - statuses := []api.PodPhase{api.PodPending, api.PodRunning, api.PodFailed, api.PodUnknown} - *j = statuses[c.Rand.Intn(len(statuses))] - }, - func(j *api.Binding, c fuzz.Continue) { - c.Fuzz(&j.ObjectMeta) - j.Target.Name = c.RandString() - }, - func(j *api.ReplicationControllerSpec, c fuzz.Continue) { - c.FuzzNoCustom(j) // fuzz self without calling this function again - //j.TemplateRef = nil // this is required for round trip - }, - func(j *extensions.DeploymentStrategy, c fuzz.Continue) { - c.FuzzNoCustom(j) // fuzz self without calling this function again - // Ensure that strategyType is one of valid values. - strategyTypes := []extensions.DeploymentStrategyType{extensions.RecreateDeploymentStrategyType, extensions.RollingUpdateDeploymentStrategyType} - j.Type = strategyTypes[c.Rand.Intn(len(strategyTypes))] - if j.Type != extensions.RollingUpdateDeploymentStrategyType { - j.RollingUpdate = nil - } else { - rollingUpdate := extensions.RollingUpdateDeployment{} - if c.RandBool() { - rollingUpdate.MaxUnavailable = intstr.FromInt(int(c.RandUint64())) - rollingUpdate.MaxSurge = intstr.FromInt(int(c.RandUint64())) - } else { - rollingUpdate.MaxSurge = intstr.FromString(fmt.Sprintf("%d%%", c.RandUint64())) - } - j.RollingUpdate = &rollingUpdate - } - }, - func(j *batch.JobSpec, c fuzz.Continue) { - c.FuzzNoCustom(j) // fuzz self without calling this function again - completions := int32(c.Rand.Int31()) - parallelism := int32(c.Rand.Int31()) - j.Completions = &completions - j.Parallelism = ¶llelism - if c.Rand.Int31()%2 == 0 { - j.ManualSelector = newBool(true) - } else { - j.ManualSelector = nil - } - }, - func(j *api.List, c fuzz.Continue) { - c.FuzzNoCustom(j) // fuzz self without calling this function again - // TODO: uncomment when round trip starts from a versioned object - if false { //j.Items == nil { - j.Items = []runtime.Object{} - } - }, - func(j *runtime.Object, c fuzz.Continue) { - // TODO: uncomment when round trip starts from a versioned object - if true { //c.RandBool() { - *j = &runtime.Unknown{ - // We do not set TypeMeta here because it is not carried through a round trip - Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`), - ContentType: runtime.ContentTypeJSON, - } - } else { - types := []runtime.Object{&api.Pod{}, &api.ReplicationController{}} - t := types[c.Rand.Intn(len(types))] - c.Fuzz(t) - *j = t - } - }, - func(q *api.ResourceRequirements, c fuzz.Continue) { - randomQuantity := func() resource.Quantity { - var q resource.Quantity - c.Fuzz(&q) - return q - } - q.Limits = make(api.ResourceList) - q.Requests = make(api.ResourceList) - cpuLimit := randomQuantity() - q.Limits[api.ResourceCPU] = *cpuLimit.Copy() - q.Requests[api.ResourceCPU] = *cpuLimit.Copy() - memoryLimit := randomQuantity() - q.Limits[api.ResourceMemory] = *memoryLimit.Copy() - q.Requests[api.ResourceMemory] = *memoryLimit.Copy() - storageLimit := randomQuantity() - q.Limits[api.ResourceStorage] = *storageLimit.Copy() - q.Requests[api.ResourceStorage] = *storageLimit.Copy() - }, - func(q *api.LimitRangeItem, c fuzz.Continue) { - var cpuLimit resource.Quantity - c.Fuzz(&cpuLimit) - - q.Type = api.LimitTypeContainer - q.Default = make(api.ResourceList) - q.Default[api.ResourceCPU] = *(cpuLimit.Copy()) - - q.DefaultRequest = make(api.ResourceList) - q.DefaultRequest[api.ResourceCPU] = *(cpuLimit.Copy()) - - q.Max = make(api.ResourceList) - q.Max[api.ResourceCPU] = *(cpuLimit.Copy()) - - q.Min = make(api.ResourceList) - q.Min[api.ResourceCPU] = *(cpuLimit.Copy()) - - q.MaxLimitRequestRatio = make(api.ResourceList) - q.MaxLimitRequestRatio[api.ResourceCPU] = resource.MustParse("10") - }, - func(p *api.PullPolicy, c fuzz.Continue) { - policies := []api.PullPolicy{api.PullAlways, api.PullNever, api.PullIfNotPresent} - *p = policies[c.Rand.Intn(len(policies))] - }, - func(rp *api.RestartPolicy, c fuzz.Continue) { - policies := []api.RestartPolicy{api.RestartPolicyAlways, api.RestartPolicyNever, api.RestartPolicyOnFailure} - *rp = policies[c.Rand.Intn(len(policies))] - }, - // Only api.DownwardAPIVolumeFile needs to have a specific func since FieldRef has to be - // defaulted to a version otherwise roundtrip will fail - // For the remaining volume plugins the default fuzzer is enough. - func(m *api.DownwardAPIVolumeFile, c fuzz.Continue) { - m.Path = c.RandString() - versions := []string{"v1"} - m.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))] - m.FieldRef.FieldPath = c.RandString() - }, - func(vs *api.VolumeSource, c fuzz.Continue) { - // Exactly one of the fields must be set. - v := reflect.ValueOf(vs).Elem() - i := int(c.RandUint64() % uint64(v.NumField())) - t := v.Field(i).Addr() - for v.Field(i).IsNil() { - c.Fuzz(t.Interface()) - } - }, - func(i *api.ISCSIVolumeSource, c fuzz.Continue) { - i.ISCSIInterface = c.RandString() - if i.ISCSIInterface == "" { - i.ISCSIInterface = "default" - } - }, - func(d *api.DNSPolicy, c fuzz.Continue) { - policies := []api.DNSPolicy{api.DNSClusterFirst, api.DNSDefault} - *d = policies[c.Rand.Intn(len(policies))] - }, - func(p *api.Protocol, c fuzz.Continue) { - protocols := []api.Protocol{api.ProtocolTCP, api.ProtocolUDP} - *p = protocols[c.Rand.Intn(len(protocols))] - }, - func(p *api.ServiceAffinity, c fuzz.Continue) { - types := []api.ServiceAffinity{api.ServiceAffinityClientIP, api.ServiceAffinityNone} - *p = types[c.Rand.Intn(len(types))] - }, - func(p *api.ServiceType, c fuzz.Continue) { - types := []api.ServiceType{api.ServiceTypeClusterIP, api.ServiceTypeNodePort, api.ServiceTypeLoadBalancer} - *p = types[c.Rand.Intn(len(types))] - }, - func(ct *api.Container, c fuzz.Continue) { - c.FuzzNoCustom(ct) // fuzz self without calling this function again - ct.TerminationMessagePath = "/" + ct.TerminationMessagePath // Must be non-empty - }, - func(p *api.Probe, c fuzz.Continue) { - c.FuzzNoCustom(p) - // These fields have default values. - intFieldsWithDefaults := [...]string{"TimeoutSeconds", "PeriodSeconds", "SuccessThreshold", "FailureThreshold"} - v := reflect.ValueOf(p).Elem() - for _, field := range intFieldsWithDefaults { - f := v.FieldByName(field) - if f.Int() == 0 { - f.SetInt(1) - } - } - }, - func(ev *api.EnvVar, c fuzz.Continue) { - ev.Name = c.RandString() - if c.RandBool() { - ev.Value = c.RandString() - } else { - ev.ValueFrom = &api.EnvVarSource{} - ev.ValueFrom.FieldRef = &api.ObjectFieldSelector{} - - var versions []unversioned.GroupVersion - for _, testGroup := range testapi.Groups { - versions = append(versions, *testGroup.GroupVersion()) - } - - ev.ValueFrom.FieldRef.APIVersion = versions[c.Rand.Intn(len(versions))].String() - ev.ValueFrom.FieldRef.FieldPath = c.RandString() - } - }, - func(sc *api.SecurityContext, c fuzz.Continue) { - c.FuzzNoCustom(sc) // fuzz self without calling this function again - if c.RandBool() { - priv := c.RandBool() - sc.Privileged = &priv - } - - if c.RandBool() { - sc.Capabilities = &api.Capabilities{ - Add: make([]api.Capability, 0), - Drop: make([]api.Capability, 0), - } - c.Fuzz(&sc.Capabilities.Add) - c.Fuzz(&sc.Capabilities.Drop) - } - }, - func(s *api.Secret, c fuzz.Continue) { - c.FuzzNoCustom(s) // fuzz self without calling this function again - s.Type = api.SecretTypeOpaque - }, - func(pv *api.PersistentVolume, c fuzz.Continue) { - c.FuzzNoCustom(pv) // fuzz self without calling this function again - types := []api.PersistentVolumePhase{api.VolumeAvailable, api.VolumePending, api.VolumeBound, api.VolumeReleased, api.VolumeFailed} - pv.Status.Phase = types[c.Rand.Intn(len(types))] - pv.Status.Message = c.RandString() - reclamationPolicies := []api.PersistentVolumeReclaimPolicy{api.PersistentVolumeReclaimRecycle, api.PersistentVolumeReclaimRetain} - pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))] - }, - func(pvc *api.PersistentVolumeClaim, c fuzz.Continue) { - c.FuzzNoCustom(pvc) // fuzz self without calling this function again - types := []api.PersistentVolumeClaimPhase{api.ClaimBound, api.ClaimPending} - pvc.Status.Phase = types[c.Rand.Intn(len(types))] - }, - func(s *api.NamespaceSpec, c fuzz.Continue) { - s.Finalizers = []api.FinalizerName{api.FinalizerKubernetes} - }, - func(s *api.NamespaceStatus, c fuzz.Continue) { - s.Phase = api.NamespaceActive - }, - func(http *api.HTTPGetAction, c fuzz.Continue) { - c.FuzzNoCustom(http) // fuzz self without calling this function again - http.Path = "/" + http.Path // can't be blank - http.Scheme = "x" + http.Scheme // can't be blank - }, - func(ss *api.ServiceSpec, c fuzz.Continue) { - c.FuzzNoCustom(ss) // fuzz self without calling this function again - if len(ss.Ports) == 0 { - // There must be at least 1 port. - ss.Ports = append(ss.Ports, api.ServicePort{}) - c.Fuzz(&ss.Ports[0]) - } - for i := range ss.Ports { - switch ss.Ports[i].TargetPort.Type { - case intstr.Int: - ss.Ports[i].TargetPort.IntVal = 1 + ss.Ports[i].TargetPort.IntVal%65535 // non-zero - case intstr.String: - ss.Ports[i].TargetPort.StrVal = "x" + ss.Ports[i].TargetPort.StrVal // non-empty - } - } - }, - func(n *api.Node, c fuzz.Continue) { - c.FuzzNoCustom(n) - n.Spec.ExternalID = "external" - }, - func(s *api.NodeStatus, c fuzz.Continue) { - c.FuzzNoCustom(s) - s.Allocatable = s.Capacity - }, - func(s *extensions.HorizontalPodAutoscalerSpec, c fuzz.Continue) { - c.FuzzNoCustom(s) // fuzz self without calling this function again - minReplicas := int32(c.Rand.Int31()) - s.MinReplicas = &minReplicas - s.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: int32(c.RandUint64())} - }, - func(s *extensions.SubresourceReference, c fuzz.Continue) { - c.FuzzNoCustom(s) // fuzz self without calling this function again - s.Subresource = "scale" - }, - func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) { - c.FuzzNoCustom(psp) // fuzz self without calling this function again - runAsUserRules := []extensions.RunAsUserStrategy{extensions.RunAsUserStrategyMustRunAsNonRoot, extensions.RunAsUserStrategyMustRunAs, extensions.RunAsUserStrategyRunAsAny} - psp.RunAsUser.Rule = runAsUserRules[c.Rand.Intn(len(runAsUserRules))] - seLinuxRules := []extensions.SELinuxStrategy{extensions.SELinuxStrategyRunAsAny, extensions.SELinuxStrategyMustRunAs} - psp.SELinux.Rule = seLinuxRules[c.Rand.Intn(len(seLinuxRules))] - }, - func(s *extensions.Scale, c fuzz.Continue) { - c.FuzzNoCustom(s) // fuzz self without calling this function again - // TODO: Implement a fuzzer to generate valid keys, values and operators for - // selector requirements. - if s.Status.Selector != nil { - s.Status.Selector = &unversioned.LabelSelector{ - MatchLabels: map[string]string{ - "testlabelkey": "testlabelval", - }, - MatchExpressions: []unversioned.LabelSelectorRequirement{ - { - Key: "testkey", - Operator: unversioned.LabelSelectorOpIn, - Values: []string{"val1", "val2", "val3"}, - }, - }, - } - } - }, - ) - return f -} - -func newBool(val bool) *bool { - p := new(bool) - *p = val - return p -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/pod_specs.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/pod_specs.go deleted file mode 100644 index 2020b3f7f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testing/pod_specs.go +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import ( - "k8s.io/kubernetes/pkg/api" -) - -// DeepEqualSafePodSpec returns a PodSpec which is ready to be used with api.Semantic.DeepEqual -func DeepEqualSafePodSpec() api.PodSpec { - grace := int64(30) - return api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - TerminationGracePeriodSeconds: &grace, - SecurityContext: &api.PodSecurityContext{}, - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/duration_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/duration_test.go deleted file mode 100644 index 6650ca9aa..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/duration_test.go +++ /dev/null @@ -1,153 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned - -import ( - "encoding/json" - "testing" - "time" - - "github.com/ghodss/yaml" -) - -type DurationHolder struct { - D Duration `json:"d"` -} - -func TestDurationMarshalYAML(t *testing.T) { - cases := []struct { - input Duration - result string - }{ - {Duration{5 * time.Second}, "d: 5s\n"}, - {Duration{2 * time.Minute}, "d: 2m0s\n"}, - {Duration{time.Hour + 3*time.Millisecond}, "d: 1h0m0.003s\n"}, - } - - for _, c := range cases { - input := DurationHolder{c.input} - result, err := yaml.Marshal(&input) - if err != nil { - t.Errorf("Failed to marshal input: %q: %v", input, err) - } - if string(result) != c.result { - t.Errorf("Failed to marshal input: %q: expected %q, got %q", input, c.result, string(result)) - } - } -} - -func TestDurationUnmarshalYAML(t *testing.T) { - cases := []struct { - input string - result Duration - }{ - {"d: 0s\n", Duration{}}, - {"d: 5s\n", Duration{5 * time.Second}}, - {"d: 2m0s\n", Duration{2 * time.Minute}}, - {"d: 1h0m0.003s\n", Duration{time.Hour + 3*time.Millisecond}}, - - // Units with zero values can optionally be dropped - {"d: 2m\n", Duration{2 * time.Minute}}, - {"d: 1h0.003s\n", Duration{time.Hour + 3*time.Millisecond}}, - } - - for _, c := range cases { - var result DurationHolder - if err := yaml.Unmarshal([]byte(c.input), &result); err != nil { - t.Errorf("Failed to unmarshal input %q: %v", c.input, err) - } - if result.D != c.result { - t.Errorf("Failed to unmarshal input %q: expected %q, got %q", c.input, c.result, result) - } - } -} - -func TestDurationMarshalJSON(t *testing.T) { - cases := []struct { - input Duration - result string - }{ - {Duration{5 * time.Second}, `{"d":"5s"}`}, - {Duration{2 * time.Minute}, `{"d":"2m0s"}`}, - {Duration{time.Hour + 3*time.Millisecond}, `{"d":"1h0m0.003s"}`}, - } - - for _, c := range cases { - input := DurationHolder{c.input} - result, err := json.Marshal(&input) - if err != nil { - t.Errorf("Failed to marshal input: %q: %v", input, err) - } - if string(result) != c.result { - t.Errorf("Failed to marshal input: %q: expected %q, got %q", input, c.result, string(result)) - } - } -} - -func TestDurationUnmarshalJSON(t *testing.T) { - cases := []struct { - input string - result Duration - }{ - {`{"d":"0s"}`, Duration{}}, - {`{"d":"5s"}`, Duration{5 * time.Second}}, - {`{"d":"2m0s"}`, Duration{2 * time.Minute}}, - {`{"d":"1h0m0.003s"}`, Duration{time.Hour + 3*time.Millisecond}}, - - // Units with zero values can optionally be dropped - {`{"d":"2m"}`, Duration{2 * time.Minute}}, - {`{"d":"1h0.003s"}`, Duration{time.Hour + 3*time.Millisecond}}, - } - - for _, c := range cases { - var result DurationHolder - if err := json.Unmarshal([]byte(c.input), &result); err != nil { - t.Errorf("Failed to unmarshal input %q: %v", c.input, err) - } - if result.D != c.result { - t.Errorf("Failed to unmarshal input %q: expected %q, got %q", c.input, c.result, result) - } - } -} - -func TestDurationMarshalJSONUnmarshalYAML(t *testing.T) { - cases := []struct { - input Duration - }{ - {Duration{}}, - {Duration{5 * time.Second}}, - {Duration{2 * time.Minute}}, - {Duration{time.Hour + 3*time.Millisecond}}, - } - - for i, c := range cases { - input := DurationHolder{c.input} - jsonMarshalled, err := json.Marshal(&input) - if err != nil { - t.Errorf("%d-1: Failed to marshal input: '%v': %v", i, input, err) - } - - var result DurationHolder - if err := yaml.Unmarshal(jsonMarshalled, &result); err != nil { - t.Errorf("%d-2: Failed to unmarshal '%+v': %v", i, string(jsonMarshalled), err) - } - - if input.D != result.D { - t.Errorf("%d-4: Failed to marshal input '%#v': got %#v", i, input, result) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/group_version_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/group_version_test.go deleted file mode 100644 index 4a26fbb10..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/group_version_test.go +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned - -import ( - "encoding/json" - "reflect" - "testing" - - "github.com/ugorji/go/codec" -) - -type GroupVersionHolder struct { - GV GroupVersion `json:"val"` -} - -func TestGroupVersionUnmarshalJSON(t *testing.T) { - cases := []struct { - input []byte - expect GroupVersion - }{ - {[]byte(`{"val": "v1"}`), GroupVersion{"", "v1"}}, - {[]byte(`{"val": "extensions/v1beta1"}`), GroupVersion{"extensions", "v1beta1"}}, - } - - for _, c := range cases { - var result GroupVersionHolder - // test golang lib's JSON codec - if err := json.Unmarshal([]byte(c.input), &result); err != nil { - t.Errorf("JSON codec failed to unmarshal input '%v': %v", c.input, err) - } - if !reflect.DeepEqual(result.GV, c.expect) { - t.Errorf("JSON codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV) - } - // test the Ugorji codec - if err := codec.NewDecoderBytes(c.input, new(codec.JsonHandle)).Decode(&result); err != nil { - t.Errorf("Ugorji codec failed to unmarshal input '%v': %v", c.input, err) - } - if !reflect.DeepEqual(result.GV, c.expect) { - t.Errorf("Ugorji codec failed to unmarshal input '%s': expected %+v, got %+v", c.input, c.expect, result.GV) - } - } -} - -func TestGroupVersionMarshalJSON(t *testing.T) { - cases := []struct { - input GroupVersion - expect []byte - }{ - {GroupVersion{"", "v1"}, []byte(`{"val":"v1"}`)}, - {GroupVersion{"extensions", "v1beta1"}, []byte(`{"val":"extensions/v1beta1"}`)}, - } - - for _, c := range cases { - input := GroupVersionHolder{c.input} - result, err := json.Marshal(&input) - if err != nil { - t.Errorf("Failed to marshal input '%v': %v", input, err) - } - if !reflect.DeepEqual(result, c.expect) { - t.Errorf("Failed to marshal input '%+v': expected: %s, got: %s", input, c.expect, result) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/helpers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/helpers_test.go deleted file mode 100644 index f803d4366..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/helpers_test.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 unversioned - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/labels" -) - -func TestLabelSelectorAsSelector(t *testing.T) { - matchLabels := map[string]string{"foo": "bar"} - matchExpressions := []LabelSelectorRequirement{{ - Key: "baz", - Operator: LabelSelectorOpIn, - Values: []string{"qux", "norf"}, - }} - mustParse := func(s string) labels.Selector { - out, e := labels.Parse(s) - if e != nil { - panic(e) - } - return out - } - tc := []struct { - in *LabelSelector - out labels.Selector - expectErr bool - }{ - {in: nil, out: labels.Nothing()}, - {in: &LabelSelector{}, out: labels.Everything()}, - { - in: &LabelSelector{MatchLabels: matchLabels}, - out: mustParse("foo=bar"), - }, - { - in: &LabelSelector{MatchExpressions: matchExpressions}, - out: mustParse("baz in (norf,qux)"), - }, - { - in: &LabelSelector{MatchLabels: matchLabels, MatchExpressions: matchExpressions}, - out: mustParse("baz in (norf,qux),foo=bar"), - }, - { - in: &LabelSelector{ - MatchExpressions: []LabelSelectorRequirement{{ - Key: "baz", - Operator: LabelSelectorOpExists, - Values: []string{"qux", "norf"}, - }}, - }, - expectErr: true, - }, - } - - for i, tc := range tc { - out, err := LabelSelectorAsSelector(tc.in) - if err == nil && tc.expectErr { - t.Errorf("[%v]expected error but got none.", i) - } - if err != nil && !tc.expectErr { - t.Errorf("[%v]did not expect error but got: %v", i, err) - } - if !reflect.DeepEqual(out, tc.out) { - t.Errorf("[%v]expected:\n\t%+v\nbut got:\n\t%+v", i, tc.out, out) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/time_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/time_test.go deleted file mode 100644 index 2f4f3696d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/time_test.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned - -import ( - "encoding/json" - "testing" - "time" - - "github.com/ghodss/yaml" -) - -type TimeHolder struct { - T Time `json:"t"` -} - -func TestTimeMarshalYAML(t *testing.T) { - cases := []struct { - input Time - result string - }{ - {Time{}, "t: null\n"}, - {Date(1998, time.May, 5, 1, 5, 5, 50, time.FixedZone("test", -4*60*60)), "t: 1998-05-05T05:05:05Z\n"}, - {Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC), "t: 1998-05-05T05:05:05Z\n"}, - } - - for _, c := range cases { - input := TimeHolder{c.input} - result, err := yaml.Marshal(&input) - if err != nil { - t.Errorf("Failed to marshal input: '%v': %v", input, err) - } - if string(result) != c.result { - t.Errorf("Failed to marshal input: '%v': expected %+v, got %q", input, c.result, string(result)) - } - } -} - -func TestTimeUnmarshalYAML(t *testing.T) { - cases := []struct { - input string - result Time - }{ - {"t: null\n", Time{}}, - {"t: 1998-05-05T05:05:05Z\n", Time{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC).Local()}}, - } - - for _, c := range cases { - var result TimeHolder - if err := yaml.Unmarshal([]byte(c.input), &result); err != nil { - t.Errorf("Failed to unmarshal input '%v': %v", c.input, err) - } - if result.T != c.result { - t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result) - } - } -} - -func TestTimeMarshalJSON(t *testing.T) { - cases := []struct { - input Time - result string - }{ - {Time{}, "{\"t\":null}"}, - {Date(1998, time.May, 5, 5, 5, 5, 50, time.UTC), "{\"t\":\"1998-05-05T05:05:05Z\"}"}, - {Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC), "{\"t\":\"1998-05-05T05:05:05Z\"}"}, - } - - for _, c := range cases { - input := TimeHolder{c.input} - result, err := json.Marshal(&input) - if err != nil { - t.Errorf("Failed to marshal input: '%v': %v", input, err) - } - if string(result) != c.result { - t.Errorf("Failed to marshal input: '%v': expected %+v, got %q", input, c.result, string(result)) - } - } -} - -func TestTimeUnmarshalJSON(t *testing.T) { - cases := []struct { - input string - result Time - }{ - {"{\"t\":null}", Time{}}, - {"{\"t\":\"1998-05-05T05:05:05Z\"}", Time{Date(1998, time.May, 5, 5, 5, 5, 0, time.UTC).Local()}}, - } - - for _, c := range cases { - var result TimeHolder - if err := json.Unmarshal([]byte(c.input), &result); err != nil { - t.Errorf("Failed to unmarshal input '%v': %v", c.input, err) - } - if result.T != c.result { - t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result) - } - } -} - -func TestTimeMarshalJSONUnmarshalYAML(t *testing.T) { - cases := []struct { - input Time - }{ - {Time{}}, - {Date(1998, time.May, 5, 5, 5, 5, 50, time.Local).Rfc3339Copy()}, - {Date(1998, time.May, 5, 5, 5, 5, 0, time.Local).Rfc3339Copy()}, - } - - for i, c := range cases { - input := TimeHolder{c.input} - jsonMarshalled, err := json.Marshal(&input) - if err != nil { - t.Errorf("%d-1: Failed to marshal input: '%v': %v", i, input, err) - } - - var result TimeHolder - err = yaml.Unmarshal(jsonMarshalled, &result) - if err != nil { - t.Errorf("%d-2: Failed to unmarshal '%+v': %v", i, string(jsonMarshalled), err) - } - - iN, iO := input.T.Zone() - oN, oO := result.T.Zone() - if iN != oN || iO != oO { - t.Errorf("%d-3: Time zones differ before and after serialization %s:%d %s:%d", i, iN, iO, oN, oO) - } - - if input.T.UnixNano() != result.T.UnixNano() { - t.Errorf("%d-4: Failed to marshal input '%#v': got %#v", i, input, result) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/validation/validation_test.go deleted file mode 100644 index 26be6fb58..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/unversioned/validation/validation_test.go +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func TestValidateLabels(t *testing.T) { - successCases := []map[string]string{ - {"simple": "bar"}, - {"now-with-dashes": "bar"}, - {"1-starts-with-num": "bar"}, - {"1234": "bar"}, - {"simple/simple": "bar"}, - {"now-with-dashes/simple": "bar"}, - {"now-with-dashes/now-with-dashes": "bar"}, - {"now.with.dots/simple": "bar"}, - {"now-with.dashes-and.dots/simple": "bar"}, - {"1-num.2-num/3-num": "bar"}, - {"1234/5678": "bar"}, - {"1.2.3.4/5678": "bar"}, - {"UpperCaseAreOK123": "bar"}, - {"goodvalue": "123_-.BaR"}, - } - for i := range successCases { - errs := ValidateLabels(successCases[i], field.NewPath("field")) - if len(errs) != 0 { - t.Errorf("case[%d] expected success, got %#v", i, errs) - } - } - - labelNameErrorCases := []map[string]string{ - {"nospecialchars^=@": "bar"}, - {"cantendwithadash-": "bar"}, - {"only/one/slash": "bar"}, - {strings.Repeat("a", 254): "bar"}, - } - for i := range labelNameErrorCases { - errs := ValidateLabels(labelNameErrorCases[i], field.NewPath("field")) - if len(errs) != 1 { - t.Errorf("case[%d] expected failure", i) - } else { - detail := errs[0].Detail - if detail != qualifiedNameErrorMsg { - t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg) - } - } - } - - labelValueErrorCases := []map[string]string{ - {"toolongvalue": strings.Repeat("a", 64)}, - {"backslashesinvalue": "some\\bad\\value"}, - {"nocommasallowed": "bad,value"}, - {"strangecharsinvalue": "?#$notsogood"}, - } - for i := range labelValueErrorCases { - errs := ValidateLabels(labelValueErrorCases[i], field.NewPath("field")) - if len(errs) != 1 { - t.Errorf("case[%d] expected failure", i) - } else { - detail := errs[0].Detail - if detail != labelValueErrorMsg { - t.Errorf("error detail %s should be equal %s", detail, labelValueErrorMsg) - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/util/group_version_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/util/group_version_test.go deleted file mode 100644 index d53b5f4e5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/util/group_version_test.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 util - -import "testing" - -func TestGetVersion(t *testing.T) { - testCases := []struct { - groupVersion string - output string - }{ - { - "v1", - "v1", - }, - { - "extensions/v1beta1", - "v1beta1", - }, - } - for _, test := range testCases { - actual := GetVersion(test.groupVersion) - if test.output != actual { - t.Errorf("expect version: %s, got: %s\n", test.output, actual) - } - } -} - -func TestGetGroup(t *testing.T) { - testCases := []struct { - groupVersion string - output string - }{ - { - "v1", - "", - }, - { - "extensions/v1beta1", - "extensions", - }, - } - for _, test := range testCases { - actual := GetGroup(test.groupVersion) - if test.output != actual { - t.Errorf("expect version: %s, got: %s\n", test.output, actual) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/backward_compatibility_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/backward_compatibility_test.go deleted file mode 100644 index 2ef3d926f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/backward_compatibility_test.go +++ /dev/null @@ -1,229 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 v1_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testing/compat" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func TestCompatibility_v1_PodSecurityContext(t *testing.T) { - cases := []struct { - name string - input string - expectedKeys map[string]string - absentKeys []string - }{ - { - name: "hostNetwork = true", - input: ` -{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"}, - "spec": { - "hostNetwork": true, - "containers":[{ - "name":"a", - "image":"my-container-image" - }] - } -} -`, - expectedKeys: map[string]string{ - "spec.hostNetwork": "true", - }, - }, - { - name: "hostNetwork = false", - input: ` -{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"}, - "spec": { - "hostNetwork": false, - "containers":[{ - "name":"a", - "image":"my-container-image" - }] - } -} -`, - absentKeys: []string{ - "spec.hostNetwork", - }, - }, - { - name: "hostIPC = true", - input: ` -{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"}, - "spec": { - "hostIPC": true, - "containers":[{ - "name":"a", - "image":"my-container-image" - }] - } -} -`, - expectedKeys: map[string]string{ - "spec.hostIPC": "true", - }, - }, - { - name: "hostIPC = false", - input: ` -{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"}, - "spec": { - "hostIPC": false, - "containers":[{ - "name":"a", - "image":"my-container-image" - }] - } -} -`, - absentKeys: []string{ - "spec.hostIPC", - }, - }, - { - name: "hostPID = true", - input: ` -{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"}, - "spec": { - "hostPID": true, - "containers":[{ - "name":"a", - "image":"my-container-image" - }] - } -} -`, - expectedKeys: map[string]string{ - "spec.hostPID": "true", - }, - }, - { - name: "hostPID = false", - input: ` -{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{"name":"my-pod-name", "namespace":"my-pod-namespace"}, - "spec": { - "hostPID": false, - "containers":[{ - "name":"a", - "image":"my-container-image" - }] - } -} -`, - absentKeys: []string{ - "spec.hostPID", - }, - }, - { - name: "reseting defaults for pre-v1.1 mirror pods", - input: ` -{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{ - "name":"my-pod-name", - "namespace":"my-pod-namespace", - "annotations": { - "kubernetes.io/config.mirror": "mirror" - } - }, - "spec": { - "containers":[{ - "name":"a", - "image":"my-container-image", - "resources": { - "limits": { - "cpu": "100m" - } - } - }] - } -} -`, - absentKeys: []string{ - "spec.terminationGracePeriodSeconds", - "spec.containers[0].resources.requests", - }, - }, - { - name: "preserving defaults for v1.1+ mirror pods", - input: ` - { - "kind":"Pod", - "apiVersion":"v1", - "metadata":{ - "name":"my-pod-name", - "namespace":"my-pod-namespace", - "annotations": { - "kubernetes.io/config.mirror": "cbe924f710c7e26f7693d6a341bcfad0" - } - }, - "spec": { - "containers":[{ - "name":"a", - "image":"my-container-image", - "resources": { - "limits": { - "cpu": "100m" - } - } - }] - } - } - `, - expectedKeys: map[string]string{ - "spec.terminationGracePeriodSeconds": "30", - "spec.containers[0].resources.requests": "map[cpu:100m]", - }, - }, - } - - validator := func(obj runtime.Object) field.ErrorList { - return validation.ValidatePodSpec(&(obj.(*api.Pod).Spec), field.NewPath("spec")) - } - - for _, tc := range cases { - t.Logf("Testing 1.0.0 backward compatibility for %v", tc.name) - compat.TestCompatibility(t, v1.SchemeGroupVersion, []byte(tc.input), validator, tc.expectedKeys, tc.absentKeys) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_test.go deleted file mode 100644 index ac0b4e682..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_test.go +++ /dev/null @@ -1,217 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 v1_test - -import ( - "net/url" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/unversioned" - versioned "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/diff" -) - -func TestPodLogOptions(t *testing.T) { - sinceSeconds := int64(1) - sinceTime := unversioned.NewTime(time.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC).Local()) - tailLines := int64(2) - limitBytes := int64(3) - - versionedLogOptions := &versioned.PodLogOptions{ - Container: "mycontainer", - Follow: true, - Previous: true, - SinceSeconds: &sinceSeconds, - SinceTime: &sinceTime, - Timestamps: true, - TailLines: &tailLines, - LimitBytes: &limitBytes, - } - unversionedLogOptions := &api.PodLogOptions{ - Container: "mycontainer", - Follow: true, - Previous: true, - SinceSeconds: &sinceSeconds, - SinceTime: &sinceTime, - Timestamps: true, - TailLines: &tailLines, - LimitBytes: &limitBytes, - } - expectedParameters := url.Values{ - "container": {"mycontainer"}, - "follow": {"true"}, - "previous": {"true"}, - "sinceSeconds": {"1"}, - "sinceTime": {"2000-01-01T12:34:56Z"}, - "timestamps": {"true"}, - "tailLines": {"2"}, - "limitBytes": {"3"}, - } - - codec := runtime.NewParameterCodec(api.Scheme) - - // unversioned -> query params - { - actualParameters, err := codec.EncodeParameters(unversionedLogOptions, versioned.SchemeGroupVersion) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(actualParameters, expectedParameters) { - t.Fatalf("Expected\n%#v\ngot\n%#v", expectedParameters, actualParameters) - } - } - - // versioned -> query params - { - actualParameters, err := codec.EncodeParameters(versionedLogOptions, versioned.SchemeGroupVersion) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(actualParameters, expectedParameters) { - t.Fatalf("Expected\n%#v\ngot\n%#v", expectedParameters, actualParameters) - } - } - - // query params -> versioned - { - convertedLogOptions := &versioned.PodLogOptions{} - err := codec.DecodeParameters(expectedParameters, versioned.SchemeGroupVersion, convertedLogOptions) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(convertedLogOptions, versionedLogOptions) { - t.Fatalf("Unexpected deserialization:\n%s", diff.ObjectGoPrintSideBySide(versionedLogOptions, convertedLogOptions)) - } - } - - // query params -> unversioned - { - convertedLogOptions := &api.PodLogOptions{} - err := codec.DecodeParameters(expectedParameters, versioned.SchemeGroupVersion, convertedLogOptions) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(convertedLogOptions, unversionedLogOptions) { - t.Fatalf("Unexpected deserialization:\n%s", diff.ObjectGoPrintSideBySide(unversionedLogOptions, convertedLogOptions)) - } - } -} - -// TestPodSpecConversion tests that ServiceAccount is an alias for -// ServiceAccountName. -func TestPodSpecConversion(t *testing.T) { - name, other := "foo", "bar" - - // Test internal -> v1. Should have both alias (DeprecatedServiceAccount) - // and new field (ServiceAccountName). - i := &api.PodSpec{ - ServiceAccountName: name, - } - v := versioned.PodSpec{} - if err := api.Scheme.Convert(i, &v); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if v.ServiceAccountName != name { - t.Fatalf("want v1.ServiceAccountName %q, got %q", name, v.ServiceAccountName) - } - if v.DeprecatedServiceAccount != name { - t.Fatalf("want v1.DeprecatedServiceAccount %q, got %q", name, v.DeprecatedServiceAccount) - } - - // Test v1 -> internal. Either DeprecatedServiceAccount, ServiceAccountName, - // or both should translate to ServiceAccountName. ServiceAccountName wins - // if both are set. - testCases := []*versioned.PodSpec{ - // New - {ServiceAccountName: name}, - // Alias - {DeprecatedServiceAccount: name}, - // Both: same - {ServiceAccountName: name, DeprecatedServiceAccount: name}, - // Both: different - {ServiceAccountName: name, DeprecatedServiceAccount: other}, - } - for k, v := range testCases { - got := api.PodSpec{} - err := api.Scheme.Convert(v, &got) - if err != nil { - t.Fatalf("unexpected error for case %d: %v", k, err) - } - if got.ServiceAccountName != name { - t.Fatalf("want api.ServiceAccountName %q, got %q", name, got.ServiceAccountName) - } - } -} - -func TestResourceListConversion(t *testing.T) { - bigMilliQuantity := resource.NewQuantity(resource.MaxMilliValue, resource.DecimalSI) - bigMilliQuantity.Add(resource.MustParse("12345m")) - - tests := []struct { - input versioned.ResourceList - expected api.ResourceList - }{ - { // No changes necessary. - input: versioned.ResourceList{ - versioned.ResourceMemory: resource.MustParse("30M"), - versioned.ResourceCPU: resource.MustParse("100m"), - versioned.ResourceStorage: resource.MustParse("1G"), - }, - expected: api.ResourceList{ - api.ResourceMemory: resource.MustParse("30M"), - api.ResourceCPU: resource.MustParse("100m"), - api.ResourceStorage: resource.MustParse("1G"), - }, - }, - { // Nano-scale values should be rounded up to milli-scale. - input: versioned.ResourceList{ - versioned.ResourceCPU: resource.MustParse("3.000023m"), - versioned.ResourceMemory: resource.MustParse("500.000050m"), - }, - expected: api.ResourceList{ - api.ResourceCPU: resource.MustParse("4m"), - api.ResourceMemory: resource.MustParse("501m"), - }, - }, - { // Large values should still be accurate. - input: versioned.ResourceList{ - versioned.ResourceCPU: *bigMilliQuantity.Copy(), - versioned.ResourceStorage: *bigMilliQuantity.Copy(), - }, - expected: api.ResourceList{ - api.ResourceCPU: *bigMilliQuantity.Copy(), - api.ResourceStorage: *bigMilliQuantity.Copy(), - }, - }, - } - - output := api.ResourceList{} - for i, test := range tests { - err := api.Scheme.Convert(&test.input, &output) - if err != nil { - t.Fatalf("unexpected error for case %d: %v", i, err) - } - if !api.Semantic.DeepEqual(test.expected, output) { - t.Errorf("unexpected conversion for case %d: Expected %+v; Got %+v", i, test.expected, output) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/defaults_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/defaults_test.go deleted file mode 100644 index b1a78e758..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/defaults_test.go +++ /dev/null @@ -1,645 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 v1_test - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - versioned "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { - codec := api.Codecs.LegacyCodec(versioned.SchemeGroupVersion) - data, err := runtime.Encode(codec, obj) - if err != nil { - t.Errorf("%v\n %#v", err, obj) - return nil - } - obj2, err := runtime.Decode(codec, data) - if err != nil { - t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj) - return nil - } - obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object) - err = api.Scheme.Convert(obj2, obj3) - if err != nil { - t.Errorf("%v\nSource: %#v", err, obj2) - return nil - } - return obj3 -} - -func TestSetDefaultReplicationController(t *testing.T) { - tests := []struct { - rc *versioned.ReplicationController - expectLabels bool - expectSelector bool - }{ - { - rc: &versioned.ReplicationController{ - Spec: versioned.ReplicationControllerSpec{ - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: true, - expectSelector: true, - }, - { - rc: &versioned.ReplicationController{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "bar": "foo", - }, - }, - Spec: versioned.ReplicationControllerSpec{ - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: false, - expectSelector: true, - }, - { - rc: &versioned.ReplicationController{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "bar": "foo", - }, - }, - Spec: versioned.ReplicationControllerSpec{ - Selector: map[string]string{ - "some": "other", - }, - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: false, - expectSelector: false, - }, - { - rc: &versioned.ReplicationController{ - Spec: versioned.ReplicationControllerSpec{ - Selector: map[string]string{ - "some": "other", - }, - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: true, - expectSelector: false, - }, - } - - for _, test := range tests { - rc := test.rc - obj2 := roundTrip(t, runtime.Object(rc)) - rc2, ok := obj2.(*versioned.ReplicationController) - if !ok { - t.Errorf("unexpected object: %v", rc2) - t.FailNow() - } - if test.expectSelector != reflect.DeepEqual(rc2.Spec.Selector, rc2.Spec.Template.Labels) { - if test.expectSelector { - t.Errorf("expected: %v, got: %v", rc2.Spec.Template.Labels, rc2.Spec.Selector) - } else { - t.Errorf("unexpected equality: %v", rc.Spec.Selector) - } - } - if test.expectLabels != reflect.DeepEqual(rc2.Labels, rc2.Spec.Template.Labels) { - if test.expectLabels { - t.Errorf("expected: %v, got: %v", rc2.Spec.Template.Labels, rc2.Labels) - } else { - t.Errorf("unexpected equality: %v", rc.Labels) - } - } - } -} - -func newInt(val int32) *int32 { - p := new(int32) - *p = val - return p -} - -func TestSetDefaultReplicationControllerReplicas(t *testing.T) { - tests := []struct { - rc versioned.ReplicationController - expectReplicas int32 - }{ - { - rc: versioned.ReplicationController{ - Spec: versioned.ReplicationControllerSpec{ - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectReplicas: 1, - }, - { - rc: versioned.ReplicationController{ - Spec: versioned.ReplicationControllerSpec{ - Replicas: newInt(0), - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectReplicas: 0, - }, - { - rc: versioned.ReplicationController{ - Spec: versioned.ReplicationControllerSpec{ - Replicas: newInt(3), - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectReplicas: 3, - }, - } - - for _, test := range tests { - rc := &test.rc - obj2 := roundTrip(t, runtime.Object(rc)) - rc2, ok := obj2.(*versioned.ReplicationController) - if !ok { - t.Errorf("unexpected object: %v", rc2) - t.FailNow() - } - if rc2.Spec.Replicas == nil { - t.Errorf("unexpected nil Replicas") - } else if test.expectReplicas != *rc2.Spec.Replicas { - t.Errorf("expected: %d replicas, got: %d", test.expectReplicas, *rc2.Spec.Replicas) - } - } -} - -func TestSetDefaultService(t *testing.T) { - svc := &versioned.Service{} - obj2 := roundTrip(t, runtime.Object(svc)) - svc2 := obj2.(*versioned.Service) - if svc2.Spec.SessionAffinity != versioned.ServiceAffinityNone { - t.Errorf("Expected default session affinity type:%s, got: %s", versioned.ServiceAffinityNone, svc2.Spec.SessionAffinity) - } - if svc2.Spec.Type != versioned.ServiceTypeClusterIP { - t.Errorf("Expected default type:%s, got: %s", versioned.ServiceTypeClusterIP, svc2.Spec.Type) - } -} - -func TestSetDefaultSecret(t *testing.T) { - s := &versioned.Secret{} - obj2 := roundTrip(t, runtime.Object(s)) - s2 := obj2.(*versioned.Secret) - - if s2.Type != versioned.SecretTypeOpaque { - t.Errorf("Expected secret type %v, got %v", versioned.SecretTypeOpaque, s2.Type) - } -} - -func TestSetDefaultPersistentVolume(t *testing.T) { - pv := &versioned.PersistentVolume{} - obj2 := roundTrip(t, runtime.Object(pv)) - pv2 := obj2.(*versioned.PersistentVolume) - - if pv2.Status.Phase != versioned.VolumePending { - t.Errorf("Expected volume phase %v, got %v", versioned.VolumePending, pv2.Status.Phase) - } - if pv2.Spec.PersistentVolumeReclaimPolicy != versioned.PersistentVolumeReclaimRetain { - t.Errorf("Expected pv reclaim policy %v, got %v", versioned.PersistentVolumeReclaimRetain, pv2.Spec.PersistentVolumeReclaimPolicy) - } -} - -func TestSetDefaultPersistentVolumeClaim(t *testing.T) { - pvc := &versioned.PersistentVolumeClaim{} - obj2 := roundTrip(t, runtime.Object(pvc)) - pvc2 := obj2.(*versioned.PersistentVolumeClaim) - - if pvc2.Status.Phase != versioned.ClaimPending { - t.Errorf("Expected claim phase %v, got %v", versioned.ClaimPending, pvc2.Status.Phase) - } -} - -func TestSetDefaulEndpointsProtocol(t *testing.T) { - in := &versioned.Endpoints{Subsets: []versioned.EndpointSubset{ - {Ports: []versioned.EndpointPort{{}, {Protocol: "UDP"}, {}}}, - }} - obj := roundTrip(t, runtime.Object(in)) - out := obj.(*versioned.Endpoints) - - for i := range out.Subsets { - for j := range out.Subsets[i].Ports { - if in.Subsets[i].Ports[j].Protocol == "" { - if out.Subsets[i].Ports[j].Protocol != versioned.ProtocolTCP { - t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Subsets[i].Ports[j].Protocol) - } - } else { - if out.Subsets[i].Ports[j].Protocol != in.Subsets[i].Ports[j].Protocol { - t.Errorf("Expected protocol %s, got %s", in.Subsets[i].Ports[j].Protocol, out.Subsets[i].Ports[j].Protocol) - } - } - } - } -} - -func TestSetDefaulServiceTargetPort(t *testing.T) { - in := &versioned.Service{Spec: versioned.ServiceSpec{Ports: []versioned.ServicePort{{Port: 1234}}}} - obj := roundTrip(t, runtime.Object(in)) - out := obj.(*versioned.Service) - if out.Spec.Ports[0].TargetPort != intstr.FromInt(1234) { - t.Errorf("Expected TargetPort to be defaulted, got %v", out.Spec.Ports[0].TargetPort) - } - - in = &versioned.Service{Spec: versioned.ServiceSpec{Ports: []versioned.ServicePort{{Port: 1234, TargetPort: intstr.FromInt(5678)}}}} - obj = roundTrip(t, runtime.Object(in)) - out = obj.(*versioned.Service) - if out.Spec.Ports[0].TargetPort != intstr.FromInt(5678) { - t.Errorf("Expected TargetPort to be unchanged, got %v", out.Spec.Ports[0].TargetPort) - } -} - -func TestSetDefaultServicePort(t *testing.T) { - // Unchanged if set. - in := &versioned.Service{Spec: versioned.ServiceSpec{ - Ports: []versioned.ServicePort{ - {Protocol: "UDP", Port: 9376, TargetPort: intstr.FromString("p")}, - {Protocol: "UDP", Port: 8675, TargetPort: intstr.FromInt(309)}, - }, - }} - out := roundTrip(t, runtime.Object(in)).(*versioned.Service) - if out.Spec.Ports[0].Protocol != versioned.ProtocolUDP { - t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[0].Protocol) - } - if out.Spec.Ports[0].TargetPort != intstr.FromString("p") { - t.Errorf("Expected port %v, got %v", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) - } - if out.Spec.Ports[1].Protocol != versioned.ProtocolUDP { - t.Errorf("Expected protocol %s, got %s", versioned.ProtocolUDP, out.Spec.Ports[1].Protocol) - } - if out.Spec.Ports[1].TargetPort != intstr.FromInt(309) { - t.Errorf("Expected port %v, got %v", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) - } - - // Defaulted. - in = &versioned.Service{Spec: versioned.ServiceSpec{ - Ports: []versioned.ServicePort{ - {Protocol: "", Port: 9376, TargetPort: intstr.FromString("")}, - {Protocol: "", Port: 8675, TargetPort: intstr.FromInt(0)}, - }, - }} - out = roundTrip(t, runtime.Object(in)).(*versioned.Service) - if out.Spec.Ports[0].Protocol != versioned.ProtocolTCP { - t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[0].Protocol) - } - if out.Spec.Ports[0].TargetPort != intstr.FromInt(int(in.Spec.Ports[0].Port)) { - t.Errorf("Expected port %v, got %v", in.Spec.Ports[0].Port, out.Spec.Ports[0].TargetPort) - } - if out.Spec.Ports[1].Protocol != versioned.ProtocolTCP { - t.Errorf("Expected protocol %s, got %s", versioned.ProtocolTCP, out.Spec.Ports[1].Protocol) - } - if out.Spec.Ports[1].TargetPort != intstr.FromInt(int(in.Spec.Ports[1].Port)) { - t.Errorf("Expected port %v, got %v", in.Spec.Ports[1].Port, out.Spec.Ports[1].TargetPort) - } -} - -func TestSetDefaultNamespace(t *testing.T) { - s := &versioned.Namespace{} - obj2 := roundTrip(t, runtime.Object(s)) - s2 := obj2.(*versioned.Namespace) - - if s2.Status.Phase != versioned.NamespaceActive { - t.Errorf("Expected phase %v, got %v", versioned.NamespaceActive, s2.Status.Phase) - } -} - -func TestSetDefaultPodSpecHostNetwork(t *testing.T) { - portNum := int32(8080) - s := versioned.PodSpec{} - s.HostNetwork = true - s.Containers = []versioned.Container{ - { - Ports: []versioned.ContainerPort{ - { - ContainerPort: portNum, - }, - }, - }, - } - pod := &versioned.Pod{ - Spec: s, - } - obj2 := roundTrip(t, runtime.Object(pod)) - pod2 := obj2.(*versioned.Pod) - s2 := pod2.Spec - - hostPortNum := s2.Containers[0].Ports[0].HostPort - if hostPortNum != portNum { - t.Errorf("Expected container port to be defaulted, was made %d instead of %d", hostPortNum, portNum) - } -} - -func TestSetDefaultNodeExternalID(t *testing.T) { - name := "node0" - n := &versioned.Node{} - n.Name = name - obj2 := roundTrip(t, runtime.Object(n)) - n2 := obj2.(*versioned.Node) - if n2.Spec.ExternalID != name { - t.Errorf("Expected default External ID: %s, got: %s", name, n2.Spec.ExternalID) - } - if n2.Spec.ProviderID != "" { - t.Errorf("Expected empty default Cloud Provider ID, got: %s", n2.Spec.ProviderID) - } -} - -func TestSetDefaultNodeStatusAllocatable(t *testing.T) { - capacity := versioned.ResourceList{ - versioned.ResourceCPU: resource.MustParse("1000m"), - versioned.ResourceMemory: resource.MustParse("10G"), - } - allocatable := versioned.ResourceList{ - versioned.ResourceCPU: resource.MustParse("500m"), - versioned.ResourceMemory: resource.MustParse("5G"), - } - tests := []struct { - capacity versioned.ResourceList - allocatable versioned.ResourceList - expectedAllocatable versioned.ResourceList - }{{ // Everything set, no defaulting. - capacity: capacity, - allocatable: allocatable, - expectedAllocatable: allocatable, - }, { // Allocatable set, no defaulting. - capacity: nil, - allocatable: allocatable, - expectedAllocatable: allocatable, - }, { // Capacity set, allocatable defaults to capacity. - capacity: capacity, - allocatable: nil, - expectedAllocatable: capacity, - }, { // Nothing set, allocatable "defaults" to capacity. - capacity: nil, - allocatable: nil, - expectedAllocatable: nil, - }} - - copyResourceList := func(rl versioned.ResourceList) versioned.ResourceList { - if rl == nil { - return nil - } - copy := make(versioned.ResourceList, len(rl)) - for k, v := range rl { - copy[k] = *v.Copy() - } - return copy - } - - resourceListsEqual := func(a versioned.ResourceList, b versioned.ResourceList) bool { - if len(a) != len(b) { - return false - } - for k, v := range a { - vb, found := b[k] - if !found { - return false - } - if v.Cmp(vb) != 0 { - return false - } - } - return true - } - - for i, testcase := range tests { - node := versioned.Node{ - Status: versioned.NodeStatus{ - Capacity: copyResourceList(testcase.capacity), - Allocatable: copyResourceList(testcase.allocatable), - }, - } - node2 := roundTrip(t, runtime.Object(&node)).(*versioned.Node) - actual := node2.Status.Allocatable - expected := testcase.expectedAllocatable - if !resourceListsEqual(expected, actual) { - t.Errorf("[%d] Expected NodeStatus.Allocatable: %+v; Got: %+v", i, expected, actual) - } - } -} - -func TestSetDefaultObjectFieldSelectorAPIVersion(t *testing.T) { - s := versioned.PodSpec{ - Containers: []versioned.Container{ - { - Env: []versioned.EnvVar{ - { - ValueFrom: &versioned.EnvVarSource{ - FieldRef: &versioned.ObjectFieldSelector{}, - }, - }, - }, - }, - }, - } - pod := &versioned.Pod{ - Spec: s, - } - obj2 := roundTrip(t, runtime.Object(pod)) - pod2 := obj2.(*versioned.Pod) - s2 := pod2.Spec - - apiVersion := s2.Containers[0].Env[0].ValueFrom.FieldRef.APIVersion - if apiVersion != "v1" { - t.Errorf("Expected default APIVersion v1, got: %v", apiVersion) - } -} - -func TestSetDefaultRequestsPod(t *testing.T) { - // verify we default if limits are specified - s := versioned.PodSpec{} - s.Containers = []versioned.Container{ - { - Resources: versioned.ResourceRequirements{ - Limits: versioned.ResourceList{ - versioned.ResourceCPU: resource.MustParse("100m"), - }, - }, - }, - } - pod := &versioned.Pod{ - Spec: s, - } - output := roundTrip(t, runtime.Object(pod)) - pod2 := output.(*versioned.Pod) - defaultRequest := pod2.Spec.Containers[0].Resources.Requests - requestValue := defaultRequest[versioned.ResourceCPU] - if requestValue.String() != "100m" { - t.Errorf("Expected request cpu: %s, got: %s", "100m", requestValue.String()) - } - - // verify we do nothing if no limits are specified - s = versioned.PodSpec{} - s.Containers = []versioned.Container{{}} - pod = &versioned.Pod{ - Spec: s, - } - output = roundTrip(t, runtime.Object(pod)) - pod2 = output.(*versioned.Pod) - defaultRequest = pod2.Spec.Containers[0].Resources.Requests - requestValue = defaultRequest[versioned.ResourceCPU] - if requestValue.String() != "0" { - t.Errorf("Expected 0 request value, got: %s", requestValue.String()) - } -} - -func TestDefaultRequestIsNotSetForReplicationController(t *testing.T) { - s := versioned.PodSpec{} - s.Containers = []versioned.Container{ - { - Resources: versioned.ResourceRequirements{ - Limits: versioned.ResourceList{ - versioned.ResourceCPU: resource.MustParse("100m"), - }, - }, - }, - } - rc := &versioned.ReplicationController{ - Spec: versioned.ReplicationControllerSpec{ - Replicas: newInt(3), - Template: &versioned.PodTemplateSpec{ - ObjectMeta: versioned.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: s, - }, - }, - } - output := roundTrip(t, runtime.Object(rc)) - rc2 := output.(*versioned.ReplicationController) - defaultRequest := rc2.Spec.Template.Spec.Containers[0].Resources.Requests - requestValue := defaultRequest[versioned.ResourceCPU] - if requestValue.String() != "0" { - t.Errorf("Expected 0 request value, got: %s", requestValue.String()) - } -} - -func TestSetDefaultLimitRangeItem(t *testing.T) { - limitRange := &versioned.LimitRange{ - ObjectMeta: versioned.ObjectMeta{ - Name: "test-defaults", - }, - Spec: versioned.LimitRangeSpec{ - Limits: []versioned.LimitRangeItem{{ - Type: versioned.LimitTypeContainer, - Max: versioned.ResourceList{ - versioned.ResourceCPU: resource.MustParse("100m"), - }, - Min: versioned.ResourceList{ - versioned.ResourceMemory: resource.MustParse("100Mi"), - }, - Default: versioned.ResourceList{}, - DefaultRequest: versioned.ResourceList{}, - }}, - }, - } - - output := roundTrip(t, runtime.Object(limitRange)) - limitRange2 := output.(*versioned.LimitRange) - defaultLimit := limitRange2.Spec.Limits[0].Default - defaultRequest := limitRange2.Spec.Limits[0].DefaultRequest - - // verify that default cpu was set to the max - defaultValue := defaultLimit[versioned.ResourceCPU] - if defaultValue.String() != "100m" { - t.Errorf("Expected default cpu: %s, got: %s", "100m", defaultValue.String()) - } - // verify that default request was set to the limit - requestValue := defaultRequest[versioned.ResourceCPU] - if requestValue.String() != "100m" { - t.Errorf("Expected request cpu: %s, got: %s", "100m", requestValue.String()) - } - // verify that if a min is provided, it will be the default if no limit is specified - requestMinValue := defaultRequest[versioned.ResourceMemory] - if requestMinValue.String() != "100Mi" { - t.Errorf("Expected request memory: %s, got: %s", "100Mi", requestMinValue.String()) - } -} - -func TestSetDefaultProbe(t *testing.T) { - originalProbe := versioned.Probe{} - expectedProbe := versioned.Probe{ - InitialDelaySeconds: 0, - TimeoutSeconds: 1, - PeriodSeconds: 10, - SuccessThreshold: 1, - FailureThreshold: 3, - } - - pod := &versioned.Pod{ - Spec: versioned.PodSpec{ - Containers: []versioned.Container{{LivenessProbe: &originalProbe}}, - }, - } - - output := roundTrip(t, runtime.Object(pod)).(*versioned.Pod) - actualProbe := *output.Spec.Containers[0].LivenessProbe - if actualProbe != expectedProbe { - t.Errorf("Expected probe: %+v\ngot: %+v\n", expectedProbe, actualProbe) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/events_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/events_test.go deleted file mode 100644 index a2910d064..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/events_test.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 validation - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func TestValidateEvent(t *testing.T) { - table := []struct { - *api.Event - valid bool - }{ - { - &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - Namespace: "foo", - }, - InvolvedObject: api.ObjectReference{ - Namespace: "bar", - }, - }, - false, - }, { - &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - Namespace: "aoeu-_-aoeu", - }, - InvolvedObject: api.ObjectReference{ - Namespace: "aoeu-_-aoeu", - }, - }, - false, - }, - } - - for _, item := range table { - if e, a := item.valid, len(ValidateEvent(item.Event)) == 0; e != a { - t.Errorf("%v: expected %v, got %v", item.Event.Name, e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/name_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/name_test.go deleted file mode 100644 index b8687cdcc..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/name_test.go +++ /dev/null @@ -1,149 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 validation - -import ( - "strings" - "testing" -) - -func TestValidatePathSegmentName(t *testing.T) { - testcases := map[string]struct { - Name string - Prefix bool - ExpectedOK bool - ExpectedMsg string - }{ - "empty": { - Name: "", - Prefix: false, - ExpectedOK: true, - ExpectedMsg: "", - }, - "empty,prefix": { - Name: "", - Prefix: true, - ExpectedOK: true, - ExpectedMsg: "", - }, - - "valid": { - Name: "foo.bar.baz", - Prefix: false, - ExpectedOK: true, - ExpectedMsg: "", - }, - "valid,prefix": { - Name: "foo.bar.baz", - Prefix: true, - ExpectedOK: true, - ExpectedMsg: "", - }, - - // Make sure mixed case, non DNS subdomain characters are tolerated - "valid complex": { - Name: "sha256:ABCDEF012345@ABCDEF012345", - Prefix: false, - ExpectedOK: true, - ExpectedMsg: "", - }, - // Make sure non-ascii characters are tolerated - "valid extended charset": { - Name: "Iñtërnâtiônàlizætiøn", - Prefix: false, - ExpectedOK: true, - ExpectedMsg: "", - }, - - "dot": { - Name: ".", - Prefix: false, - ExpectedOK: false, - ExpectedMsg: ".", - }, - "dot leading": { - Name: ".test", - Prefix: false, - ExpectedOK: true, - ExpectedMsg: "", - }, - "dot,prefix": { - Name: ".", - Prefix: true, - ExpectedOK: true, // allowed because a suffix could make it valid - ExpectedMsg: "", - }, - - "dot dot": { - Name: "..", - Prefix: false, - ExpectedOK: false, - ExpectedMsg: "..", - }, - "dot dot leading": { - Name: "..test", - Prefix: false, - ExpectedOK: true, - ExpectedMsg: "", - }, - "dot dot,prefix": { - Name: "..", - Prefix: true, - ExpectedOK: true, // allowed because a suffix could make it valid - ExpectedMsg: "", - }, - - "slash": { - Name: "foo/bar", - Prefix: false, - ExpectedOK: false, - ExpectedMsg: "/", - }, - "slash,prefix": { - Name: "foo/bar", - Prefix: true, - ExpectedOK: false, - ExpectedMsg: "/", - }, - - "percent": { - Name: "foo%bar", - Prefix: false, - ExpectedOK: false, - ExpectedMsg: "%", - }, - "percent,prefix": { - Name: "foo%bar", - Prefix: true, - ExpectedOK: false, - ExpectedMsg: "%", - }, - } - - for k, tc := range testcases { - ok, msg := ValidatePathSegmentName(tc.Name, tc.Prefix) - if ok != tc.ExpectedOK { - t.Errorf("%s: expected ok=%v, got %v", k, tc.ExpectedOK, ok) - } - if len(tc.ExpectedMsg) == 0 && len(msg) > 0 { - t.Errorf("%s: expected no message, got %v", k, msg) - } - if len(tc.ExpectedMsg) > 0 && !strings.Contains(msg, tc.ExpectedMsg) { - t.Errorf("%s: expected message containing %q, got %v", k, tc.ExpectedMsg, msg) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/schema_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/schema_test.go deleted file mode 100644 index 9754110a5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/schema_test.go +++ /dev/null @@ -1,200 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 validation - -import ( - "io/ioutil" - "math/rand" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/runtime" - - "github.com/ghodss/yaml" -) - -func readPod(filename string) ([]byte, error) { - data, err := ioutil.ReadFile("testdata/" + testapi.Default.GroupVersion().Version + "/" + filename) - if err != nil { - return nil, err - } - return data, nil -} - -func readSwaggerFile() ([]byte, error) { - // TODO this path is broken - pathToSwaggerSpec := "../../../api/swagger-spec/" + testapi.Default.GroupVersion().Version + ".json" - return ioutil.ReadFile(pathToSwaggerSpec) -} - -func loadSchemaForTest() (Schema, error) { - data, err := readSwaggerFile() - if err != nil { - return nil, err - } - return NewSwaggerSchemaFromBytes(data) -} - -func TestLoad(t *testing.T) { - _, err := loadSchemaForTest() - if err != nil { - t.Errorf("Failed to load: %v", err) - } -} - -func TestValidateOk(t *testing.T) { - schema, err := loadSchemaForTest() - if err != nil { - t.Errorf("Failed to load: %v", err) - } - tests := []struct { - obj runtime.Object - typeName string - }{ - {obj: &api.Pod{}}, - {obj: &api.Service{}}, - {obj: &api.ReplicationController{}}, - } - - seed := rand.Int63() - apiObjectFuzzer := apitesting.FuzzerFor(nil, testapi.Default.InternalGroupVersion(), rand.NewSource(seed)) - for i := 0; i < 5; i++ { - for _, test := range tests { - testObj := test.obj - apiObjectFuzzer.Fuzz(testObj) - data, err := runtime.Encode(testapi.Default.Codec(), testObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - err = schema.ValidateBytes(data) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - } - } -} - -func TestInvalid(t *testing.T) { - schema, err := loadSchemaForTest() - if err != nil { - t.Errorf("Failed to load: %v", err) - } - tests := []string{ - "invalidPod1.json", // command is a string, instead of []string. - "invalidPod2.json", // hostPort if of type string, instead of int. - "invalidPod3.json", // volumes is not an array of objects. - "invalidPod.yaml", // command is a string, instead of []string. - } - for _, test := range tests { - pod, err := readPod(test) - if err != nil { - t.Errorf("could not read file: %s, err: %v", test, err) - } - err = schema.ValidateBytes(pod) - if err == nil { - t.Errorf("unexpected non-error, err: %s for pod: %s", err, pod) - } - } -} - -func TestValid(t *testing.T) { - schema, err := loadSchemaForTest() - if err != nil { - t.Errorf("Failed to load: %v", err) - } - tests := []string{ - "validPod.yaml", - } - for _, test := range tests { - pod, err := readPod(test) - if err != nil { - t.Errorf("could not read file: %s, err: %v", test, err) - } - err = schema.ValidateBytes(pod) - if err != nil { - t.Errorf("unexpected error %s, for pod %s", err, pod) - } - } -} - -func TestVersionRegex(t *testing.T) { - testCases := []struct { - typeName string - match bool - }{ - { - typeName: "v1.Binding", - match: true, - }, - { - typeName: "v1beta1.Binding", - match: true, - }, - { - typeName: "Binding", - match: false, - }, - } - for _, test := range testCases { - if versionRegexp.MatchString(test.typeName) && !test.match { - t.Errorf("unexpected error: expect %s not to match the regular expression", test.typeName) - } - if !versionRegexp.MatchString(test.typeName) && test.match { - t.Errorf("unexpected error: expect %s to match the regular expression", test.typeName) - } - } -} - -// Tests that validation works fine when spec contains "type": "any" instead of "type": "object" -// Ref: https://github.com/kubernetes/kubernetes/issues/24309 -func TestTypeOAny(t *testing.T) { - data, err := readSwaggerFile() - if err != nil { - t.Errorf("failed to read swagger file: %v", err) - } - // Replace type: "any" in the spec by type: "object" and verify that the validation still passes. - newData := strings.Replace(string(data), `"type": "object"`, `"type": "any"`, -1) - schema, err := NewSwaggerSchemaFromBytes([]byte(newData)) - if err != nil { - t.Errorf("Failed to load: %v", err) - } - tests := []string{ - "validPod.yaml", - } - for _, test := range tests { - podBytes, err := readPod(test) - if err != nil { - t.Errorf("could not read file: %s, err: %v", test, err) - } - // Verify that pod has at least one label (labels are type "any") - var pod api.Pod - err = yaml.Unmarshal(podBytes, &pod) - if err != nil { - t.Errorf("error in unmarshalling pod: %v", err) - } - if len(pod.Labels) == 0 { - t.Errorf("invalid test input: the pod should have at least one label") - } - err = schema.ValidateBytes(podBytes) - if err != nil { - t.Errorf("unexpected error %s, for pod %s", err, string(podBytes)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod.yaml b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod.yaml deleted file mode 100644 index 9557c55ff..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - labels: - name: redis-master - name: name -spec: - containers: - - args: "this is a bad command" - image: gcr.io/fake_project/fake_image:fake_tag - name: master diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod1.json b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod1.json deleted file mode 100644 index d935742d7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod1.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "name", - "labels": { - "name": "redis-master" - } - }, - "spec": { - "containers": [ - { - "name": "master", - "image": "gcr.io/fake_project/fake_image:fake_tag", - "args": "this is a bad command" - } - ] - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod2.json b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod2.json deleted file mode 100644 index 56e8f93ba..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod2.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "apache-php", - "labels": { - "name": "apache-php" - } - }, - "spec": { - "volumes": [{ - "name": "shared-disk" - }], - "containers": [ - { - "name": "apache-php", - "image": "gcr.io/fake_project/fake_image:fake_tag", - "ports": [ - { - "name": "apache", - "hostPort": "13380", - "containerPort": 80, - "protocol": "TCP" - } - ], - "volumeMounts": [ - { - "name": "shared-disk", - "mountPath": "/var/www/html" - } - ] - } - ] - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod3.json b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod3.json deleted file mode 100644 index 4d99181dc..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/invalidPod3.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "kind": "Pod", - "apiVersion": "v1", - "metadata": { - "name": "apache-php", - "labels": { - "name": "apache-php" - } - }, - "spec": { - "volumes": [ - "name": "shared-disk" - ], - "containers": [ - { - "name": "apache-php", - "image": "gcr.io/fake_project/fake_image:fake_tag", - "ports": [ - { - "name": "apache", - "hostPort": 13380, - "containerPort": 80, - "protocol": "TCP" - } - ], - "volumeMounts": [ - { - "name": "shared-disk", - "mountPath": "/var/www/html" - } - ] - } - ] - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/validPod.yaml b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/validPod.yaml deleted file mode 100644 index 3849ba7a1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/testdata/v1/validPod.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - labels: - name: redis-master - name: name -spec: - containers: - - args: - - this - - is - - an - - ok - - command - image: gcr.io/fake_project/fake_image:fake_tag - name: master diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/validation_test.go deleted file mode 100644 index eb1c325f0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/validation/validation_test.go +++ /dev/null @@ -1,5781 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 validation - -import ( - "math/rand" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/service" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/capabilities" - "k8s.io/kubernetes/pkg/util/intstr" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func expectPrefix(t *testing.T, prefix string, errs field.ErrorList) { - for i := range errs { - if f, p := errs[i].Field, prefix; !strings.HasPrefix(f, p) { - t.Errorf("expected prefix '%s' for field '%s' (%v)", p, f, errs[i]) - } - } -} - -// Ensure custom name functions are allowed -func TestValidateObjectMetaCustomName(t *testing.T) { - errs := ValidateObjectMeta( - &api.ObjectMeta{Name: "test", GenerateName: "foo"}, - false, - func(s string, prefix bool) (bool, string) { - if s == "test" { - return true, "" - } - return false, "name-gen" - }, - field.NewPath("field")) - if len(errs) != 1 { - t.Fatalf("unexpected errors: %v", errs) - } - if !strings.Contains(errs[0].Error(), "name-gen") { - t.Errorf("unexpected error message: %v", errs) - } -} - -// Ensure namespace names follow dns label format -func TestValidateObjectMetaNamespaces(t *testing.T) { - errs := ValidateObjectMeta( - &api.ObjectMeta{Name: "test", Namespace: "foo.bar"}, - true, - func(s string, prefix bool) (bool, string) { - return true, "" - }, - field.NewPath("field")) - if len(errs) != 1 { - t.Fatalf("unexpected errors: %v", errs) - } - if !strings.Contains(errs[0].Error(), `Invalid value: "foo.bar"`) { - t.Errorf("unexpected error message: %v", errs) - } - maxLength := 63 - letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") - b := make([]rune, maxLength+1) - for i := range b { - b[i] = letters[rand.Intn(len(letters))] - } - errs = ValidateObjectMeta( - &api.ObjectMeta{Name: "test", Namespace: string(b)}, - true, - func(s string, prefix bool) (bool, string) { - return true, "" - }, - field.NewPath("field")) - if len(errs) != 1 { - t.Fatalf("unexpected errors: %v", errs) - } - if !strings.Contains(errs[0].Error(), "Invalid value") { - t.Errorf("unexpected error message: %v", errs) - } -} - -func TestValidateObjectMetaOwnerReferences(t *testing.T) { - testCases := []struct { - ownerReferences []api.OwnerReference - expectError bool - }{ - { - []api.OwnerReference{ - { - APIVersion: "thirdpartyVersion", - Kind: "thirdpartyKind", - Name: "name", - UID: "1", - }, - }, - false, - }, - { - // event shouldn't be set as an owner - []api.OwnerReference{ - { - APIVersion: "v1", - Kind: "Event", - Name: "name", - UID: "1", - }, - }, - true, - }, - } - - for _, tc := range testCases { - errs := ValidateObjectMeta( - &api.ObjectMeta{Name: "test", Namespace: "test", OwnerReferences: tc.ownerReferences}, - true, - func(s string, prefix bool) (bool, string) { - return true, "" - }, - field.NewPath("field")) - if len(errs) != 0 && !tc.expectError { - t.Errorf("unexpected error: %v", errs) - } - if len(errs) == 0 && tc.expectError { - t.Errorf("expect error") - } - if len(errs) != 0 && !strings.Contains(errs[0].Error(), "is disallowed from being an owner") { - t.Errorf("unexpected error message: %v", errs) - } - } -} - -func TestValidateObjectMetaUpdateIgnoresCreationTimestamp(t *testing.T) { - if errs := ValidateObjectMetaUpdate( - &api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - &api.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: unversioned.NewTime(time.Unix(10, 0))}, - field.NewPath("field"), - ); len(errs) != 0 { - t.Fatalf("unexpected errors: %v", errs) - } - if errs := ValidateObjectMetaUpdate( - &api.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: unversioned.NewTime(time.Unix(10, 0))}, - &api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - field.NewPath("field"), - ); len(errs) != 0 { - t.Fatalf("unexpected errors: %v", errs) - } - if errs := ValidateObjectMetaUpdate( - &api.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: unversioned.NewTime(time.Unix(10, 0))}, - &api.ObjectMeta{Name: "test", ResourceVersion: "1", CreationTimestamp: unversioned.NewTime(time.Unix(11, 0))}, - field.NewPath("field"), - ); len(errs) != 0 { - t.Fatalf("unexpected errors: %v", errs) - } -} - -func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) { - now := unversioned.NewTime(time.Unix(1000, 0).UTC()) - later := unversioned.NewTime(time.Unix(2000, 0).UTC()) - gracePeriodShort := int64(30) - gracePeriodLong := int64(40) - - testcases := map[string]struct { - Old api.ObjectMeta - New api.ObjectMeta - ExpectedNew api.ObjectMeta - ExpectedErrs []string - }{ - "valid without deletion fields": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedErrs: []string{}, - }, - "valid with deletion fields": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedErrs: []string{}, - }, - - "invalid set deletionTimestamp": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{"field.deletionTimestamp: Invalid value: \"1970-01-01T00:16:40Z\": field is immutable; may only be changed via deletion"}, - }, - "invalid clear deletionTimestamp": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{}, // no errors, validation copies the old value - }, - "invalid change deletionTimestamp": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &later}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionTimestamp: &now}, - ExpectedErrs: []string{}, // no errors, validation copies the old value - }, - - "invalid set deletionGracePeriodSeconds": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 30: field is immutable; may only be changed via deletion"}, - }, - "invalid clear deletionGracePeriodSeconds": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - ExpectedErrs: []string{}, // no errors, validation copies the old value - }, - "invalid change deletionGracePeriodSeconds": { - Old: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodShort}, - New: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong}, - ExpectedNew: api.ObjectMeta{Name: "test", ResourceVersion: "1", DeletionGracePeriodSeconds: &gracePeriodLong}, - ExpectedErrs: []string{"field.deletionGracePeriodSeconds: Invalid value: 40: field is immutable; may only be changed via deletion"}, - }, - } - - for k, tc := range testcases { - errs := ValidateObjectMetaUpdate(&tc.New, &tc.Old, field.NewPath("field")) - if len(errs) != len(tc.ExpectedErrs) { - t.Logf("%s: Expected: %#v", k, tc.ExpectedErrs) - t.Logf("%s: Got: %#v", k, errs) - t.Errorf("%s: expected %d errors, got %d", k, len(tc.ExpectedErrs), len(errs)) - continue - } - for i := range errs { - if errs[i].Error() != tc.ExpectedErrs[i] { - t.Errorf("%s: error #%d: expected %q, got %q", k, i, tc.ExpectedErrs[i], errs[i].Error()) - } - } - if !reflect.DeepEqual(tc.New, tc.ExpectedNew) { - t.Errorf("%s: Expected after validation:\n%#v\ngot\n%#v", k, tc.ExpectedNew, tc.New) - } - } -} - -// Ensure trailing slash is allowed in generate name -func TestValidateObjectMetaTrimsTrailingSlash(t *testing.T) { - errs := ValidateObjectMeta( - &api.ObjectMeta{Name: "test", GenerateName: "foo-"}, - false, - NameIsDNSSubdomain, - field.NewPath("field")) - if len(errs) != 0 { - t.Fatalf("unexpected errors: %v", errs) - } -} - -// Ensure updating finalizers is disallowed -func TestValidateObjectMetaUpdateDisallowsUpdatingFinalizers(t *testing.T) { - errs := ValidateObjectMetaUpdate( - &api.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{"orphaning"}}, - &api.ObjectMeta{Name: "test", ResourceVersion: "1"}, - field.NewPath("field"), - ) - if len(errs) != 1 { - t.Fatalf("unexpected errors: %v", errs) - } - if !strings.Contains(errs[0].Error(), "field is immutable") { - t.Errorf("unexpected error message: %v", errs) - } -} - -func TestValidateAnnotations(t *testing.T) { - successCases := []map[string]string{ - {"simple": "bar"}, - {"now-with-dashes": "bar"}, - {"1-starts-with-num": "bar"}, - {"1234": "bar"}, - {"simple/simple": "bar"}, - {"now-with-dashes/simple": "bar"}, - {"now-with-dashes/now-with-dashes": "bar"}, - {"now.with.dots/simple": "bar"}, - {"now-with.dashes-and.dots/simple": "bar"}, - {"1-num.2-num/3-num": "bar"}, - {"1234/5678": "bar"}, - {"1.2.3.4/5678": "bar"}, - {"UpperCase123": "bar"}, - {"a": strings.Repeat("b", totalAnnotationSizeLimitB-1)}, - { - "a": strings.Repeat("b", totalAnnotationSizeLimitB/2-1), - "c": strings.Repeat("d", totalAnnotationSizeLimitB/2-1), - }, - } - for i := range successCases { - errs := ValidateAnnotations(successCases[i], field.NewPath("field")) - if len(errs) != 0 { - t.Errorf("case[%d] expected success, got %#v", i, errs) - } - } - - nameErrorCases := []map[string]string{ - {"nospecialchars^=@": "bar"}, - {"cantendwithadash-": "bar"}, - {"only/one/slash": "bar"}, - {strings.Repeat("a", 254): "bar"}, - } - for i := range nameErrorCases { - errs := ValidateAnnotations(nameErrorCases[i], field.NewPath("field")) - if len(errs) != 1 { - t.Errorf("case[%d] expected failure", i) - } - detail := errs[0].Detail - if detail != qualifiedNameErrorMsg { - t.Errorf("error detail %s should be equal %s", detail, qualifiedNameErrorMsg) - } - } - totalSizeErrorCases := []map[string]string{ - {"a": strings.Repeat("b", totalAnnotationSizeLimitB)}, - { - "a": strings.Repeat("b", totalAnnotationSizeLimitB/2), - "c": strings.Repeat("d", totalAnnotationSizeLimitB/2), - }, - } - for i := range totalSizeErrorCases { - errs := ValidateAnnotations(totalSizeErrorCases[i], field.NewPath("field")) - if len(errs) != 1 { - t.Errorf("case[%d] expected failure", i) - } - } -} - -func testVolume(name string, namespace string, spec api.PersistentVolumeSpec) *api.PersistentVolume { - objMeta := api.ObjectMeta{Name: name} - if namespace != "" { - objMeta.Namespace = namespace - } - - return &api.PersistentVolume{ - ObjectMeta: objMeta, - Spec: spec, - } -} - -func TestValidatePersistentVolumes(t *testing.T) { - scenarios := map[string]struct { - isExpectedFailure bool - volume *api.PersistentVolume - }{ - "good-volume": { - isExpectedFailure: false, - volume: testVolume("foo", "", api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }), - }, - "invalid-accessmode": { - isExpectedFailure: true, - volume: testVolume("foo", "", api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - AccessModes: []api.PersistentVolumeAccessMode{"fakemode"}, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }), - }, - "unexpected-namespace": { - isExpectedFailure: true, - volume: testVolume("foo", "unexpected-namespace", api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }), - }, - "bad-name": { - isExpectedFailure: true, - volume: testVolume("123*Bad(Name", "unexpected-namespace", api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }), - }, - "missing-name": { - isExpectedFailure: true, - volume: testVolume("", "", api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - }), - }, - "missing-capacity": { - isExpectedFailure: true, - volume: testVolume("foo", "", api.PersistentVolumeSpec{}), - }, - "missing-accessmodes": { - isExpectedFailure: true, - volume: testVolume("goodname", "missing-accessmodes", api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }), - }, - "too-many-sources": { - isExpectedFailure: true, - volume: testVolume("", "", api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("5G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "foo", FSType: "ext4"}, - }, - }), - }, - } - - for name, scenario := range scenarios { - errs := ValidatePersistentVolume(scenario.volume) - if len(errs) == 0 && scenario.isExpectedFailure { - t.Errorf("Unexpected success for scenario: %s", name) - } - if len(errs) > 0 && !scenario.isExpectedFailure { - t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs) - } - } - -} - -func testVolumeClaim(name string, namespace string, spec api.PersistentVolumeClaimSpec) *api.PersistentVolumeClaim { - return &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace}, - Spec: spec, - } -} - -func TestValidatePersistentVolumeClaim(t *testing.T) { - scenarios := map[string]struct { - isExpectedFailure bool - claim *api.PersistentVolumeClaim - }{ - "good-claim": { - isExpectedFailure: false, - claim: testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }), - }, - "invalid-accessmode": { - isExpectedFailure: true, - claim: testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{"fakemode"}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }), - }, - "missing-namespace": { - isExpectedFailure: true, - claim: testVolumeClaim("foo", "", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }), - }, - "no-access-modes": { - isExpectedFailure: true, - claim: testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }), - }, - "no-resource-requests": { - isExpectedFailure: true, - claim: testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - }, - }), - }, - "invalid-resource-requests": { - isExpectedFailure: true, - claim: testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - }), - }, - } - - for name, scenario := range scenarios { - errs := ValidatePersistentVolumeClaim(scenario.claim) - if len(errs) == 0 && scenario.isExpectedFailure { - t.Errorf("Unexpected success for scenario: %s", name) - } - if len(errs) > 0 && !scenario.isExpectedFailure { - t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs) - } - } -} - -func TestValidatePersistentVolumeClaimUpdate(t *testing.T) { - validClaim := testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }) - validUpdateClaim := testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - VolumeName: "volume", - }) - invalidUpdateClaimResources := testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("20G"), - }, - }, - VolumeName: "volume", - }) - invalidUpdateClaimAccessModes := testVolumeClaim("foo", "ns", api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - VolumeName: "volume", - }) - scenarios := map[string]struct { - isExpectedFailure bool - oldClaim *api.PersistentVolumeClaim - newClaim *api.PersistentVolumeClaim - }{ - "valid-update": { - isExpectedFailure: false, - oldClaim: validClaim, - newClaim: validUpdateClaim, - }, - "invalid-update-change-resources-on-bound-claim": { - isExpectedFailure: true, - oldClaim: validUpdateClaim, - newClaim: invalidUpdateClaimResources, - }, - "invalid-update-change-access-modes-on-bound-claim": { - isExpectedFailure: true, - oldClaim: validUpdateClaim, - newClaim: invalidUpdateClaimAccessModes, - }, - } - - for name, scenario := range scenarios { - // ensure we have a resource version specified for updates - scenario.oldClaim.ResourceVersion = "1" - scenario.newClaim.ResourceVersion = "1" - errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim) - if len(errs) == 0 && scenario.isExpectedFailure { - t.Errorf("Unexpected success for scenario: %s", name) - } - if len(errs) > 0 && !scenario.isExpectedFailure { - t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs) - } - } -} - -func TestValidateVolumes(t *testing.T) { - lun := int32(1) - successCase := []api.Volume{ - {Name: "abc", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/mnt/path1"}}}, - {Name: "123", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/mnt/path2"}}}, - {Name: "abc-123", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/mnt/path3"}}}, - {Name: "empty", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}, - {Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}, - {Name: "awsebs", VolumeSource: api.VolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{VolumeID: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}, - {Name: "gitrepo", VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "my-repo", Revision: "hashstring", Directory: "target"}}}, - {Name: "gitrepodot", VolumeSource: api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "my-repo", Directory: "."}}}, - {Name: "iscsidisk", VolumeSource: api.VolumeSource{ISCSI: &api.ISCSIVolumeSource{TargetPortal: "127.0.0.1", IQN: "iqn.2015-02.example.com:test", Lun: 1, FSType: "ext4", ReadOnly: false}}}, - {Name: "secret", VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "my-secret"}}}, - {Name: "glusterfs", VolumeSource: api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "host1", Path: "path", ReadOnly: false}}}, - {Name: "flocker", VolumeSource: api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "datasetName"}}}, - {Name: "rbd", VolumeSource: api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{"foo"}, RBDImage: "bar", FSType: "ext4"}}}, - {Name: "cinder", VolumeSource: api.VolumeSource{Cinder: &api.CinderVolumeSource{VolumeID: "29ea5088-4f60-4757-962e-dba678767887", FSType: "ext4", ReadOnly: false}}}, - {Name: "cephfs", VolumeSource: api.VolumeSource{CephFS: &api.CephFSVolumeSource{Monitors: []string{"foo"}}}}, - {Name: "downwardapi", VolumeSource: api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{ - {Path: "labels", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}, - {Path: "annotations", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.annotations"}}, - {Path: "namespace", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.namespace"}}, - {Path: "name", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.name"}}, - {Path: "path/withslash/andslash", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}, - {Path: "path/./withdot", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}, - {Path: "path/with..dot", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}, - {Path: "second-level-dirent-can-have/..dot", FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}, - }}}}, - {Name: "fc", VolumeSource: api.VolumeSource{FC: &api.FCVolumeSource{TargetWWNs: []string{"some_wwn"}, Lun: &lun, FSType: "ext4", ReadOnly: false}}}, - {Name: "flexvolume", VolumeSource: api.VolumeSource{FlexVolume: &api.FlexVolumeSource{Driver: "kubernetes.io/blue", FSType: "ext4"}}}, - {Name: "azure", VolumeSource: api.VolumeSource{AzureFile: &api.AzureFileVolumeSource{SecretName: "key", ShareName: "share", ReadOnly: false}}}, - } - names, errs := validateVolumes(successCase, field.NewPath("field")) - if len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - if len(names) != len(successCase) || !names.HasAll("abc", "123", "abc-123", "empty", "gcepd", "gitrepo", "secret", "iscsidisk", "cinder", "cephfs", "flexvolume", "fc") { - t.Errorf("wrong names result: %v", names) - } - emptyVS := api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}} - emptyPortal := api.VolumeSource{ISCSI: &api.ISCSIVolumeSource{TargetPortal: "", IQN: "iqn.2015-02.example.com:test", Lun: 1, FSType: "ext4", ReadOnly: false}} - emptyIQN := api.VolumeSource{ISCSI: &api.ISCSIVolumeSource{TargetPortal: "127.0.0.1", IQN: "", Lun: 1, FSType: "ext4", ReadOnly: false}} - emptyHosts := api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "", Path: "path", ReadOnly: false}} - emptyPath := api.VolumeSource{Glusterfs: &api.GlusterfsVolumeSource{EndpointsName: "host", Path: "", ReadOnly: false}} - emptyName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: ""}} - emptyMon := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{}, RBDImage: "bar", FSType: "ext4"}} - emptyImage := api.VolumeSource{RBD: &api.RBDVolumeSource{CephMonitors: []string{"foo"}, RBDImage: "", FSType: "ext4"}} - emptyCephFSMon := api.VolumeSource{CephFS: &api.CephFSVolumeSource{Monitors: []string{}}} - startsWithDots := api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "foo", Directory: "..dots/bar"}} - containsDots := api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "foo", Directory: "dots/../bar"}} - absPath := api.VolumeSource{GitRepo: &api.GitRepoVolumeSource{Repository: "foo", Directory: "/abstarget"}} - emptyPathName := api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{{Path: "", - FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}}, - }} - absolutePathName := api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{{Path: "/absolutepath", - FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}}, - }} - dotDotInPath := api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{{Path: "../../passwd", - FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}}, - }} - dotDotPathName := api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{{Path: "..badFileName", - FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}}, - }} - dotDotFirstLevelDirent := api.VolumeSource{DownwardAPI: &api.DownwardAPIVolumeSource{Items: []api.DownwardAPIVolumeFile{{Path: "..badDirName/goodFileName", - FieldRef: api.ObjectFieldSelector{ - APIVersion: "v1", - FieldPath: "metadata.labels"}}}, - }} - zeroWWN := api.VolumeSource{FC: &api.FCVolumeSource{TargetWWNs: []string{}, Lun: &lun, FSType: "ext4", ReadOnly: false}} - emptyLun := api.VolumeSource{FC: &api.FCVolumeSource{TargetWWNs: []string{"wwn"}, Lun: nil, FSType: "ext4", ReadOnly: false}} - slashInName := api.VolumeSource{Flocker: &api.FlockerVolumeSource{DatasetName: "foo/bar"}} - emptyAzureSecret := api.VolumeSource{AzureFile: &api.AzureFileVolumeSource{SecretName: "", ShareName: "share", ReadOnly: false}} - emptyAzureShare := api.VolumeSource{AzureFile: &api.AzureFileVolumeSource{SecretName: "name", ShareName: "", ReadOnly: false}} - errorCases := map[string]struct { - V []api.Volume - T field.ErrorType - F string - D string - }{ - "zero-length name": { - []api.Volume{{Name: "", VolumeSource: emptyVS}}, - field.ErrorTypeRequired, - "name", "", - }, - "name > 63 characters": { - []api.Volume{{Name: strings.Repeat("a", 64), VolumeSource: emptyVS}}, - field.ErrorTypeInvalid, - "name", "must be a DNS label", - }, - "name not a DNS label": { - []api.Volume{{Name: "a.b.c", VolumeSource: emptyVS}}, - field.ErrorTypeInvalid, - "name", "must be a DNS label", - }, - "name not unique": { - []api.Volume{{Name: "abc", VolumeSource: emptyVS}, {Name: "abc", VolumeSource: emptyVS}}, - field.ErrorTypeDuplicate, - "[1].name", "", - }, - "empty portal": { - []api.Volume{{Name: "badportal", VolumeSource: emptyPortal}}, - field.ErrorTypeRequired, - "iscsi.targetPortal", "", - }, - "empty iqn": { - []api.Volume{{Name: "badiqn", VolumeSource: emptyIQN}}, - field.ErrorTypeRequired, - "iscsi.iqn", "", - }, - "empty hosts": { - []api.Volume{{Name: "badhost", VolumeSource: emptyHosts}}, - field.ErrorTypeRequired, - "glusterfs.endpoints", "", - }, - "empty path": { - []api.Volume{{Name: "badpath", VolumeSource: emptyPath}}, - field.ErrorTypeRequired, - "glusterfs.path", "", - }, - "empty datasetName": { - []api.Volume{{Name: "badname", VolumeSource: emptyName}}, - field.ErrorTypeRequired, - "flocker.datasetName", "", - }, - "empty mon": { - []api.Volume{{Name: "badmon", VolumeSource: emptyMon}}, - field.ErrorTypeRequired, - "rbd.monitors", "", - }, - "empty image": { - []api.Volume{{Name: "badimage", VolumeSource: emptyImage}}, - field.ErrorTypeRequired, - "rbd.image", "", - }, - "empty cephfs mon": { - []api.Volume{{Name: "badmon", VolumeSource: emptyCephFSMon}}, - field.ErrorTypeRequired, - "cephfs.monitors", "", - }, - "empty metatada path": { - []api.Volume{{Name: "emptyname", VolumeSource: emptyPathName}}, - field.ErrorTypeRequired, - "downwardAPI.path", "", - }, - "absolute path": { - []api.Volume{{Name: "absolutepath", VolumeSource: absolutePathName}}, - field.ErrorTypeInvalid, - "downwardAPI.path", "", - }, - "dot dot path": { - []api.Volume{{Name: "dotdotpath", VolumeSource: dotDotInPath}}, - field.ErrorTypeInvalid, - "downwardAPI.path", `must not contain '..'`, - }, - "dot dot file name": { - []api.Volume{{Name: "dotdotfilename", VolumeSource: dotDotPathName}}, - field.ErrorTypeInvalid, - "downwardAPI.path", `must not start with '..'`, - }, - "dot dot first level dirent": { - []api.Volume{{Name: "dotdotdirfilename", VolumeSource: dotDotFirstLevelDirent}}, - field.ErrorTypeInvalid, - "downwardAPI.path", `must not start with '..'`, - }, - "empty wwn": { - []api.Volume{{Name: "badimage", VolumeSource: zeroWWN}}, - field.ErrorTypeRequired, - "fc.targetWWNs", "", - }, - "empty lun": { - []api.Volume{{Name: "badimage", VolumeSource: emptyLun}}, - field.ErrorTypeRequired, - "fc.lun", "", - }, - "slash in datasetName": { - []api.Volume{{Name: "slashinname", VolumeSource: slashInName}}, - field.ErrorTypeInvalid, - "flocker.datasetName", "must not contain '/'", - }, - "starts with '..'": { - []api.Volume{{Name: "badprefix", VolumeSource: startsWithDots}}, - field.ErrorTypeInvalid, - "gitRepo.directory", `must not start with '..'`, - }, - "contains '..'": { - []api.Volume{{Name: "containsdots", VolumeSource: containsDots}}, - field.ErrorTypeInvalid, - "gitRepo.directory", `must not contain '..'`, - }, - "absolute target": { - []api.Volume{{Name: "absolutetarget", VolumeSource: absPath}}, - field.ErrorTypeInvalid, - "gitRepo.directory", "", - }, - "empty secret": { - []api.Volume{{Name: "emptyaccount", VolumeSource: emptyAzureSecret}}, - field.ErrorTypeRequired, - "azureFile.secretName", "", - }, - "empty share": { - []api.Volume{{Name: "emptyaccount", VolumeSource: emptyAzureShare}}, - field.ErrorTypeRequired, - "azureFile.shareName", "", - }, - } - for k, v := range errorCases { - _, errs := validateVolumes(v.V, field.NewPath("field")) - if len(errs) == 0 { - t.Errorf("expected failure %s for %v", k, v.V) - continue - } - for i := range errs { - if errs[i].Type != v.T { - t.Errorf("%s: expected error to have type %q: %q", k, v.T, errs[i].Type) - } - if !strings.Contains(errs[i].Field, v.F) { - t.Errorf("%s: expected error field %q: %q", k, v.F, errs[i].Field) - } - if !strings.Contains(errs[i].Detail, v.D) { - t.Errorf("%s: expected error detail %q, got %q", k, v.D, errs[i].Detail) - } - } - } -} - -func TestValidatePorts(t *testing.T) { - successCase := []api.ContainerPort{ - {Name: "abc", ContainerPort: 80, HostPort: 80, Protocol: "TCP"}, - {Name: "easy", ContainerPort: 82, Protocol: "TCP"}, - {Name: "as", ContainerPort: 83, Protocol: "UDP"}, - {Name: "do-re-me", ContainerPort: 84, Protocol: "UDP"}, - {ContainerPort: 85, Protocol: "TCP"}, - } - if errs := validateContainerPorts(successCase, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - - nonCanonicalCase := []api.ContainerPort{ - {ContainerPort: 80, Protocol: "TCP"}, - } - if errs := validateContainerPorts(nonCanonicalCase, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - - errorCases := map[string]struct { - P []api.ContainerPort - T field.ErrorType - F string - D string - }{ - "name > 15 characters": { - []api.ContainerPort{{Name: strings.Repeat("a", 16), ContainerPort: 80, Protocol: "TCP"}}, - field.ErrorTypeInvalid, - "name", PortNameErrorMsg, - }, - "name not a IANA svc name ": { - []api.ContainerPort{{Name: "a.b.c", ContainerPort: 80, Protocol: "TCP"}}, - field.ErrorTypeInvalid, - "name", PortNameErrorMsg, - }, - "name not a IANA svc name (i.e. a number)": { - []api.ContainerPort{{Name: "80", ContainerPort: 80, Protocol: "TCP"}}, - field.ErrorTypeInvalid, - "name", PortNameErrorMsg, - }, - "name not unique": { - []api.ContainerPort{ - {Name: "abc", ContainerPort: 80, Protocol: "TCP"}, - {Name: "abc", ContainerPort: 81, Protocol: "TCP"}, - }, - field.ErrorTypeDuplicate, - "[1].name", "", - }, - "zero container port": { - []api.ContainerPort{{ContainerPort: 0, Protocol: "TCP"}}, - field.ErrorTypeInvalid, - "containerPort", PortRangeErrorMsg, - }, - "invalid container port": { - []api.ContainerPort{{ContainerPort: 65536, Protocol: "TCP"}}, - field.ErrorTypeInvalid, - "containerPort", PortRangeErrorMsg, - }, - "invalid host port": { - []api.ContainerPort{{ContainerPort: 80, HostPort: 65536, Protocol: "TCP"}}, - field.ErrorTypeInvalid, - "hostPort", PortRangeErrorMsg, - }, - "invalid protocol case": { - []api.ContainerPort{{ContainerPort: 80, Protocol: "tcp"}}, - field.ErrorTypeNotSupported, - "protocol", "supported values: TCP, UDP", - }, - "invalid protocol": { - []api.ContainerPort{{ContainerPort: 80, Protocol: "ICMP"}}, - field.ErrorTypeNotSupported, - "protocol", "supported values: TCP, UDP", - }, - "protocol required": { - []api.ContainerPort{{Name: "abc", ContainerPort: 80}}, - field.ErrorTypeRequired, - "protocol", "", - }, - } - for k, v := range errorCases { - errs := validateContainerPorts(v.P, field.NewPath("field")) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - if errs[i].Type != v.T { - t.Errorf("%s: expected error to have type %q: %q", k, v.T, errs[i].Type) - } - if !strings.Contains(errs[i].Field, v.F) { - t.Errorf("%s: expected error field %q: %q", k, v.F, errs[i].Field) - } - if !strings.Contains(errs[i].Detail, v.D) { - t.Errorf("%s: expected error detail %q, got %q", k, v.D, errs[i].Detail) - } - } - } -} - -func TestValidateEnv(t *testing.T) { - successCase := []api.EnvVar{ - {Name: "abc", Value: "value"}, - {Name: "ABC", Value: "value"}, - {Name: "AbC_123", Value: "value"}, - {Name: "abc", Value: ""}, - { - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - APIVersion: testapi.Default.GroupVersion().String(), - FieldPath: "metadata.name", - }, - }, - }, - { - Name: "secret_value", - ValueFrom: &api.EnvVarSource{ - SecretKeyRef: &api.SecretKeySelector{ - LocalObjectReference: api.LocalObjectReference{ - Name: "some-secret", - }, - Key: "secret-key", - }, - }, - }, - { - Name: "ENV_VAR_1", - ValueFrom: &api.EnvVarSource{ - ConfigMapKeyRef: &api.ConfigMapKeySelector{ - LocalObjectReference: api.LocalObjectReference{ - Name: "some-config-map", - }, - Key: "some-key", - }, - }, - }, - } - if errs := validateEnv(successCase, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - - errorCases := []struct { - name string - envs []api.EnvVar - expectedError string - }{ - { - name: "zero-length name", - envs: []api.EnvVar{{Name: ""}}, - expectedError: "[0].name: Required value", - }, - { - name: "name not a C identifier", - envs: []api.EnvVar{{Name: "a.b.c"}}, - expectedError: `[0].name: Invalid value: "a.b.c": must be a C identifier (matching regex [A-Za-z_][A-Za-z0-9_]*): e.g. "my_name" or "MyName"`, - }, - { - name: "value and valueFrom specified", - envs: []api.EnvVar{{ - Name: "abc", - Value: "foo", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - APIVersion: testapi.Default.GroupVersion().String(), - FieldPath: "metadata.name", - }, - }, - }}, - expectedError: "[0].valueFrom: Invalid value: \"\": may not be specified when `value` is not empty", - }, - { - name: "valueFrom.fieldRef and valueFrom.secretKeyRef specified", - envs: []api.EnvVar{{ - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - APIVersion: testapi.Default.GroupVersion().String(), - FieldPath: "metadata.name", - }, - SecretKeyRef: &api.SecretKeySelector{ - LocalObjectReference: api.LocalObjectReference{ - Name: "a-secret", - }, - Key: "a-key", - }, - }, - }}, - expectedError: "[0].valueFrom: Invalid value: \"\": may not have more than one field specified at a time", - }, - { - name: "valueFrom.fieldRef and valueFrom.configMapKeyRef set", - envs: []api.EnvVar{{ - Name: "some_var_name", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - APIVersion: testapi.Default.GroupVersion().String(), - FieldPath: "metadata.name", - }, - ConfigMapKeyRef: &api.ConfigMapKeySelector{ - LocalObjectReference: api.LocalObjectReference{ - Name: "some-config-map", - }, - Key: "some-key", - }, - }, - }}, - expectedError: `[0].valueFrom: Invalid value: "": may not have more than one field specified at a time`, - }, - { - name: "valueFrom.fieldRef and valueFrom.secretKeyRef specified", - envs: []api.EnvVar{{ - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - APIVersion: testapi.Default.GroupVersion().String(), - FieldPath: "metadata.name", - }, - SecretKeyRef: &api.SecretKeySelector{ - LocalObjectReference: api.LocalObjectReference{ - Name: "a-secret", - }, - Key: "a-key", - }, - ConfigMapKeyRef: &api.ConfigMapKeySelector{ - LocalObjectReference: api.LocalObjectReference{ - Name: "some-config-map", - }, - Key: "some-key", - }, - }, - }}, - expectedError: `[0].valueFrom: Invalid value: "": may not have more than one field specified at a time`, - }, - { - name: "missing FieldPath on ObjectFieldSelector", - envs: []api.EnvVar{{ - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - APIVersion: testapi.Default.GroupVersion().String(), - }, - }, - }}, - expectedError: `[0].valueFrom.fieldRef.fieldPath: Required value`, - }, - { - name: "missing APIVersion on ObjectFieldSelector", - envs: []api.EnvVar{{ - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - FieldPath: "metadata.name", - }, - }, - }}, - expectedError: `[0].valueFrom.fieldRef.apiVersion: Required value`, - }, - { - name: "invalid fieldPath", - envs: []api.EnvVar{{ - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - FieldPath: "metadata.whoops", - APIVersion: testapi.Default.GroupVersion().String(), - }, - }, - }}, - expectedError: `[0].valueFrom.fieldRef.fieldPath: Invalid value: "metadata.whoops": error converting fieldPath`, - }, - { - name: "invalid fieldPath labels", - envs: []api.EnvVar{{ - Name: "labels", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - FieldPath: "metadata.labels", - APIVersion: "v1", - }, - }, - }}, - expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: metadata.name, metadata.namespace, status.podIP`, - }, - { - name: "invalid fieldPath annotations", - envs: []api.EnvVar{{ - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - FieldPath: "metadata.annotations", - APIVersion: "v1", - }, - }, - }}, - expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: metadata.name, metadata.namespace, status.podIP`, - }, - { - name: "unsupported fieldPath", - envs: []api.EnvVar{{ - Name: "abc", - ValueFrom: &api.EnvVarSource{ - FieldRef: &api.ObjectFieldSelector{ - FieldPath: "status.phase", - APIVersion: testapi.Default.GroupVersion().String(), - }, - }, - }}, - expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: metadata.name, metadata.namespace, status.podIP`, - }, - } - for _, tc := range errorCases { - if errs := validateEnv(tc.envs, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %s", tc.name) - } else { - for i := range errs { - str := errs[i].Error() - if str != "" && !strings.Contains(str, tc.expectedError) { - t.Errorf("%s: expected error detail either empty or %q, got %q", tc.name, tc.expectedError, str) - } - } - } - } -} - -func TestValidateVolumeMounts(t *testing.T) { - volumes := sets.NewString("abc", "123", "abc-123") - - successCase := []api.VolumeMount{ - {Name: "abc", MountPath: "/foo"}, - {Name: "123", MountPath: "/bar"}, - {Name: "abc-123", MountPath: "/baz"}, - {Name: "abc-123", MountPath: "/baa", SubPath: ""}, - {Name: "abc-123", MountPath: "/bab", SubPath: "baz"}, - {Name: "abc-123", MountPath: "/bac", SubPath: ".baz"}, - {Name: "abc-123", MountPath: "/bad", SubPath: "..baz"}, - } - if errs := validateVolumeMounts(successCase, volumes, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - - errorCases := map[string][]api.VolumeMount{ - "empty name": {{Name: "", MountPath: "/foo"}}, - "name not found": {{Name: "", MountPath: "/foo"}}, - "empty mountpath": {{Name: "abc", MountPath: ""}}, - "colon mountpath": {{Name: "abc", MountPath: "foo:bar"}}, - "mountpath collision": {{Name: "foo", MountPath: "/path/a"}, {Name: "bar", MountPath: "/path/a"}}, - "absolute subpath": {{Name: "abc", MountPath: "/bar", SubPath: "/baz"}}, - "subpath in ..": {{Name: "abc", MountPath: "/bar", SubPath: "../baz"}}, - "subpath contains ..": {{Name: "abc", MountPath: "/bar", SubPath: "baz/../bat"}}, - "subpath ends in ..": {{Name: "abc", MountPath: "/bar", SubPath: "./.."}}, - } - for k, v := range errorCases { - if errs := validateVolumeMounts(v, volumes, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - } -} - -func TestValidateProbe(t *testing.T) { - handler := api.Handler{Exec: &api.ExecAction{Command: []string{"echo"}}} - // These fields must be positive. - positiveFields := [...]string{"InitialDelaySeconds", "TimeoutSeconds", "PeriodSeconds", "SuccessThreshold", "FailureThreshold"} - successCases := []*api.Probe{nil} - for _, field := range positiveFields { - probe := &api.Probe{Handler: handler} - reflect.ValueOf(probe).Elem().FieldByName(field).SetInt(10) - successCases = append(successCases, probe) - } - - for _, p := range successCases { - if errs := validateProbe(p, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []*api.Probe{{TimeoutSeconds: 10, InitialDelaySeconds: 10}} - for _, field := range positiveFields { - probe := &api.Probe{Handler: handler} - reflect.ValueOf(probe).Elem().FieldByName(field).SetInt(-10) - errorCases = append(errorCases, probe) - } - for _, p := range errorCases { - if errs := validateProbe(p, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %v", p) - } - } -} - -func TestValidateHandler(t *testing.T) { - successCases := []api.Handler{ - {Exec: &api.ExecAction{Command: []string{"echo"}}}, - {HTTPGet: &api.HTTPGetAction{Path: "/", Port: intstr.FromInt(1), Host: "", Scheme: "HTTP"}}, - {HTTPGet: &api.HTTPGetAction{Path: "/foo", Port: intstr.FromInt(65535), Host: "host", Scheme: "HTTP"}}, - {HTTPGet: &api.HTTPGetAction{Path: "/", Port: intstr.FromString("port"), Host: "", Scheme: "HTTP"}}, - {HTTPGet: &api.HTTPGetAction{Path: "/", Port: intstr.FromString("port"), Host: "", Scheme: "HTTP", HTTPHeaders: []api.HTTPHeader{{"Host", "foo.example.com"}}}}, - {HTTPGet: &api.HTTPGetAction{Path: "/", Port: intstr.FromString("port"), Host: "", Scheme: "HTTP", HTTPHeaders: []api.HTTPHeader{{"X-Forwarded-For", "1.2.3.4"}, {"X-Forwarded-For", "5.6.7.8"}}}}, - } - for _, h := range successCases { - if errs := validateHandler(&h, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []api.Handler{ - {}, - {Exec: &api.ExecAction{Command: []string{}}}, - {HTTPGet: &api.HTTPGetAction{Path: "", Port: intstr.FromInt(0), Host: ""}}, - {HTTPGet: &api.HTTPGetAction{Path: "/foo", Port: intstr.FromInt(65536), Host: "host"}}, - {HTTPGet: &api.HTTPGetAction{Path: "", Port: intstr.FromString(""), Host: ""}}, - {HTTPGet: &api.HTTPGetAction{Path: "/", Port: intstr.FromString("port"), Host: "", Scheme: "HTTP", HTTPHeaders: []api.HTTPHeader{{"Host:", "foo.example.com"}}}}, - {HTTPGet: &api.HTTPGetAction{Path: "/", Port: intstr.FromString("port"), Host: "", Scheme: "HTTP", HTTPHeaders: []api.HTTPHeader{{"X_Forwarded_For", "foo.example.com"}}}}, - } - for _, h := range errorCases { - if errs := validateHandler(&h, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %#v", h) - } - } -} - -func TestValidatePullPolicy(t *testing.T) { - type T struct { - Container api.Container - ExpectedPolicy api.PullPolicy - } - testCases := map[string]T{ - "NotPresent1": { - api.Container{Name: "abc", Image: "image:latest", ImagePullPolicy: "IfNotPresent"}, - api.PullIfNotPresent, - }, - "NotPresent2": { - api.Container{Name: "abc1", Image: "image", ImagePullPolicy: "IfNotPresent"}, - api.PullIfNotPresent, - }, - "Always1": { - api.Container{Name: "123", Image: "image:latest", ImagePullPolicy: "Always"}, - api.PullAlways, - }, - "Always2": { - api.Container{Name: "1234", Image: "image", ImagePullPolicy: "Always"}, - api.PullAlways, - }, - "Never1": { - api.Container{Name: "abc-123", Image: "image:latest", ImagePullPolicy: "Never"}, - api.PullNever, - }, - "Never2": { - api.Container{Name: "abc-1234", Image: "image", ImagePullPolicy: "Never"}, - api.PullNever, - }, - } - for k, v := range testCases { - ctr := &v.Container - errs := validatePullPolicy(ctr.ImagePullPolicy, field.NewPath("field")) - if len(errs) != 0 { - t.Errorf("case[%s] expected success, got %#v", k, errs) - } - if ctr.ImagePullPolicy != v.ExpectedPolicy { - t.Errorf("case[%s] expected policy %v, got %v", k, v.ExpectedPolicy, ctr.ImagePullPolicy) - } - } -} - -func getResourceLimits(cpu, memory string) api.ResourceList { - res := api.ResourceList{} - res[api.ResourceCPU] = resource.MustParse(cpu) - res[api.ResourceMemory] = resource.MustParse(memory) - return res -} - -func TestValidateContainers(t *testing.T) { - volumes := sets.String{} - capabilities.SetForTests(capabilities.Capabilities{ - AllowPrivileged: true, - }) - - successCase := []api.Container{ - {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}, - {Name: "123", Image: "image", ImagePullPolicy: "IfNotPresent"}, - {Name: "abc-123", Image: "image", ImagePullPolicy: "IfNotPresent"}, - { - Name: "life-123", - Image: "image", - Lifecycle: &api.Lifecycle{ - PreStop: &api.Handler{ - Exec: &api.ExecAction{Command: []string{"ls", "-l"}}, - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - { - Name: "resources-test", - Image: "image", - Resources: api.ResourceRequirements{ - Limits: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - api.ResourceName("my.org/resource"): resource.MustParse("10m"), - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - { - Name: "resources-request-limit-simple", - Image: "image", - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("8"), - }, - Limits: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - { - Name: "resources-request-limit-edge", - Image: "image", - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - api.ResourceName("my.org/resource"): resource.MustParse("10m"), - }, - Limits: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - api.ResourceName("my.org/resource"): resource.MustParse("10m"), - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - { - Name: "resources-request-limit-partials", - Image: "image", - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("9.5"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - Limits: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName("my.org/resource"): resource.MustParse("10m"), - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - { - Name: "resources-request", - Image: "image", - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("9.5"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - { - Name: "same-host-port-different-protocol", - Image: "image", - Ports: []api.ContainerPort{ - {ContainerPort: 80, HostPort: 80, Protocol: "TCP"}, - {ContainerPort: 80, HostPort: 80, Protocol: "UDP"}, - }, - ImagePullPolicy: "IfNotPresent", - }, - {Name: "abc-1234", Image: "image", ImagePullPolicy: "IfNotPresent", SecurityContext: fakeValidSecurityContext(true)}, - } - if errs := validateContainers(successCase, volumes, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - - capabilities.SetForTests(capabilities.Capabilities{ - AllowPrivileged: false, - }) - errorCases := map[string][]api.Container{ - "zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - "name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent"}}, - "name not a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - "name not unique": { - {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}, - {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}, - }, - "zero-length image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent"}}, - "host port not unique": { - {Name: "abc", Image: "image", Ports: []api.ContainerPort{{ContainerPort: 80, HostPort: 80, Protocol: "TCP"}}, - ImagePullPolicy: "IfNotPresent"}, - {Name: "def", Image: "image", Ports: []api.ContainerPort{{ContainerPort: 81, HostPort: 80, Protocol: "TCP"}}, - ImagePullPolicy: "IfNotPresent"}, - }, - "invalid env var name": { - {Name: "abc", Image: "image", Env: []api.EnvVar{{Name: "ev.1"}}, ImagePullPolicy: "IfNotPresent"}, - }, - "unknown volume name": { - {Name: "abc", Image: "image", VolumeMounts: []api.VolumeMount{{Name: "anything", MountPath: "/foo"}}, - ImagePullPolicy: "IfNotPresent"}, - }, - "invalid lifecycle, no exec command.": { - { - Name: "life-123", - Image: "image", - Lifecycle: &api.Lifecycle{ - PreStop: &api.Handler{ - Exec: &api.ExecAction{}, - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "invalid lifecycle, no http path.": { - { - Name: "life-123", - Image: "image", - Lifecycle: &api.Lifecycle{ - PreStop: &api.Handler{ - HTTPGet: &api.HTTPGetAction{}, - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "invalid lifecycle, no tcp socket port.": { - { - Name: "life-123", - Image: "image", - Lifecycle: &api.Lifecycle{ - PreStop: &api.Handler{ - TCPSocket: &api.TCPSocketAction{}, - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "invalid lifecycle, zero tcp socket port.": { - { - Name: "life-123", - Image: "image", - Lifecycle: &api.Lifecycle{ - PreStop: &api.Handler{ - TCPSocket: &api.TCPSocketAction{ - Port: intstr.FromInt(0), - }, - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "invalid lifecycle, no action.": { - { - Name: "life-123", - Image: "image", - Lifecycle: &api.Lifecycle{ - PreStop: &api.Handler{}, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "invalid liveness probe, no tcp socket port.": { - { - Name: "life-123", - Image: "image", - LivenessProbe: &api.Probe{ - Handler: api.Handler{ - TCPSocket: &api.TCPSocketAction{}, - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "invalid liveness probe, no action.": { - { - Name: "life-123", - Image: "image", - LivenessProbe: &api.Probe{ - Handler: api.Handler{}, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "privilege disabled": { - {Name: "abc", Image: "image", SecurityContext: fakeValidSecurityContext(true)}, - }, - "invalid compute resource": { - { - Name: "abc-123", - Image: "image", - Resources: api.ResourceRequirements{ - Limits: api.ResourceList{ - "disk": resource.MustParse("10G"), - }, - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "Resource CPU invalid": { - { - Name: "abc-123", - Image: "image", - Resources: api.ResourceRequirements{ - Limits: getResourceLimits("-10", "0"), - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "Resource Requests CPU invalid": { - { - Name: "abc-123", - Image: "image", - Resources: api.ResourceRequirements{ - Requests: getResourceLimits("-10", "0"), - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "Resource Memory invalid": { - { - Name: "abc-123", - Image: "image", - Resources: api.ResourceRequirements{ - Limits: getResourceLimits("0", "-10"), - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "Request limit simple invalid": { - { - Name: "abc-123", - Image: "image", - Resources: api.ResourceRequirements{ - Limits: getResourceLimits("5", "3"), - Requests: getResourceLimits("6", "3"), - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - "Request limit multiple invalid": { - { - Name: "abc-123", - Image: "image", - Resources: api.ResourceRequirements{ - Limits: getResourceLimits("5", "3"), - Requests: getResourceLimits("6", "4"), - }, - ImagePullPolicy: "IfNotPresent", - }, - }, - } - for k, v := range errorCases { - if errs := validateContainers(v, volumes, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - } -} - -func TestValidateRestartPolicy(t *testing.T) { - successCases := []api.RestartPolicy{ - api.RestartPolicyAlways, - api.RestartPolicyOnFailure, - api.RestartPolicyNever, - } - for _, policy := range successCases { - if errs := validateRestartPolicy(&policy, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []api.RestartPolicy{"", "newpolicy"} - - for k, policy := range errorCases { - if errs := validateRestartPolicy(&policy, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %d", k) - } - } -} - -func TestValidateDNSPolicy(t *testing.T) { - successCases := []api.DNSPolicy{api.DNSClusterFirst, api.DNSDefault, api.DNSPolicy(api.DNSClusterFirst)} - for _, policy := range successCases { - if errs := validateDNSPolicy(&policy, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []api.DNSPolicy{api.DNSPolicy("invalid")} - for _, policy := range errorCases { - if errs := validateDNSPolicy(&policy, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %v", policy) - } - } -} - -func TestValidatePodSpec(t *testing.T) { - activeDeadlineSeconds := int64(30) - minID := int64(0) - maxID := int64(2147483647) - successCases := []api.PodSpec{ - { // Populate basic fields, leave defaults for most. - Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - { // Populate all fields. - Volumes: []api.Volume{ - {Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}, - }, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - NodeSelector: map[string]string{ - "key": "value", - }, - NodeName: "foobar", - DNSPolicy: api.DNSClusterFirst, - ActiveDeadlineSeconds: &activeDeadlineSeconds, - ServiceAccountName: "acct", - }, - { // Populate HostNetwork. - Containers: []api.Container{ - {Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", Ports: []api.ContainerPort{ - {HostPort: 8080, ContainerPort: 8080, Protocol: "TCP"}}, - }, - }, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: true, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - { // Populate RunAsUser SupplementalGroups FSGroup with minID 0 - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - SupplementalGroups: []int64{minID}, - RunAsUser: &minID, - FSGroup: &minID, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - { // Populate RunAsUser SupplementalGroups FSGroup with maxID 2147483647 - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - SupplementalGroups: []int64{maxID}, - RunAsUser: &maxID, - FSGroup: &maxID, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - { // Populate HostIPC. - SecurityContext: &api.PodSecurityContext{ - HostIPC: true, - }, - Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - { // Populate HostPID. - SecurityContext: &api.PodSecurityContext{ - HostPID: true, - }, - Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - { // Populate Affinity. - Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - } - for i := range successCases { - if errs := ValidatePodSpec(&successCases[i], field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - activeDeadlineSeconds = int64(0) - minID = int64(-1) - maxID = int64(2147483648) - failureCases := map[string]api.PodSpec{ - "bad volume": { - Volumes: []api.Volume{{}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - "no containers": { - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad container": { - Containers: []api.Container{{}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad DNS policy": { - DNSPolicy: api.DNSPolicy("invalid"), - RestartPolicy: api.RestartPolicyAlways, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - "bad service account name": { - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - ServiceAccountName: "invalidName", - }, - "bad restart policy": { - RestartPolicy: "UnknowPolicy", - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - "with hostNetwork hostPort not equal to containerPort": { - Containers: []api.Container{ - {Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", Ports: []api.ContainerPort{ - {HostPort: 8080, ContainerPort: 2600, Protocol: "TCP"}}, - }, - }, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: true, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad supplementalGroups large than math.MaxInt32": { - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: false, - SupplementalGroups: []int64{maxID, 1234}, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad supplementalGroups less than 0": { - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: false, - SupplementalGroups: []int64{minID, 1234}, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad runAsUser large than math.MaxInt32": { - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: false, - RunAsUser: &maxID, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad runAsUser less than 0": { - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: false, - RunAsUser: &minID, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad fsGroup large than math.MaxInt32": { - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: false, - FSGroup: &maxID, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad fsGroup less than 0": { - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - SecurityContext: &api.PodSecurityContext{ - HostNetwork: false, - FSGroup: &minID, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - "bad-active-deadline-seconds": { - Volumes: []api.Volume{ - {Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}, - }, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - NodeSelector: map[string]string{ - "key": "value", - }, - NodeName: "foobar", - DNSPolicy: api.DNSClusterFirst, - ActiveDeadlineSeconds: &activeDeadlineSeconds, - }, - "bad nodeName": { - NodeName: "node name", - Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - } - for k, v := range failureCases { - if errs := ValidatePodSpec(&v, field.NewPath("field")); len(errs) == 0 { - t.Errorf("expected failure for %q", k) - } - } -} - -func TestValidatePod(t *testing.T) { - successCases := []api.Pod{ - { // Basic fields. - ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"}, - Spec: api.PodSpec{ - Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}}, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - { // Just about everything. - ObjectMeta: api.ObjectMeta{Name: "abc.123.do-re-mi", Namespace: "ns"}, - Spec: api.PodSpec{ - Volumes: []api.Volume{ - {Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}, - }, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - NodeSelector: map[string]string{ - "key": "value", - }, - NodeName: "foobar", - }, - }, - } - for _, pod := range successCases { - if errs := ValidatePod(&pod); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]api.Pod{ - "bad name": { - ObjectMeta: api.ObjectMeta{Name: "", Namespace: "ns"}, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - "bad namespace": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - "bad spec": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "ns"}, - Spec: api.PodSpec{ - Containers: []api.Container{{}}, - }, - }, - "bad label": { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "ns", - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - for k, v := range errorCases { - if errs := ValidatePod(&v); len(errs) == 0 { - t.Errorf("expected failure for %q", k) - } - } -} - -func TestValidateAffinity(t *testing.T) { - successCases := []api.Pod{ - { // Serialized affinity requirements in annotations. - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - // TODO: Uncomment and move this block into Annotations map once - // RequiredDuringSchedulingRequiredDuringExecution is implemented - // "requiredDuringSchedulingRequiredDuringExecution": { - // "nodeSelectorTerms": [{ - // "matchExpressions": [{ - // "key": "key1", - // "operator": "Exists" - // }] - // }] - // }, - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"nodeAffinity": { - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [{ - "matchExpressions": [{ - "key": "key2", - "operator": "In", - "values": ["value1", "value2"] - }] - }] - }, - "preferredDuringSchedulingIgnoredDuringExecution": [ - { - "weight": 10, - "preference": {"matchExpressions": [ - { - "key": "foo", - "operator": "In", "values": ["bar"] - } - ]} - } - ] - }}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - { // Serialized pod affinity in affinity requirements in annotations. - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - // TODO: Uncomment and move this block into Annotations map once - // RequiredDuringSchedulingRequiredDuringExecution is implemented - // "requiredDuringSchedulingRequiredDuringExecution": [{ - // "labelSelector": { - // "matchExpressions": [{ - // "key": "key2", - // "operator": "In", - // "values": ["value1", "value2"] - // }] - // }, - // "namespaces":["ns"], - // "topologyKey": "zone" - // }] - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAffinity": { - "requiredDuringSchedulingIgnoredDuringExecution": [{ - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "In", - "values": ["value1", "value2"] - }] - }, - "topologyKey": "zone", - "namespaces": ["ns"] - }], - "preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "NotIn", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["ns"], - "topologyKey": "region" - } - }] - }}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - { // Serialized pod anti affinity with different Label Operators in affinity requirements in annotations. - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - // TODO: Uncomment and move this block into Annotations map once - // RequiredDuringSchedulingRequiredDuringExecution is implemented - // "requiredDuringSchedulingRequiredDuringExecution": [{ - // "labelSelector": { - // "matchExpressions": [{ - // "key": "key2", - // "operator": "In", - // "values": ["value1", "value2"] - // }] - // }, - // "namespaces":["ns"], - // "topologyKey": "zone" - // }] - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAntiAffinity": { - "requiredDuringSchedulingIgnoredDuringExecution": [{ - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "Exists" - }] - }, - "topologyKey": "zone", - "namespaces": ["ns"] - }], - "preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "DoesNotExist" - }] - }, - "namespaces": ["ns"], - "topologyKey": "region" - } - }] - }}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - } - for _, pod := range successCases { - if errs := ValidatePod(&pod); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]api.Pod{ - "invalid json of node affinity in pod annotations": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"nodeAffinity": { - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [{ - `, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid node selector requirement in node affinity in pod annotations, operator can't be null": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"nodeAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [{ - "matchExpressions": [{ - "key": "key1", - }] - }] - }}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid preferredSchedulingTerm in node affinity in pod annotations, weight should be in range 1-100": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"nodeAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [ - { - "weight": 199, - "preference": {"matchExpressions": [ - { - "key": "foo", - "operator": "In", - "values": ["bar"] - } - ]} - } - ]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid requiredDuringSchedulingIgnoredDuringExecution node selector, nodeSelectorTerms must have at least one term": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"nodeAffinity": { - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [] - }, - }}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid requiredDuringSchedulingIgnoredDuringExecution node selector term, matchExpressions must have at least one node selector requirement": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"nodeAffinity": { - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [{ - "matchExpressions": [] - }] - }, - }}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid weight in preferredDuringSchedulingIgnoredDuringExecution in pod affinity annotations, weight should be in range 1-100": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 109, - "podAffinityTerm": - { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "NotIn", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["ns"], - "topologyKey": "region" - } - }]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid labelSelector in preferredDuringSchedulingIgnoredDuringExecution in podaffinity annotations, values should be empty if the operator is Exists": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": - { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "Exists", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["ns"], - "topologyKey": "region" - } - }]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid name space in preferredDuringSchedulingIgnoredDuringExecution in podaffinity annotations, name space shouldbe valid": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": - { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "Exists", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["INVALID_NAMESPACE"], - "topologyKey": "region" - } - }]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid labelOperator in preferredDuringSchedulingIgnoredDuringExecution in podantiaffinity annotations, labelOperator should be proper": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAntiAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": - { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "WrongOp", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["ns"], - "topologyKey": "region" - } - }]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid pod affinity, empty topologyKey is not allowed for hard pod affinity": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": - { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "In", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["ns"], - "topologyKey": "" - } - }]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid pod anti-affinity, empty topologyKey is not allowed for hard pod anti-affinity": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAntiAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": - { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "In", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["ns"], - "topologyKey": "" - } - }]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - "invalid pod anti-affinity, empty topologyKey is not allowed for soft pod affinity": { - ObjectMeta: api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Annotations: map[string]string{ - api.AffinityAnnotationKey: ` - {"podAffinity": {"preferredDuringSchedulingIgnoredDuringExecution": [{ - "weight": 10, - "podAffinityTerm": - { - "labelSelector": { - "matchExpressions": [{ - "key": "key2", - "operator": "In", - "values": ["value1", "value2"] - }] - }, - "namespaces": ["ns"], - "topologyKey": "" - } - }]}}`, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - }, - } - for k, v := range errorCases { - if errs := ValidatePod(&v); len(errs) == 0 { - t.Errorf("expected failure for %q", k) - } - } -} - -func TestValidatePodUpdate(t *testing.T) { - var ( - activeDeadlineSecondsZero = int64(0) - activeDeadlineSecondsNegative = int64(-30) - activeDeadlineSecondsPositive = int64(30) - activeDeadlineSecondsLarger = int64(31) - - now = unversioned.Now() - grace = int64(30) - grace2 = int64(31) - ) - - tests := []struct { - a api.Pod - b api.Pod - isValid bool - test string - }{ - {api.Pod{}, api.Pod{}, true, "nothing"}, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "bar"}, - }, - false, - "ids", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "bar": "foo", - }, - }, - }, - true, - "labels", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Annotations: map[string]string{ - "foo": "bar", - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Annotations: map[string]string{ - "bar": "foo", - }, - }, - }, - true, - "annotations", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V1", - }, - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V2", - }, - { - Image: "bar:V2", - }, - }, - }, - }, - false, - "more containers", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{Containers: []api.Container{{Image: "foo:V1"}}}, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", DeletionTimestamp: &now}, - Spec: api.PodSpec{Containers: []api.Container{{Image: "foo:V1"}}}, - }, - true, - "deletion timestamp filled out", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &grace}, - Spec: api.PodSpec{Containers: []api.Container{{Image: "foo:V1"}}}, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", DeletionTimestamp: &now, DeletionGracePeriodSeconds: &grace2}, - Spec: api.PodSpec{Containers: []api.Container{{Image: "foo:V1"}}}, - }, - false, - "deletion grace period seconds cleared", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V1", - }, - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V2", - }, - }, - }, - }, - true, - "image change", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - {}, - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V2", - }, - }, - }, - }, - false, - "image change to empty", - }, - { - api.Pod{ - Spec: api.PodSpec{}, - }, - api.Pod{ - Spec: api.PodSpec{}, - }, - true, - "activeDeadlineSeconds no change, nil", - }, - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - true, - "activeDeadlineSeconds no change, set", - }, - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - api.Pod{}, - true, - "activeDeadlineSeconds change to positive from nil", - }, - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsLarger, - }, - }, - true, - "activeDeadlineSeconds change to smaller positive", - }, - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsLarger, - }, - }, - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - false, - "activeDeadlineSeconds change to larger positive", - }, - - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsNegative, - }, - }, - api.Pod{}, - false, - "activeDeadlineSeconds change to negative from nil", - }, - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsNegative, - }, - }, - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - false, - "activeDeadlineSeconds change to negative from positive", - }, - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsZero, - }, - }, - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - true, - "activeDeadlineSeconds change to zero from positive", - }, - { - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsZero, - }, - }, - api.Pod{}, - true, - "activeDeadlineSeconds change to zero from nil", - }, - { - api.Pod{}, - api.Pod{ - Spec: api.PodSpec{ - ActiveDeadlineSeconds: &activeDeadlineSecondsPositive, - }, - }, - false, - "activeDeadlineSeconds change to nil from positive", - }, - - { - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V1", - Resources: api.ResourceRequirements{ - Limits: getResourceLimits("100m", "0"), - }, - }, - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V2", - Resources: api.ResourceRequirements{ - Limits: getResourceLimits("1000m", "0"), - }, - }, - }, - }, - }, - false, - "cpu change", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V1", - Ports: []api.ContainerPort{ - {HostPort: 8080, ContainerPort: 80}, - }, - }, - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo:V2", - Ports: []api.ContainerPort{ - {HostPort: 8000, ContainerPort: 80}, - }, - }, - }, - }, - }, - false, - "port change", - }, - { - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "Bar": "foo", - }, - }, - }, - true, - "bad label change", - }, - } - - for _, test := range tests { - test.a.ObjectMeta.ResourceVersion = "1" - test.b.ObjectMeta.ResourceVersion = "1" - errs := ValidatePodUpdate(&test.a, &test.b) - if test.isValid { - if len(errs) != 0 { - t.Errorf("unexpected invalid: %s (%+v)\nA: %+v\nB: %+v", test.test, errs, test.a, test.b) - } - } else { - if len(errs) == 0 { - t.Errorf("unexpected valid: %s\nA: %+v\nB: %+v", test.test, test.a, test.b) - } - } - } -} - -func makeValidService() api.Service { - return api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "valid", - Namespace: "valid", - Labels: map[string]string{}, - Annotations: map[string]string{}, - ResourceVersion: "1", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{"key": "val"}, - SessionAffinity: "None", - Type: api.ServiceTypeClusterIP, - Ports: []api.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675, TargetPort: intstr.FromInt(8675)}}, - }, - } -} - -func TestValidateService(t *testing.T) { - testCases := []struct { - name string - tweakSvc func(svc *api.Service) // given a basic valid service, each test case can customize it - numErrs int - }{ - { - name: "missing namespace", - tweakSvc: func(s *api.Service) { - s.Namespace = "" - }, - numErrs: 1, - }, - { - name: "invalid namespace", - tweakSvc: func(s *api.Service) { - s.Namespace = "-123" - }, - numErrs: 1, - }, - { - name: "missing name", - tweakSvc: func(s *api.Service) { - s.Name = "" - }, - numErrs: 1, - }, - { - name: "invalid name", - tweakSvc: func(s *api.Service) { - s.Name = "-123" - }, - numErrs: 1, - }, - { - name: "too long name", - tweakSvc: func(s *api.Service) { - s.Name = strings.Repeat("a", 25) - }, - numErrs: 1, - }, - { - name: "invalid generateName", - tweakSvc: func(s *api.Service) { - s.GenerateName = "-123" - }, - numErrs: 1, - }, - { - name: "too long generateName", - tweakSvc: func(s *api.Service) { - s.GenerateName = strings.Repeat("a", 25) - }, - numErrs: 1, - }, - { - name: "invalid label", - tweakSvc: func(s *api.Service) { - s.Labels["NoUppercaseOrSpecialCharsLike=Equals"] = "bar" - }, - numErrs: 1, - }, - { - name: "invalid annotation", - tweakSvc: func(s *api.Service) { - s.Annotations["NoSpecialCharsLike=Equals"] = "bar" - }, - numErrs: 1, - }, - { - name: "nil selector", - tweakSvc: func(s *api.Service) { - s.Spec.Selector = nil - }, - numErrs: 0, - }, - { - name: "invalid selector", - tweakSvc: func(s *api.Service) { - s.Spec.Selector["NoSpecialCharsLike=Equals"] = "bar" - }, - numErrs: 1, - }, - { - name: "missing session affinity", - tweakSvc: func(s *api.Service) { - s.Spec.SessionAffinity = "" - }, - numErrs: 1, - }, - { - name: "missing type", - tweakSvc: func(s *api.Service) { - s.Spec.Type = "" - }, - numErrs: 1, - }, - { - name: "missing ports", - tweakSvc: func(s *api.Service) { - s.Spec.Ports = nil - }, - numErrs: 1, - }, - { - name: "missing ports but headless", - tweakSvc: func(s *api.Service) { - s.Spec.Ports = nil - s.Spec.ClusterIP = api.ClusterIPNone - }, - numErrs: 0, - }, - { - name: "empty port[0] name", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Name = "" - }, - numErrs: 0, - }, - { - name: "empty port[1] name", - tweakSvc: func(s *api.Service) { - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "", Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 1, - }, - { - name: "empty multi-port port[0] name", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Name = "" - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "p", Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 1, - }, - { - name: "invalid port name", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Name = "INVALID" - }, - numErrs: 1, - }, - { - name: "missing protocol", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Protocol = "" - }, - numErrs: 1, - }, - { - name: "invalid protocol", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Protocol = "INVALID" - }, - numErrs: 1, - }, - { - name: "invalid cluster ip", - tweakSvc: func(s *api.Service) { - s.Spec.ClusterIP = "invalid" - }, - numErrs: 1, - }, - { - name: "missing port", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Port = 0 - }, - numErrs: 1, - }, - { - name: "invalid port", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Port = 65536 - }, - numErrs: 1, - }, - { - name: "invalid TargetPort int", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].TargetPort = intstr.FromInt(65536) - }, - numErrs: 1, - }, - { - name: "valid port headless", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Port = 11722 - s.Spec.Ports[0].TargetPort = intstr.FromInt(11722) - s.Spec.ClusterIP = api.ClusterIPNone - }, - numErrs: 0, - }, - { - name: "invalid port headless 1", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Port = 11722 - s.Spec.Ports[0].TargetPort = intstr.FromInt(11721) - s.Spec.ClusterIP = api.ClusterIPNone - }, - // in the v1 API, targetPorts on headless services were tolerated. - // once we have version-specific validation, we can reject this on newer API versions, but until then, we have to tolerate it for compatibility. - // numErrs: 1, - numErrs: 0, - }, - { - name: "invalid port headless 2", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Port = 11722 - s.Spec.Ports[0].TargetPort = intstr.FromString("target") - s.Spec.ClusterIP = api.ClusterIPNone - }, - // in the v1 API, targetPorts on headless services were tolerated. - // once we have version-specific validation, we can reject this on newer API versions, but until then, we have to tolerate it for compatibility. - // numErrs: 1, - numErrs: 0, - }, - { - name: "invalid publicIPs localhost", - tweakSvc: func(s *api.Service) { - s.Spec.ExternalIPs = []string{"127.0.0.1"} - }, - numErrs: 1, - }, - { - name: "invalid publicIPs", - tweakSvc: func(s *api.Service) { - s.Spec.ExternalIPs = []string{"0.0.0.0"} - }, - numErrs: 1, - }, - { - name: "invalid publicIPs host", - tweakSvc: func(s *api.Service) { - s.Spec.ExternalIPs = []string{"myhost.mydomain"} - }, - numErrs: 1, - }, - { - name: "dup port name", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Name = "p" - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "p", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 1, - }, - { - name: "valid load balancer protocol UDP 1", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports[0].Protocol = "UDP" - }, - numErrs: 0, - }, - { - name: "valid load balancer protocol UDP 2", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports[0] = api.ServicePort{Name: "q", Port: 12345, Protocol: "UDP", TargetPort: intstr.FromInt(12345)} - }, - numErrs: 0, - }, - { - name: "invalid load balancer with mix protocol", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "UDP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 1, - }, - { - name: "valid 1", - tweakSvc: func(s *api.Service) { - // do nothing - }, - numErrs: 0, - }, - { - name: "valid 2", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].Protocol = "UDP" - s.Spec.Ports[0].TargetPort = intstr.FromInt(12345) - }, - numErrs: 0, - }, - { - name: "valid 3", - tweakSvc: func(s *api.Service) { - s.Spec.Ports[0].TargetPort = intstr.FromString("http") - }, - numErrs: 0, - }, - { - name: "valid cluster ip - none ", - tweakSvc: func(s *api.Service) { - s.Spec.ClusterIP = "None" - }, - numErrs: 0, - }, - { - name: "valid cluster ip - empty", - tweakSvc: func(s *api.Service) { - s.Spec.ClusterIP = "" - s.Spec.Ports[0].TargetPort = intstr.FromString("http") - }, - numErrs: 0, - }, - { - name: "valid type - cluster", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeClusterIP - }, - numErrs: 0, - }, - { - name: "valid type - loadbalancer", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - }, - numErrs: 0, - }, - { - name: "valid type loadbalancer 2 ports", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - name: "valid external load balancer 2 ports", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - name: "duplicate nodeports", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeNodePort - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", NodePort: 1, TargetPort: intstr.FromInt(1)}) - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "TCP", NodePort: 1, TargetPort: intstr.FromInt(2)}) - }, - numErrs: 1, - }, - { - name: "duplicate nodeports (different protocols)", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeNodePort - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", NodePort: 1, TargetPort: intstr.FromInt(1)}) - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "UDP", NodePort: 1, TargetPort: intstr.FromInt(2)}) - }, - numErrs: 0, - }, - { - name: "valid type - cluster", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeClusterIP - }, - numErrs: 0, - }, - { - name: "valid type - nodeport", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeNodePort - }, - numErrs: 0, - }, - { - name: "valid type - loadbalancer", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - }, - numErrs: 0, - }, - { - name: "valid type loadbalancer 2 ports", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - name: "valid type loadbalancer with NodePort", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", NodePort: 12345, TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - name: "valid type=NodePort service with NodePort", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeNodePort - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", NodePort: 12345, TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - name: "valid type=NodePort service without NodePort", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeNodePort - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - name: "valid cluster service without NodePort", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeClusterIP - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - name: "invalid cluster service with NodePort", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeClusterIP - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", NodePort: 12345, TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 1, - }, - { - name: "invalid public service with duplicate NodePort", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeNodePort - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "p1", Port: 1, Protocol: "TCP", NodePort: 1, TargetPort: intstr.FromInt(1)}) - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "p2", Port: 2, Protocol: "TCP", NodePort: 1, TargetPort: intstr.FromInt(2)}) - }, - numErrs: 1, - }, - { - name: "valid type=LoadBalancer", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 12345, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 0, - }, - { - // For now we open firewalls, and its insecure if we open 10250, remove this - // when we have better protections in place. - name: "invalid port type=LoadBalancer", - tweakSvc: func(s *api.Service) { - s.Spec.Type = api.ServiceTypeLoadBalancer - s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "kubelet", Port: 10250, Protocol: "TCP", TargetPort: intstr.FromInt(12345)}) - }, - numErrs: 1, - }, - { - name: "valid LoadBalancer source range annotation", - tweakSvc: func(s *api.Service) { - s.Annotations[service.AnnotationLoadBalancerSourceRangesKey] = "1.2.3.4/8, 5.6.7.8/16" - }, - numErrs: 0, - }, - { - name: "empty LoadBalancer source range annotation", - tweakSvc: func(s *api.Service) { - s.Annotations[service.AnnotationLoadBalancerSourceRangesKey] = "" - }, - numErrs: 0, - }, - { - name: "invalid LoadBalancer source range annotation (hostname)", - tweakSvc: func(s *api.Service) { - s.Annotations[service.AnnotationLoadBalancerSourceRangesKey] = "foo.bar" - }, - numErrs: 1, - }, - { - name: "invalid LoadBalancer source range annotation (invalid CIDR)", - tweakSvc: func(s *api.Service) { - s.Annotations[service.AnnotationLoadBalancerSourceRangesKey] = "1.2.3.4/33" - }, - numErrs: 1, - }, - } - - for _, tc := range testCases { - svc := makeValidService() - tc.tweakSvc(&svc) - errs := ValidateService(&svc) - if len(errs) != tc.numErrs { - t.Errorf("Unexpected error list for case %q: %v", tc.name, errs.ToAggregate()) - } - } -} - -func TestValidateReplicationControllerStatusUpdate(t *testing.T) { - validSelector := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - type rcUpdateTest struct { - old api.ReplicationController - update api.ReplicationController - } - successCases := []rcUpdateTest{ - { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 2, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 3, - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 4, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateReplicationControllerStatusUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]rcUpdateTest{ - "negative replicas": { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 3, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - Status: api.ReplicationControllerStatus{ - Replicas: -3, - }, - }, - }, - } - for testName, errorCase := range errorCases { - if errs := ValidateReplicationControllerStatusUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } - -} - -func TestValidateReplicationControllerUpdate(t *testing.T) { - validSelector := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - readWriteVolumePodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - Volumes: []api.Volume{{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}}, - }, - }, - } - invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidSelector, - }, - }, - } - type rcUpdateTest struct { - old api.ReplicationController - update api.ReplicationController - } - successCases := []rcUpdateTest{ - { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 3, - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - }, - { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: validSelector, - Template: &readWriteVolumePodTemplate.Template, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateReplicationControllerUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]rcUpdateTest{ - "more than one read/write": { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Selector: validSelector, - Template: &readWriteVolumePodTemplate.Template, - }, - }, - }, - "invalid selector": { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Selector: invalidSelector, - Template: &validPodTemplate.Template, - }, - }, - }, - "invalid pod": { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Selector: validSelector, - Template: &invalidPodTemplate.Template, - }, - }, - }, - "negative replicas": { - old: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - update: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: -1, - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - }, - } - for testName, errorCase := range errorCases { - if errs := ValidateReplicationControllerUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } -} - -func TestValidateReplicationController(t *testing.T) { - validSelector := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - readWriteVolumePodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: api.PodSpec{ - Volumes: []api.Volume{{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidSelector, - }, - }, - } - successCases := []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: validSelector, - Template: &readWriteVolumePodTemplate.Template, - }, - }, - } - for _, successCase := range successCases { - if errs := ValidateReplicationController(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]api.ReplicationController{ - "zero-length ID": { - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - "missing-namespace": { - ObjectMeta: api.ObjectMeta{Name: "abc-123"}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - "empty selector": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Template: &validPodTemplate.Template, - }, - }, - "selector_doesnt_match": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"foo": "bar"}, - Template: &validPodTemplate.Template, - }, - }, - "invalid manifest": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - }, - }, - "read-write persistent disk with > 1 pod": { - ObjectMeta: api.ObjectMeta{Name: "abc"}, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Selector: validSelector, - Template: &readWriteVolumePodTemplate.Template, - }, - }, - "negative_replicas": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: api.ReplicationControllerSpec{ - Replicas: -1, - Selector: validSelector, - }, - }, - "invalid_label": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - "invalid_label 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: api.ReplicationControllerSpec{ - Template: &invalidPodTemplate.Template, - }, - }, - "invalid_annotation": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &validPodTemplate.Template, - }, - }, - "invalid restart policy 1": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - }, - }, - }, - "invalid restart policy 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: api.ReplicationControllerSpec{ - Selector: validSelector, - Template: &api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - }, - }, - }, - } - for k, v := range errorCases { - errs := ValidateReplicationController(&v) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - field := errs[i].Field - if !strings.HasPrefix(field, "spec.template.") && - field != "metadata.name" && - field != "metadata.namespace" && - field != "spec.selector" && - field != "spec.template" && - field != "GCEPersistentDisk.ReadOnly" && - field != "spec.replicas" && - field != "spec.template.labels" && - field != "metadata.annotations" && - field != "metadata.labels" && - field != "status.replicas" { - t.Errorf("%s: missing prefix for: %v", k, errs[i]) - } - } - } -} - -func TestValidateNode(t *testing.T) { - validSelector := map[string]string{"a": "b"} - invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - successCases := []api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Labels: validSelector, - }, - Status: api.NodeStatus{ - Addresses: []api.NodeAddress{ - {Type: api.NodeLegacyHostIP, Address: "something"}, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - api.ResourceName("my.org/gpu"): resource.MustParse("10"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "external", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - Status: api.NodeStatus{ - Addresses: []api.NodeAddress{ - {Type: api.NodeLegacyHostIP, Address: "something"}, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("0"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "external", - }, - }, - } - for _, successCase := range successCases { - if errs := ValidateNode(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]api.Node{ - "zero-length Name": { - ObjectMeta: api.ObjectMeta{ - Name: "", - Labels: validSelector, - }, - Status: api.NodeStatus{ - Addresses: []api.NodeAddress{}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "external", - }, - }, - "invalid-labels": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Labels: invalidSelector, - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "external", - }, - }, - "missing-external-id": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Labels: validSelector, - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - }, - } - for k, v := range errorCases { - errs := ValidateNode(&v) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - field := errs[i].Field - expectedFields := map[string]bool{ - "metadata.name": true, - "metadata.labels": true, - "metadata.annotations": true, - "metadata.namespace": true, - "spec.externalID": true, - } - if expectedFields[field] == false { - t.Errorf("%s: missing prefix for: %v", k, errs[i]) - } - } - } -} - -func TestValidateNodeUpdate(t *testing.T) { - tests := []struct { - oldNode api.Node - node api.Node - valid bool - }{ - {api.Node{}, api.Node{}, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}}, - api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "bar"}, - }, false}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar"}, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "baz"}, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "baz"}, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"bar": "foo"}, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "baz"}, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - PodCIDR: "", - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - PodCIDR: "192.168.0.0/16", - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - PodCIDR: "192.123.0.0/16", - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - PodCIDR: "192.168.0.0/16", - }, - }, false}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceCPU: resource.MustParse("10000"), - api.ResourceMemory: resource.MustParse("100"), - }, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - }, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"bar": "foo"}, - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceCPU: resource.MustParse("10000"), - api.ResourceMemory: resource.MustParse("100"), - }, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"bar": "fooobaz"}, - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - }, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"bar": "foo"}, - }, - Status: api.NodeStatus{ - Addresses: []api.NodeAddress{ - {Type: api.NodeLegacyHostIP, Address: "1.2.3.4"}, - }, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"bar": "fooobaz"}, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "baz"}, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"Foo": "baz"}, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - Unschedulable: false, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - Unschedulable: true, - }, - }, true}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - Unschedulable: false, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Status: api.NodeStatus{ - Addresses: []api.NodeAddress{ - {Type: api.NodeExternalIP, Address: "1.1.1.1"}, - {Type: api.NodeExternalIP, Address: "1.1.1.1"}, - }, - }, - }, false}, - {api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - Unschedulable: false, - }, - }, api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Status: api.NodeStatus{ - Addresses: []api.NodeAddress{ - {Type: api.NodeExternalIP, Address: "1.1.1.1"}, - {Type: api.NodeInternalIP, Address: "10.1.1.1"}, - }, - }, - }, true}, - } - for i, test := range tests { - test.oldNode.ObjectMeta.ResourceVersion = "1" - test.node.ObjectMeta.ResourceVersion = "1" - errs := ValidateNodeUpdate(&test.node, &test.oldNode) - if test.valid && len(errs) > 0 { - t.Errorf("%d: Unexpected error: %v", i, errs) - t.Logf("%#v vs %#v", test.oldNode.ObjectMeta, test.node.ObjectMeta) - } - if !test.valid && len(errs) == 0 { - t.Errorf("%d: Unexpected non-error", i) - } - } -} - -func TestValidateServiceUpdate(t *testing.T) { - testCases := []struct { - name string - tweakSvc func(oldSvc, newSvc *api.Service) // given basic valid services, each test case can customize them - numErrs int - }{ - { - name: "no change", - tweakSvc: func(oldSvc, newSvc *api.Service) { - // do nothing - }, - numErrs: 0, - }, - { - name: "change name", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Name += "2" - }, - numErrs: 1, - }, - { - name: "change namespace", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Namespace += "2" - }, - numErrs: 1, - }, - { - name: "change label valid", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Labels["key"] = "other-value" - }, - numErrs: 0, - }, - { - name: "add label", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Labels["key2"] = "value2" - }, - numErrs: 0, - }, - { - name: "change cluster IP", - tweakSvc: func(oldSvc, newSvc *api.Service) { - oldSvc.Spec.ClusterIP = "1.2.3.4" - newSvc.Spec.ClusterIP = "8.6.7.5" - }, - numErrs: 1, - }, - { - name: "remove cluster IP", - tweakSvc: func(oldSvc, newSvc *api.Service) { - oldSvc.Spec.ClusterIP = "1.2.3.4" - newSvc.Spec.ClusterIP = "" - }, - numErrs: 1, - }, - { - name: "change affinity", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Spec.SessionAffinity = "ClientIP" - }, - numErrs: 0, - }, - { - name: "remove affinity", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Spec.SessionAffinity = "" - }, - numErrs: 1, - }, - { - name: "change type", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Spec.Type = api.ServiceTypeLoadBalancer - }, - numErrs: 0, - }, - { - name: "remove type", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Spec.Type = "" - }, - numErrs: 1, - }, - { - name: "change type -> nodeport", - tweakSvc: func(oldSvc, newSvc *api.Service) { - newSvc.Spec.Type = api.ServiceTypeNodePort - }, - numErrs: 0, - }, - } - - for _, tc := range testCases { - oldSvc := makeValidService() - newSvc := makeValidService() - tc.tweakSvc(&oldSvc, &newSvc) - errs := ValidateServiceUpdate(&newSvc, &oldSvc) - if len(errs) != tc.numErrs { - t.Errorf("Unexpected error list for case %q: %v", tc.name, errs.ToAggregate()) - } - } -} - -func TestValidateResourceNames(t *testing.T) { - table := []struct { - input string - success bool - }{ - {"memory", true}, - {"cpu", true}, - {"network", false}, - {"disk", false}, - {"", false}, - {".", false}, - {"..", false}, - {"my.favorite.app.co/12345", true}, - {"my.favorite.app.co/_12345", false}, - {"my.favorite.app.co/12345_", false}, - {"kubernetes.io/..", false}, - {"kubernetes.io/" + strings.Repeat("a", 63), true}, - {"kubernetes.io/" + strings.Repeat("a", 64), false}, - {"kubernetes.io//", false}, - {"kubernetes.io", false}, - {"kubernetes.io/will/not/work/", false}, - } - for k, item := range table { - err := validateResourceName(item.input, field.NewPath("field")) - if len(err) != 0 && item.success { - t.Errorf("expected no failure for input %q", item.input) - } else if len(err) == 0 && !item.success { - t.Errorf("expected failure for input %q", item.input) - for i := range err { - detail := err[i].Detail - if detail != "" && detail != qualifiedNameErrorMsg { - t.Errorf("%d: expected error detail either empty or %s, got %s", k, qualifiedNameErrorMsg, detail) - } - } - } - } -} - -func getResourceList(cpu, memory string) api.ResourceList { - res := api.ResourceList{} - if cpu != "" { - res[api.ResourceCPU] = resource.MustParse(cpu) - } - if memory != "" { - res[api.ResourceMemory] = resource.MustParse(memory) - } - return res -} - -func getStorageResourceList(storage string) api.ResourceList { - res := api.ResourceList{} - if storage != "" { - res[api.ResourceStorage] = resource.MustParse(storage) - } - return res -} - -func TestValidateLimitRange(t *testing.T) { - successCases := []struct { - name string - spec api.LimitRangeSpec - }{ - { - name: "all-fields-valid", - spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: getResourceList("100m", "10000Mi"), - Min: getResourceList("5m", "100Mi"), - MaxLimitRequestRatio: getResourceList("10", ""), - }, - { - Type: api.LimitTypeContainer, - Max: getResourceList("100m", "10000Mi"), - Min: getResourceList("5m", "100Mi"), - Default: getResourceList("50m", "500Mi"), - DefaultRequest: getResourceList("10m", "200Mi"), - MaxLimitRequestRatio: getResourceList("10", ""), - }, - }, - }, - }, - { - name: "all-fields-valid-big-numbers", - spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypeContainer, - Max: getResourceList("100m", "10000T"), - Min: getResourceList("5m", "100Mi"), - Default: getResourceList("50m", "500Mi"), - DefaultRequest: getResourceList("10m", "200Mi"), - MaxLimitRequestRatio: getResourceList("10", ""), - }, - }, - }, - }, - { - name: "thirdparty-fields-all-valid-standard-container-resources", - spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: "thirdparty.com/foo", - Max: getResourceList("100m", "10000T"), - Min: getResourceList("5m", "100Mi"), - Default: getResourceList("50m", "500Mi"), - DefaultRequest: getResourceList("10m", "200Mi"), - MaxLimitRequestRatio: getResourceList("10", ""), - }, - }, - }, - }, - { - name: "thirdparty-fields-all-valid-storage-resources", - spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: "thirdparty.com/foo", - Max: getStorageResourceList("10000T"), - Min: getStorageResourceList("100Mi"), - Default: getStorageResourceList("500Mi"), - DefaultRequest: getStorageResourceList("200Mi"), - MaxLimitRequestRatio: getStorageResourceList(""), - }, - }, - }, - }, - } - - for _, successCase := range successCases { - limitRange := &api.LimitRange{ObjectMeta: api.ObjectMeta{Name: successCase.name, Namespace: "foo"}, Spec: successCase.spec} - if errs := ValidateLimitRange(limitRange); len(errs) != 0 { - t.Errorf("Case %v, unexpected error: %v", successCase.name, errs) - } - } - - errorCases := map[string]struct { - R api.LimitRange - D string - }{ - "zero-length-name": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "", Namespace: "foo"}, Spec: api.LimitRangeSpec{}}, - "name or generateName is required", - }, - "zero-length-namespace": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}, Spec: api.LimitRangeSpec{}}, - "", - }, - "invalid-name": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "^Invalid", Namespace: "foo"}, Spec: api.LimitRangeSpec{}}, - DNSSubdomainErrorMsg, - }, - "invalid-namespace": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "^Invalid"}, Spec: api.LimitRangeSpec{}}, - DNS1123LabelErrorMsg, - }, - "duplicate-limit-type": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: getResourceList("100m", "10000m"), - Min: getResourceList("0m", "100m"), - }, - { - Type: api.LimitTypePod, - Min: getResourceList("0m", "100m"), - }, - }, - }}, - "", - }, - "default-limit-type-pod": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: getResourceList("100m", "10000m"), - Min: getResourceList("0m", "100m"), - Default: getResourceList("10m", "100m"), - }, - }, - }}, - "may not be specified when `type` is 'Pod'", - }, - "default-request-limit-type-pod": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: getResourceList("100m", "10000m"), - Min: getResourceList("0m", "100m"), - DefaultRequest: getResourceList("10m", "100m"), - }, - }, - }}, - "may not be specified when `type` is 'Pod'", - }, - "min value 100m is greater than max value 10m": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: getResourceList("10m", ""), - Min: getResourceList("100m", ""), - }, - }, - }}, - "min value 100m is greater than max value 10m", - }, - "invalid spec default outside range": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypeContainer, - Max: getResourceList("1", ""), - Min: getResourceList("100m", ""), - Default: getResourceList("2000m", ""), - }, - }, - }}, - "default value 2 is greater than max value 1", - }, - "invalid spec defaultrequest outside range": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypeContainer, - Max: getResourceList("1", ""), - Min: getResourceList("100m", ""), - DefaultRequest: getResourceList("2000m", ""), - }, - }, - }}, - "default request value 2 is greater than max value 1", - }, - "invalid spec defaultrequest more than default": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypeContainer, - Max: getResourceList("2", ""), - Min: getResourceList("100m", ""), - Default: getResourceList("500m", ""), - DefaultRequest: getResourceList("800m", ""), - }, - }, - }}, - "default request value 800m is greater than default limit value 500m", - }, - "invalid spec maxLimitRequestRatio less than 1": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - MaxLimitRequestRatio: getResourceList("800m", ""), - }, - }, - }}, - "ratio 800m is less than 1", - }, - "invalid spec maxLimitRequestRatio greater than max/min": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypeContainer, - Max: getResourceList("", "2Gi"), - Min: getResourceList("", "512Mi"), - MaxLimitRequestRatio: getResourceList("", "10"), - }, - }, - }}, - "ratio 10 is greater than max/min = 4.000000", - }, - "invalid non standard limit type": { - api.LimitRange{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: "foo", - Max: getStorageResourceList("10000T"), - Min: getStorageResourceList("100Mi"), - Default: getStorageResourceList("500Mi"), - DefaultRequest: getStorageResourceList("200Mi"), - MaxLimitRequestRatio: getStorageResourceList(""), - }, - }, - }}, - "must be a standard limit type or fully qualified", - }, - } - - for k, v := range errorCases { - errs := ValidateLimitRange(&v.R) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - detail := errs[i].Detail - if detail != v.D { - t.Errorf("[%s]: expected error detail either empty or %q, got %q", k, v.D, detail) - } - } - } - -} - -func TestValidateResourceQuota(t *testing.T) { - spec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - api.ResourceRequestsCPU: resource.MustParse("100"), - api.ResourceRequestsMemory: resource.MustParse("10000"), - api.ResourceLimitsCPU: resource.MustParse("100"), - api.ResourceLimitsMemory: resource.MustParse("10000"), - api.ResourcePods: resource.MustParse("10"), - api.ResourceServices: resource.MustParse("0"), - api.ResourceReplicationControllers: resource.MustParse("10"), - api.ResourceQuotas: resource.MustParse("10"), - api.ResourceConfigMaps: resource.MustParse("10"), - api.ResourceSecrets: resource.MustParse("10"), - }, - } - - terminatingSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceLimitsCPU: resource.MustParse("200"), - }, - Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeTerminating}, - } - - nonTerminatingSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - }, - Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeNotTerminating}, - } - - bestEffortSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourcePods: resource.MustParse("100"), - }, - Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort}, - } - - nonBestEffortSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - }, - Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeNotBestEffort}, - } - - // storage is not yet supported as a quota tracked resource - invalidQuotaResourceSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceStorage: resource.MustParse("10"), - }, - } - - negativeSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("-100"), - api.ResourceMemory: resource.MustParse("-10000"), - api.ResourcePods: resource.MustParse("-10"), - api.ResourceServices: resource.MustParse("-10"), - api.ResourceReplicationControllers: resource.MustParse("-10"), - api.ResourceQuotas: resource.MustParse("-10"), - api.ResourceConfigMaps: resource.MustParse("-10"), - api.ResourceSecrets: resource.MustParse("-10"), - }, - } - - fractionalComputeSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100m"), - }, - } - - fractionalPodSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourcePods: resource.MustParse(".1"), - api.ResourceServices: resource.MustParse(".5"), - api.ResourceReplicationControllers: resource.MustParse("1.25"), - api.ResourceQuotas: resource.MustParse("2.5"), - }, - } - - invalidTerminatingScopePairsSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - }, - Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeTerminating, api.ResourceQuotaScopeNotTerminating}, - } - - invalidBestEffortScopePairsSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourcePods: resource.MustParse("100"), - }, - Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScopeBestEffort, api.ResourceQuotaScopeNotBestEffort}, - } - - invalidScopeNameSpec := api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - }, - Scopes: []api.ResourceQuotaScope{api.ResourceQuotaScope("foo")}, - } - - successCases := []api.ResourceQuota{ - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: spec, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: fractionalComputeSpec, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: terminatingSpec, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: nonTerminatingSpec, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: bestEffortSpec, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: nonBestEffortSpec, - }, - } - - for _, successCase := range successCases { - if errs := ValidateResourceQuota(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]struct { - R api.ResourceQuota - D string - }{ - "zero-length Name": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "", Namespace: "foo"}, Spec: spec}, - "name or generateName is required", - }, - "zero-length Namespace": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: ""}, Spec: spec}, - "", - }, - "invalid Name": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "^Invalid", Namespace: "foo"}, Spec: spec}, - DNSSubdomainErrorMsg, - }, - "invalid Namespace": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "^Invalid"}, Spec: spec}, - DNS1123LabelErrorMsg, - }, - "negative-limits": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: negativeSpec}, - isNegativeErrorMsg, - }, - "fractional-api-resource": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: fractionalPodSpec}, - isNotIntegerErrorMsg, - }, - "invalid-quota-resource": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: invalidQuotaResourceSpec}, - isInvalidQuotaResource, - }, - "invalid-quota-terminating-pair": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: invalidTerminatingScopePairsSpec}, - "conflicting scopes", - }, - "invalid-quota-besteffort-pair": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: invalidBestEffortScopePairsSpec}, - "conflicting scopes", - }, - "invalid-quota-scope-name": { - api.ResourceQuota{ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: "foo"}, Spec: invalidScopeNameSpec}, - "unsupported scope", - }, - } - for k, v := range errorCases { - errs := ValidateResourceQuota(&v.R) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - if errs[i].Detail != v.D { - t.Errorf("[%s]: expected error detail either empty or %s, got %s", k, v.D, errs[i].Detail) - } - } - } -} - -func TestValidateNamespace(t *testing.T) { - validLabels := map[string]string{"a": "b"} - invalidLabels := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - successCases := []api.Namespace{ - { - ObjectMeta: api.ObjectMeta{Name: "abc", Labels: validLabels}, - }, - { - ObjectMeta: api.ObjectMeta{Name: "abc-123"}, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"example.com/something", "example.com/other"}, - }, - }, - } - for _, successCase := range successCases { - if errs := ValidateNamespace(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]struct { - R api.Namespace - D string - }{ - "zero-length name": { - api.Namespace{ObjectMeta: api.ObjectMeta{Name: ""}}, - "", - }, - "defined-namespace": { - api.Namespace{ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: "makesnosense"}}, - "", - }, - "invalid-labels": { - api.Namespace{ObjectMeta: api.ObjectMeta{Name: "abc", Labels: invalidLabels}}, - "", - }, - } - for k, v := range errorCases { - errs := ValidateNamespace(&v.R) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - } -} - -func TestValidateNamespaceFinalizeUpdate(t *testing.T) { - tests := []struct { - oldNamespace api.Namespace - namespace api.Namespace - valid bool - }{ - {api.Namespace{}, api.Namespace{}, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}}, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"Foo"}, - }, - }, false}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"foo.com/bar"}, - }, - }, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"foo.com/bar", "what.com/bar"}, - }, - }, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "fooemptyfinalizer"}, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"foo.com/bar"}, - }, - }, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "fooemptyfinalizer"}, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"", "foo.com/bar", "what.com/bar"}, - }, - }, false}, - } - for i, test := range tests { - test.namespace.ObjectMeta.ResourceVersion = "1" - test.oldNamespace.ObjectMeta.ResourceVersion = "1" - errs := ValidateNamespaceFinalizeUpdate(&test.namespace, &test.oldNamespace) - if test.valid && len(errs) > 0 { - t.Errorf("%d: Unexpected error: %v", i, errs) - t.Logf("%#v vs %#v", test.oldNamespace, test.namespace) - } - if !test.valid && len(errs) == 0 { - t.Errorf("%d: Unexpected non-error", i) - } - } -} - -func TestValidateNamespaceStatusUpdate(t *testing.T) { - now := unversioned.Now() - - tests := []struct { - oldNamespace api.Namespace - namespace api.Namespace - valid bool - }{ - {api.Namespace{}, api.Namespace{ - Status: api.NamespaceStatus{ - Phase: api.NamespaceActive, - }, - }, true}, - // Cannot set deletionTimestamp via status update - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}}, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - DeletionTimestamp: &now}, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - }, false}, - // Can update phase via status update - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - DeletionTimestamp: &now}}, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - DeletionTimestamp: &now}, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - }, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}}, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - }, false}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo"}}, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "bar"}, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - }, false}, - } - for i, test := range tests { - test.namespace.ObjectMeta.ResourceVersion = "1" - test.oldNamespace.ObjectMeta.ResourceVersion = "1" - errs := ValidateNamespaceStatusUpdate(&test.namespace, &test.oldNamespace) - if test.valid && len(errs) > 0 { - t.Errorf("%d: Unexpected error: %v", i, errs) - t.Logf("%#v vs %#v", test.oldNamespace.ObjectMeta, test.namespace.ObjectMeta) - } - if !test.valid && len(errs) == 0 { - t.Errorf("%d: Unexpected non-error", i) - } - } -} - -func TestValidateNamespaceUpdate(t *testing.T) { - tests := []struct { - oldNamespace api.Namespace - namespace api.Namespace - valid bool - }{ - {api.Namespace{}, api.Namespace{}, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo1"}}, - api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "bar1"}, - }, false}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo2", - Labels: map[string]string{"foo": "bar"}, - }, - }, api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo2", - Labels: map[string]string{"foo": "baz"}, - }, - }, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo3", - }, - }, api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo3", - Labels: map[string]string{"foo": "baz"}, - }, - }, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo4", - Labels: map[string]string{"bar": "foo"}, - }, - }, api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo4", - Labels: map[string]string{"foo": "baz"}, - }, - }, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo5", - Labels: map[string]string{"foo": "baz"}, - }, - }, api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo5", - Labels: map[string]string{"Foo": "baz"}, - }, - }, true}, - {api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo6", - Labels: map[string]string{"foo": "baz"}, - }, - }, api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo6", - Labels: map[string]string{"Foo": "baz"}, - }, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"kubernetes"}, - }, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - }, true}, - } - for i, test := range tests { - test.namespace.ObjectMeta.ResourceVersion = "1" - test.oldNamespace.ObjectMeta.ResourceVersion = "1" - errs := ValidateNamespaceUpdate(&test.namespace, &test.oldNamespace) - if test.valid && len(errs) > 0 { - t.Errorf("%d: Unexpected error: %v", i, errs) - t.Logf("%#v vs %#v", test.oldNamespace.ObjectMeta, test.namespace.ObjectMeta) - } - if !test.valid && len(errs) == 0 { - t.Errorf("%d: Unexpected non-error", i) - } - } -} - -func TestValidateSecret(t *testing.T) { - // Opaque secret validation - validSecret := func() api.Secret { - return api.Secret{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, - Data: map[string][]byte{ - "data-1": []byte("bar"), - }, - } - } - - var ( - emptyName = validSecret() - invalidName = validSecret() - emptyNs = validSecret() - invalidNs = validSecret() - overMaxSize = validSecret() - invalidKey = validSecret() - leadingDotKey = validSecret() - dotKey = validSecret() - doubleDotKey = validSecret() - ) - - emptyName.Name = "" - invalidName.Name = "NoUppercaseOrSpecialCharsLike=Equals" - emptyNs.Namespace = "" - invalidNs.Namespace = "NoUppercaseOrSpecialCharsLike=Equals" - overMaxSize.Data = map[string][]byte{ - "over": make([]byte, api.MaxSecretSize+1), - } - invalidKey.Data["a..b"] = []byte("whoops") - leadingDotKey.Data[".key"] = []byte("bar") - dotKey.Data["."] = []byte("bar") - doubleDotKey.Data[".."] = []byte("bar") - - // kubernetes.io/service-account-token secret validation - validServiceAccountTokenSecret := func() api.Secret { - return api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "bar", - Annotations: map[string]string{ - api.ServiceAccountNameKey: "foo", - }, - }, - Type: api.SecretTypeServiceAccountToken, - Data: map[string][]byte{ - "data-1": []byte("bar"), - }, - } - } - - var ( - emptyTokenAnnotation = validServiceAccountTokenSecret() - missingTokenAnnotation = validServiceAccountTokenSecret() - missingTokenAnnotations = validServiceAccountTokenSecret() - ) - emptyTokenAnnotation.Annotations[api.ServiceAccountNameKey] = "" - delete(missingTokenAnnotation.Annotations, api.ServiceAccountNameKey) - missingTokenAnnotations.Annotations = nil - - tests := map[string]struct { - secret api.Secret - valid bool - }{ - "valid": {validSecret(), true}, - "empty name": {emptyName, false}, - "invalid name": {invalidName, false}, - "empty namespace": {emptyNs, false}, - "invalid namespace": {invalidNs, false}, - "over max size": {overMaxSize, false}, - "invalid key": {invalidKey, false}, - "valid service-account-token secret": {validServiceAccountTokenSecret(), true}, - "empty service-account-token annotation": {emptyTokenAnnotation, false}, - "missing service-account-token annotation": {missingTokenAnnotation, false}, - "missing service-account-token annotations": {missingTokenAnnotations, false}, - "leading dot key": {leadingDotKey, true}, - "dot key": {dotKey, false}, - "double dot key": {doubleDotKey, false}, - } - - for name, tc := range tests { - errs := ValidateSecret(&tc.secret) - if tc.valid && len(errs) > 0 { - t.Errorf("%v: Unexpected error: %v", name, errs) - } - if !tc.valid && len(errs) == 0 { - t.Errorf("%v: Unexpected non-error", name) - } - } -} - -func TestValidateDockerConfigSecret(t *testing.T) { - validDockerSecret := func() api.Secret { - return api.Secret{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, - Type: api.SecretTypeDockercfg, - Data: map[string][]byte{ - api.DockerConfigKey: []byte(`{"https://index.docker.io/v1/": {"auth": "Y2x1ZWRyb29sZXIwMDAxOnBhc3N3b3Jk","email": "fake@example.com"}}`), - }, - } - } - validDockerSecret2 := func() api.Secret { - return api.Secret{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, - Type: api.SecretTypeDockerConfigJson, - Data: map[string][]byte{ - api.DockerConfigJsonKey: []byte(`{"auths":{"https://index.docker.io/v1/": {"auth": "Y2x1ZWRyb29sZXIwMDAxOnBhc3N3b3Jk","email": "fake@example.com"}}}`), - }, - } - } - - var ( - missingDockerConfigKey = validDockerSecret() - emptyDockerConfigKey = validDockerSecret() - invalidDockerConfigKey = validDockerSecret() - missingDockerConfigKey2 = validDockerSecret2() - emptyDockerConfigKey2 = validDockerSecret2() - invalidDockerConfigKey2 = validDockerSecret2() - ) - - delete(missingDockerConfigKey.Data, api.DockerConfigKey) - emptyDockerConfigKey.Data[api.DockerConfigKey] = []byte("") - invalidDockerConfigKey.Data[api.DockerConfigKey] = []byte("bad") - delete(missingDockerConfigKey2.Data, api.DockerConfigJsonKey) - emptyDockerConfigKey2.Data[api.DockerConfigJsonKey] = []byte("") - invalidDockerConfigKey2.Data[api.DockerConfigJsonKey] = []byte("bad") - - tests := map[string]struct { - secret api.Secret - valid bool - }{ - "valid dockercfg": {validDockerSecret(), true}, - "missing dockercfg": {missingDockerConfigKey, false}, - "empty dockercfg": {emptyDockerConfigKey, false}, - "invalid dockercfg": {invalidDockerConfigKey, false}, - "valid config.json": {validDockerSecret2(), true}, - "missing config.json": {missingDockerConfigKey2, false}, - "empty config.json": {emptyDockerConfigKey2, false}, - "invalid config.json": {invalidDockerConfigKey2, false}, - } - - for name, tc := range tests { - errs := ValidateSecret(&tc.secret) - if tc.valid && len(errs) > 0 { - t.Errorf("%v: Unexpected error: %v", name, errs) - } - if !tc.valid && len(errs) == 0 { - t.Errorf("%v: Unexpected non-error", name) - } - } -} - -func TestValidateBasicAuthSecret(t *testing.T) { - validBasicAuthSecret := func() api.Secret { - return api.Secret{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, - Type: api.SecretTypeBasicAuth, - Data: map[string][]byte{ - api.BasicAuthUsernameKey: []byte("username"), - api.BasicAuthPasswordKey: []byte("password"), - }, - } - } - - var ( - missingBasicAuthUsernamePasswordKeys = validBasicAuthSecret() - // invalidBasicAuthUsernamePasswordKey = validBasicAuthSecret() - // emptyBasicAuthUsernameKey = validBasicAuthSecret() - // emptyBasicAuthPasswordKey = validBasicAuthSecret() - ) - - delete(missingBasicAuthUsernamePasswordKeys.Data, api.BasicAuthUsernameKey) - delete(missingBasicAuthUsernamePasswordKeys.Data, api.BasicAuthPasswordKey) - - // invalidBasicAuthUsernamePasswordKey.Data[api.BasicAuthUsernameKey] = []byte("bad") - // invalidBasicAuthUsernamePasswordKey.Data[api.BasicAuthPasswordKey] = []byte("bad") - - // emptyBasicAuthUsernameKey.Data[api.BasicAuthUsernameKey] = []byte("") - // emptyBasicAuthPasswordKey.Data[api.BasicAuthPasswordKey] = []byte("") - - tests := map[string]struct { - secret api.Secret - valid bool - }{ - "valid": {validBasicAuthSecret(), true}, - "missing username and password": {missingBasicAuthUsernamePasswordKeys, false}, - // "invalid username and password": {invalidBasicAuthUsernamePasswordKey, false}, - // "empty username": {emptyBasicAuthUsernameKey, false}, - // "empty password": {emptyBasicAuthPasswordKey, false}, - } - - for name, tc := range tests { - errs := ValidateSecret(&tc.secret) - if tc.valid && len(errs) > 0 { - t.Errorf("%v: Unexpected error: %v", name, errs) - } - if !tc.valid && len(errs) == 0 { - t.Errorf("%v: Unexpected non-error", name) - } - } -} - -func TestValidateSSHAuthSecret(t *testing.T) { - validSSHAuthSecret := func() api.Secret { - return api.Secret{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, - Type: api.SecretTypeSSHAuth, - Data: map[string][]byte{ - api.SSHAuthPrivateKey: []byte("foo-bar-baz"), - }, - } - } - - missingSSHAuthPrivateKey := validSSHAuthSecret() - - delete(missingSSHAuthPrivateKey.Data, api.SSHAuthPrivateKey) - - tests := map[string]struct { - secret api.Secret - valid bool - }{ - "valid": {validSSHAuthSecret(), true}, - "missing private key": {missingSSHAuthPrivateKey, false}, - } - - for name, tc := range tests { - errs := ValidateSecret(&tc.secret) - if tc.valid && len(errs) > 0 { - t.Errorf("%v: Unexpected error: %v", name, errs) - } - if !tc.valid && len(errs) == 0 { - t.Errorf("%v: Unexpected non-error", name) - } - } -} - -func TestValidateEndpoints(t *testing.T) { - successCases := map[string]api.Endpoints{ - "simple endpoint": { - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.1.1"}, {IP: "10.10.2.2"}}, - Ports: []api.EndpointPort{{Name: "a", Port: 8675, Protocol: "TCP"}, {Name: "b", Port: 309, Protocol: "TCP"}}, - }, - { - Addresses: []api.EndpointAddress{{IP: "10.10.3.3"}}, - Ports: []api.EndpointPort{{Name: "a", Port: 93, Protocol: "TCP"}, {Name: "b", Port: 76, Protocol: "TCP"}}, - }, - }, - }, - "empty subsets": { - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - }, - "no name required for singleton port": { - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.1.1"}}, - Ports: []api.EndpointPort{{Port: 8675, Protocol: "TCP"}}, - }, - }, - }, - } - - for k, v := range successCases { - if errs := ValidateEndpoints(&v); len(errs) != 0 { - t.Errorf("Expected success for %s, got %v", k, errs) - } - } - - errorCases := map[string]struct { - endpoints api.Endpoints - errorType field.ErrorType - errorDetail string - }{ - "missing namespace": { - endpoints: api.Endpoints{ObjectMeta: api.ObjectMeta{Name: "mysvc"}}, - errorType: "FieldValueRequired", - }, - "missing name": { - endpoints: api.Endpoints{ObjectMeta: api.ObjectMeta{Namespace: "namespace"}}, - errorType: "FieldValueRequired", - }, - "invalid namespace": { - endpoints: api.Endpoints{ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "no@#invalid.;chars\"allowed"}}, - errorType: "FieldValueInvalid", - errorDetail: DNS1123LabelErrorMsg, - }, - "invalid name": { - endpoints: api.Endpoints{ObjectMeta: api.ObjectMeta{Name: "-_Invliad^&Characters", Namespace: "namespace"}}, - errorType: "FieldValueInvalid", - errorDetail: DNSSubdomainErrorMsg, - }, - "empty addresses": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Ports: []api.EndpointPort{{Name: "a", Port: 93, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueRequired", - }, - "empty ports": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.3.3"}}, - }, - }, - }, - errorType: "FieldValueRequired", - }, - "invalid IP": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "[2001:0db8:85a3:0042:1000:8a2e:0370:7334]"}}, - Ports: []api.EndpointPort{{Name: "a", Port: 93, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueInvalid", - errorDetail: "must be a valid IP address", - }, - "Multiple ports, one without name": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.1.1"}}, - Ports: []api.EndpointPort{{Port: 8675, Protocol: "TCP"}, {Name: "b", Port: 309, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueRequired", - }, - "Invalid port number": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.1.1"}}, - Ports: []api.EndpointPort{{Name: "a", Port: 66000, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueInvalid", - errorDetail: PortRangeErrorMsg, - }, - "Invalid protocol": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.1.1"}}, - Ports: []api.EndpointPort{{Name: "a", Port: 93, Protocol: "Protocol"}}, - }, - }, - }, - errorType: "FieldValueNotSupported", - }, - "Address missing IP": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{}}, - Ports: []api.EndpointPort{{Name: "a", Port: 93, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueInvalid", - errorDetail: "must be a valid IP address", - }, - "Port missing number": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.1.1"}}, - Ports: []api.EndpointPort{{Name: "a", Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueInvalid", - errorDetail: PortRangeErrorMsg, - }, - "Port missing protocol": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.1.1"}}, - Ports: []api.EndpointPort{{Name: "a", Port: 93}}, - }, - }, - }, - errorType: "FieldValueRequired", - }, - "Address is loopback": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}}, - Ports: []api.EndpointPort{{Name: "p", Port: 93, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueInvalid", - errorDetail: "loopback", - }, - "Address is link-local": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "169.254.169.254"}}, - Ports: []api.EndpointPort{{Name: "p", Port: 93, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueInvalid", - errorDetail: "link-local", - }, - "Address is link-local multicast": { - endpoints: api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "224.0.0.1"}}, - Ports: []api.EndpointPort{{Name: "p", Port: 93, Protocol: "TCP"}}, - }, - }, - }, - errorType: "FieldValueInvalid", - errorDetail: "link-local multicast", - }, - } - - for k, v := range errorCases { - if errs := ValidateEndpoints(&v.endpoints); len(errs) == 0 || errs[0].Type != v.errorType || !strings.Contains(errs[0].Detail, v.errorDetail) { - t.Errorf("[%s] Expected error type %s with detail %q, got %v", k, v.errorType, v.errorDetail, errs) - } - } -} - -func TestValidateTLSSecret(t *testing.T) { - successCases := map[string]api.Secret{ - "emtpy certificate chain": { - ObjectMeta: api.ObjectMeta{Name: "tls-cert", Namespace: "namespace"}, - Data: map[string][]byte{ - api.TLSCertKey: []byte("public key"), - api.TLSPrivateKeyKey: []byte("private key"), - }, - }, - } - for k, v := range successCases { - if errs := ValidateSecret(&v); len(errs) != 0 { - t.Errorf("Expected success for %s, got %v", k, errs) - } - } - errorCases := map[string]struct { - secrets api.Secret - errorType field.ErrorType - errorDetail string - }{ - "missing public key": { - secrets: api.Secret{ - ObjectMeta: api.ObjectMeta{Name: "tls-cert"}, - Data: map[string][]byte{ - api.TLSCertKey: []byte("public key"), - }, - }, - errorType: "FieldValueRequired", - }, - "missing private key": { - secrets: api.Secret{ - ObjectMeta: api.ObjectMeta{Name: "tls-cert"}, - Data: map[string][]byte{ - api.TLSCertKey: []byte("public key"), - }, - }, - errorType: "FieldValueRequired", - }, - } - for k, v := range errorCases { - if errs := ValidateSecret(&v.secrets); len(errs) == 0 || errs[0].Type != v.errorType || !strings.Contains(errs[0].Detail, v.errorDetail) { - t.Errorf("[%s] Expected error type %s with detail %q, got %v", k, v.errorType, v.errorDetail, errs) - } - } -} - -func TestValidateSecurityContext(t *testing.T) { - priv := false - var runAsUser int64 = 1 - fullValidSC := func() *api.SecurityContext { - return &api.SecurityContext{ - Privileged: &priv, - Capabilities: &api.Capabilities{ - Add: []api.Capability{"foo"}, - Drop: []api.Capability{"bar"}, - }, - SELinuxOptions: &api.SELinuxOptions{ - User: "user", - Role: "role", - Type: "type", - Level: "level", - }, - RunAsUser: &runAsUser, - } - } - - //setup data - allSettings := fullValidSC() - noCaps := fullValidSC() - noCaps.Capabilities = nil - - noSELinux := fullValidSC() - noSELinux.SELinuxOptions = nil - - noPrivRequest := fullValidSC() - noPrivRequest.Privileged = nil - - noRunAsUser := fullValidSC() - noRunAsUser.RunAsUser = nil - - successCases := map[string]struct { - sc *api.SecurityContext - }{ - "all settings": {allSettings}, - "no capabilities": {noCaps}, - "no selinux": {noSELinux}, - "no priv request": {noPrivRequest}, - "no run as user": {noRunAsUser}, - } - for k, v := range successCases { - if errs := ValidateSecurityContext(v.sc, field.NewPath("field")); len(errs) != 0 { - t.Errorf("[%s] Expected success, got %v", k, errs) - } - } - - privRequestWithGlobalDeny := fullValidSC() - requestPrivileged := true - privRequestWithGlobalDeny.Privileged = &requestPrivileged - - negativeRunAsUser := fullValidSC() - var negativeUser int64 = -1 - negativeRunAsUser.RunAsUser = &negativeUser - - errorCases := map[string]struct { - sc *api.SecurityContext - errorType field.ErrorType - errorDetail string - }{ - "request privileged when capabilities forbids": { - sc: privRequestWithGlobalDeny, - errorType: "FieldValueForbidden", - errorDetail: "disallowed by policy", - }, - "negative RunAsUser": { - sc: negativeRunAsUser, - errorType: "FieldValueInvalid", - errorDetail: isNegativeErrorMsg, - }, - } - for k, v := range errorCases { - if errs := ValidateSecurityContext(v.sc, field.NewPath("field")); len(errs) == 0 || errs[0].Type != v.errorType || !strings.Contains(errs[0].Detail, v.errorDetail) { - t.Errorf("[%s] Expected error type %q with detail %q, got %v", k, v.errorType, v.errorDetail, errs) - } - } -} - -func fakeValidSecurityContext(priv bool) *api.SecurityContext { - return &api.SecurityContext{ - Privileged: &priv, - } -} - -func TestValidPodLogOptions(t *testing.T) { - now := unversioned.Now() - negative := int64(-1) - zero := int64(0) - positive := int64(1) - tests := []struct { - opt api.PodLogOptions - errs int - }{ - {api.PodLogOptions{}, 0}, - {api.PodLogOptions{Previous: true}, 0}, - {api.PodLogOptions{Follow: true}, 0}, - {api.PodLogOptions{TailLines: &zero}, 0}, - {api.PodLogOptions{TailLines: &negative}, 1}, - {api.PodLogOptions{TailLines: &positive}, 0}, - {api.PodLogOptions{LimitBytes: &zero}, 1}, - {api.PodLogOptions{LimitBytes: &negative}, 1}, - {api.PodLogOptions{LimitBytes: &positive}, 0}, - {api.PodLogOptions{SinceSeconds: &negative}, 1}, - {api.PodLogOptions{SinceSeconds: &positive}, 0}, - {api.PodLogOptions{SinceSeconds: &zero}, 1}, - {api.PodLogOptions{SinceTime: &now}, 0}, - } - for i, test := range tests { - errs := ValidatePodLogOptions(&test.opt) - if test.errs != len(errs) { - t.Errorf("%d: Unexpected errors: %v", i, errs) - } - } -} - -func TestValidateConfigMap(t *testing.T) { - newConfigMap := func(name, namespace string, data map[string]string) api.ConfigMap { - return api.ConfigMap{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Data: data, - } - } - - var ( - validConfigMap = newConfigMap("validname", "validns", map[string]string{"key": "value"}) - maxKeyLength = newConfigMap("validname", "validns", map[string]string{strings.Repeat("a", 253): "value"}) - - emptyName = newConfigMap("", "validns", nil) - invalidName = newConfigMap("NoUppercaseOrSpecialCharsLike=Equals", "validns", nil) - emptyNs = newConfigMap("validname", "", nil) - invalidNs = newConfigMap("validname", "NoUppercaseOrSpecialCharsLike=Equals", nil) - invalidKey = newConfigMap("validname", "validns", map[string]string{"a..b": "value"}) - leadingDotKey = newConfigMap("validname", "validns", map[string]string{".ab": "value"}) - dotKey = newConfigMap("validname", "validns", map[string]string{".": "value"}) - doubleDotKey = newConfigMap("validname", "validns", map[string]string{"..": "value"}) - overMaxKeyLength = newConfigMap("validname", "validns", map[string]string{strings.Repeat("a", 254): "value"}) - overMaxSize = newConfigMap("validname", "validns", map[string]string{"key": strings.Repeat("a", api.MaxSecretSize+1)}) - ) - - tests := map[string]struct { - cfg api.ConfigMap - isValid bool - }{ - "valid": {validConfigMap, true}, - "max key length": {maxKeyLength, true}, - "leading dot key": {leadingDotKey, true}, - "empty name": {emptyName, false}, - "invalid name": {invalidName, false}, - "invalid key": {invalidKey, false}, - "empty namespace": {emptyNs, false}, - "invalid namespace": {invalidNs, false}, - "dot key": {dotKey, false}, - "double dot key": {doubleDotKey, false}, - "over max key length": {overMaxKeyLength, false}, - "over max size": {overMaxSize, false}, - } - - for name, tc := range tests { - errs := ValidateConfigMap(&tc.cfg) - if tc.isValid && len(errs) > 0 { - t.Errorf("%v: unexpected error: %v", name, errs) - } - if !tc.isValid && len(errs) == 0 { - t.Errorf("%v: unexpected non-error", name) - } - } -} - -func TestValidateConfigMapUpdate(t *testing.T) { - newConfigMap := func(version, name, namespace string, data map[string]string) api.ConfigMap { - return api.ConfigMap{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: namespace, - ResourceVersion: version, - }, - Data: data, - } - } - - var ( - validConfigMap = newConfigMap("1", "validname", "validns", map[string]string{"key": "value"}) - noVersion = newConfigMap("", "validname", "validns", map[string]string{"key": "value"}) - ) - - cases := []struct { - name string - newCfg api.ConfigMap - oldCfg api.ConfigMap - isValid bool - }{ - { - name: "valid", - newCfg: validConfigMap, - oldCfg: validConfigMap, - isValid: true, - }, - { - name: "invalid", - newCfg: noVersion, - oldCfg: validConfigMap, - isValid: false, - }, - } - - for _, tc := range cases { - errs := ValidateConfigMapUpdate(&tc.newCfg, &tc.oldCfg) - if tc.isValid && len(errs) > 0 { - t.Errorf("%v: unexpected error: %v", tc.name, errs) - } - if !tc.isValid && len(errs) == 0 { - t.Errorf("%v: unexpected non-error", tc.name) - } - } -} - -func TestValidateHasLabel(t *testing.T) { - successCase := api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Labels: map[string]string{ - "other": "blah", - "foo": "bar", - }, - } - if errs := ValidateHasLabel(successCase, field.NewPath("field"), "foo", "bar"); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - - missingCase := api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Labels: map[string]string{ - "other": "blah", - }, - } - if errs := ValidateHasLabel(missingCase, field.NewPath("field"), "foo", "bar"); len(errs) == 0 { - t.Errorf("expected failure") - } - - wrongValueCase := api.ObjectMeta{ - Name: "123", - Namespace: "ns", - Labels: map[string]string{ - "other": "blah", - "foo": "notbar", - }, - } - if errs := ValidateHasLabel(wrongValueCase, field.NewPath("field"), "foo", "bar"); len(errs) == 0 { - t.Errorf("expected failure") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apimachinery/registered/registered_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apimachinery/registered/registered_test.go deleted file mode 100644 index 001b65e92..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apimachinery/registered/registered_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 registered - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apimachinery" -) - -func TestAllPreferredGroupVersions(t *testing.T) { - testCases := []struct { - groupMetas []apimachinery.GroupMeta - expect string - }{ - { - groupMetas: []apimachinery.GroupMeta{ - { - GroupVersion: unversioned.GroupVersion{Group: "group1", Version: "v1"}, - }, - { - GroupVersion: unversioned.GroupVersion{Group: "group2", Version: "v2"}, - }, - { - GroupVersion: unversioned.GroupVersion{Group: "", Version: "v1"}, - }, - }, - expect: "group1/v1,group2/v2,v1", - }, - { - groupMetas: []apimachinery.GroupMeta{ - { - GroupVersion: unversioned.GroupVersion{Group: "", Version: "v1"}, - }, - }, - expect: "v1", - }, - { - groupMetas: []apimachinery.GroupMeta{}, - expect: "", - }, - } - for _, testCase := range testCases { - for _, groupMeta := range testCase.groupMetas { - RegisterGroup(groupMeta) - } - output := AllPreferredGroupVersions() - if testCase.expect != output { - t.Errorf("Error. expect: %s, got: %s", testCase.expect, output) - } - reset() - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/apps/validation/validation.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/apps/validation/validation.go deleted file mode 100644 index ce83ef8c5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/apps/validation/validation.go +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "reflect" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - unversionedvalidation "k8s.io/kubernetes/pkg/api/unversioned/validation" - apivalidation "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -// ValidatePetSetName can be used to check whether the given PetSet -// name is valid. -// Prefix indicates this name will be used as part of generation, in which case -// trailing dashes are allowed. -func ValidatePetSetName(name string, prefix bool) (bool, string) { - // TODO: Validate that there's name for the suffix inserted by the pets. - // Currently this is just "-index". In the future we may allow a user - // specified list of suffixes and we need to validate the longest one. - return apivalidation.NameIsDNSSubdomain(name, prefix) -} - -// Validates the given template and ensures that it is in accordance with the desired selector. -func ValidatePodTemplateSpecForPetSet(template *api.PodTemplateSpec, selector labels.Selector, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if template == nil { - allErrs = append(allErrs, field.Required(fldPath, "")) - } else { - if !selector.Empty() { - // Verify that the PetSet selector matches the labels in template. - labels := labels.Set(template.Labels) - if !selector.Matches(labels) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("metadata", "labels"), template.Labels, "`selector` does not match template `labels`")) - } - } - // TODO: Add validation for PodSpec, currently this will check volumes, which we know will - // fail. We should really check that the union of the given volumes and volumeClaims match - // volume mounts in the containers. - // allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(template, fldPath)...) - allErrs = append(allErrs, unversionedvalidation.ValidateLabels(template.Labels, fldPath.Child("labels"))...) - allErrs = append(allErrs, apivalidation.ValidateAnnotations(template.Annotations, fldPath.Child("annotations"))...) - allErrs = append(allErrs, apivalidation.ValidatePodSpecificAnnotations(template.Annotations, fldPath.Child("annotations"))...) - } - return allErrs -} - -// ValidatePetSetSpec tests if required fields in the PetSet spec are set. -func ValidatePetSetSpec(spec *apps.PetSetSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...) - if spec.Selector == nil { - allErrs = append(allErrs, field.Required(fldPath.Child("selector"), "")) - } else { - allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...) - if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is not valid for petset.")) - } - } - - selector, err := unversioned.LabelSelectorAsSelector(spec.Selector) - if err != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "")) - } else { - allErrs = append(allErrs, ValidatePodTemplateSpecForPetSet(&spec.Template, selector, fldPath.Child("template"))...) - } - - if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) - } - - return allErrs -} - -// ValidatePetSet validates a PetSet. -func ValidatePetSet(petSet *apps.PetSet) field.ErrorList { - allErrs := apivalidation.ValidateObjectMeta(&petSet.ObjectMeta, true, ValidatePetSetName, field.NewPath("metadata")) - allErrs = append(allErrs, ValidatePetSetSpec(&petSet.Spec, field.NewPath("spec"))...) - return allErrs -} - -// ValidatePetSetUpdate tests if required fields in the PetSet are set. -func ValidatePetSetUpdate(petSet, oldPetSet *apps.PetSet) field.ErrorList { - allErrs := field.ErrorList{} - - // TODO: For now we're taking the safe route and disallowing all updates to spec except for Spec.Replicas. - // Enable on a case by case basis. - restoreReplicas := petSet.Spec.Replicas - petSet.Spec.Replicas = oldPetSet.Spec.Replicas - - // The generation changes for this update - restoreGeneration := petSet.Generation - petSet.Generation = oldPetSet.Generation - - if !reflect.DeepEqual(petSet, oldPetSet) { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "updates to petset spec for fields other than 'replicas' are forbidden.")) - } - petSet.Spec.Replicas = restoreReplicas - petSet.Generation = restoreGeneration - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(petSet.Spec.Replicas), field.NewPath("spec", "replicas"))...) - return allErrs -} - -// ValidatePetSetStatusUpdate tests if required fields in the PetSet are set. -func ValidatePetSetStatusUpdate(petSet, oldPetSet *apps.PetSet) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&petSet.ObjectMeta, &oldPetSet.ObjectMeta, field.NewPath("metadata"))...) - // TODO: Validate status. - return allErrs -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/apps/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/apps/validation/validation_test.go deleted file mode 100644 index 851ea895f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/apps/validation/validation_test.go +++ /dev/null @@ -1,379 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/apps" -) - -func TestValidatePetSet(t *testing.T) { - validLabels := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - invalidLabels := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidLabels, - }, - }, - } - successCases := []apps.PetSet{ - { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - } - for _, successCase := range successCases { - if errs := ValidatePetSet(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]apps.PetSet{ - "zero-length ID": { - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "missing-namespace": { - ObjectMeta: api.ObjectMeta{Name: "abc-123"}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "empty selector": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Template: validPodTemplate.Template, - }, - }, - "selector_doesnt_match": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - Template: validPodTemplate.Template, - }, - }, - "invalid manifest": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - }, - }, - "negative_replicas": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Replicas: -1, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - }, - }, - "invalid_label": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "invalid_label 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: apps.PetSetSpec{ - Template: invalidPodTemplate.Template, - }, - }, - "invalid_annotation": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "invalid restart policy 1": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - }, - }, - }, - "invalid restart policy 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - }, - }, - }, - } - for k, v := range errorCases { - errs := ValidatePetSet(&v) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - field := errs[i].Field - if !strings.HasPrefix(field, "spec.template.") && - field != "metadata.name" && - field != "metadata.namespace" && - field != "spec.selector" && - field != "spec.template" && - field != "GCEPersistentDisk.ReadOnly" && - field != "spec.replicas" && - field != "spec.template.labels" && - field != "metadata.annotations" && - field != "metadata.labels" && - field != "status.replicas" { - t.Errorf("%s: missing prefix for: %v", k, errs[i]) - } - } - } -} - -func TestValidatePetSetUpdate(t *testing.T) { - validLabels := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - readWriteVolumePodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - Volumes: []api.Volume{{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}}, - }, - }, - } - invalidLabels := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidLabels, - }, - }, - } - type psUpdateTest struct { - old apps.PetSet - update apps.PetSet - } - successCases := []psUpdateTest{ - { - old: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Replicas: 3, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidatePetSetUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]psUpdateTest{ - "more than one read/write": { - old: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: readWriteVolumePodTemplate.Template, - }, - }, - }, - "updates to a field other than spec.Replicas": { - old: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Replicas: 1, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: readWriteVolumePodTemplate.Template, - }, - }, - }, - "invalid selector": { - old: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: invalidLabels}, - Template: validPodTemplate.Template, - }, - }, - }, - "invalid pod": { - old: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: invalidPodTemplate.Template, - }, - }, - }, - "negative replicas": { - old: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: apps.PetSetSpec{ - Replicas: -1, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - }, - } - for testName, errorCase := range errorCases { - if errs := ValidatePetSetUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/validation/validation.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/validation/validation.go deleted file mode 100644 index 11a548f41..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/validation/validation.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 validation - -import ( - authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func ValidateSubjectAccessReviewSpec(spec authorizationapi.SubjectAccessReviewSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if spec.ResourceAttributes != nil && spec.NonResourceAttributes != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Child("nonResourceAttributes"), spec.NonResourceAttributes, `cannot be specified in combination with resourceAttributes`)) - } - if spec.ResourceAttributes == nil && spec.NonResourceAttributes == nil { - allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceAttributes"), spec.NonResourceAttributes, `exactly one of nonResourceAttributes or resourceAttributes must be specified`)) - } - if len(spec.User) == 0 && len(spec.Groups) == 0 { - allErrs = append(allErrs, field.Invalid(fldPath.Child("user"), spec.User, `at least one of user or group must be specified`)) - } - - return allErrs -} - -func ValidateSelfSubjectAccessReviewSpec(spec authorizationapi.SelfSubjectAccessReviewSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - if spec.ResourceAttributes != nil && spec.NonResourceAttributes != nil { - allErrs = append(allErrs, field.Invalid(fldPath.Child("nonResourceAttributes"), spec.NonResourceAttributes, `cannot be specified in combination with resourceAttributes`)) - } - if spec.ResourceAttributes == nil && spec.NonResourceAttributes == nil { - allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceAttributes"), spec.NonResourceAttributes, `exactly one of nonResourceAttributes or resourceAttributes must be specified`)) - } - - return allErrs -} - -func ValidateSubjectAccessReview(sar *authorizationapi.SubjectAccessReview) field.ErrorList { - allErrs := ValidateSubjectAccessReviewSpec(sar.Spec, field.NewPath("spec")) - return allErrs -} - -func ValidateSelfSubjectAccessReview(sar *authorizationapi.SelfSubjectAccessReview) field.ErrorList { - allErrs := ValidateSelfSubjectAccessReviewSpec(sar.Spec, field.NewPath("spec")) - return allErrs -} - -func ValidateLocalSubjectAccessReview(sar *authorizationapi.LocalSubjectAccessReview) field.ErrorList { - allErrs := ValidateSubjectAccessReviewSpec(sar.Spec, field.NewPath("spec")) - return allErrs -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/validation/validation_test.go deleted file mode 100644 index c2776c404..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/validation/validation_test.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 validation - -import ( - "strings" - "testing" - - authorizationapi "k8s.io/kubernetes/pkg/apis/authorization" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func TestValidateSARSpec(t *testing.T) { - successCases := []authorizationapi.SubjectAccessReviewSpec{ - {ResourceAttributes: &authorizationapi.ResourceAttributes{}, User: "me"}, - {NonResourceAttributes: &authorizationapi.NonResourceAttributes{}, Groups: []string{"my-group"}}, - } - for _, successCase := range successCases { - if errs := ValidateSubjectAccessReviewSpec(successCase, field.NewPath("spec")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []struct { - name string - obj authorizationapi.SubjectAccessReviewSpec - msg string - }{ - { - name: "neither request", - obj: authorizationapi.SubjectAccessReviewSpec{User: "me"}, - msg: "exactly one of nonResourceAttributes or resourceAttributes must be specified", - }, - { - name: "both requests", - obj: authorizationapi.SubjectAccessReviewSpec{ - ResourceAttributes: &authorizationapi.ResourceAttributes{}, - NonResourceAttributes: &authorizationapi.NonResourceAttributes{}, - User: "me", - }, - msg: "cannot be specified in combination with resourceAttributes", - }, - { - name: "no subject", - obj: authorizationapi.SubjectAccessReviewSpec{ - ResourceAttributes: &authorizationapi.ResourceAttributes{}, - }, - msg: `spec.user: Invalid value: "": at least one of user or group must be specified`, - }, - } - - for _, c := range errorCases { - errs := ValidateSubjectAccessReviewSpec(c.obj, field.NewPath("spec")) - if len(errs) == 0 { - t.Errorf("%s: expected failure for %q", c.name, c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("%s: unexpected error: %q, expected: %q", c.name, errs[0], c.msg) - } - - errs = ValidateSubjectAccessReview(&authorizationapi.SubjectAccessReview{Spec: c.obj}) - if len(errs) == 0 { - t.Errorf("%s: expected failure for %q", c.name, c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("%s: unexpected error: %q, expected: %q", c.name, errs[0], c.msg) - } - errs = ValidateLocalSubjectAccessReview(&authorizationapi.LocalSubjectAccessReview{Spec: c.obj}) - if len(errs) == 0 { - t.Errorf("%s: expected failure for %q", c.name, c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("%s: unexpected error: %q, expected: %q", c.name, errs[0], c.msg) - } - - } -} - -func TestValidateSelfSAR(t *testing.T) { - successCases := []authorizationapi.SelfSubjectAccessReviewSpec{ - {ResourceAttributes: &authorizationapi.ResourceAttributes{}}, - } - for _, successCase := range successCases { - if errs := ValidateSelfSubjectAccessReviewSpec(successCase, field.NewPath("spec")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []struct { - name string - obj authorizationapi.SelfSubjectAccessReviewSpec - msg string - }{ - { - name: "neither request", - obj: authorizationapi.SelfSubjectAccessReviewSpec{}, - msg: "exactly one of nonResourceAttributes or resourceAttributes must be specified", - }, - { - name: "both requests", - obj: authorizationapi.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &authorizationapi.ResourceAttributes{}, - NonResourceAttributes: &authorizationapi.NonResourceAttributes{}, - }, - msg: "cannot be specified in combination with resourceAttributes", - }, - } - - for _, c := range errorCases { - errs := ValidateSelfSubjectAccessReviewSpec(c.obj, field.NewPath("spec")) - if len(errs) == 0 { - t.Errorf("%s: expected failure for %q", c.name, c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("%s: unexpected error: %q, expected: %q", c.name, errs[0], c.msg) - } - - errs = ValidateSelfSubjectAccessReview(&authorizationapi.SelfSubjectAccessReview{Spec: c.obj}) - if len(errs) == 0 { - t.Errorf("%s: expected failure for %q", c.name, c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("%s: unexpected error: %q, expected: %q", c.name, errs[0], c.msg) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/autoscaling/validation/validation.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/autoscaling/validation/validation.go deleted file mode 100644 index 8b9a21a9d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/autoscaling/validation/validation.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - apivalidation "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/apis/autoscaling" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func ValidateScale(scale *autoscaling.Scale) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&scale.ObjectMeta, true, apivalidation.NameIsDNSSubdomain, field.NewPath("metadata"))...) - - if scale.Spec.Replicas < 0 { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "replicas"), scale.Spec.Replicas, "must be greater than or equal to 0")) - } - - return allErrs -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/autoscaling/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/autoscaling/validation/validation_test.go deleted file mode 100644 index ac8921ee0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/autoscaling/validation/validation_test.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/autoscaling" -) - -func TestValidateScale(t *testing.T) { - successCases := []autoscaling.Scale{ - { - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: autoscaling.ScaleSpec{ - Replicas: 1, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: autoscaling.ScaleSpec{ - Replicas: 10, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: autoscaling.ScaleSpec{ - Replicas: 0, - }, - }, - } - - for _, successCase := range successCases { - if errs := ValidateScale(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []struct { - scale autoscaling.Scale - msg string - }{ - { - scale: autoscaling.Scale{ - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: autoscaling.ScaleSpec{ - Replicas: -1, - }, - }, - msg: "must be greater than or equal to 0", - }, - } - - for _, c := range errorCases { - if errs := ValidateScale(&c.scale); len(errs) == 0 { - t.Errorf("expected failure for %s", c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("unexpected error: %v, expected: %s", errs[0], c.msg) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/batch/validation/validation.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/batch/validation/validation.go deleted file mode 100644 index d4d187578..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/batch/validation/validation.go +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - unversionedvalidation "k8s.io/kubernetes/pkg/api/unversioned/validation" - apivalidation "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -// TODO: generalize for other controller objects that will follow the same pattern, such as ReplicaSet and DaemonSet, and -// move to new location. Replace batch.Job with an interface. -// -// ValidateGeneratedSelector validates that the generated selector on a controller object match the controller object -// metadata, and the labels on the pod template are as generated. -func ValidateGeneratedSelector(obj *batch.Job) field.ErrorList { - allErrs := field.ErrorList{} - if obj.Spec.ManualSelector != nil && *obj.Spec.ManualSelector { - return allErrs - } - - if obj.Spec.Selector == nil { - return allErrs // This case should already have been checked in caller. No need for more errors. - } - - // If somehow uid was unset then we would get "controller-uid=" as the selector - // which is bad. - if obj.ObjectMeta.UID == "" { - allErrs = append(allErrs, field.Required(field.NewPath("metadata").Child("uid"), "")) - } - - // If somehow uid was unset then we would get "controller-uid=" as the selector - // which is bad. - if obj.ObjectMeta.UID == "" { - allErrs = append(allErrs, field.Required(field.NewPath("metadata").Child("uid"), "")) - } - - // If selector generation was requested, then expected labels must be - // present on pod template, and much match job's uid and name. The - // generated (not-manual) selectors/labels ensure no overlap with other - // controllers. The manual mode allows orphaning, adoption, - // backward-compatibility, and experimentation with new - // labeling/selection schemes. Automatic selector generation should - // have placed certain labels on the pod, but this could have failed if - // the user added coflicting labels. Validate that the expected - // generated ones are there. - - allErrs = append(allErrs, apivalidation.ValidateHasLabel(obj.Spec.Template.ObjectMeta, field.NewPath("spec").Child("template").Child("metadata"), "controller-uid", string(obj.UID))...) - allErrs = append(allErrs, apivalidation.ValidateHasLabel(obj.Spec.Template.ObjectMeta, field.NewPath("spec").Child("template").Child("metadata"), "job-name", string(obj.Name))...) - expectedLabels := make(map[string]string) - expectedLabels["controller-uid"] = string(obj.UID) - expectedLabels["job-name"] = string(obj.Name) - // Whether manually or automatically generated, the selector of the job must match the pods it will produce. - if selector, err := unversioned.LabelSelectorAsSelector(obj.Spec.Selector); err == nil { - if !selector.Matches(labels.Set(expectedLabels)) { - allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("selector"), obj.Spec.Selector, "`selector` not auto-generated")) - } - } - - return allErrs -} - -func ValidateJob(job *batch.Job) field.ErrorList { - // Jobs and rcs have the same name validation - allErrs := apivalidation.ValidateObjectMeta(&job.ObjectMeta, true, apivalidation.ValidateReplicationControllerName, field.NewPath("metadata")) - allErrs = append(allErrs, ValidateGeneratedSelector(job)...) - allErrs = append(allErrs, ValidateJobSpec(&job.Spec, field.NewPath("spec"))...) - return allErrs -} - -func ValidateJobSpec(spec *batch.JobSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - if spec.Parallelism != nil { - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Parallelism), fldPath.Child("parallelism"))...) - } - if spec.Completions != nil { - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Completions), fldPath.Child("completions"))...) - } - if spec.ActiveDeadlineSeconds != nil { - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.ActiveDeadlineSeconds), fldPath.Child("activeDeadlineSeconds"))...) - } - if spec.Selector == nil { - allErrs = append(allErrs, field.Required(fldPath.Child("selector"), "")) - } else { - allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...) - } - - // Whether manually or automatically generated, the selector of the job must match the pods it will produce. - if selector, err := unversioned.LabelSelectorAsSelector(spec.Selector); err == nil { - labels := labels.Set(spec.Template.Labels) - if !selector.Matches(labels) { - allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`")) - } - } - - allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...) - if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && - spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { - allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), - spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)})) - } - return allErrs -} - -func ValidateJobStatus(status *batch.JobStatus, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Active), fldPath.Child("active"))...) - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Succeeded), fldPath.Child("succeeded"))...) - allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(status.Failed), fldPath.Child("failed"))...) - return allErrs -} - -func ValidateJobUpdate(job, oldJob *batch.Job) field.ErrorList { - allErrs := apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta, field.NewPath("metadata")) - allErrs = append(allErrs, ValidateJobSpecUpdate(job.Spec, oldJob.Spec, field.NewPath("spec"))...) - return allErrs -} - -func ValidateJobUpdateStatus(job, oldJob *batch.Job) field.ErrorList { - allErrs := apivalidation.ValidateObjectMetaUpdate(&oldJob.ObjectMeta, &job.ObjectMeta, field.NewPath("metadata")) - allErrs = append(allErrs, ValidateJobStatusUpdate(job.Status, oldJob.Status)...) - return allErrs -} - -func ValidateJobSpecUpdate(spec, oldSpec batch.JobSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, ValidateJobSpec(&spec, fldPath)...) - allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Completions, oldSpec.Completions, fldPath.Child("completions"))...) - allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Selector, oldSpec.Selector, fldPath.Child("selector"))...) - allErrs = append(allErrs, apivalidation.ValidateImmutableField(spec.Template, oldSpec.Template, fldPath.Child("template"))...) - return allErrs -} - -func ValidateJobStatusUpdate(status, oldStatus batch.JobStatus) field.ErrorList { - allErrs := field.ErrorList{} - allErrs = append(allErrs, ValidateJobStatus(&status, field.NewPath("status"))...) - return allErrs -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/batch/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/batch/validation/validation_test.go deleted file mode 100644 index 5b59a4c6e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/batch/validation/validation_test.go +++ /dev/null @@ -1,297 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/types" -) - -func TestValidateJob(t *testing.T) { - validManualSelector := &unversioned.LabelSelector{ - MatchLabels: map[string]string{"a": "b"}, - } - validGeneratedSelector := &unversioned.LabelSelector{ - MatchLabels: map[string]string{"controller-uid": "1a2b3c", "job-name": "myjob"}, - } - validPodTemplateSpecForManual := api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validManualSelector.MatchLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - } - validPodTemplateSpecForGenerated := api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validGeneratedSelector.MatchLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - } - successCases := map[string]batch.Job{ - "manual selector": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Selector: validManualSelector, - ManualSelector: newBool(true), - Template: validPodTemplateSpecForManual, - }, - }, - "generated selector": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Selector: validGeneratedSelector, - ManualSelector: newBool(false), - Template: validPodTemplateSpecForGenerated, - }, - }, - } - for k, v := range successCases { - if errs := ValidateJob(&v); len(errs) != 0 { - t.Errorf("expected success for %s: %v", k, errs) - } - } - negative := int32(-1) - negative64 := int64(-1) - errorCases := map[string]batch.Job{ - "spec.parallelism:must be greater than or equal to 0": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Parallelism: &negative, - ManualSelector: newBool(true), - Template: validPodTemplateSpecForGenerated, - }, - }, - "spec.completions:must be greater than or equal to 0": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Completions: &negative, - Selector: validManualSelector, - ManualSelector: newBool(true), - Template: validPodTemplateSpecForGenerated, - }, - }, - "spec.activeDeadlineSeconds:must be greater than or equal to 0": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - ActiveDeadlineSeconds: &negative64, - Selector: validManualSelector, - ManualSelector: newBool(true), - Template: validPodTemplateSpecForGenerated, - }, - }, - "spec.selector:Required value": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Template: validPodTemplateSpecForGenerated, - }, - }, - "spec.template.metadata.labels: Invalid value: {\"y\":\"z\"}: `selector` does not match template `labels`": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Selector: validManualSelector, - ManualSelector: newBool(true), - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"y": "z"}, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - }, - }, - "spec.template.metadata.labels: Invalid value: {\"controller-uid\":\"4d5e6f\"}: `selector` does not match template `labels`": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Selector: validManualSelector, - ManualSelector: newBool(true), - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"controller-uid": "4d5e6f"}, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - }, - }, - "spec.template.spec.restartPolicy: Unsupported value": { - ObjectMeta: api.ObjectMeta{ - Name: "myjob", - Namespace: api.NamespaceDefault, - UID: types.UID("1a2b3c"), - }, - Spec: batch.JobSpec{ - Selector: validManualSelector, - ManualSelector: newBool(true), - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validManualSelector.MatchLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - }, - }, - } - - for k, v := range errorCases { - errs := ValidateJob(&v) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } else { - s := strings.Split(k, ":") - err := errs[0] - if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { - t.Errorf("unexpected error: %v, expected: %s", err, k) - } - } - } -} - -func TestValidateJobUpdateStatus(t *testing.T) { - type testcase struct { - old batch.Job - update batch.Job - } - - successCases := []testcase{ - { - old: batch.Job{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Status: batch.JobStatus{ - Active: 1, - Succeeded: 2, - Failed: 3, - }, - }, - update: batch.Job{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Status: batch.JobStatus{ - Active: 1, - Succeeded: 1, - Failed: 3, - }, - }, - }, - } - - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateJobUpdateStatus(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]testcase{ - "[status.active: Invalid value: -1: must be greater than or equal to 0, status.succeeded: Invalid value: -2: must be greater than or equal to 0]": { - old: batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: api.NamespaceDefault, - ResourceVersion: "10", - }, - Status: batch.JobStatus{ - Active: 1, - Succeeded: 2, - Failed: 3, - }, - }, - update: batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: api.NamespaceDefault, - ResourceVersion: "10", - }, - Status: batch.JobStatus{ - Active: -1, - Succeeded: -2, - Failed: 3, - }, - }, - }, - } - - for testName, errorCase := range errorCases { - errs := ValidateJobUpdateStatus(&errorCase.update, &errorCase.old) - if len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - continue - } - if errs.ToAggregate().Error() != testName { - t.Errorf("expected '%s' got '%s'", errs.ToAggregate().Error(), testName) - } - } -} - -func newBool(val bool) *bool { - p := new(bool) - *p = val - return p -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/helpers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/helpers_test.go deleted file mode 100644 index 7aece8257..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/helpers_test.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 componentconfig - -import ( - "strings" - "testing" - - "github.com/spf13/pflag" -) - -func TestIPVar(t *testing.T) { - defaultIP := "0.0.0.0" - cases := []struct { - argc string - expectErr bool - expectVal string - }{ - - { - argc: "blah --ip=1.2.3.4", - expectVal: "1.2.3.4", - }, - { - argc: "blah --ip=1.2.3.4a", - expectErr: true, - expectVal: defaultIP, - }, - } - for _, c := range cases { - fs := pflag.NewFlagSet("blah", pflag.PanicOnError) - ip := defaultIP - fs.Var(IPVar{&ip}, "ip", "the ip") - - var err error - func() { - defer func() { - if r := recover(); r != nil { - err = r.(error) - } - }() - fs.Parse(strings.Split(c.argc, " ")) - }() - - if c.expectErr && err == nil { - t.Errorf("did not observe an expected error") - continue - } - if !c.expectErr && err != nil { - t.Errorf("observed an unexpected error") - continue - } - if c.expectVal != ip { - t.Errorf("unexpected ip: expected %q, saw %q", c.expectVal, ip) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/install/install_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/install/install_test.go deleted file mode 100644 index 940e17567..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/install/install_test.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 install - -import ( - "encoding/json" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/apis/componentconfig" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestCodec(t *testing.T) { - daemonSet := componentconfig.KubeProxyConfiguration{} - // We do want to use package registered rather than testapi here, because we - // want to test if the package install and package registered work as expected. - data, err := runtime.Encode(api.Codecs.LegacyCodec(registered.GroupOrDie(componentconfig.GroupName).GroupVersion), &daemonSet) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - other := componentconfig.KubeProxyConfiguration{} - if err := json.Unmarshal(data, &other); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if other.APIVersion != registered.GroupOrDie(componentconfig.GroupName).GroupVersion.String() || other.Kind != "KubeProxyConfiguration" { - t.Errorf("unexpected unmarshalled object %#v", other) - } -} - -func TestInterfacesFor(t *testing.T) { - if _, err := registered.GroupOrDie(componentconfig.GroupName).InterfacesFor(componentconfig.SchemeGroupVersion); err == nil { - t.Fatalf("unexpected non-error: %v", err) - } - for i, version := range registered.GroupOrDie(componentconfig.GroupName).GroupVersions { - if vi, err := registered.GroupOrDie(componentconfig.GroupName).InterfacesFor(version); err != nil || vi == nil { - t.Fatalf("%d: unexpected result: %v", i, err) - } - } -} - -func TestRESTMapper(t *testing.T) { - gv := unversioned.GroupVersion{Group: componentconfig.GroupName, Version: "v1alpha1"} - proxyGVK := gv.WithKind("KubeProxyConfiguration") - - if gvk, err := registered.GroupOrDie(componentconfig.GroupName).RESTMapper.KindFor(gv.WithResource("kubeproxyconfiguration")); err != nil || gvk != proxyGVK { - t.Errorf("unexpected version mapping: %v %v", gvk, err) - } - - if m, err := registered.GroupOrDie(componentconfig.GroupName).RESTMapper.RESTMapping(proxyGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != proxyGVK || m.Resource != "kubeproxyconfigurations" { - t.Errorf("unexpected version mapping: %#v %v", m, err) - } - - for _, version := range registered.GroupOrDie(componentconfig.GroupName).GroupVersions { - mapping, err := registered.GroupOrDie(componentconfig.GroupName).RESTMapper.RESTMapping(proxyGVK.GroupKind(), version.Version) - if err != nil { - t.Errorf("unexpected error: %v", err) - continue - } - - if mapping.Resource != "kubeproxyconfigurations" { - t.Errorf("incorrect resource name: %#v", mapping) - } - if mapping.GroupVersionKind.GroupVersion() != version { - t.Errorf("incorrect groupVersion: %v", mapping) - } - - interfaces, _ := registered.GroupOrDie(componentconfig.GroupName).InterfacesFor(version) - if mapping.ObjectConvertor != interfaces.ObjectConvertor { - t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/install/install_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/install/install_test.go deleted file mode 100644 index 311fad56d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/install/install_test.go +++ /dev/null @@ -1,119 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 install - -import ( - "encoding/json" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestResourceVersioner(t *testing.T) { - daemonSet := extensions.DaemonSet{ObjectMeta: api.ObjectMeta{ResourceVersion: "10"}} - version, err := accessor.ResourceVersion(&daemonSet) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != "10" { - t.Errorf("unexpected version %v", version) - } - - daemonSetList := extensions.DaemonSetList{ListMeta: unversioned.ListMeta{ResourceVersion: "10"}} - version, err = accessor.ResourceVersion(&daemonSetList) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != "10" { - t.Errorf("unexpected version %v", version) - } -} - -func TestCodec(t *testing.T) { - daemonSet := extensions.DaemonSet{} - // We do want to use package registered rather than testapi here, because we - // want to test if the package install and package registered work as expected. - data, err := runtime.Encode(api.Codecs.LegacyCodec(registered.GroupOrDie(extensions.GroupName).GroupVersion), &daemonSet) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - other := extensions.DaemonSet{} - if err := json.Unmarshal(data, &other); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if other.APIVersion != registered.GroupOrDie(extensions.GroupName).GroupVersion.String() || other.Kind != "DaemonSet" { - t.Errorf("unexpected unmarshalled object %#v", other) - } -} - -func TestInterfacesFor(t *testing.T) { - if _, err := registered.GroupOrDie(extensions.GroupName).InterfacesFor(extensions.SchemeGroupVersion); err == nil { - t.Fatalf("unexpected non-error: %v", err) - } - for i, version := range registered.GroupOrDie(extensions.GroupName).GroupVersions { - if vi, err := registered.GroupOrDie(extensions.GroupName).InterfacesFor(version); err != nil || vi == nil { - t.Fatalf("%d: unexpected result: %v", i, err) - } - } -} - -func TestRESTMapper(t *testing.T) { - gv := v1beta1.SchemeGroupVersion - hpaGVK := gv.WithKind("HorizontalPodAutoscaler") - daemonSetGVK := gv.WithKind("DaemonSet") - - if gvk, err := registered.GroupOrDie(extensions.GroupName).RESTMapper.KindFor(gv.WithResource("horizontalpodautoscalers")); err != nil || gvk != hpaGVK { - t.Errorf("unexpected version mapping: %v %v", gvk, err) - } - - if m, err := registered.GroupOrDie(extensions.GroupName).RESTMapper.RESTMapping(daemonSetGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != daemonSetGVK || m.Resource != "daemonsets" { - t.Errorf("unexpected version mapping: %#v %v", m, err) - } - - for _, version := range registered.GroupOrDie(extensions.GroupName).GroupVersions { - mapping, err := registered.GroupOrDie(extensions.GroupName).RESTMapper.RESTMapping(hpaGVK.GroupKind(), version.Version) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if mapping.Resource != "horizontalpodautoscalers" { - t.Errorf("incorrect resource name: %#v", mapping) - } - if mapping.GroupVersionKind.GroupVersion() != version { - t.Errorf("incorrect groupVersion: %v", mapping) - } - - interfaces, _ := registered.GroupOrDie(extensions.GroupName).InterfacesFor(version) - if mapping.ObjectConvertor != interfaces.ObjectConvertor { - t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces) - } - - rc := &extensions.HorizontalPodAutoscaler{ObjectMeta: api.ObjectMeta{Name: "foo"}} - name, err := mapping.MetadataAccessor.Name(rc) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if name != "foo" { - t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_test.go deleted file mode 100644 index 759e38ca1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_test.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 v1beta1_test - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/batch" - versioned "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" -) - -// TestJobSpecConversion tests that ManualSelector and AutoSelector -// are handled correctly. -func TestJobSpecConversion(t *testing.T) { - pTrue := new(bool) - *pTrue = true - pFalse := new(bool) - *pFalse = false - - // False or nil convert to true. - // True converts to nil. - tests := []struct { - in *bool - expectOut *bool - }{ - { - in: nil, - expectOut: pTrue, - }, - { - in: pFalse, - expectOut: pTrue, - }, - { - in: pTrue, - expectOut: nil, - }, - } - - // Test internal -> v1beta1. - for _, test := range tests { - i := &batch.JobSpec{ - ManualSelector: test.in, - } - v := versioned.JobSpec{} - if err := api.Scheme.Convert(i, &v); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectOut, v.AutoSelector) { - t.Fatalf("want v1beta1.AutoSelector %v, got %v", test.expectOut, v.AutoSelector) - } - } - - // Test v1beta1 -> internal. - for _, test := range tests { - i := &versioned.JobSpec{ - AutoSelector: test.in, - } - e := batch.JobSpec{} - if err := api.Scheme.Convert(i, &e); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !reflect.DeepEqual(test.expectOut, e.ManualSelector) { - t.Fatalf("want extensions.ManualSelector %v, got %v", test.expectOut, e.ManualSelector) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/defaults_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/defaults_test.go deleted file mode 100644 index f02b2c0d4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/defaults_test.go +++ /dev/null @@ -1,731 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 v1beta1_test - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - _ "k8s.io/kubernetes/pkg/api/install" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/v1" - _ "k8s.io/kubernetes/pkg/apis/extensions/install" - . "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func TestSetDefaultDaemonSet(t *testing.T) { - defaultLabels := map[string]string{"foo": "bar"} - period := int64(v1.DefaultTerminationGracePeriodSeconds) - defaultTemplate := v1.PodTemplateSpec{ - Spec: v1.PodSpec{ - DNSPolicy: v1.DNSClusterFirst, - RestartPolicy: v1.RestartPolicyAlways, - SecurityContext: &v1.PodSecurityContext{}, - TerminationGracePeriodSeconds: &period, - }, - ObjectMeta: v1.ObjectMeta{ - Labels: defaultLabels, - }, - } - templateNoLabel := v1.PodTemplateSpec{ - Spec: v1.PodSpec{ - DNSPolicy: v1.DNSClusterFirst, - RestartPolicy: v1.RestartPolicyAlways, - SecurityContext: &v1.PodSecurityContext{}, - TerminationGracePeriodSeconds: &period, - }, - } - tests := []struct { - original *DaemonSet - expected *DaemonSet - }{ - { // Labels change/defaulting test. - original: &DaemonSet{ - Spec: DaemonSetSpec{ - Template: defaultTemplate, - }, - }, - expected: &DaemonSet{ - ObjectMeta: v1.ObjectMeta{ - Labels: defaultLabels, - }, - Spec: DaemonSetSpec{ - Selector: &LabelSelector{ - MatchLabels: defaultLabels, - }, - Template: defaultTemplate, - }, - }, - }, - { // Labels change/defaulting test. - original: &DaemonSet{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "bar": "foo", - }, - }, - Spec: DaemonSetSpec{ - Template: defaultTemplate, - }, - }, - expected: &DaemonSet{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "bar": "foo", - }, - }, - Spec: DaemonSetSpec{ - Selector: &LabelSelector{ - MatchLabels: defaultLabels, - }, - Template: defaultTemplate, - }, - }, - }, - { // Update strategy. - original: &DaemonSet{}, - expected: &DaemonSet{ - Spec: DaemonSetSpec{ - Template: templateNoLabel, - }, - }, - }, - { // Update strategy. - original: &DaemonSet{ - Spec: DaemonSetSpec{}, - }, - expected: &DaemonSet{ - Spec: DaemonSetSpec{ - Template: templateNoLabel, - }, - }, - }, - { // Custom unique label key. - original: &DaemonSet{ - Spec: DaemonSetSpec{}, - }, - expected: &DaemonSet{ - Spec: DaemonSetSpec{ - Template: templateNoLabel, - }, - }, - }, - } - - for i, test := range tests { - original := test.original - expected := test.expected - obj2 := roundTrip(t, runtime.Object(original)) - got, ok := obj2.(*DaemonSet) - if !ok { - t.Errorf("(%d) unexpected object: %v", i, got) - t.FailNow() - } - if !reflect.DeepEqual(got.Spec, expected.Spec) { - t.Errorf("(%d) got different than expected\ngot:\n\t%+v\nexpected:\n\t%+v", i, got.Spec, expected.Spec) - } - } -} - -func TestSetDefaultDeployment(t *testing.T) { - defaultIntOrString := intstr.FromInt(1) - differentIntOrString := intstr.FromInt(5) - period := int64(v1.DefaultTerminationGracePeriodSeconds) - defaultTemplate := v1.PodTemplateSpec{ - Spec: v1.PodSpec{ - DNSPolicy: v1.DNSClusterFirst, - RestartPolicy: v1.RestartPolicyAlways, - SecurityContext: &v1.PodSecurityContext{}, - TerminationGracePeriodSeconds: &period, - }, - } - tests := []struct { - original *Deployment - expected *Deployment - }{ - { - original: &Deployment{}, - expected: &Deployment{ - Spec: DeploymentSpec{ - Replicas: newInt32(1), - Strategy: DeploymentStrategy{ - Type: RollingUpdateDeploymentStrategyType, - RollingUpdate: &RollingUpdateDeployment{ - MaxSurge: &defaultIntOrString, - MaxUnavailable: &defaultIntOrString, - }, - }, - Template: defaultTemplate, - }, - }, - }, - { - original: &Deployment{ - Spec: DeploymentSpec{ - Replicas: newInt32(5), - Strategy: DeploymentStrategy{ - RollingUpdate: &RollingUpdateDeployment{ - MaxSurge: &differentIntOrString, - }, - }, - }, - }, - expected: &Deployment{ - Spec: DeploymentSpec{ - Replicas: newInt32(5), - Strategy: DeploymentStrategy{ - Type: RollingUpdateDeploymentStrategyType, - RollingUpdate: &RollingUpdateDeployment{ - MaxSurge: &differentIntOrString, - MaxUnavailable: &defaultIntOrString, - }, - }, - Template: defaultTemplate, - }, - }, - }, - { - original: &Deployment{ - Spec: DeploymentSpec{ - Replicas: newInt32(5), - Strategy: DeploymentStrategy{ - Type: RecreateDeploymentStrategyType, - }, - }, - }, - expected: &Deployment{ - Spec: DeploymentSpec{ - Replicas: newInt32(5), - Strategy: DeploymentStrategy{ - Type: RecreateDeploymentStrategyType, - }, - Template: defaultTemplate, - }, - }, - }, - { - original: &Deployment{ - Spec: DeploymentSpec{ - Replicas: newInt32(5), - Strategy: DeploymentStrategy{ - Type: RecreateDeploymentStrategyType, - }, - }, - }, - expected: &Deployment{ - Spec: DeploymentSpec{ - Replicas: newInt32(5), - Strategy: DeploymentStrategy{ - Type: RecreateDeploymentStrategyType, - }, - Template: defaultTemplate, - }, - }, - }, - } - - for _, test := range tests { - original := test.original - expected := test.expected - obj2 := roundTrip(t, runtime.Object(original)) - got, ok := obj2.(*Deployment) - if !ok { - t.Errorf("unexpected object: %v", got) - t.FailNow() - } - if !reflect.DeepEqual(got.Spec, expected.Spec) { - t.Errorf("got different than expected:\n\t%+v\ngot:\n\t%+v", got.Spec, expected.Spec) - } - } -} - -func TestSetDefaultJobParallelismAndCompletions(t *testing.T) { - tests := []struct { - original *Job - expected *Job - }{ - // both unspecified -> sets both to 1 - { - original: &Job{ - Spec: JobSpec{}, - }, - expected: &Job{ - Spec: JobSpec{ - Completions: newInt32(1), - Parallelism: newInt32(1), - }, - }, - }, - // WQ: Parallelism explicitly 0 and completions unset -> no change - { - original: &Job{ - Spec: JobSpec{ - Parallelism: newInt32(0), - }, - }, - expected: &Job{ - Spec: JobSpec{ - Parallelism: newInt32(0), - }, - }, - }, - // WQ: Parallelism explicitly 2 and completions unset -> no change - { - original: &Job{ - Spec: JobSpec{ - Parallelism: newInt32(2), - }, - }, - expected: &Job{ - Spec: JobSpec{ - Parallelism: newInt32(2), - }, - }, - }, - // Completions explicitly 2 and parallelism unset -> parallelism is defaulted - { - original: &Job{ - Spec: JobSpec{ - Completions: newInt32(2), - }, - }, - expected: &Job{ - Spec: JobSpec{ - Completions: newInt32(2), - Parallelism: newInt32(1), - }, - }, - }, - // Both set -> no change - { - original: &Job{ - Spec: JobSpec{ - Completions: newInt32(10), - Parallelism: newInt32(11), - }, - }, - expected: &Job{ - Spec: JobSpec{ - Completions: newInt32(10), - Parallelism: newInt32(11), - }, - }, - }, - // Both set, flipped -> no change - { - original: &Job{ - Spec: JobSpec{ - Completions: newInt32(11), - Parallelism: newInt32(10), - }, - }, - expected: &Job{ - Spec: JobSpec{ - Completions: newInt32(11), - Parallelism: newInt32(10), - }, - }, - }, - } - - for _, tc := range tests { - original := tc.original - expected := tc.expected - obj2 := roundTrip(t, runtime.Object(original)) - got, ok := obj2.(*Job) - if !ok { - t.Errorf("unexpected object: %v", got) - t.FailNow() - } - if (got.Spec.Completions == nil) != (expected.Spec.Completions == nil) { - t.Errorf("got different *completions than expected: %v %v", got.Spec.Completions, expected.Spec.Completions) - } - if got.Spec.Completions != nil && expected.Spec.Completions != nil { - if *got.Spec.Completions != *expected.Spec.Completions { - t.Errorf("got different completions than expected: %d %d", *got.Spec.Completions, *expected.Spec.Completions) - } - } - if (got.Spec.Parallelism == nil) != (expected.Spec.Parallelism == nil) { - t.Errorf("got different *Parallelism than expected: %v %v", got.Spec.Parallelism, expected.Spec.Parallelism) - } - if got.Spec.Parallelism != nil && expected.Spec.Parallelism != nil { - if *got.Spec.Parallelism != *expected.Spec.Parallelism { - t.Errorf("got different parallelism than expected: %d %d", *got.Spec.Parallelism, *expected.Spec.Parallelism) - } - } - } -} - -func TestSetDefaultJobSelector(t *testing.T) { - tests := []struct { - original *Job - expectedSelector *LabelSelector - }{ - // selector set explicitly, nil autoSelector - { - original: &Job{ - Spec: JobSpec{ - Selector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - }, - }, - expectedSelector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - }, - // selector set explicitly, autoSelector=true - { - original: &Job{ - Spec: JobSpec{ - Selector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - AutoSelector: newBool(true), - }, - }, - expectedSelector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - }, - // selector set explicitly, autoSelector=false - { - original: &Job{ - Spec: JobSpec{ - Selector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - AutoSelector: newBool(false), - }, - }, - expectedSelector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - }, - // selector from template labels - { - original: &Job{ - Spec: JobSpec{ - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{"job": "selector"}, - }, - }, - }, - }, - expectedSelector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - }, - // selector from template labels, autoSelector=false - { - original: &Job{ - Spec: JobSpec{ - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{"job": "selector"}, - }, - }, - AutoSelector: newBool(false), - }, - }, - expectedSelector: &LabelSelector{ - MatchLabels: map[string]string{"job": "selector"}, - }, - }, - // selector not copied from template labels, autoSelector=true - { - original: &Job{ - Spec: JobSpec{ - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{"job": "selector"}, - }, - }, - AutoSelector: newBool(true), - }, - }, - expectedSelector: nil, - }, - } - - for i, testcase := range tests { - obj2 := roundTrip(t, runtime.Object(testcase.original)) - got, ok := obj2.(*Job) - if !ok { - t.Errorf("%d: unexpected object: %v", i, got) - t.FailNow() - } - if !reflect.DeepEqual(got.Spec.Selector, testcase.expectedSelector) { - t.Errorf("%d: got different selectors %#v %#v", i, got.Spec.Selector, testcase.expectedSelector) - } - } -} - -func TestSetDefaultReplicaSet(t *testing.T) { - tests := []struct { - rs *ReplicaSet - expectLabels bool - expectSelector bool - }{ - { - rs: &ReplicaSet{ - Spec: ReplicaSetSpec{ - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: true, - expectSelector: true, - }, - { - rs: &ReplicaSet{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "bar": "foo", - }, - }, - Spec: ReplicaSetSpec{ - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: false, - expectSelector: true, - }, - { - rs: &ReplicaSet{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "bar": "foo", - }, - }, - Spec: ReplicaSetSpec{ - Selector: &LabelSelector{ - MatchLabels: map[string]string{ - "some": "other", - }, - }, - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: false, - expectSelector: false, - }, - { - rs: &ReplicaSet{ - Spec: ReplicaSetSpec{ - Selector: &LabelSelector{ - MatchLabels: map[string]string{ - "some": "other", - }, - }, - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectLabels: true, - expectSelector: false, - }, - } - - for _, test := range tests { - rs := test.rs - obj2 := roundTrip(t, runtime.Object(rs)) - rs2, ok := obj2.(*ReplicaSet) - if !ok { - t.Errorf("unexpected object: %v", rs2) - t.FailNow() - } - if test.expectSelector != reflect.DeepEqual(rs2.Spec.Selector.MatchLabels, rs2.Spec.Template.Labels) { - if test.expectSelector { - t.Errorf("expected: %v, got: %v", rs2.Spec.Template.Labels, rs2.Spec.Selector) - } else { - t.Errorf("unexpected equality: %v", rs.Spec.Selector) - } - } - if test.expectLabels != reflect.DeepEqual(rs2.Labels, rs2.Spec.Template.Labels) { - if test.expectLabels { - t.Errorf("expected: %v, got: %v", rs2.Spec.Template.Labels, rs2.Labels) - } else { - t.Errorf("unexpected equality: %v", rs.Labels) - } - } - } -} - -func TestSetDefaultReplicaSetReplicas(t *testing.T) { - tests := []struct { - rs ReplicaSet - expectReplicas int32 - }{ - { - rs: ReplicaSet{ - Spec: ReplicaSetSpec{ - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectReplicas: 1, - }, - { - rs: ReplicaSet{ - Spec: ReplicaSetSpec{ - Replicas: newInt32(0), - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectReplicas: 0, - }, - { - rs: ReplicaSet{ - Spec: ReplicaSetSpec{ - Replicas: newInt32(3), - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - }, - expectReplicas: 3, - }, - } - - for _, test := range tests { - rs := &test.rs - obj2 := roundTrip(t, runtime.Object(rs)) - rs2, ok := obj2.(*ReplicaSet) - if !ok { - t.Errorf("unexpected object: %v", rs2) - t.FailNow() - } - if rs2.Spec.Replicas == nil { - t.Errorf("unexpected nil Replicas") - } else if test.expectReplicas != *rs2.Spec.Replicas { - t.Errorf("expected: %d replicas, got: %d", test.expectReplicas, *rs2.Spec.Replicas) - } - } -} - -func TestDefaultRequestIsNotSetForReplicaSet(t *testing.T) { - s := v1.PodSpec{} - s.Containers = []v1.Container{ - { - Resources: v1.ResourceRequirements{ - Limits: v1.ResourceList{ - v1.ResourceCPU: resource.MustParse("100m"), - }, - }, - }, - } - rs := &ReplicaSet{ - Spec: ReplicaSetSpec{ - Replicas: newInt32(3), - Template: v1.PodTemplateSpec{ - ObjectMeta: v1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: s, - }, - }, - } - output := roundTrip(t, runtime.Object(rs)) - rs2 := output.(*ReplicaSet) - defaultRequest := rs2.Spec.Template.Spec.Containers[0].Resources.Requests - requestValue := defaultRequest[v1.ResourceCPU] - if requestValue.String() != "0" { - t.Errorf("Expected 0 request value, got: %s", requestValue.String()) - } -} - -func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { - data, err := runtime.Encode(api.Codecs.LegacyCodec(SchemeGroupVersion), obj) - if err != nil { - t.Errorf("%v\n %#v", err, obj) - return nil - } - obj2, err := runtime.Decode(api.Codecs.UniversalDecoder(), data) - if err != nil { - t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj) - return nil - } - obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object) - err = api.Scheme.Convert(obj2, obj3) - if err != nil { - t.Errorf("%v\nSource: %#v", err, obj2) - return nil - } - return obj3 -} - -func newInt32(val int32) *int32 { - p := new(int32) - *p = val - return p -} - -func newString(val string) *string { - p := new(string) - *p = val - return p -} - -func newBool(val bool) *bool { - b := new(bool) - *b = val - return b -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/validation/validation_test.go deleted file mode 100644 index 51e09597b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/validation/validation_test.go +++ /dev/null @@ -1,1845 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 validation - -import ( - "fmt" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/controller/podautoscaler" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func TestValidateHorizontalPodAutoscaler(t *testing.T) { - successCases := []extensions.HorizontalPodAutoscaler{ - { - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: "ReplicationController", - Name: "myrc", - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: "ReplicationController", - Name: "myrc", - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"name\":\"qps\",\"value\":\"20\"}]}", - }, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: "ReplicationController", - Name: "myrc", - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - }, - }, - } - for _, successCase := range successCases { - if errs := ValidateHorizontalPodAutoscaler(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []struct { - horizontalPodAutoscaler extensions.HorizontalPodAutoscaler - msg string - }{ - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault}, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{Name: "myrc", Subresource: "scale"}, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - msg: "scaleRef.kind: Required", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault}, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{Kind: "..", Name: "myrc", Subresource: "scale"}, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - msg: "scaleRef.kind: Invalid", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault}, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Subresource: "scale"}, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - msg: "scaleRef.name: Required", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault}, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "..", Subresource: "scale"}, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - msg: "scaleRef.name: Invalid", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault}, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "myrc", Subresource: ""}, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - msg: "scaleRef.subresource: Required", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault}, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "myrc", Subresource: ".."}, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - msg: "scaleRef.subresource: Invalid", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{Name: "myautoscaler", Namespace: api.NamespaceDefault}, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{Kind: "ReplicationController", Name: "myrc", Subresource: "randomsubresource"}, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: 70}, - }, - }, - msg: "scaleRef.subresource: Unsupported", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Subresource: "scale", - }, - MinReplicas: newInt32(-1), - MaxReplicas: 5, - }, - }, - msg: "must be greater than 0", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Subresource: "scale", - }, - MinReplicas: newInt32(7), - MaxReplicas: 5, - }, - }, - msg: "must be greater than or equal to `minReplicas`", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - CPUUtilization: &extensions.CPUTargetUtilization{TargetPercentage: -70}, - }, - }, - msg: "must be greater than 0", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - podautoscaler.HpaCustomMetricsTargetAnnotationName: "broken", - }, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: "ReplicationController", - Name: "myrc", - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - }, - }, - msg: "failed to parse custom metrics target annotation", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - podautoscaler.HpaCustomMetricsTargetAnnotationName: "{}", - }, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: "ReplicationController", - Name: "myrc", - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - }, - }, - msg: "custom metrics target must not be empty", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"value\":\"20\"}]}", - }, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: "ReplicationController", - Name: "myrc", - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - }, - }, - msg: "missing custom metric target name", - }, - { - horizontalPodAutoscaler: extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "myautoscaler", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - podautoscaler.HpaCustomMetricsTargetAnnotationName: "{\"items\":[{\"name\":\"qps\",\"value\":\"0\"}]}", - }, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: "ReplicationController", - Name: "myrc", - Subresource: "scale", - }, - MinReplicas: newInt32(1), - MaxReplicas: 5, - }, - }, - msg: "custom metric target value must be greater than 0", - }, - } - - for _, c := range errorCases { - errs := ValidateHorizontalPodAutoscaler(&c.horizontalPodAutoscaler) - if len(errs) == 0 { - t.Errorf("expected failure for %q", c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("unexpected error: %q, expected: %q", errs[0], c.msg) - } - } -} - -func TestValidateDaemonSetStatusUpdate(t *testing.T) { - type dsUpdateTest struct { - old extensions.DaemonSet - update extensions.DaemonSet - } - - successCases := []dsUpdateTest{ - { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Status: extensions.DaemonSetStatus{ - CurrentNumberScheduled: 1, - NumberMisscheduled: 2, - DesiredNumberScheduled: 3, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Status: extensions.DaemonSetStatus{ - CurrentNumberScheduled: 1, - NumberMisscheduled: 1, - DesiredNumberScheduled: 3, - }, - }, - }, - } - - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateDaemonSetStatusUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]dsUpdateTest{ - "negative values": { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: api.NamespaceDefault, - ResourceVersion: "10", - }, - Status: extensions.DaemonSetStatus{ - CurrentNumberScheduled: 1, - NumberMisscheduled: 2, - DesiredNumberScheduled: 3, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: api.NamespaceDefault, - ResourceVersion: "10", - }, - Status: extensions.DaemonSetStatus{ - CurrentNumberScheduled: -1, - NumberMisscheduled: -1, - DesiredNumberScheduled: -3, - }, - }, - }, - } - - for testName, errorCase := range errorCases { - if errs := ValidateDaemonSetStatusUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } -} - -func TestValidateDaemonSetUpdate(t *testing.T) { - validSelector := map[string]string{"a": "b"} - validSelector2 := map[string]string{"c": "d"} - invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - - validPodSpecAbc := api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - } - validPodSpecDef := api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "def", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - } - validPodSpecNodeSelector := api.PodSpec{ - NodeSelector: validSelector, - NodeName: "xyz", - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - } - validPodSpecVolume := api.PodSpec{ - Volumes: []api.Volume{{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - } - - validPodTemplateAbc := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: validPodSpecAbc, - }, - } - validPodTemplateNodeSelector := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: validPodSpecNodeSelector, - }, - } - validPodTemplateAbc2 := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector2, - }, - Spec: validPodSpecAbc, - }, - } - validPodTemplateDef := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector2, - }, - Spec: validPodSpecDef, - }, - } - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidSelector, - }, - }, - } - readWriteVolumePodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: validPodSpecVolume, - }, - } - - type dsUpdateTest struct { - old extensions.DaemonSet - update extensions.DaemonSet - } - successCases := []dsUpdateTest{ - { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - }, - { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector2}, - Template: validPodTemplateAbc2.Template, - }, - }, - }, - { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateNodeSelector.Template, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateDaemonSetUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]dsUpdateTest{ - "change daemon name": { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - }, - "invalid selector": { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: invalidSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - }, - "invalid pod": { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: invalidPodTemplate.Template, - }, - }, - }, - "change container image": { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateDef.Template, - }, - }, - }, - "read-write volume": { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: readWriteVolumePodTemplate.Template, - }, - }, - }, - "invalid update strategy": { - old: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - update: extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: invalidSelector}, - Template: validPodTemplateAbc.Template, - }, - }, - }, - } - for testName, errorCase := range errorCases { - if errs := ValidateDaemonSetUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } -} - -func TestValidateDaemonSet(t *testing.T) { - validSelector := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - invalidSelector := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidSelector, - }, - }, - } - successCases := []extensions.DaemonSet{ - { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplate.Template, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplate.Template, - }, - }, - } - for _, successCase := range successCases { - if errs := ValidateDaemonSet(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]extensions.DaemonSet{ - "zero-length ID": { - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplate.Template, - }, - }, - "missing-namespace": { - ObjectMeta: api.ObjectMeta{Name: "abc-123"}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplate.Template, - }, - }, - "nil selector": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Template: validPodTemplate.Template, - }, - }, - "empty selector": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{}, - Template: validPodTemplate.Template, - }, - }, - "selector_doesnt_match": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - Template: validPodTemplate.Template, - }, - }, - "invalid template": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - }, - }, - "invalid_label": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplate.Template, - }, - }, - "invalid_label 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: extensions.DaemonSetSpec{ - Template: invalidPodTemplate.Template, - }, - }, - "invalid_annotation": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: validPodTemplate.Template, - }, - }, - "invalid restart policy 1": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - }, - }, - }, - "invalid restart policy 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validSelector}, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validSelector, - }, - }, - }, - }, - } - for k, v := range errorCases { - errs := ValidateDaemonSet(&v) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - field := errs[i].Field - if !strings.HasPrefix(field, "spec.template.") && - !strings.HasPrefix(field, "spec.updateStrategy") && - field != "metadata.name" && - field != "metadata.namespace" && - field != "spec.selector" && - field != "spec.template" && - field != "GCEPersistentDisk.ReadOnly" && - field != "spec.template.labels" && - field != "metadata.annotations" && - field != "metadata.labels" { - t.Errorf("%s: missing prefix for: %v", k, errs[i]) - } - } - } -} - -func validDeployment() *extensions.Deployment { - return &extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.DeploymentSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{ - "name": "abc", - }, - }, - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "name": "abc", - }, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSDefault, - Containers: []api.Container{ - { - Name: "nginx", - Image: "image", - ImagePullPolicy: api.PullNever, - }, - }, - }, - }, - RollbackTo: &extensions.RollbackConfig{ - Revision: 1, - }, - }, - } -} - -func TestValidateDeployment(t *testing.T) { - successCases := []*extensions.Deployment{ - validDeployment(), - } - for _, successCase := range successCases { - if errs := ValidateDeployment(successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]*extensions.Deployment{} - errorCases["metadata.name: Required value"] = &extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Namespace: api.NamespaceDefault, - }, - } - // selector should match the labels in pod template. - invalidSelectorDeployment := validDeployment() - invalidSelectorDeployment.Spec.Selector = &unversioned.LabelSelector{ - MatchLabels: map[string]string{ - "name": "def", - }, - } - errorCases["`selector` does not match template `labels`"] = invalidSelectorDeployment - - // RestartPolicy should be always. - invalidRestartPolicyDeployment := validDeployment() - invalidRestartPolicyDeployment.Spec.Template.Spec.RestartPolicy = api.RestartPolicyNever - errorCases["Unsupported value: \"Never\""] = invalidRestartPolicyDeployment - - // rollingUpdate should be nil for recreate. - invalidRecreateDeployment := validDeployment() - invalidRecreateDeployment.Spec.Strategy = extensions.DeploymentStrategy{ - Type: extensions.RecreateDeploymentStrategyType, - RollingUpdate: &extensions.RollingUpdateDeployment{}, - } - errorCases["may not be specified when strategy `type` is 'Recreate'"] = invalidRecreateDeployment - - // MaxSurge should be in the form of 20%. - invalidMaxSurgeDeployment := validDeployment() - invalidMaxSurgeDeployment.Spec.Strategy = extensions.DeploymentStrategy{ - Type: extensions.RollingUpdateDeploymentStrategyType, - RollingUpdate: &extensions.RollingUpdateDeployment{ - MaxSurge: intstr.FromString("20Percent"), - }, - } - errorCases["must be an integer or percentage"] = invalidMaxSurgeDeployment - - // MaxSurge and MaxUnavailable cannot both be zero. - invalidRollingUpdateDeployment := validDeployment() - invalidRollingUpdateDeployment.Spec.Strategy = extensions.DeploymentStrategy{ - Type: extensions.RollingUpdateDeploymentStrategyType, - RollingUpdate: &extensions.RollingUpdateDeployment{ - MaxSurge: intstr.FromString("0%"), - MaxUnavailable: intstr.FromInt(0), - }, - } - errorCases["may not be 0 when `maxSurge` is 0"] = invalidRollingUpdateDeployment - - // MaxUnavailable should not be more than 100%. - invalidMaxUnavailableDeployment := validDeployment() - invalidMaxUnavailableDeployment.Spec.Strategy = extensions.DeploymentStrategy{ - Type: extensions.RollingUpdateDeploymentStrategyType, - RollingUpdate: &extensions.RollingUpdateDeployment{ - MaxUnavailable: intstr.FromString("110%"), - }, - } - errorCases["must not be greater than 100%"] = invalidMaxUnavailableDeployment - - // Rollback.Revision must be non-negative - invalidRollbackRevisionDeployment := validDeployment() - invalidRollbackRevisionDeployment.Spec.RollbackTo.Revision = -3 - errorCases["must be greater than or equal to 0"] = invalidRollbackRevisionDeployment - - for k, v := range errorCases { - errs := ValidateDeployment(v) - if len(errs) == 0 { - t.Errorf("[%s] expected failure", k) - } else if !strings.Contains(errs[0].Error(), k) { - t.Errorf("unexpected error: %q, expected: %q", errs[0].Error(), k) - } - } -} - -func validDeploymentRollback() *extensions.DeploymentRollback { - return &extensions.DeploymentRollback{ - Name: "abc", - UpdatedAnnotations: map[string]string{ - "created-by": "abc", - }, - RollbackTo: extensions.RollbackConfig{ - Revision: 1, - }, - } -} - -func TestValidateDeploymentRollback(t *testing.T) { - noAnnotation := validDeploymentRollback() - noAnnotation.UpdatedAnnotations = nil - successCases := []*extensions.DeploymentRollback{ - validDeploymentRollback(), - noAnnotation, - } - for _, successCase := range successCases { - if errs := ValidateDeploymentRollback(successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]*extensions.DeploymentRollback{} - invalidNoName := validDeploymentRollback() - invalidNoName.Name = "" - errorCases["name: Required value"] = invalidNoName - - for k, v := range errorCases { - errs := ValidateDeploymentRollback(v) - if len(errs) == 0 { - t.Errorf("[%s] expected failure", k) - } else if !strings.Contains(errs[0].Error(), k) { - t.Errorf("unexpected error: %q, expected: %q", errs[0].Error(), k) - } - } -} - -type ingressRules map[string]string - -func TestValidateIngress(t *testing.T) { - defaultBackend := extensions.IngressBackend{ - ServiceName: "default-backend", - ServicePort: intstr.FromInt(80), - } - - newValid := func() extensions.Ingress { - return extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.IngressSpec{ - Backend: &extensions.IngressBackend{ - ServiceName: "default-backend", - ServicePort: intstr.FromInt(80), - }, - Rules: []extensions.IngressRule{ - { - Host: "foo.bar.com", - IngressRuleValue: extensions.IngressRuleValue{ - HTTP: &extensions.HTTPIngressRuleValue{ - Paths: []extensions.HTTPIngressPath{ - { - Path: "/foo", - Backend: defaultBackend, - }, - }, - }, - }, - }, - }, - }, - Status: extensions.IngressStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - {IP: "127.0.0.1"}, - }, - }, - }, - } - } - servicelessBackend := newValid() - servicelessBackend.Spec.Backend.ServiceName = "" - invalidNameBackend := newValid() - invalidNameBackend.Spec.Backend.ServiceName = "defaultBackend" - noPortBackend := newValid() - noPortBackend.Spec.Backend = &extensions.IngressBackend{ServiceName: defaultBackend.ServiceName} - noForwardSlashPath := newValid() - noForwardSlashPath.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []extensions.HTTPIngressPath{ - { - Path: "invalid", - Backend: defaultBackend, - }, - } - noPaths := newValid() - noPaths.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []extensions.HTTPIngressPath{} - badHost := newValid() - badHost.Spec.Rules[0].Host = "foobar:80" - badRegexPath := newValid() - badPathExpr := "/invalid[" - badRegexPath.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []extensions.HTTPIngressPath{ - { - Path: badPathExpr, - Backend: defaultBackend, - }, - } - badPathErr := fmt.Sprintf("spec.rules[0].http.paths[0].path: Invalid value: '%v'", badPathExpr) - hostIP := "127.0.0.1" - badHostIP := newValid() - badHostIP.Spec.Rules[0].Host = hostIP - badHostIPErr := fmt.Sprintf("spec.rules[0].host: Invalid value: '%v'", hostIP) - - errorCases := map[string]extensions.Ingress{ - "spec.backend.serviceName: Required value": servicelessBackend, - "spec.backend.serviceName: Invalid value": invalidNameBackend, - "spec.backend.servicePort: Invalid value": noPortBackend, - "spec.rules[0].host: Invalid value": badHost, - "spec.rules[0].http.paths: Required value": noPaths, - "spec.rules[0].http.paths[0].path: Invalid value": noForwardSlashPath, - } - errorCases[badPathErr] = badRegexPath - errorCases[badHostIPErr] = badHostIP - - for k, v := range errorCases { - errs := ValidateIngress(&v) - if len(errs) == 0 { - t.Errorf("expected failure for %q", k) - } else { - s := strings.Split(k, ":") - err := errs[0] - if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { - t.Errorf("unexpected error: %q, expected: %q", err, k) - } - } - } -} - -func TestValidateIngressStatusUpdate(t *testing.T) { - defaultBackend := extensions.IngressBackend{ - ServiceName: "default-backend", - ServicePort: intstr.FromInt(80), - } - - newValid := func() extensions.Ingress { - return extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: api.NamespaceDefault, - ResourceVersion: "9", - }, - Spec: extensions.IngressSpec{ - Backend: &extensions.IngressBackend{ - ServiceName: "default-backend", - ServicePort: intstr.FromInt(80), - }, - Rules: []extensions.IngressRule{ - { - Host: "foo.bar.com", - IngressRuleValue: extensions.IngressRuleValue{ - HTTP: &extensions.HTTPIngressRuleValue{ - Paths: []extensions.HTTPIngressPath{ - { - Path: "/foo", - Backend: defaultBackend, - }, - }, - }, - }, - }, - }, - }, - Status: extensions.IngressStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - {IP: "127.0.0.1", Hostname: "foo.bar.com"}, - }, - }, - }, - } - } - oldValue := newValid() - newValue := newValid() - newValue.Status = extensions.IngressStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - {IP: "127.0.0.2", Hostname: "foo.com"}, - }, - }, - } - invalidIP := newValid() - invalidIP.Status = extensions.IngressStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - {IP: "abcd", Hostname: "foo.com"}, - }, - }, - } - invalidHostname := newValid() - invalidHostname.Status = extensions.IngressStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - {IP: "127.0.0.1", Hostname: "127.0.0.1"}, - }, - }, - } - - errs := ValidateIngressStatusUpdate(&newValue, &oldValue) - if len(errs) != 0 { - t.Errorf("Unexpected error %v", errs) - } - - errorCases := map[string]extensions.Ingress{ - "status.loadBalancer.ingress[0].ip: Invalid value": invalidIP, - "status.loadBalancer.ingress[0].hostname: Invalid value": invalidHostname, - } - for k, v := range errorCases { - errs := ValidateIngressStatusUpdate(&v, &oldValue) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } else { - s := strings.Split(k, ":") - err := errs[0] - if err.Field != s[0] || !strings.Contains(err.Error(), s[1]) { - t.Errorf("unexpected error: %q, expected: %q", err, k) - } - } - } -} - -func TestValidateScale(t *testing.T) { - successCases := []extensions.Scale{ - { - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.ScaleSpec{ - Replicas: 1, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.ScaleSpec{ - Replicas: 10, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.ScaleSpec{ - Replicas: 0, - }, - }, - } - - for _, successCase := range successCases { - if errs := ValidateScale(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := []struct { - scale extensions.Scale - msg string - }{ - { - scale: extensions.Scale{ - ObjectMeta: api.ObjectMeta{ - Name: "frontend", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.ScaleSpec{ - Replicas: -1, - }, - }, - msg: "must be greater than or equal to 0", - }, - } - - for _, c := range errorCases { - if errs := ValidateScale(&c.scale); len(errs) == 0 { - t.Errorf("expected failure for %s", c.msg) - } else if !strings.Contains(errs[0].Error(), c.msg) { - t.Errorf("unexpected error: %v, expected: %s", errs[0], c.msg) - } - } -} - -func TestValidateReplicaSetStatusUpdate(t *testing.T) { - validLabels := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - type rcUpdateTest struct { - old extensions.ReplicaSet - update extensions.ReplicaSet - } - successCases := []rcUpdateTest{ - { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - Status: extensions.ReplicaSetStatus{ - Replicas: 2, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 3, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - Status: extensions.ReplicaSetStatus{ - Replicas: 4, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateReplicaSetStatusUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]rcUpdateTest{ - "negative replicas": { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - Status: extensions.ReplicaSetStatus{ - Replicas: 3, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - Status: extensions.ReplicaSetStatus{ - Replicas: -3, - }, - }, - }, - } - for testName, errorCase := range errorCases { - if errs := ValidateReplicaSetStatusUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } - -} - -func TestValidateReplicaSetUpdate(t *testing.T) { - validLabels := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - readWriteVolumePodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - Volumes: []api.Volume{{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}}, - }, - }, - } - invalidLabels := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidLabels, - }, - }, - } - type rcUpdateTest struct { - old extensions.ReplicaSet - update extensions.ReplicaSet - } - successCases := []rcUpdateTest{ - { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 3, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - }, - { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 1, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: readWriteVolumePodTemplate.Template, - }, - }, - }, - } - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateReplicaSetUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]rcUpdateTest{ - "more than one read/write": { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: readWriteVolumePodTemplate.Template, - }, - }, - }, - "invalid selector": { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: invalidLabels}, - Template: validPodTemplate.Template, - }, - }, - }, - "invalid pod": { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: invalidPodTemplate.Template, - }, - }, - }, - "negative replicas": { - old: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - update: extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: -1, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - }, - } - for testName, errorCase := range errorCases { - if errs := ValidateReplicaSetUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { - t.Errorf("expected failure: %s", testName) - } - } -} - -func TestValidateReplicaSet(t *testing.T) { - validLabels := map[string]string{"a": "b"} - validPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - readWriteVolumePodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - Spec: api.PodSpec{ - Volumes: []api.Volume{{Name: "gcepd", VolumeSource: api.VolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{PDName: "my-PD", FSType: "ext4", Partition: 1, ReadOnly: false}}}}, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - }, - } - invalidLabels := map[string]string{"NoUppercaseOrSpecialCharsLike=Equals": "b"} - invalidPodTemplate := api.PodTemplate{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - }, - ObjectMeta: api.ObjectMeta{ - Labels: invalidLabels, - }, - }, - } - successCases := []extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "abc-123", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 1, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: readWriteVolumePodTemplate.Template, - }, - }, - } - for _, successCase := range successCases { - if errs := ValidateReplicaSet(&successCase); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - - errorCases := map[string]extensions.ReplicaSet{ - "zero-length ID": { - ObjectMeta: api.ObjectMeta{Name: "", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "missing-namespace": { - ObjectMeta: api.ObjectMeta{Name: "abc-123"}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "empty selector": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Template: validPodTemplate.Template, - }, - }, - "selector_doesnt_match": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - Template: validPodTemplate.Template, - }, - }, - "invalid manifest": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - }, - }, - "read-write persistent disk with > 1 pod": { - ObjectMeta: api.ObjectMeta{Name: "abc"}, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: readWriteVolumePodTemplate.Template, - }, - }, - "negative_replicas": { - ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault}, - Spec: extensions.ReplicaSetSpec{ - Replicas: -1, - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - }, - }, - "invalid_label": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "invalid_label 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Labels: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Template: invalidPodTemplate.Template, - }, - }, - "invalid_annotation": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - Annotations: map[string]string{ - "NoUppercaseOrSpecialCharsLike=Equals": "bar", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: validPodTemplate.Template, - }, - }, - "invalid restart policy 1": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - }, - }, - }, - "invalid restart policy 2": { - ObjectMeta: api.ObjectMeta{ - Name: "abc-123", - Namespace: api.NamespaceDefault, - }, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: validLabels}, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyNever, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, - }, - ObjectMeta: api.ObjectMeta{ - Labels: validLabels, - }, - }, - }, - }, - } - for k, v := range errorCases { - errs := ValidateReplicaSet(&v) - if len(errs) == 0 { - t.Errorf("expected failure for %s", k) - } - for i := range errs { - field := errs[i].Field - if !strings.HasPrefix(field, "spec.template.") && - field != "metadata.name" && - field != "metadata.namespace" && - field != "spec.selector" && - field != "spec.template" && - field != "GCEPersistentDisk.ReadOnly" && - field != "spec.replicas" && - field != "spec.template.labels" && - field != "metadata.annotations" && - field != "metadata.labels" && - field != "status.replicas" { - t.Errorf("%s: missing prefix for: %v", k, errs[i]) - } - } - } -} - -func newInt32(val int32) *int32 { - p := new(int32) - *p = val - return p -} - -func TestValidatePodSecurityPolicy(t *testing.T) { - validSCC := func() *extensions.PodSecurityPolicy { - return &extensions.PodSecurityPolicy{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: extensions.PodSecurityPolicySpec{ - SELinux: extensions.SELinuxStrategyOptions{ - Rule: extensions.SELinuxStrategyRunAsAny, - }, - RunAsUser: extensions.RunAsUserStrategyOptions{ - Rule: extensions.RunAsUserStrategyRunAsAny, - }, - }, - } - } - - noUserOptions := validSCC() - noUserOptions.Spec.RunAsUser.Rule = "" - - noSELinuxOptions := validSCC() - noSELinuxOptions.Spec.SELinux.Rule = "" - - invalidUserStratRule := validSCC() - invalidUserStratRule.Spec.RunAsUser.Rule = "invalid" - - invalidSELinuxStratRule := validSCC() - invalidSELinuxStratRule.Spec.SELinux.Rule = "invalid" - - missingObjectMetaName := validSCC() - missingObjectMetaName.ObjectMeta.Name = "" - - invalidRangeMinGreaterThanMax := validSCC() - invalidRangeMinGreaterThanMax.Spec.RunAsUser.Ranges = []extensions.IDRange{ - {Min: 2, Max: 1}, - } - - invalidRangeNegativeMin := validSCC() - invalidRangeNegativeMin.Spec.RunAsUser.Ranges = []extensions.IDRange{ - {Min: -1, Max: 10}, - } - - invalidRangeNegativeMax := validSCC() - invalidRangeNegativeMax.Spec.RunAsUser.Ranges = []extensions.IDRange{ - {Min: 1, Max: -10}, - } - - errorCases := map[string]struct { - scc *extensions.PodSecurityPolicy - errorDetail string - }{ - "no user options": { - scc: noUserOptions, - errorDetail: "supported values: MustRunAs, MustRunAsNonRoot, RunAsAny", - }, - "no selinux options": { - scc: noSELinuxOptions, - errorDetail: "supported values: MustRunAs, RunAsAny", - }, - "invalid user strategy rule": { - scc: invalidUserStratRule, - errorDetail: "supported values: MustRunAs, MustRunAsNonRoot, RunAsAny", - }, - "invalid selinux strategy rule": { - scc: invalidSELinuxStratRule, - errorDetail: "supported values: MustRunAs, RunAsAny", - }, - "missing object meta name": { - scc: missingObjectMetaName, - errorDetail: "name or generateName is required", - }, - "invalid range min greater than max": { - scc: invalidRangeMinGreaterThanMax, - errorDetail: "min cannot be greater than max", - }, - "invalid range negative min": { - scc: invalidRangeNegativeMin, - errorDetail: "min cannot be negative", - }, - "invalid range negative max": { - scc: invalidRangeNegativeMax, - errorDetail: "max cannot be negative", - }, - } - - for k, v := range errorCases { - if errs := ValidatePodSecurityPolicy(v.scc); len(errs) == 0 || errs[0].Detail != v.errorDetail { - t.Errorf("Expected error with detail %s for %s, got %v", v.errorDetail, k, errs[0].Detail) - } - } - - mustRunAs := validSCC() - mustRunAs.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAs - mustRunAs.Spec.RunAsUser.Ranges = []extensions.IDRange{ - { - Min: 1, - Max: 1, - }, - } - mustRunAs.Spec.SELinux.Rule = extensions.SELinuxStrategyMustRunAs - - runAsNonRoot := validSCC() - runAsNonRoot.Spec.RunAsUser.Rule = extensions.RunAsUserStrategyMustRunAsNonRoot - - successCases := map[string]struct { - scc *extensions.PodSecurityPolicy - }{ - "must run as": { - scc: mustRunAs, - }, - "run as any": { - scc: validSCC(), - }, - "run as non-root (user only)": { - scc: runAsNonRoot, - }, - } - - for k, v := range successCases { - if errs := ValidatePodSecurityPolicy(v.scc); len(errs) != 0 { - t.Errorf("Expected success for %s, got %v", k, errs) - } - } -} - -func newBool(val bool) *bool { - p := new(bool) - *p = val - return p -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/policy/validation/validation.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/policy/validation/validation.go deleted file mode 100644 index d9ce117ae..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/policy/validation/validation.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - unversionedvalidation "k8s.io/kubernetes/pkg/api/unversioned/validation" - extensionsvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation" - "k8s.io/kubernetes/pkg/apis/policy" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func ValidatePodDisruptionBudgetSpec(spec policy.PodDisruptionBudgetSpec, fldPath *field.Path) field.ErrorList { - allErrs := field.ErrorList{} - - allErrs = append(allErrs, extensionsvalidation.ValidatePositiveIntOrPercent(spec.MinAvailable, fldPath.Child("minAvailable"))...) - allErrs = append(allErrs, extensionsvalidation.IsNotMoreThan100Percent(spec.MinAvailable, fldPath.Child("minAvailable"))...) - allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...) - - return allErrs -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/policy/validation/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/policy/validation/validation_test.go deleted file mode 100644 index 9b0737156..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/policy/validation/validation_test.go +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 validation - -import ( - "testing" - - "k8s.io/kubernetes/pkg/apis/policy" - "k8s.io/kubernetes/pkg/util/intstr" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func TestValidatePodDisruptionBudgetSpec(t *testing.T) { - successCases := []intstr.IntOrString{ - intstr.FromString("0%"), - intstr.FromString("1%"), - intstr.FromString("100%"), - intstr.FromInt(0), - intstr.FromInt(1), - intstr.FromInt(100), - } - for _, c := range successCases { - spec := policy.PodDisruptionBudgetSpec{ - MinAvailable: c, - } - errs := ValidatePodDisruptionBudgetSpec(spec, field.NewPath("foo")) - if len(errs) != 0 { - t.Errorf("unexpected failure %v for %v", errs, spec) - } - } - - failureCases := []intstr.IntOrString{ - intstr.FromString("1.1%"), - intstr.FromString("nope"), - intstr.FromString("-1%"), - intstr.FromString("101%"), - intstr.FromInt(-1), - } - for _, c := range failureCases { - spec := policy.PodDisruptionBudgetSpec{ - MinAvailable: c, - } - errs := ValidatePodDisruptionBudgetSpec(spec, field.NewPath("foo")) - if len(errs) == 0 { - t.Errorf("unexpected success for %v", spec) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/delta_fifo_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/delta_fifo_test.go deleted file mode 100644 index 8efd982b5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/delta_fifo_test.go +++ /dev/null @@ -1,385 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cache - -import ( - "reflect" - "testing" - "time" -) - -// helper function to reduce stuttering -func testPop(f *DeltaFIFO) testFifoObject { - return f.Pop().(Deltas).Newest().Object.(testFifoObject) -} - -// keyLookupFunc adapts a raw function to be a KeyLookup. -type keyLookupFunc func() []string - -// ListKeys just calls kl. -func (kl keyLookupFunc) ListKeys() []string { - return kl() -} - -// GetByKey returns the key if it exists in the list returned by kl. -func (kl keyLookupFunc) GetByKey(key string) (interface{}, bool, error) { - for _, v := range kl() { - if v == key { - return key, true, nil - } - } - return nil, false, nil -} - -func TestDeltaFIFO_basic(t *testing.T) { - f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil) - const amount = 500 - go func() { - for i := 0; i < amount; i++ { - f.Add(mkFifoObj(string([]rune{'a', rune(i)}), i+1)) - } - }() - go func() { - for u := uint64(0); u < amount; u++ { - f.Add(mkFifoObj(string([]rune{'b', rune(u)}), u+1)) - } - }() - - lastInt := int(0) - lastUint := uint64(0) - for i := 0; i < amount*2; i++ { - switch obj := testPop(f).val.(type) { - case int: - if obj <= lastInt { - t.Errorf("got %v (int) out of order, last was %v", obj, lastInt) - } - lastInt = obj - case uint64: - if obj <= lastUint { - t.Errorf("got %v (uint) out of order, last was %v", obj, lastUint) - } else { - lastUint = obj - } - default: - t.Fatalf("unexpected type %#v", obj) - } - } -} - -func TestDeltaFIFO_compressorWorks(t *testing.T) { - oldestTypes := []DeltaType{} - f := NewDeltaFIFO( - testFifoObjectKeyFunc, - // This function just keeps the most recent delta - // and puts deleted ones in the list. - DeltaCompressorFunc(func(d Deltas) Deltas { - if n := len(d); n > 1 { - oldestTypes = append(oldestTypes, d[0].Type) - d = d[1:] - } - return d - }), - nil, - ) - f.Add(mkFifoObj("foo", 10)) - f.Update(mkFifoObj("foo", 12)) - f.Replace([]interface{}{mkFifoObj("foo", 20)}, "0") - f.Delete(mkFifoObj("foo", 22)) - f.Add(mkFifoObj("foo", 25)) // flush the last one out - expect := []DeltaType{Added, Updated, Sync, Deleted} - if e, a := expect, oldestTypes; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } - if e, a := (Deltas{{Added, mkFifoObj("foo", 25)}}), f.Pop().(Deltas); !reflect.DeepEqual(e, a) { - t.Fatalf("Expected %#v, got %#v", e, a) - } - -} - -func TestDeltaFIFO_addUpdate(t *testing.T) { - f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil) - f.Add(mkFifoObj("foo", 10)) - f.Update(mkFifoObj("foo", 12)) - f.Delete(mkFifoObj("foo", 15)) - - if e, a := []interface{}{mkFifoObj("foo", 15)}, f.List(); !reflect.DeepEqual(e, a) { - t.Errorf("Expected %+v, got %+v", e, a) - } - if e, a := []string{"foo"}, f.ListKeys(); !reflect.DeepEqual(e, a) { - t.Errorf("Expected %+v, got %+v", e, a) - } - - got := make(chan testFifoObject, 2) - go func() { - for { - obj := f.Pop().(Deltas).Newest().Object.(testFifoObject) - t.Logf("got a thing %#v", obj) - t.Logf("D len: %v", len(f.queue)) - got <- obj - } - }() - - first := <-got - if e, a := 15, first.val; e != a { - t.Errorf("Didn't get updated value (%v), got %v", e, a) - } - select { - case unexpected := <-got: - t.Errorf("Got second value %v", unexpected.val) - case <-time.After(50 * time.Millisecond): - } - _, exists, _ := f.Get(mkFifoObj("foo", "")) - if exists { - t.Errorf("item did not get removed") - } -} - -func TestDeltaFIFO_enqueueingNoLister(t *testing.T) { - f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil) - f.Add(mkFifoObj("foo", 10)) - f.Update(mkFifoObj("bar", 15)) - f.Add(mkFifoObj("qux", 17)) - f.Delete(mkFifoObj("qux", 18)) - - // This delete does not enqueue anything because baz doesn't exist. - f.Delete(mkFifoObj("baz", 20)) - - expectList := []int{10, 15, 18} - for _, expect := range expectList { - if e, a := expect, testPop(f).val; e != a { - t.Errorf("Didn't get updated value (%v), got %v", e, a) - } - } - if e, a := 0, len(f.items); e != a { - t.Errorf("queue unexpectedly not empty: %v != %v\n%#v", e, a, f.items) - } -} - -func TestDeltaFIFO_enqueueingWithLister(t *testing.T) { - f := NewDeltaFIFO( - testFifoObjectKeyFunc, - nil, - keyLookupFunc(func() []string { - return []string{"foo", "bar", "baz"} - }), - ) - f.Add(mkFifoObj("foo", 10)) - f.Update(mkFifoObj("bar", 15)) - - // This delete does enqueue the deletion, because "baz" is in the key lister. - f.Delete(mkFifoObj("baz", 20)) - - expectList := []int{10, 15, 20} - for _, expect := range expectList { - if e, a := expect, testPop(f).val; e != a { - t.Errorf("Didn't get updated value (%v), got %v", e, a) - } - } - if e, a := 0, len(f.items); e != a { - t.Errorf("queue unexpectedly not empty: %v != %v", e, a) - } -} - -func TestDeltaFIFO_addReplace(t *testing.T) { - f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil) - f.Add(mkFifoObj("foo", 10)) - f.Replace([]interface{}{mkFifoObj("foo", 15)}, "0") - got := make(chan testFifoObject, 2) - go func() { - for { - got <- testPop(f) - } - }() - - first := <-got - if e, a := 15, first.val; e != a { - t.Errorf("Didn't get updated value (%v), got %v", e, a) - } - select { - case unexpected := <-got: - t.Errorf("Got second value %v", unexpected.val) - case <-time.After(50 * time.Millisecond): - } - _, exists, _ := f.Get(mkFifoObj("foo", "")) - if exists { - t.Errorf("item did not get removed") - } -} - -func TestDeltaFIFO_ReplaceMakesDeletions(t *testing.T) { - f := NewDeltaFIFO( - testFifoObjectKeyFunc, - nil, - keyLookupFunc(func() []string { - return []string{"foo", "bar", "baz"} - }), - ) - f.Delete(mkFifoObj("baz", 10)) - f.Replace([]interface{}{mkFifoObj("foo", 5)}, "0") - - expectedList := []Deltas{ - {{Deleted, mkFifoObj("baz", 10)}}, - {{Sync, mkFifoObj("foo", 5)}}, - // Since "bar" didn't have a delete event and wasn't in the Replace list - // it should get a tombstone key with the right Obj. - {{Deleted, DeletedFinalStateUnknown{Key: "bar", Obj: "bar"}}}, - } - - for _, expected := range expectedList { - cur := f.Pop().(Deltas) - if e, a := expected, cur; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } - } -} - -func TestDeltaFIFO_detectLineJumpers(t *testing.T) { - f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil) - - f.Add(mkFifoObj("foo", 10)) - f.Add(mkFifoObj("bar", 1)) - f.Add(mkFifoObj("foo", 11)) - f.Add(mkFifoObj("foo", 13)) - f.Add(mkFifoObj("zab", 30)) - - if e, a := 13, testPop(f).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } - - f.Add(mkFifoObj("foo", 14)) // ensure foo doesn't jump back in line - - if e, a := 1, testPop(f).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } - - if e, a := 30, testPop(f).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } - - if e, a := 14, testPop(f).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } -} - -func TestDeltaFIFO_addIfNotPresent(t *testing.T) { - f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil) - - f.Add(mkFifoObj("b", 3)) - b3 := f.Pop() - f.Add(mkFifoObj("c", 4)) - c4 := f.Pop() - if e, a := 0, len(f.items); e != a { - t.Fatalf("Expected %v, got %v items in queue", e, a) - } - - f.Add(mkFifoObj("a", 1)) - f.Add(mkFifoObj("b", 2)) - f.AddIfNotPresent(b3) - f.AddIfNotPresent(c4) - - if e, a := 3, len(f.items); a != e { - t.Fatalf("expected queue length %d, got %d", e, a) - } - - expectedValues := []int{1, 2, 4} - for _, expected := range expectedValues { - if actual := testPop(f).val; actual != expected { - t.Fatalf("expected value %d, got %d", expected, actual) - } - } -} - -func TestDeltaFIFO_KeyOf(t *testing.T) { - f := DeltaFIFO{keyFunc: testFifoObjectKeyFunc} - - table := []struct { - obj interface{} - key string - }{ - {obj: testFifoObject{name: "A"}, key: "A"}, - {obj: DeletedFinalStateUnknown{Key: "B", Obj: nil}, key: "B"}, - {obj: Deltas{{Object: testFifoObject{name: "C"}}}, key: "C"}, - {obj: Deltas{{Object: DeletedFinalStateUnknown{Key: "D", Obj: nil}}}, key: "D"}, - } - - for _, item := range table { - got, err := f.KeyOf(item.obj) - if err != nil { - t.Errorf("Unexpected error for %q: %v", item.obj, err) - continue - } - if e, a := item.key, got; e != a { - t.Errorf("Expected %v, got %v", e, a) - } - } -} - -func TestDeltaFIFO_HasSynced(t *testing.T) { - tests := []struct { - actions []func(f *DeltaFIFO) - expectedSynced bool - }{ - { - actions: []func(f *DeltaFIFO){}, - expectedSynced: false, - }, - { - actions: []func(f *DeltaFIFO){ - func(f *DeltaFIFO) { f.Add(mkFifoObj("a", 1)) }, - }, - expectedSynced: true, - }, - { - actions: []func(f *DeltaFIFO){ - func(f *DeltaFIFO) { f.Replace([]interface{}{}, "0") }, - }, - expectedSynced: true, - }, - { - actions: []func(f *DeltaFIFO){ - func(f *DeltaFIFO) { f.Replace([]interface{}{mkFifoObj("a", 1), mkFifoObj("b", 2)}, "0") }, - }, - expectedSynced: false, - }, - { - actions: []func(f *DeltaFIFO){ - func(f *DeltaFIFO) { f.Replace([]interface{}{mkFifoObj("a", 1), mkFifoObj("b", 2)}, "0") }, - func(f *DeltaFIFO) { f.Pop() }, - }, - expectedSynced: false, - }, - { - actions: []func(f *DeltaFIFO){ - func(f *DeltaFIFO) { f.Replace([]interface{}{mkFifoObj("a", 1), mkFifoObj("b", 2)}, "0") }, - func(f *DeltaFIFO) { f.Pop() }, - func(f *DeltaFIFO) { f.Pop() }, - }, - expectedSynced: true, - }, - } - - for i, test := range tests { - f := NewDeltaFIFO(testFifoObjectKeyFunc, nil, nil) - - for _, action := range test.actions { - action(f) - } - if e, a := test.expectedSynced, f.HasSynced(); a != e { - t.Errorf("test case %v failed, expected: %v , got %v", i, e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/expiration_cache_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/expiration_cache_test.go deleted file mode 100644 index 04a05786f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/expiration_cache_test.go +++ /dev/null @@ -1,189 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cache - -import ( - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" -) - -func TestTTLExpirationBasic(t *testing.T) { - testObj := testStoreObject{id: "foo", val: "bar"} - deleteChan := make(chan string, 1) - ttlStore := NewFakeExpirationStore( - testStoreKeyFunc, deleteChan, - &FakeExpirationPolicy{ - NeverExpire: sets.NewString(), - RetrieveKeyFunc: func(obj interface{}) (string, error) { - return obj.(*timestampedEntry).obj.(testStoreObject).id, nil - }, - }, - util.RealClock{}, - ) - err := ttlStore.Add(testObj) - if err != nil { - t.Errorf("Unable to add obj %#v", testObj) - } - item, exists, err := ttlStore.Get(testObj) - if err != nil { - t.Errorf("Failed to get from store, %v", err) - } - if exists || item != nil { - t.Errorf("Got unexpected item %#v", item) - } - key, _ := testStoreKeyFunc(testObj) - select { - case delKey := <-deleteChan: - if delKey != key { - t.Errorf("Unexpected delete for key %s", key) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Unexpected timeout waiting on delete") - } - close(deleteChan) -} - -func TestReAddExpiredItem(t *testing.T) { - deleteChan := make(chan string, 1) - exp := &FakeExpirationPolicy{ - NeverExpire: sets.NewString(), - RetrieveKeyFunc: func(obj interface{}) (string, error) { - return obj.(*timestampedEntry).obj.(testStoreObject).id, nil - }, - } - ttlStore := NewFakeExpirationStore( - testStoreKeyFunc, deleteChan, exp, util.RealClock{}) - testKey := "foo" - testObj := testStoreObject{id: testKey, val: "bar"} - err := ttlStore.Add(testObj) - if err != nil { - t.Errorf("Unable to add obj %#v", testObj) - } - - // This get will expire the item. - item, exists, err := ttlStore.Get(testObj) - if err != nil { - t.Errorf("Failed to get from store, %v", err) - } - if exists || item != nil { - t.Errorf("Got unexpected item %#v", item) - } - - key, _ := testStoreKeyFunc(testObj) - differentValue := "different_bar" - err = ttlStore.Add( - testStoreObject{id: testKey, val: differentValue}) - if err != nil { - t.Errorf("Failed to add second value") - } - - select { - case delKey := <-deleteChan: - if delKey != key { - t.Errorf("Unexpected delete for key %s", key) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Unexpected timeout waiting on delete") - } - exp.NeverExpire = sets.NewString(testKey) - item, exists, err = ttlStore.GetByKey(testKey) - if err != nil { - t.Errorf("Failed to get from store, %v", err) - } - if !exists || item == nil || item.(testStoreObject).val != differentValue { - t.Errorf("Got unexpected item %#v", item) - } - close(deleteChan) -} - -func TestTTLList(t *testing.T) { - testObjs := []testStoreObject{ - {id: "foo", val: "bar"}, - {id: "foo1", val: "bar1"}, - {id: "foo2", val: "bar2"}, - } - expireKeys := sets.NewString(testObjs[0].id, testObjs[2].id) - deleteChan := make(chan string, len(testObjs)) - defer close(deleteChan) - - ttlStore := NewFakeExpirationStore( - testStoreKeyFunc, deleteChan, - &FakeExpirationPolicy{ - NeverExpire: sets.NewString(testObjs[1].id), - RetrieveKeyFunc: func(obj interface{}) (string, error) { - return obj.(*timestampedEntry).obj.(testStoreObject).id, nil - }, - }, - util.RealClock{}, - ) - for _, obj := range testObjs { - err := ttlStore.Add(obj) - if err != nil { - t.Errorf("Unable to add obj %#v", obj) - } - } - listObjs := ttlStore.List() - if len(listObjs) != 1 || !reflect.DeepEqual(listObjs[0], testObjs[1]) { - t.Errorf("List returned unexpected results %#v", listObjs) - } - - // Make sure all our deletes come through in an acceptable rate (1/100ms) - for expireKeys.Len() != 0 { - select { - case delKey := <-deleteChan: - if !expireKeys.Has(delKey) { - t.Errorf("Unexpected delete for key %s", delKey) - } - expireKeys.Delete(delKey) - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Unexpected timeout waiting on delete") - return - } - } -} - -func TestTTLPolicy(t *testing.T) { - fakeTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) - ttl := 30 * time.Second - exactlyOnTTL := fakeTime.Add(-ttl) - expiredTime := fakeTime.Add(-(ttl + 1)) - - policy := TTLPolicy{ttl, util.NewFakeClock(fakeTime)} - fakeTimestampedEntry := ×tampedEntry{obj: struct{}{}, timestamp: exactlyOnTTL} - if policy.IsExpired(fakeTimestampedEntry) { - t.Errorf("TTL cache should not expire entries exactly on ttl") - } - fakeTimestampedEntry.timestamp = fakeTime - if policy.IsExpired(fakeTimestampedEntry) { - t.Errorf("TTL Cache should not expire entries before ttl") - } - fakeTimestampedEntry.timestamp = expiredTime - if !policy.IsExpired(fakeTimestampedEntry) { - t.Errorf("TTL Cache should expire entries older than ttl") - } - for _, ttl = range []time.Duration{0, -1} { - policy.Ttl = ttl - if policy.IsExpired(fakeTimestampedEntry) { - t.Errorf("TTL policy should only expire entries when initialized with a ttl > 0") - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/fifo_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/fifo_test.go deleted file mode 100644 index 974fa6d3b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/fifo_test.go +++ /dev/null @@ -1,235 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cache - -import ( - "reflect" - "testing" - "time" -) - -func testFifoObjectKeyFunc(obj interface{}) (string, error) { - return obj.(testFifoObject).name, nil -} - -type testFifoObject struct { - name string - val interface{} -} - -func mkFifoObj(name string, val interface{}) testFifoObject { - return testFifoObject{name: name, val: val} -} - -func TestFIFO_basic(t *testing.T) { - f := NewFIFO(testFifoObjectKeyFunc) - const amount = 500 - go func() { - for i := 0; i < amount; i++ { - f.Add(mkFifoObj(string([]rune{'a', rune(i)}), i+1)) - } - }() - go func() { - for u := uint64(0); u < amount; u++ { - f.Add(mkFifoObj(string([]rune{'b', rune(u)}), u+1)) - } - }() - - lastInt := int(0) - lastUint := uint64(0) - for i := 0; i < amount*2; i++ { - switch obj := f.Pop().(testFifoObject).val.(type) { - case int: - if obj <= lastInt { - t.Errorf("got %v (int) out of order, last was %v", obj, lastInt) - } - lastInt = obj - case uint64: - if obj <= lastUint { - t.Errorf("got %v (uint) out of order, last was %v", obj, lastUint) - } else { - lastUint = obj - } - default: - t.Fatalf("unexpected type %#v", obj) - } - } -} - -func TestFIFO_addUpdate(t *testing.T) { - f := NewFIFO(testFifoObjectKeyFunc) - f.Add(mkFifoObj("foo", 10)) - f.Update(mkFifoObj("foo", 15)) - - if e, a := []interface{}{mkFifoObj("foo", 15)}, f.List(); !reflect.DeepEqual(e, a) { - t.Errorf("Expected %+v, got %+v", e, a) - } - if e, a := []string{"foo"}, f.ListKeys(); !reflect.DeepEqual(e, a) { - t.Errorf("Expected %+v, got %+v", e, a) - } - - got := make(chan testFifoObject, 2) - go func() { - for { - got <- f.Pop().(testFifoObject) - } - }() - - first := <-got - if e, a := 15, first.val; e != a { - t.Errorf("Didn't get updated value (%v), got %v", e, a) - } - select { - case unexpected := <-got: - t.Errorf("Got second value %v", unexpected.val) - case <-time.After(50 * time.Millisecond): - } - _, exists, _ := f.Get(mkFifoObj("foo", "")) - if exists { - t.Errorf("item did not get removed") - } -} - -func TestFIFO_addReplace(t *testing.T) { - f := NewFIFO(testFifoObjectKeyFunc) - f.Add(mkFifoObj("foo", 10)) - f.Replace([]interface{}{mkFifoObj("foo", 15)}, "15") - got := make(chan testFifoObject, 2) - go func() { - for { - got <- f.Pop().(testFifoObject) - } - }() - - first := <-got - if e, a := 15, first.val; e != a { - t.Errorf("Didn't get updated value (%v), got %v", e, a) - } - select { - case unexpected := <-got: - t.Errorf("Got second value %v", unexpected.val) - case <-time.After(50 * time.Millisecond): - } - _, exists, _ := f.Get(mkFifoObj("foo", "")) - if exists { - t.Errorf("item did not get removed") - } -} - -func TestFIFO_detectLineJumpers(t *testing.T) { - f := NewFIFO(testFifoObjectKeyFunc) - - f.Add(mkFifoObj("foo", 10)) - f.Add(mkFifoObj("bar", 1)) - f.Add(mkFifoObj("foo", 11)) - f.Add(mkFifoObj("foo", 13)) - f.Add(mkFifoObj("zab", 30)) - - if e, a := 13, f.Pop().(testFifoObject).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } - - f.Add(mkFifoObj("foo", 14)) // ensure foo doesn't jump back in line - - if e, a := 1, f.Pop().(testFifoObject).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } - - if e, a := 30, f.Pop().(testFifoObject).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } - - if e, a := 14, f.Pop().(testFifoObject).val; a != e { - t.Fatalf("expected %d, got %d", e, a) - } -} - -func TestFIFO_addIfNotPresent(t *testing.T) { - f := NewFIFO(testFifoObjectKeyFunc) - - f.Add(mkFifoObj("a", 1)) - f.Add(mkFifoObj("b", 2)) - f.AddIfNotPresent(mkFifoObj("b", 3)) - f.AddIfNotPresent(mkFifoObj("c", 4)) - - if e, a := 3, len(f.items); a != e { - t.Fatalf("expected queue length %d, got %d", e, a) - } - - expectedValues := []int{1, 2, 4} - for _, expected := range expectedValues { - if actual := f.Pop().(testFifoObject).val; actual != expected { - t.Fatalf("expected value %d, got %d", expected, actual) - } - } -} - -func TestFIFO_HasSynced(t *testing.T) { - tests := []struct { - actions []func(f *FIFO) - expectedSynced bool - }{ - { - actions: []func(f *FIFO){}, - expectedSynced: false, - }, - { - actions: []func(f *FIFO){ - func(f *FIFO) { f.Add(mkFifoObj("a", 1)) }, - }, - expectedSynced: true, - }, - { - actions: []func(f *FIFO){ - func(f *FIFO) { f.Replace([]interface{}{}, "0") }, - }, - expectedSynced: true, - }, - { - actions: []func(f *FIFO){ - func(f *FIFO) { f.Replace([]interface{}{mkFifoObj("a", 1), mkFifoObj("b", 2)}, "0") }, - }, - expectedSynced: false, - }, - { - actions: []func(f *FIFO){ - func(f *FIFO) { f.Replace([]interface{}{mkFifoObj("a", 1), mkFifoObj("b", 2)}, "0") }, - func(f *FIFO) { f.Pop() }, - }, - expectedSynced: false, - }, - { - actions: []func(f *FIFO){ - func(f *FIFO) { f.Replace([]interface{}{mkFifoObj("a", 1), mkFifoObj("b", 2)}, "0") }, - func(f *FIFO) { f.Pop() }, - func(f *FIFO) { f.Pop() }, - }, - expectedSynced: true, - }, - } - - for i, test := range tests { - f := NewFIFO(testFifoObjectKeyFunc) - - for _, action := range test.actions { - action(f) - } - if e, a := test.expectedSynced, f.HasSynced(); a != e { - t.Errorf("test case %v failed, expected: %v , got %v", i, e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/index_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/index_test.go deleted file mode 100644 index 4b0d5ff4f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/index_test.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cache - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func testIndexFunc(obj interface{}) ([]string, error) { - pod := obj.(*api.Pod) - return []string{pod.Labels["foo"]}, nil -} - -func TestGetIndexFuncValues(t *testing.T) { - index := NewIndexer(MetaNamespaceKeyFunc, Indexers{"testmodes": testIndexFunc}) - - pod1 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "one", Labels: map[string]string{"foo": "bar"}}} - pod2 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "two", Labels: map[string]string{"foo": "bar"}}} - pod3 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "tre", Labels: map[string]string{"foo": "biz"}}} - - index.Add(pod1) - index.Add(pod2) - index.Add(pod3) - - keys := index.ListIndexFuncValues("testmodes") - if len(keys) != 2 { - t.Errorf("Expected 2 keys but got %v", len(keys)) - } - - for _, key := range keys { - if key != "bar" && key != "biz" { - t.Errorf("Expected only 'bar' or 'biz' but got %s", key) - } - } -} - -func testUsersIndexFunc(obj interface{}) ([]string, error) { - pod := obj.(*api.Pod) - usersString := pod.Annotations["users"] - - return strings.Split(usersString, ","), nil -} - -func TestMultiIndexKeys(t *testing.T) { - index := NewIndexer(MetaNamespaceKeyFunc, Indexers{"byUser": testUsersIndexFunc}) - - pod1 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "one", Annotations: map[string]string{"users": "ernie,bert"}}} - pod2 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "two", Annotations: map[string]string{"users": "bert,oscar"}}} - pod3 := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "tre", Annotations: map[string]string{"users": "ernie,elmo"}}} - - index.Add(pod1) - index.Add(pod2) - index.Add(pod3) - - erniePods, err := index.ByIndex("byUser", "ernie") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(erniePods) != 2 { - t.Errorf("Expected 2 pods but got %v", len(erniePods)) - } - - bertPods, err := index.ByIndex("byUser", "bert") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(bertPods) != 2 { - t.Errorf("Expected 2 pods but got %v", len(bertPods)) - } - - oscarPods, err := index.ByIndex("byUser", "oscar") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(oscarPods) != 1 { - t.Errorf("Expected 1 pods but got %v", len(erniePods)) - } - - ernieAndBertKeys, err := index.Index("byUser", pod1) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(ernieAndBertKeys) != 3 { - t.Errorf("Expected 3 pods but got %v", len(ernieAndBertKeys)) - } - - index.Delete(pod3) - erniePods, err = index.ByIndex("byUser", "ernie") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(erniePods) != 1 { - t.Errorf("Expected 1 pods but got %v", len(erniePods)) - } - elmoPods, err := index.ByIndex("byUser", "elmo") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(elmoPods) != 0 { - t.Errorf("Expected 0 pods but got %v", len(elmoPods)) - } - - obj, err := api.Scheme.DeepCopy(pod2) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - copyOfPod2 := obj.(*api.Pod) - copyOfPod2.Annotations["users"] = "oscar" - index.Update(copyOfPod2) - bertPods, err = index.ByIndex("byUser", "bert") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(bertPods) != 1 { - t.Errorf("Expected 1 pods but got %v", len(bertPods)) - } - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/listers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/listers_test.go deleted file mode 100644 index 5e062fd90..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/listers_test.go +++ /dev/null @@ -1,722 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cache - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/util/sets" -) - -func TestStoreToNodeLister(t *testing.T) { - store := NewStore(MetaNamespaceKeyFunc) - ids := sets.NewString("foo", "bar", "baz") - for id := range ids { - store.Add(&api.Node{ObjectMeta: api.ObjectMeta{Name: id}}) - } - sml := StoreToNodeLister{store} - - gotNodes, err := sml.List() - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - got := make([]string, len(gotNodes.Items)) - for ix := range gotNodes.Items { - got[ix] = gotNodes.Items[ix].Name - } - if !ids.HasAll(got...) || len(got) != len(ids) { - t.Errorf("Expected %v, got %v", ids, got) - } -} - -func TestStoreToNodeConditionLister(t *testing.T) { - store := NewStore(MetaNamespaceKeyFunc) - nodes := []*api.Node{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionFalse, - }, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar"}, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeOutOfDisk, - Status: api.ConditionTrue, - }, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "baz"}, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionFalse, - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionUnknown, - }, - }, - }, - }, - } - for _, n := range nodes { - store.Add(n) - } - - predicate := func(node api.Node) bool { - for _, cond := range node.Status.Conditions { - if cond.Type == api.NodeOutOfDisk && cond.Status == api.ConditionTrue { - return false - } - } - return true - } - - snl := StoreToNodeLister{store} - sncl := snl.NodeCondition(predicate) - - want := sets.NewString("foo", "baz") - gotNodes, err := sncl.List() - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - got := make([]string, len(gotNodes.Items)) - for ix := range gotNodes.Items { - got[ix] = gotNodes.Items[ix].Name - } - if !want.HasAll(got...) || len(got) != len(want) { - t.Errorf("Expected %v, got %v", want, got) - } -} - -func TestStoreToReplicationControllerLister(t *testing.T) { - store := NewIndexer(MetaNamespaceKeyFunc, Indexers{NamespaceIndex: MetaNamespaceIndexFunc}) - lister := StoreToReplicationControllerLister{store} - testCases := []struct { - inRCs []*api.ReplicationController - list func() ([]api.ReplicationController, error) - outRCNames sets.String - expectErr bool - }{ - // Basic listing with all labels and no selectors - { - inRCs: []*api.ReplicationController{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}, - }, - list: func() ([]api.ReplicationController, error) { - return lister.List() - }, - outRCNames: sets.NewString("basic"), - }, - // No pod labels - { - inRCs: []*api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"foo": "baz"}, - }, - }, - }, - list: func() ([]api.ReplicationController, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "pod1", Namespace: "ns"}, - } - return lister.GetPodControllers(pod) - }, - outRCNames: sets.NewString(), - expectErr: true, - }, - // No RC selectors - { - inRCs: []*api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - }, - }, - list: func() ([]api.ReplicationController, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod1", - Namespace: "ns", - Labels: map[string]string{"foo": "bar"}, - }, - } - return lister.GetPodControllers(pod) - }, - outRCNames: sets.NewString(), - expectErr: true, - }, - // Matching labels to selectors and namespace - { - inRCs: []*api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"foo": "bar"}, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"foo": "bar"}, - }, - }, - }, - list: func() ([]api.ReplicationController, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod1", - Labels: map[string]string{"foo": "bar"}, - Namespace: "ns", - }, - } - return lister.GetPodControllers(pod) - }, - outRCNames: sets.NewString("bar"), - }, - } - for _, c := range testCases { - for _, r := range c.inRCs { - store.Add(r) - } - - gotControllers, err := c.list() - if err != nil && c.expectErr { - continue - } else if c.expectErr { - t.Error("Expected error, got none") - continue - } else if err != nil { - t.Errorf("Unexpected error %#v", err) - continue - } - gotNames := make([]string, len(gotControllers)) - for ix := range gotControllers { - gotNames[ix] = gotControllers[ix].Name - } - if !c.outRCNames.HasAll(gotNames...) || len(gotNames) != len(c.outRCNames) { - t.Errorf("Unexpected got controllers %+v expected %+v", gotNames, c.outRCNames) - } - } -} - -func TestStoreToReplicaSetLister(t *testing.T) { - store := NewStore(MetaNamespaceKeyFunc) - lister := StoreToReplicaSetLister{store} - testCases := []struct { - inRSs []*extensions.ReplicaSet - list func() ([]extensions.ReplicaSet, error) - outRSNames sets.String - expectErr bool - }{ - // Basic listing with all labels and no selectors - { - inRSs: []*extensions.ReplicaSet{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}, - }, - list: func() ([]extensions.ReplicaSet, error) { - return lister.List() - }, - outRSNames: sets.NewString("basic"), - }, - // No pod labels - { - inRSs: []*extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "baz"}}, - }, - }, - }, - list: func() ([]extensions.ReplicaSet, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "pod1", Namespace: "ns"}, - } - return lister.GetPodReplicaSets(pod) - }, - outRSNames: sets.NewString(), - expectErr: true, - }, - // No ReplicaSet selectors - { - inRSs: []*extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - }, - }, - list: func() ([]extensions.ReplicaSet, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod1", - Namespace: "ns", - Labels: map[string]string{"foo": "bar"}, - }, - } - return lister.GetPodReplicaSets(pod) - }, - outRSNames: sets.NewString(), - expectErr: true, - }, - // Matching labels to selectors and namespace - { - inRSs: []*extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - }, - list: func() ([]extensions.ReplicaSet, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod1", - Labels: map[string]string{"foo": "bar"}, - Namespace: "ns", - }, - } - return lister.GetPodReplicaSets(pod) - }, - outRSNames: sets.NewString("bar"), - }, - } - for _, c := range testCases { - for _, r := range c.inRSs { - store.Add(r) - } - - gotRSs, err := c.list() - if err != nil && c.expectErr { - continue - } else if c.expectErr { - t.Error("Expected error, got none") - continue - } else if err != nil { - t.Errorf("Unexpected error %#v", err) - continue - } - gotNames := make([]string, len(gotRSs)) - for ix := range gotRSs { - gotNames[ix] = gotRSs[ix].Name - } - if !c.outRSNames.HasAll(gotNames...) || len(gotNames) != len(c.outRSNames) { - t.Errorf("Unexpected got ReplicaSets %+v expected %+v", gotNames, c.outRSNames) - } - } -} - -func TestStoreToDaemonSetLister(t *testing.T) { - store := NewStore(MetaNamespaceKeyFunc) - lister := StoreToDaemonSetLister{store} - testCases := []struct { - inDSs []*extensions.DaemonSet - list func() ([]extensions.DaemonSet, error) - outDaemonSetNames sets.String - expectErr bool - }{ - // Basic listing - { - inDSs: []*extensions.DaemonSet{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}, - }, - list: func() ([]extensions.DaemonSet, error) { - list, err := lister.List() - return list.Items, err - }, - outDaemonSetNames: sets.NewString("basic"), - }, - // Listing multiple daemon sets - { - inDSs: []*extensions.DaemonSet{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}, - {ObjectMeta: api.ObjectMeta{Name: "complex"}}, - {ObjectMeta: api.ObjectMeta{Name: "complex2"}}, - }, - list: func() ([]extensions.DaemonSet, error) { - list, err := lister.List() - return list.Items, err - }, - outDaemonSetNames: sets.NewString("basic", "complex", "complex2"), - }, - // No pod labels - { - inDSs: []*extensions.DaemonSet{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "baz"}}, - }, - }, - }, - list: func() ([]extensions.DaemonSet, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "pod1", Namespace: "ns"}, - } - return lister.GetPodDaemonSets(pod) - }, - outDaemonSetNames: sets.NewString(), - expectErr: true, - }, - // No DS selectors - { - inDSs: []*extensions.DaemonSet{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - }, - }, - list: func() ([]extensions.DaemonSet, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod1", - Namespace: "ns", - Labels: map[string]string{"foo": "bar"}, - }, - } - return lister.GetPodDaemonSets(pod) - }, - outDaemonSetNames: sets.NewString(), - expectErr: true, - }, - // Matching labels to selectors and namespace - { - inDSs: []*extensions.DaemonSet{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - }, - list: func() ([]extensions.DaemonSet, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod1", - Labels: map[string]string{"foo": "bar"}, - Namespace: "ns", - }, - } - return lister.GetPodDaemonSets(pod) - }, - outDaemonSetNames: sets.NewString("bar"), - }, - } - for _, c := range testCases { - for _, r := range c.inDSs { - store.Add(r) - } - - daemonSets, err := c.list() - if err != nil && c.expectErr { - continue - } else if c.expectErr { - t.Error("Expected error, got none") - continue - } else if err != nil { - t.Errorf("Unexpected error %#v", err) - continue - } - daemonSetNames := make([]string, len(daemonSets)) - for ix := range daemonSets { - daemonSetNames[ix] = daemonSets[ix].Name - } - if !c.outDaemonSetNames.HasAll(daemonSetNames...) || len(daemonSetNames) != len(c.outDaemonSetNames) { - t.Errorf("Unexpected got controllers %+v expected %+v", daemonSetNames, c.outDaemonSetNames) - } - } -} - -func TestStoreToJobLister(t *testing.T) { - store := NewStore(MetaNamespaceKeyFunc) - lister := StoreToJobLister{store} - testCases := []struct { - inJobs []*batch.Job - list func() ([]batch.Job, error) - outJobNames sets.String - expectErr bool - msg string - }{ - // Basic listing - { - inJobs: []*batch.Job{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}, - }, - list: func() ([]batch.Job, error) { - list, err := lister.List() - return list.Items, err - }, - outJobNames: sets.NewString("basic"), - msg: "basic listing failed", - }, - // Listing multiple jobs - { - inJobs: []*batch.Job{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}, - {ObjectMeta: api.ObjectMeta{Name: "complex"}}, - {ObjectMeta: api.ObjectMeta{Name: "complex2"}}, - }, - list: func() ([]batch.Job, error) { - list, err := lister.List() - return list.Items, err - }, - outJobNames: sets.NewString("basic", "complex", "complex2"), - msg: "listing multiple jobs failed", - }, - // No pod labels - { - inJobs: []*batch.Job{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "baz"}, - }, - }, - }, - }, - list: func() ([]batch.Job, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "pod", Namespace: "ns"}, - } - return lister.GetPodJobs(pod) - }, - outJobNames: sets.NewString(), - expectErr: true, - msg: "listing jobs failed when pod has no labels: expected error, got none", - }, - // No Job selectors - { - inJobs: []*batch.Job{ - { - ObjectMeta: api.ObjectMeta{Name: "basic", Namespace: "ns"}, - }, - }, - list: func() ([]batch.Job, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod", - Namespace: "ns", - Labels: map[string]string{"foo": "bar"}, - }, - } - return lister.GetPodJobs(pod) - }, - outJobNames: sets.NewString(), - expectErr: true, - msg: "listing jobs failed when job has no selector: expected error, got none", - }, - // Matching labels to selectors and namespace - { - inJobs: []*batch.Job{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar"}, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar"}, - }, - }, - }, - }, - list: func() ([]batch.Job, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod", - Labels: map[string]string{"foo": "bar"}, - Namespace: "ns", - }, - } - return lister.GetPodJobs(pod) - }, - outJobNames: sets.NewString("bar"), - msg: "listing jobs with namespace and selector failed", - }, - // Matching labels to selectors and namespace, error case - { - inJobs: []*batch.Job{ - { - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "foo"}, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar"}, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "bar"}, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar"}, - }, - }, - }, - }, - list: func() ([]batch.Job, error) { - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod", - Labels: map[string]string{"foo": "bar"}, - Namespace: "baz", - }, - } - return lister.GetPodJobs(pod) - }, - expectErr: true, - msg: "listing jobs with namespace and selector failed: expected error, got none", - }, - } - for _, c := range testCases { - for _, r := range c.inJobs { - store.Add(r) - } - - Jobs, err := c.list() - if err != nil && c.expectErr { - continue - } else if c.expectErr { - t.Errorf("%v", c.msg) - continue - } else if err != nil { - t.Errorf("Unexpected error %#v", err) - continue - } - JobNames := make([]string, len(Jobs)) - for ix := range Jobs { - JobNames[ix] = Jobs[ix].Name - } - if !c.outJobNames.HasAll(JobNames...) || len(JobNames) != len(c.outJobNames) { - t.Errorf("%v : expected %v, got %v", c.msg, JobNames, c.outJobNames) - } - } -} - -func TestStoreToPodLister(t *testing.T) { - store := NewIndexer(MetaNamespaceKeyFunc, Indexers{NamespaceIndex: MetaNamespaceIndexFunc}) - ids := []string{"foo", "bar", "baz"} - for _, id := range ids { - store.Add(&api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: id, - Labels: map[string]string{"name": id}, - }, - }) - } - spl := StoreToPodLister{store} - - for _, id := range ids { - got, err := spl.List(labels.Set{"name": id}.AsSelector()) - if err != nil { - t.Errorf("Unexpected error: %v", err) - continue - } - if e, a := 1, len(got); e != a { - t.Errorf("Expected %v, got %v", e, a) - continue - } - if e, a := id, got[0].Name; e != a { - t.Errorf("Expected %v, got %v", e, a) - continue - } - - exists, err := spl.Exists(&api.Pod{ObjectMeta: api.ObjectMeta{Name: id}}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !exists { - t.Errorf("exists returned false for %v", id) - } - } - - exists, err := spl.Exists(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "qux"}}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if exists { - t.Error("Unexpected pod exists") - } -} - -func TestStoreToServiceLister(t *testing.T) { - store := NewStore(MetaNamespaceKeyFunc) - store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{}, - }, - }) - store.Add(&api.Service{ObjectMeta: api.ObjectMeta{Name: "bar"}}) - ssl := StoreToServiceLister{store} - - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foopod", - Labels: map[string]string{"role": "foo"}, - }, - } - - services, err := ssl.GetPodServices(pod) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if len(services) != 1 { - t.Fatalf("Expected 1 service, got %v", len(services)) - } - if e, a := "foo", services[0].Name; e != a { - t.Errorf("Expected service %q, got %q", e, a) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/listwatch_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/listwatch_test.go deleted file mode 100644 index ddd58cf74..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/listwatch_test.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cache - -import ( - "net/http/httptest" - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/fields" - utiltesting "k8s.io/kubernetes/pkg/util/testing" -) - -func parseSelectorOrDie(s string) fields.Selector { - selector, err := fields.ParseSelector(s) - if err != nil { - panic(err) - } - return selector -} - -// buildQueryValues is a convenience function for knowing if a namespace should be in a query param or not -func buildQueryValues(query url.Values) url.Values { - v := url.Values{} - if query != nil { - for key, values := range query { - for _, value := range values { - v.Add(key, value) - } - } - } - return v -} - -func buildLocation(resourcePath string, query url.Values) string { - return resourcePath + "?" + query.Encode() -} - -func TestListWatchesCanList(t *testing.T) { - fieldSelectorQueryParamName := unversioned.FieldSelectorQueryParam(testapi.Default.GroupVersion().String()) - table := []struct { - location string - resource string - namespace string - fieldSelector fields.Selector - }{ - // Node - { - location: testapi.Default.ResourcePath("nodes", api.NamespaceAll, ""), - resource: "nodes", - namespace: api.NamespaceAll, - fieldSelector: parseSelectorOrDie(""), - }, - // pod with "assigned" field selector. - { - location: buildLocation( - testapi.Default.ResourcePath("pods", api.NamespaceAll, ""), - buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})), - resource: "pods", - namespace: api.NamespaceAll, - fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), - }, - // pod in namespace "foo" - { - location: buildLocation( - testapi.Default.ResourcePath("pods", "foo", ""), - buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})), - resource: "pods", - namespace: "foo", - fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), - }, - } - for _, item := range table { - handler := utiltesting.FakeHandler{ - StatusCode: 500, - ResponseBody: "", - T: t, - } - server := httptest.NewServer(&handler) - defer server.Close() - client := client.NewOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - lw := NewListWatchFromClient(client, item.resource, item.namespace, item.fieldSelector) - // This test merely tests that the correct request is made. - lw.List(api.ListOptions{}) - handler.ValidateRequest(t, item.location, "GET", nil) - } -} - -func TestListWatchesCanWatch(t *testing.T) { - fieldSelectorQueryParamName := unversioned.FieldSelectorQueryParam(testapi.Default.GroupVersion().String()) - table := []struct { - rv string - location string - resource string - namespace string - fieldSelector fields.Selector - }{ - // Node - { - location: buildLocation( - testapi.Default.ResourcePathWithPrefix("watch", "nodes", api.NamespaceAll, ""), - buildQueryValues(url.Values{})), - rv: "", - resource: "nodes", - namespace: api.NamespaceAll, - fieldSelector: parseSelectorOrDie(""), - }, - { - location: buildLocation( - testapi.Default.ResourcePathWithPrefix("watch", "nodes", api.NamespaceAll, ""), - buildQueryValues(url.Values{"resourceVersion": []string{"42"}})), - rv: "42", - resource: "nodes", - namespace: api.NamespaceAll, - fieldSelector: parseSelectorOrDie(""), - }, - // pod with "assigned" field selector. - { - location: buildLocation( - testapi.Default.ResourcePathWithPrefix("watch", "pods", api.NamespaceAll, ""), - buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}})), - rv: "0", - resource: "pods", - namespace: api.NamespaceAll, - fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), - }, - // pod with namespace foo and assigned field selector - { - location: buildLocation( - testapi.Default.ResourcePathWithPrefix("watch", "pods", "foo", ""), - buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}, "resourceVersion": []string{"0"}})), - rv: "0", - resource: "pods", - namespace: "foo", - fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), - }, - } - - for _, item := range table { - handler := utiltesting.FakeHandler{ - StatusCode: 500, - ResponseBody: "", - T: t, - } - server := httptest.NewServer(&handler) - defer server.Close() - client := client.NewOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - lw := NewListWatchFromClient(client, item.resource, item.namespace, item.fieldSelector) - // This test merely tests that the correct request is made. - lw.Watch(api.ListOptions{ResourceVersion: item.rv}) - handler.ValidateRequest(t, item.location, "GET", nil) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/reflector_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/reflector_test.go deleted file mode 100644 index 223769ade..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/reflector_test.go +++ /dev/null @@ -1,404 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cache - -import ( - "fmt" - "math/rand" - "strconv" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" -) - -type testLW struct { - ListFunc func() (runtime.Object, error) - WatchFunc func(resourceVersion string) (watch.Interface, error) -} - -func (t *testLW) List(options api.ListOptions) (runtime.Object, error) { - return t.ListFunc() -} -func (t *testLW) Watch(options api.ListOptions) (watch.Interface, error) { - return t.WatchFunc(options.ResourceVersion) -} - -func TestCloseWatchChannelOnError(t *testing.T) { - r := NewReflector(&testLW{}, &api.Pod{}, NewStore(MetaNamespaceKeyFunc), 0) - pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}} - fw := watch.NewFake() - r.listerWatcher = &testLW{ - WatchFunc: func(rv string) (watch.Interface, error) { - return fw, nil - }, - ListFunc: func() (runtime.Object, error) { - return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil - }, - } - go r.ListAndWatch(wait.NeverStop) - fw.Error(pod) - select { - case _, ok := <-fw.ResultChan(): - if ok { - t.Errorf("Watch channel left open after cancellation") - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("the cancellation is at least %s late", wait.ForeverTestTimeout.String()) - break - } -} - -func TestRunUntil(t *testing.T) { - stopCh := make(chan struct{}) - store := NewStore(MetaNamespaceKeyFunc) - r := NewReflector(&testLW{}, &api.Pod{}, store, 0) - fw := watch.NewFake() - r.listerWatcher = &testLW{ - WatchFunc: func(rv string) (watch.Interface, error) { - return fw, nil - }, - ListFunc: func() (runtime.Object, error) { - return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil - }, - } - r.RunUntil(stopCh) - // Synchronously add a dummy pod into the watch channel so we - // know the RunUntil go routine is in the watch handler. - fw.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}}) - stopCh <- struct{}{} - select { - case _, ok := <-fw.ResultChan(): - if ok { - t.Errorf("Watch channel left open after stopping the watch") - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("the cancellation is at least %s late", wait.ForeverTestTimeout.String()) - break - } -} - -func TestReflectorResyncChan(t *testing.T) { - s := NewStore(MetaNamespaceKeyFunc) - g := NewReflector(&testLW{}, &api.Pod{}, s, time.Millisecond) - a, _ := g.resyncChan() - b := time.After(wait.ForeverTestTimeout) - select { - case <-a: - t.Logf("got timeout as expected") - case <-b: - t.Errorf("resyncChan() is at least 99 milliseconds late??") - } -} - -func BenchmarkReflectorResyncChanMany(b *testing.B) { - s := NewStore(MetaNamespaceKeyFunc) - g := NewReflector(&testLW{}, &api.Pod{}, s, 25*time.Millisecond) - // The improvement to this (calling the timer's Stop() method) makes - // this benchmark about 40% faster. - for i := 0; i < b.N; i++ { - g.resyncPeriod = time.Duration(rand.Float64() * float64(time.Millisecond) * 25) - _, stop := g.resyncChan() - stop() - } -} - -func TestReflectorWatchHandlerError(t *testing.T) { - s := NewStore(MetaNamespaceKeyFunc) - g := NewReflector(&testLW{}, &api.Pod{}, s, 0) - fw := watch.NewFake() - go func() { - fw.Stop() - }() - var resumeRV string - err := g.watchHandler(fw, &resumeRV, neverExitWatch, wait.NeverStop) - if err == nil { - t.Errorf("unexpected non-error") - } -} - -func TestReflectorWatchHandler(t *testing.T) { - s := NewStore(MetaNamespaceKeyFunc) - g := NewReflector(&testLW{}, &api.Pod{}, s, 0) - fw := watch.NewFake() - s.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - s.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}}) - go func() { - fw.Add(&api.Service{ObjectMeta: api.ObjectMeta{Name: "rejected"}}) - fw.Delete(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - fw.Modify(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "55"}}) - fw.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "baz", ResourceVersion: "32"}}) - fw.Stop() - }() - var resumeRV string - err := g.watchHandler(fw, &resumeRV, neverExitWatch, wait.NeverStop) - if err != nil { - t.Errorf("unexpected error %v", err) - } - - mkPod := func(id string, rv string) *api.Pod { - return &api.Pod{ObjectMeta: api.ObjectMeta{Name: id, ResourceVersion: rv}} - } - - table := []struct { - Pod *api.Pod - exists bool - }{ - {mkPod("foo", ""), false}, - {mkPod("rejected", ""), false}, - {mkPod("bar", "55"), true}, - {mkPod("baz", "32"), true}, - } - for _, item := range table { - obj, exists, _ := s.Get(item.Pod) - if e, a := item.exists, exists; e != a { - t.Errorf("%v: expected %v, got %v", item.Pod, e, a) - } - if !exists { - continue - } - if e, a := item.Pod.ResourceVersion, obj.(*api.Pod).ResourceVersion; e != a { - t.Errorf("%v: expected %v, got %v", item.Pod, e, a) - } - } - - // RV should send the last version we see. - if e, a := "32", resumeRV; e != a { - t.Errorf("expected %v, got %v", e, a) - } - - // last sync resource version should be the last version synced with store - if e, a := "32", g.LastSyncResourceVersion(); e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestReflectorWatchHandlerTimeout(t *testing.T) { - s := NewStore(MetaNamespaceKeyFunc) - g := NewReflector(&testLW{}, &api.Pod{}, s, 0) - fw := watch.NewFake() - var resumeRV string - exit := make(chan time.Time, 1) - exit <- time.Now() - err := g.watchHandler(fw, &resumeRV, exit, wait.NeverStop) - if err != errorResyncRequested { - t.Errorf("expected timeout error, but got %q", err) - } -} - -func TestReflectorStopWatch(t *testing.T) { - s := NewStore(MetaNamespaceKeyFunc) - g := NewReflector(&testLW{}, &api.Pod{}, s, 0) - fw := watch.NewFake() - var resumeRV string - stopWatch := make(chan struct{}, 1) - stopWatch <- struct{}{} - err := g.watchHandler(fw, &resumeRV, neverExitWatch, stopWatch) - if err != errorStopRequested { - t.Errorf("expected stop error, got %q", err) - } -} - -func TestReflectorListAndWatch(t *testing.T) { - createdFakes := make(chan *watch.FakeWatcher) - - // The ListFunc says that it's at revision 1. Therefore, we expect our WatchFunc - // to get called at the beginning of the watch with 1, and again with 3 when we - // inject an error. - expectedRVs := []string{"1", "3"} - lw := &testLW{ - WatchFunc: func(rv string) (watch.Interface, error) { - fw := watch.NewFake() - if e, a := expectedRVs[0], rv; e != a { - t.Errorf("Expected rv %v, but got %v", e, a) - } - expectedRVs = expectedRVs[1:] - // channel is not buffered because the for loop below needs to block. But - // we don't want to block here, so report the new fake via a go routine. - go func() { createdFakes <- fw }() - return fw, nil - }, - ListFunc: func() (runtime.Object, error) { - return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}, nil - }, - } - s := NewFIFO(MetaNamespaceKeyFunc) - r := NewReflector(lw, &api.Pod{}, s, 0) - go r.ListAndWatch(wait.NeverStop) - - ids := []string{"foo", "bar", "baz", "qux", "zoo"} - var fw *watch.FakeWatcher - for i, id := range ids { - if fw == nil { - fw = <-createdFakes - } - sendingRV := strconv.FormatUint(uint64(i+2), 10) - fw.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: id, ResourceVersion: sendingRV}}) - if sendingRV == "3" { - // Inject a failure. - fw.Stop() - fw = nil - } - } - - // Verify we received the right ids with the right resource versions. - for i, id := range ids { - pod := s.Pop().(*api.Pod) - if e, a := id, pod.Name; e != a { - t.Errorf("%v: Expected %v, got %v", i, e, a) - } - if e, a := strconv.FormatUint(uint64(i+2), 10), pod.ResourceVersion; e != a { - t.Errorf("%v: Expected %v, got %v", i, e, a) - } - } - - if len(expectedRVs) != 0 { - t.Error("called watchStarter an unexpected number of times") - } -} - -func TestReflectorListAndWatchWithErrors(t *testing.T) { - mkPod := func(id string, rv string) *api.Pod { - return &api.Pod{ObjectMeta: api.ObjectMeta{Name: id, ResourceVersion: rv}} - } - mkList := func(rv string, pods ...*api.Pod) *api.PodList { - list := &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: rv}} - for _, pod := range pods { - list.Items = append(list.Items, *pod) - } - return list - } - table := []struct { - list *api.PodList - listErr error - events []watch.Event - watchErr error - }{ - { - list: mkList("1"), - events: []watch.Event{ - {watch.Added, mkPod("foo", "2")}, - {watch.Added, mkPod("bar", "3")}, - }, - }, { - list: mkList("3", mkPod("foo", "2"), mkPod("bar", "3")), - events: []watch.Event{ - {watch.Deleted, mkPod("foo", "4")}, - {watch.Added, mkPod("qux", "5")}, - }, - }, { - listErr: fmt.Errorf("a list error"), - }, { - list: mkList("5", mkPod("bar", "3"), mkPod("qux", "5")), - watchErr: fmt.Errorf("a watch error"), - }, { - list: mkList("5", mkPod("bar", "3"), mkPod("qux", "5")), - events: []watch.Event{ - {watch.Added, mkPod("baz", "6")}, - }, - }, { - list: mkList("6", mkPod("bar", "3"), mkPod("qux", "5"), mkPod("baz", "6")), - }, - } - - s := NewFIFO(MetaNamespaceKeyFunc) - for line, item := range table { - if item.list != nil { - // Test that the list is what currently exists in the store. - current := s.List() - checkMap := map[string]string{} - for _, item := range current { - pod := item.(*api.Pod) - checkMap[pod.Name] = pod.ResourceVersion - } - for _, pod := range item.list.Items { - if e, a := pod.ResourceVersion, checkMap[pod.Name]; e != a { - t.Errorf("%v: expected %v, got %v for pod %v", line, e, a, pod.Name) - } - } - if e, a := len(item.list.Items), len(checkMap); e != a { - t.Errorf("%v: expected %v, got %v", line, e, a) - } - } - watchRet, watchErr := item.events, item.watchErr - lw := &testLW{ - WatchFunc: func(rv string) (watch.Interface, error) { - if watchErr != nil { - return nil, watchErr - } - watchErr = fmt.Errorf("second watch") - fw := watch.NewFake() - go func() { - for _, e := range watchRet { - fw.Action(e.Type, e.Object) - } - fw.Stop() - }() - return fw, nil - }, - ListFunc: func() (runtime.Object, error) { - return item.list, item.listErr - }, - } - r := NewReflector(lw, &api.Pod{}, s, 0) - r.ListAndWatch(wait.NeverStop) - } -} - -func TestReflectorResync(t *testing.T) { - s := NewStore(MetaNamespaceKeyFunc) - - currentTime := time.Time{} - iteration := 0 - - lw := &testLW{ - WatchFunc: func(rv string) (watch.Interface, error) { - if iteration == 0 { - // Move time, but do not force resync. - currentTime = currentTime.Add(30 * time.Second) - } else if iteration == 1 { - // Move time to force resync. - currentTime = currentTime.Add(28 * time.Second) - } else if iteration >= 2 { - t.Fatalf("should have forced resync earlier") - } - iteration++ - fw := watch.NewFake() - // Send something to the watcher to avoid "watch too short" errors. - go func() { - fw.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: strconv.Itoa(iteration)}}) - fw.Stop() - }() - return fw, nil - }, - ListFunc: func() (runtime.Object, error) { - return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "0"}}, nil - }, - } - resyncPeriod := time.Minute - r := NewReflector(lw, &api.Pod{}, s, resyncPeriod) - r.now = func() time.Time { return currentTime } - - r.ListAndWatch(wait.NeverStop) - if iteration != 2 { - t.Errorf("exactly 2 iterations were expected, got: %v", iteration) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/store_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/store_test.go deleted file mode 100644 index 07275f493..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/store_test.go +++ /dev/null @@ -1,156 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cache - -import ( - "testing" - - "k8s.io/kubernetes/pkg/util/sets" -) - -// Test public interface -func doTestStore(t *testing.T, store Store) { - mkObj := func(id string, val string) testStoreObject { - return testStoreObject{id: id, val: val} - } - - store.Add(mkObj("foo", "bar")) - if item, ok, _ := store.Get(mkObj("foo", "")); !ok { - t.Errorf("didn't find inserted item") - } else { - if e, a := "bar", item.(testStoreObject).val; e != a { - t.Errorf("expected %v, got %v", e, a) - } - } - store.Update(mkObj("foo", "baz")) - if item, ok, _ := store.Get(mkObj("foo", "")); !ok { - t.Errorf("didn't find inserted item") - } else { - if e, a := "baz", item.(testStoreObject).val; e != a { - t.Errorf("expected %v, got %v", e, a) - } - } - store.Delete(mkObj("foo", "")) - if _, ok, _ := store.Get(mkObj("foo", "")); ok { - t.Errorf("found deleted item??") - } - - // Test List. - store.Add(mkObj("a", "b")) - store.Add(mkObj("c", "d")) - store.Add(mkObj("e", "e")) - { - found := sets.String{} - for _, item := range store.List() { - found.Insert(item.(testStoreObject).val) - } - if !found.HasAll("b", "d", "e") { - t.Errorf("missing items, found: %v", found) - } - if len(found) != 3 { - t.Errorf("extra items") - } - } - - // Test Replace. - store.Replace([]interface{}{ - mkObj("foo", "foo"), - mkObj("bar", "bar"), - }, "0") - - { - found := sets.String{} - for _, item := range store.List() { - found.Insert(item.(testStoreObject).val) - } - if !found.HasAll("foo", "bar") { - t.Errorf("missing items") - } - if len(found) != 2 { - t.Errorf("extra items") - } - } -} - -// Test public interface -func doTestIndex(t *testing.T, indexer Indexer) { - mkObj := func(id string, val string) testStoreObject { - return testStoreObject{id: id, val: val} - } - - // Test Index - expected := map[string]sets.String{} - expected["b"] = sets.NewString("a", "c") - expected["f"] = sets.NewString("e") - expected["h"] = sets.NewString("g") - indexer.Add(mkObj("a", "b")) - indexer.Add(mkObj("c", "b")) - indexer.Add(mkObj("e", "f")) - indexer.Add(mkObj("g", "h")) - { - for k, v := range expected { - found := sets.String{} - indexResults, err := indexer.Index("by_val", mkObj("", k)) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - for _, item := range indexResults { - found.Insert(item.(testStoreObject).id) - } - items := v.List() - if !found.HasAll(items...) { - t.Errorf("missing items, index %s, expected %v but found %v", k, items, found.List()) - } - } - } -} - -func testStoreKeyFunc(obj interface{}) (string, error) { - return obj.(testStoreObject).id, nil -} - -func testStoreIndexFunc(obj interface{}) ([]string, error) { - return []string{obj.(testStoreObject).val}, nil -} - -func testStoreIndexers() Indexers { - indexers := Indexers{} - indexers["by_val"] = testStoreIndexFunc - return indexers -} - -type testStoreObject struct { - id string - val string -} - -func TestCache(t *testing.T) { - doTestStore(t, NewStore(testStoreKeyFunc)) -} - -func TestFIFOCache(t *testing.T) { - doTestStore(t, NewFIFO(testStoreKeyFunc)) -} - -func TestUndeltaStore(t *testing.T) { - nop := func([]interface{}) {} - doTestStore(t, NewUndeltaStore(nop, testStoreKeyFunc)) -} - -func TestIndex(t *testing.T) { - doTestIndex(t, NewIndexer(testStoreKeyFunc, testStoreIndexers())) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/undelta_store_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/undelta_store_test.go deleted file mode 100644 index c14b7a800..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/cache/undelta_store_test.go +++ /dev/null @@ -1,131 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cache - -import ( - "reflect" - "testing" -) - -// store_test.go checks that UndeltaStore conforms to the Store interface -// behavior. This test just tests that it calls the push func in addition. - -type testUndeltaObject struct { - name string - val interface{} -} - -func testUndeltaKeyFunc(obj interface{}) (string, error) { - return obj.(testUndeltaObject).name, nil -} - -/* -var ( - o1 interface{} = t{1} - o2 interface{} = t{2} - l1 []interface{} = []interface{}{t{1}} -) -*/ - -func TestUpdateCallsPush(t *testing.T) { - mkObj := func(name string, val interface{}) testUndeltaObject { - return testUndeltaObject{name: name, val: val} - } - - var got []interface{} - var callcount int = 0 - push := func(m []interface{}) { - callcount++ - got = m - } - - u := NewUndeltaStore(push, testUndeltaKeyFunc) - - u.Add(mkObj("a", 2)) - u.Update(mkObj("a", 1)) - if callcount != 2 { - t.Errorf("Expected 2 calls, got %d", callcount) - } - - l := []interface{}{mkObj("a", 1)} - if !reflect.DeepEqual(l, got) { - t.Errorf("Expected %#v, Got %#v", l, got) - } -} - -func TestDeleteCallsPush(t *testing.T) { - mkObj := func(name string, val interface{}) testUndeltaObject { - return testUndeltaObject{name: name, val: val} - } - - var got []interface{} - var callcount int = 0 - push := func(m []interface{}) { - callcount++ - got = m - } - - u := NewUndeltaStore(push, testUndeltaKeyFunc) - - u.Add(mkObj("a", 2)) - u.Delete(mkObj("a", "")) - if callcount != 2 { - t.Errorf("Expected 2 calls, got %d", callcount) - } - expected := []interface{}{} - if !reflect.DeepEqual(expected, got) { - t.Errorf("Expected %#v, Got %#v", expected, got) - } -} - -func TestReadsDoNotCallPush(t *testing.T) { - push := func(m []interface{}) { - t.Errorf("Unexpected call to push!") - } - - u := NewUndeltaStore(push, testUndeltaKeyFunc) - - // These should not call push. - _ = u.List() - _, _, _ = u.Get(testUndeltaObject{"a", ""}) -} - -func TestReplaceCallsPush(t *testing.T) { - mkObj := func(name string, val interface{}) testUndeltaObject { - return testUndeltaObject{name: name, val: val} - } - - var got []interface{} - var callcount int = 0 - push := func(m []interface{}) { - callcount++ - got = m - } - - u := NewUndeltaStore(push, testUndeltaKeyFunc) - - m := []interface{}{mkObj("a", 1)} - - u.Replace(m, "0") - if callcount != 1 { - t.Errorf("Expected 1 calls, got %d", callcount) - } - expected := []interface{}{mkObj("a", 1)} - if !reflect.DeepEqual(expected, got) { - t.Errorf("Expected %#v, Got %#v", expected, got) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go deleted file mode 100644 index b303034d6..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/clientset_generated.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apimachinery/registered" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversionedbatch "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned" - fakeunversionedbatch "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - fakeunversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake" - unversionedextensions "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned" - fakeunversionedextensions "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/client/typed/discovery" - fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/watch" -) - -// Clientset returns a clientset that will respond with the provided objects -func NewSimpleClientset(objects ...runtime.Object) *Clientset { - o := core.NewObjects(api.Scheme, api.Codecs.UniversalDecoder()) - for _, obj := range objects { - if err := o.Add(obj); err != nil { - panic(err) - } - } - - fakePtr := core.Fake{} - fakePtr.AddReactor("*", "*", core.ObjectReaction(o, registered.RESTMapper())) - - fakePtr.AddWatchReactor("*", core.DefaultWatchReactor(watch.NewFake(), nil)) - - return &Clientset{fakePtr} -} - -// 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 { - core.Fake -} - -func (c *Clientset) Discovery() discovery.DiscoveryInterface { - return &fakediscovery.FakeDiscovery{Fake: &c.Fake} -} - -var _ clientset.Interface = &Clientset{} - -// Core retrieves the CoreClient -func (c *Clientset) Core() unversionedcore.CoreInterface { - return &fakeunversionedcore.FakeCore{Fake: &c.Fake} -} - -// Extensions retrieves the ExtensionsClient -func (c *Clientset) Extensions() unversionedextensions.ExtensionsInterface { - return &fakeunversionedextensions.FakeExtensions{Fake: &c.Fake} -} - -// Batch retrieves the BatchClient -func (c *Clientset) Batch() unversionedbatch.BatchInterface { - return &fakeunversionedbatch.FakeBatch{Fake: &c.Fake} -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/doc.go deleted file mode 100644 index 559cf8914..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This package is generated by client-gen with the default arguments. - -// This package has the automatically generated fake clientset. -package fake diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/doc.go deleted file mode 100644 index eb358c26c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This package is generated by client-gen with the default arguments. - -// Package fake has the automatically generated clients. -package fake diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/fake_batch_client.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/fake_batch_client.go deleted file mode 100644 index 884593467..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/fake_batch_client.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - unversioned "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned" - restclient "k8s.io/kubernetes/pkg/client/restclient" - core "k8s.io/kubernetes/pkg/client/testing/core" -) - -type FakeBatch struct { - *core.Fake -} - -func (c *FakeBatch) Jobs(namespace string) unversioned.JobInterface { - return &FakeJobs{c, namespace} -} - -// GetRESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *FakeBatch) GetRESTClient() *restclient.RESTClient { - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/fake_job.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/fake_job.go deleted file mode 100644 index 701c102b4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/unversioned/fake/fake_job.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - batch "k8s.io/kubernetes/pkg/apis/batch" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeJobs implements JobInterface -type FakeJobs struct { - Fake *FakeBatch - ns string -} - -var jobsResource = unversioned.GroupVersionResource{Group: "batch", Version: "", Resource: "jobs"} - -func (c *FakeJobs) Create(job *batch.Job) (result *batch.Job, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(jobsResource, c.ns, job), &batch.Job{}) - - if obj == nil { - return nil, err - } - return obj.(*batch.Job), err -} - -func (c *FakeJobs) Update(job *batch.Job) (result *batch.Job, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(jobsResource, c.ns, job), &batch.Job{}) - - if obj == nil { - return nil, err - } - return obj.(*batch.Job), err -} - -func (c *FakeJobs) UpdateStatus(job *batch.Job) (*batch.Job, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(jobsResource, "status", c.ns, job), &batch.Job{}) - - if obj == nil { - return nil, err - } - return obj.(*batch.Job), err -} - -func (c *FakeJobs) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(jobsResource, c.ns, name), &batch.Job{}) - - return err -} - -func (c *FakeJobs) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(jobsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &batch.JobList{}) - return err -} - -func (c *FakeJobs) Get(name string) (result *batch.Job, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(jobsResource, c.ns, name), &batch.Job{}) - - if obj == nil { - return nil, err - } - return obj.(*batch.Job), err -} - -func (c *FakeJobs) List(opts api.ListOptions) (result *batch.JobList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(jobsResource, c.ns, opts), &batch.JobList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &batch.JobList{} - for _, item := range obj.(*batch.JobList).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 jobs. -func (c *FakeJobs) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(jobsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/doc.go deleted file mode 100644 index eb358c26c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This package is generated by client-gen with the default arguments. - -// Package fake has the automatically generated clients. -package fake diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_componentstatus.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_componentstatus.go deleted file mode 100644 index 84dca9984..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_componentstatus.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeComponentStatuses implements ComponentStatusInterface -type FakeComponentStatuses struct { - Fake *FakeCore -} - -var componentstatusesResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "componentstatuses"} - -func (c *FakeComponentStatuses) Create(componentStatus *api.ComponentStatus) (result *api.ComponentStatus, err error) { - obj, err := c.Fake. - Invokes(core.NewRootCreateAction(componentstatusesResource, componentStatus), &api.ComponentStatus{}) - if obj == nil { - return nil, err - } - return obj.(*api.ComponentStatus), err -} - -func (c *FakeComponentStatuses) Update(componentStatus *api.ComponentStatus) (result *api.ComponentStatus, err error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateAction(componentstatusesResource, componentStatus), &api.ComponentStatus{}) - if obj == nil { - return nil, err - } - return obj.(*api.ComponentStatus), err -} - -func (c *FakeComponentStatuses) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewRootDeleteAction(componentstatusesResource, name), &api.ComponentStatus{}) - return err -} - -func (c *FakeComponentStatuses) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewRootDeleteCollectionAction(componentstatusesResource, listOptions) - - _, err := c.Fake.Invokes(action, &api.ComponentStatusList{}) - return err -} - -func (c *FakeComponentStatuses) Get(name string) (result *api.ComponentStatus, err error) { - obj, err := c.Fake. - Invokes(core.NewRootGetAction(componentstatusesResource, name), &api.ComponentStatus{}) - if obj == nil { - return nil, err - } - return obj.(*api.ComponentStatus), err -} - -func (c *FakeComponentStatuses) List(opts api.ListOptions) (result *api.ComponentStatusList, err error) { - obj, err := c.Fake. - Invokes(core.NewRootListAction(componentstatusesResource, opts), &api.ComponentStatusList{}) - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.ComponentStatusList{} - for _, item := range obj.(*api.ComponentStatusList).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 componentStatuses. -func (c *FakeComponentStatuses) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewRootWatchAction(componentstatusesResource, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_configmap.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_configmap.go deleted file mode 100644 index 8908c26a3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_configmap.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeConfigMaps implements ConfigMapInterface -type FakeConfigMaps struct { - Fake *FakeCore - ns string -} - -var configmapsResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "configmaps"} - -func (c *FakeConfigMaps) Create(configMap *api.ConfigMap) (result *api.ConfigMap, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(configmapsResource, c.ns, configMap), &api.ConfigMap{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ConfigMap), err -} - -func (c *FakeConfigMaps) Update(configMap *api.ConfigMap) (result *api.ConfigMap, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(configmapsResource, c.ns, configMap), &api.ConfigMap{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ConfigMap), err -} - -func (c *FakeConfigMaps) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(configmapsResource, c.ns, name), &api.ConfigMap{}) - - return err -} - -func (c *FakeConfigMaps) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(configmapsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.ConfigMapList{}) - return err -} - -func (c *FakeConfigMaps) Get(name string) (result *api.ConfigMap, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(configmapsResource, c.ns, name), &api.ConfigMap{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ConfigMap), err -} - -func (c *FakeConfigMaps) List(opts api.ListOptions) (result *api.ConfigMapList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(configmapsResource, c.ns, opts), &api.ConfigMapList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.ConfigMapList{} - for _, item := range obj.(*api.ConfigMapList).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 configMaps. -func (c *FakeConfigMaps) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(configmapsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_core_client.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_core_client.go deleted file mode 100644 index 533735e7c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_core_client.go +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - unversioned "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - restclient "k8s.io/kubernetes/pkg/client/restclient" - core "k8s.io/kubernetes/pkg/client/testing/core" -) - -type FakeCore struct { - *core.Fake -} - -func (c *FakeCore) ComponentStatuses() unversioned.ComponentStatusInterface { - return &FakeComponentStatuses{c} -} - -func (c *FakeCore) ConfigMaps(namespace string) unversioned.ConfigMapInterface { - return &FakeConfigMaps{c, namespace} -} - -func (c *FakeCore) Endpoints(namespace string) unversioned.EndpointsInterface { - return &FakeEndpoints{c, namespace} -} - -func (c *FakeCore) Events(namespace string) unversioned.EventInterface { - return &FakeEvents{c, namespace} -} - -func (c *FakeCore) LimitRanges(namespace string) unversioned.LimitRangeInterface { - return &FakeLimitRanges{c, namespace} -} - -func (c *FakeCore) Namespaces() unversioned.NamespaceInterface { - return &FakeNamespaces{c} -} - -func (c *FakeCore) Nodes() unversioned.NodeInterface { - return &FakeNodes{c} -} - -func (c *FakeCore) PersistentVolumes() unversioned.PersistentVolumeInterface { - return &FakePersistentVolumes{c} -} - -func (c *FakeCore) PersistentVolumeClaims(namespace string) unversioned.PersistentVolumeClaimInterface { - return &FakePersistentVolumeClaims{c, namespace} -} - -func (c *FakeCore) Pods(namespace string) unversioned.PodInterface { - return &FakePods{c, namespace} -} - -func (c *FakeCore) PodTemplates(namespace string) unversioned.PodTemplateInterface { - return &FakePodTemplates{c, namespace} -} - -func (c *FakeCore) ReplicationControllers(namespace string) unversioned.ReplicationControllerInterface { - return &FakeReplicationControllers{c, namespace} -} - -func (c *FakeCore) ResourceQuotas(namespace string) unversioned.ResourceQuotaInterface { - return &FakeResourceQuotas{c, namespace} -} - -func (c *FakeCore) Secrets(namespace string) unversioned.SecretInterface { - return &FakeSecrets{c, namespace} -} - -func (c *FakeCore) Services(namespace string) unversioned.ServiceInterface { - return &FakeServices{c, namespace} -} - -func (c *FakeCore) ServiceAccounts(namespace string) unversioned.ServiceAccountInterface { - return &FakeServiceAccounts{c, namespace} -} - -// GetRESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *FakeCore) GetRESTClient() *restclient.RESTClient { - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_endpoints.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_endpoints.go deleted file mode 100644 index b888d89c0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_endpoints.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeEndpoints implements EndpointsInterface -type FakeEndpoints struct { - Fake *FakeCore - ns string -} - -var endpointsResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "endpoints"} - -func (c *FakeEndpoints) Create(endpoints *api.Endpoints) (result *api.Endpoints, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(endpointsResource, c.ns, endpoints), &api.Endpoints{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Endpoints), err -} - -func (c *FakeEndpoints) Update(endpoints *api.Endpoints) (result *api.Endpoints, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(endpointsResource, c.ns, endpoints), &api.Endpoints{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Endpoints), err -} - -func (c *FakeEndpoints) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(endpointsResource, c.ns, name), &api.Endpoints{}) - - return err -} - -func (c *FakeEndpoints) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(endpointsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.EndpointsList{}) - return err -} - -func (c *FakeEndpoints) Get(name string) (result *api.Endpoints, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(endpointsResource, c.ns, name), &api.Endpoints{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Endpoints), err -} - -func (c *FakeEndpoints) List(opts api.ListOptions) (result *api.EndpointsList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(endpointsResource, c.ns, opts), &api.EndpointsList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.EndpointsList{} - for _, item := range obj.(*api.EndpointsList).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 endpoints. -func (c *FakeEndpoints) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(endpointsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_event.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_event.go deleted file mode 100644 index d86b05a7b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_event.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeEvents implements EventInterface -type FakeEvents struct { - Fake *FakeCore - ns string -} - -var eventsResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "events"} - -func (c *FakeEvents) Create(event *api.Event) (result *api.Event, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(eventsResource, c.ns, event), &api.Event{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Event), err -} - -func (c *FakeEvents) Update(event *api.Event) (result *api.Event, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(eventsResource, c.ns, event), &api.Event{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Event), err -} - -func (c *FakeEvents) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(eventsResource, c.ns, name), &api.Event{}) - - return err -} - -func (c *FakeEvents) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(eventsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.EventList{}) - return err -} - -func (c *FakeEvents) Get(name string) (result *api.Event, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(eventsResource, c.ns, name), &api.Event{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Event), err -} - -func (c *FakeEvents) List(opts api.ListOptions) (result *api.EventList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(eventsResource, c.ns, opts), &api.EventList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.EventList{} - for _, item := range obj.(*api.EventList).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 events. -func (c *FakeEvents) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(eventsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_event_expansion.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_event_expansion.go deleted file mode 100644 index b76be860d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_event_expansion.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 fake - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/runtime" -) - -func (c *FakeEvents) CreateWithEventNamespace(event *api.Event) (*api.Event, error) { - action := core.NewRootCreateAction(eventsResource, event) - if c.ns != "" { - action = core.NewCreateAction(eventsResource, c.ns, event) - } - obj, err := c.Fake.Invokes(action, event) - if obj == nil { - return nil, err - } - - return obj.(*api.Event), err -} - -// Update replaces an existing event. Returns the copy of the event the server returns, or an error. -func (c *FakeEvents) UpdateWithEventNamespace(event *api.Event) (*api.Event, error) { - action := core.NewRootUpdateAction(eventsResource, event) - if c.ns != "" { - action = core.NewUpdateAction(eventsResource, c.ns, event) - } - obj, err := c.Fake.Invokes(action, event) - if obj == nil { - return nil, err - } - - return obj.(*api.Event), err -} - -// Patch patches an existing event. Returns the copy of the event the server returns, or an error. -func (c *FakeEvents) Patch(event *api.Event, data []byte) (*api.Event, error) { - action := core.NewRootPatchAction(eventsResource, event) - if c.ns != "" { - action = core.NewPatchAction(eventsResource, c.ns, event) - } - obj, err := c.Fake.Invokes(action, event) - if obj == nil { - return nil, err - } - - return obj.(*api.Event), err -} - -// Search returns a list of events matching the specified object. -func (c *FakeEvents) Search(objOrRef runtime.Object) (*api.EventList, error) { - action := core.NewRootListAction(eventsResource, api.ListOptions{}) - if c.ns != "" { - action = core.NewListAction(eventsResource, c.ns, api.ListOptions{}) - } - obj, err := c.Fake.Invokes(action, &api.EventList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.EventList), err -} - -func (c *FakeEvents) GetFieldSelector(involvedObjectName, involvedObjectNamespace, involvedObjectKind, involvedObjectUID *string) fields.Selector { - action := core.GenericActionImpl{} - action.Verb = "get-field-selector" - action.Resource = eventsResource - - c.Fake.Invokes(action, nil) - return fields.Everything() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_limitrange.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_limitrange.go deleted file mode 100644 index b46f5eba4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_limitrange.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeLimitRanges implements LimitRangeInterface -type FakeLimitRanges struct { - Fake *FakeCore - ns string -} - -var limitrangesResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "limitranges"} - -func (c *FakeLimitRanges) Create(limitRange *api.LimitRange) (result *api.LimitRange, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(limitrangesResource, c.ns, limitRange), &api.LimitRange{}) - - if obj == nil { - return nil, err - } - return obj.(*api.LimitRange), err -} - -func (c *FakeLimitRanges) Update(limitRange *api.LimitRange) (result *api.LimitRange, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(limitrangesResource, c.ns, limitRange), &api.LimitRange{}) - - if obj == nil { - return nil, err - } - return obj.(*api.LimitRange), err -} - -func (c *FakeLimitRanges) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(limitrangesResource, c.ns, name), &api.LimitRange{}) - - return err -} - -func (c *FakeLimitRanges) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(limitrangesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.LimitRangeList{}) - return err -} - -func (c *FakeLimitRanges) Get(name string) (result *api.LimitRange, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(limitrangesResource, c.ns, name), &api.LimitRange{}) - - if obj == nil { - return nil, err - } - return obj.(*api.LimitRange), err -} - -func (c *FakeLimitRanges) List(opts api.ListOptions) (result *api.LimitRangeList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(limitrangesResource, c.ns, opts), &api.LimitRangeList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.LimitRangeList{} - for _, item := range obj.(*api.LimitRangeList).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 limitRanges. -func (c *FakeLimitRanges) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(limitrangesResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_namespace.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_namespace.go deleted file mode 100644 index 233dd8ff9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_namespace.go +++ /dev/null @@ -1,107 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeNamespaces implements NamespaceInterface -type FakeNamespaces struct { - Fake *FakeCore -} - -var namespacesResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "namespaces"} - -func (c *FakeNamespaces) Create(namespace *api.Namespace) (result *api.Namespace, err error) { - obj, err := c.Fake. - Invokes(core.NewRootCreateAction(namespacesResource, namespace), &api.Namespace{}) - if obj == nil { - return nil, err - } - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) Update(namespace *api.Namespace) (result *api.Namespace, err error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateAction(namespacesResource, namespace), &api.Namespace{}) - if obj == nil { - return nil, err - } - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) UpdateStatus(namespace *api.Namespace) (*api.Namespace, error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateSubresourceAction(namespacesResource, "status", namespace), &api.Namespace{}) - if obj == nil { - return nil, err - } - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewRootDeleteAction(namespacesResource, name), &api.Namespace{}) - return err -} - -func (c *FakeNamespaces) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewRootDeleteCollectionAction(namespacesResource, listOptions) - - _, err := c.Fake.Invokes(action, &api.NamespaceList{}) - return err -} - -func (c *FakeNamespaces) Get(name string) (result *api.Namespace, err error) { - obj, err := c.Fake. - Invokes(core.NewRootGetAction(namespacesResource, name), &api.Namespace{}) - if obj == nil { - return nil, err - } - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) List(opts api.ListOptions) (result *api.NamespaceList, err error) { - obj, err := c.Fake. - Invokes(core.NewRootListAction(namespacesResource, opts), &api.NamespaceList{}) - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.NamespaceList{} - for _, item := range obj.(*api.NamespaceList).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 namespaces. -func (c *FakeNamespaces) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewRootWatchAction(namespacesResource, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_namespace_expansion.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_namespace_expansion.go deleted file mode 100644 index 04b3acc14..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_namespace_expansion.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 fake - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/testing/core" -) - -func (c *FakeNamespaces) Finalize(namespace *api.Namespace) (*api.Namespace, error) { - action := core.CreateActionImpl{} - action.Verb = "create" - action.Resource = namespacesResource - action.Subresource = "finalize" - action.Object = namespace - - obj, err := c.Fake.Invokes(action, namespace) - if obj == nil { - return nil, err - } - - return obj.(*api.Namespace), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_node.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_node.go deleted file mode 100644 index 7370e5a2a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_node.go +++ /dev/null @@ -1,107 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeNodes implements NodeInterface -type FakeNodes struct { - Fake *FakeCore -} - -var nodesResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "nodes"} - -func (c *FakeNodes) Create(node *api.Node) (result *api.Node, err error) { - obj, err := c.Fake. - Invokes(core.NewRootCreateAction(nodesResource, node), &api.Node{}) - if obj == nil { - return nil, err - } - return obj.(*api.Node), err -} - -func (c *FakeNodes) Update(node *api.Node) (result *api.Node, err error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateAction(nodesResource, node), &api.Node{}) - if obj == nil { - return nil, err - } - return obj.(*api.Node), err -} - -func (c *FakeNodes) UpdateStatus(node *api.Node) (*api.Node, error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateSubresourceAction(nodesResource, "status", node), &api.Node{}) - if obj == nil { - return nil, err - } - return obj.(*api.Node), err -} - -func (c *FakeNodes) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewRootDeleteAction(nodesResource, name), &api.Node{}) - return err -} - -func (c *FakeNodes) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewRootDeleteCollectionAction(nodesResource, listOptions) - - _, err := c.Fake.Invokes(action, &api.NodeList{}) - return err -} - -func (c *FakeNodes) Get(name string) (result *api.Node, err error) { - obj, err := c.Fake. - Invokes(core.NewRootGetAction(nodesResource, name), &api.Node{}) - if obj == nil { - return nil, err - } - return obj.(*api.Node), err -} - -func (c *FakeNodes) List(opts api.ListOptions) (result *api.NodeList, err error) { - obj, err := c.Fake. - Invokes(core.NewRootListAction(nodesResource, opts), &api.NodeList{}) - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.NodeList{} - for _, item := range obj.(*api.NodeList).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 nodes. -func (c *FakeNodes) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewRootWatchAction(nodesResource, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_persistentvolume.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_persistentvolume.go deleted file mode 100644 index fd0ae18ae..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_persistentvolume.go +++ /dev/null @@ -1,107 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakePersistentVolumes implements PersistentVolumeInterface -type FakePersistentVolumes struct { - Fake *FakeCore -} - -var persistentvolumesResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "persistentvolumes"} - -func (c *FakePersistentVolumes) Create(persistentVolume *api.PersistentVolume) (result *api.PersistentVolume, err error) { - obj, err := c.Fake. - Invokes(core.NewRootCreateAction(persistentvolumesResource, persistentVolume), &api.PersistentVolume{}) - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolume), err -} - -func (c *FakePersistentVolumes) Update(persistentVolume *api.PersistentVolume) (result *api.PersistentVolume, err error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateAction(persistentvolumesResource, persistentVolume), &api.PersistentVolume{}) - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolume), err -} - -func (c *FakePersistentVolumes) UpdateStatus(persistentVolume *api.PersistentVolume) (*api.PersistentVolume, error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateSubresourceAction(persistentvolumesResource, "status", persistentVolume), &api.PersistentVolume{}) - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolume), err -} - -func (c *FakePersistentVolumes) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewRootDeleteAction(persistentvolumesResource, name), &api.PersistentVolume{}) - return err -} - -func (c *FakePersistentVolumes) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewRootDeleteCollectionAction(persistentvolumesResource, listOptions) - - _, err := c.Fake.Invokes(action, &api.PersistentVolumeList{}) - return err -} - -func (c *FakePersistentVolumes) Get(name string) (result *api.PersistentVolume, err error) { - obj, err := c.Fake. - Invokes(core.NewRootGetAction(persistentvolumesResource, name), &api.PersistentVolume{}) - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolume), err -} - -func (c *FakePersistentVolumes) List(opts api.ListOptions) (result *api.PersistentVolumeList, err error) { - obj, err := c.Fake. - Invokes(core.NewRootListAction(persistentvolumesResource, opts), &api.PersistentVolumeList{}) - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.PersistentVolumeList{} - for _, item := range obj.(*api.PersistentVolumeList).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 persistentVolumes. -func (c *FakePersistentVolumes) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewRootWatchAction(persistentvolumesResource, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_persistentvolumeclaim.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_persistentvolumeclaim.go deleted file mode 100644 index bd10e834d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_persistentvolumeclaim.go +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakePersistentVolumeClaims implements PersistentVolumeClaimInterface -type FakePersistentVolumeClaims struct { - Fake *FakeCore - ns string -} - -var persistentvolumeclaimsResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "persistentvolumeclaims"} - -func (c *FakePersistentVolumeClaims) Create(persistentVolumeClaim *api.PersistentVolumeClaim) (result *api.PersistentVolumeClaim, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(persistentvolumeclaimsResource, c.ns, persistentVolumeClaim), &api.PersistentVolumeClaim{}) - - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolumeClaim), err -} - -func (c *FakePersistentVolumeClaims) Update(persistentVolumeClaim *api.PersistentVolumeClaim) (result *api.PersistentVolumeClaim, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(persistentvolumeclaimsResource, c.ns, persistentVolumeClaim), &api.PersistentVolumeClaim{}) - - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolumeClaim), err -} - -func (c *FakePersistentVolumeClaims) UpdateStatus(persistentVolumeClaim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(persistentvolumeclaimsResource, "status", c.ns, persistentVolumeClaim), &api.PersistentVolumeClaim{}) - - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolumeClaim), err -} - -func (c *FakePersistentVolumeClaims) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(persistentvolumeclaimsResource, c.ns, name), &api.PersistentVolumeClaim{}) - - return err -} - -func (c *FakePersistentVolumeClaims) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(persistentvolumeclaimsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.PersistentVolumeClaimList{}) - return err -} - -func (c *FakePersistentVolumeClaims) Get(name string) (result *api.PersistentVolumeClaim, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(persistentvolumeclaimsResource, c.ns, name), &api.PersistentVolumeClaim{}) - - if obj == nil { - return nil, err - } - return obj.(*api.PersistentVolumeClaim), err -} - -func (c *FakePersistentVolumeClaims) List(opts api.ListOptions) (result *api.PersistentVolumeClaimList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(persistentvolumeclaimsResource, c.ns, opts), &api.PersistentVolumeClaimList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.PersistentVolumeClaimList{} - for _, item := range obj.(*api.PersistentVolumeClaimList).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 persistentVolumeClaims. -func (c *FakePersistentVolumeClaims) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(persistentvolumeclaimsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_pod.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_pod.go deleted file mode 100644 index 98c0b8e3f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_pod.go +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakePods implements PodInterface -type FakePods struct { - Fake *FakeCore - ns string -} - -var podsResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "pods"} - -func (c *FakePods) Create(pod *api.Pod) (result *api.Pod, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(podsResource, c.ns, pod), &api.Pod{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Pod), err -} - -func (c *FakePods) Update(pod *api.Pod) (result *api.Pod, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(podsResource, c.ns, pod), &api.Pod{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Pod), err -} - -func (c *FakePods) UpdateStatus(pod *api.Pod) (*api.Pod, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(podsResource, "status", c.ns, pod), &api.Pod{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Pod), err -} - -func (c *FakePods) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(podsResource, c.ns, name), &api.Pod{}) - - return err -} - -func (c *FakePods) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(podsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.PodList{}) - return err -} - -func (c *FakePods) Get(name string) (result *api.Pod, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(podsResource, c.ns, name), &api.Pod{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Pod), err -} - -func (c *FakePods) List(opts api.ListOptions) (result *api.PodList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(podsResource, c.ns, opts), &api.PodList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.PodList{} - for _, item := range obj.(*api.PodList).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 pods. -func (c *FakePods) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(podsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_pod_expansion.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_pod_expansion.go deleted file mode 100644 index 32fd74c02..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_pod_expansion.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 fake - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" -) - -func (c *FakePods) Bind(binding *api.Binding) error { - action := core.CreateActionImpl{} - action.Verb = "create" - action.Resource = podsResource - action.Subresource = "bindings" - action.Object = binding - - _, err := c.Fake.Invokes(action, binding) - return err -} - -func (c *FakePods) GetLogs(name string, opts *api.PodLogOptions) *restclient.Request { - action := core.GenericActionImpl{} - action.Verb = "get" - action.Namespace = c.ns - action.Resource = podsResource - action.Subresource = "logs" - action.Value = opts - - _, _ = c.Fake.Invokes(action, &api.Pod{}) - return &restclient.Request{} -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_podtemplate.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_podtemplate.go deleted file mode 100644 index c08d06bea..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_podtemplate.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakePodTemplates implements PodTemplateInterface -type FakePodTemplates struct { - Fake *FakeCore - ns string -} - -var podtemplatesResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "podtemplates"} - -func (c *FakePodTemplates) Create(podTemplate *api.PodTemplate) (result *api.PodTemplate, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(podtemplatesResource, c.ns, podTemplate), &api.PodTemplate{}) - - if obj == nil { - return nil, err - } - return obj.(*api.PodTemplate), err -} - -func (c *FakePodTemplates) Update(podTemplate *api.PodTemplate) (result *api.PodTemplate, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(podtemplatesResource, c.ns, podTemplate), &api.PodTemplate{}) - - if obj == nil { - return nil, err - } - return obj.(*api.PodTemplate), err -} - -func (c *FakePodTemplates) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(podtemplatesResource, c.ns, name), &api.PodTemplate{}) - - return err -} - -func (c *FakePodTemplates) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(podtemplatesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.PodTemplateList{}) - return err -} - -func (c *FakePodTemplates) Get(name string) (result *api.PodTemplate, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(podtemplatesResource, c.ns, name), &api.PodTemplate{}) - - if obj == nil { - return nil, err - } - return obj.(*api.PodTemplate), err -} - -func (c *FakePodTemplates) List(opts api.ListOptions) (result *api.PodTemplateList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(podtemplatesResource, c.ns, opts), &api.PodTemplateList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.PodTemplateList{} - for _, item := range obj.(*api.PodTemplateList).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 podTemplates. -func (c *FakePodTemplates) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(podtemplatesResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_replicationcontroller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_replicationcontroller.go deleted file mode 100644 index 0a7faddbc..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_replicationcontroller.go +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeReplicationControllers implements ReplicationControllerInterface -type FakeReplicationControllers struct { - Fake *FakeCore - ns string -} - -var replicationcontrollersResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "replicationcontrollers"} - -func (c *FakeReplicationControllers) Create(replicationController *api.ReplicationController) (result *api.ReplicationController, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(replicationcontrollersResource, c.ns, replicationController), &api.ReplicationController{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) Update(replicationController *api.ReplicationController) (result *api.ReplicationController, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(replicationcontrollersResource, c.ns, replicationController), &api.ReplicationController{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) UpdateStatus(replicationController *api.ReplicationController) (*api.ReplicationController, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(replicationcontrollersResource, "status", c.ns, replicationController), &api.ReplicationController{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(replicationcontrollersResource, c.ns, name), &api.ReplicationController{}) - - return err -} - -func (c *FakeReplicationControllers) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(replicationcontrollersResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.ReplicationControllerList{}) - return err -} - -func (c *FakeReplicationControllers) Get(name string) (result *api.ReplicationController, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(replicationcontrollersResource, c.ns, name), &api.ReplicationController{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) List(opts api.ListOptions) (result *api.ReplicationControllerList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(replicationcontrollersResource, c.ns, opts), &api.ReplicationControllerList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.ReplicationControllerList{} - for _, item := range obj.(*api.ReplicationControllerList).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 replicationControllers. -func (c *FakeReplicationControllers) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(replicationcontrollersResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_resourcequota.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_resourcequota.go deleted file mode 100644 index d91ee2685..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_resourcequota.go +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeResourceQuotas implements ResourceQuotaInterface -type FakeResourceQuotas struct { - Fake *FakeCore - ns string -} - -var resourcequotasResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "resourcequotas"} - -func (c *FakeResourceQuotas) Create(resourceQuota *api.ResourceQuota) (result *api.ResourceQuota, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(resourcequotasResource, c.ns, resourceQuota), &api.ResourceQuota{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ResourceQuota), err -} - -func (c *FakeResourceQuotas) Update(resourceQuota *api.ResourceQuota) (result *api.ResourceQuota, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(resourcequotasResource, c.ns, resourceQuota), &api.ResourceQuota{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ResourceQuota), err -} - -func (c *FakeResourceQuotas) UpdateStatus(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(resourcequotasResource, "status", c.ns, resourceQuota), &api.ResourceQuota{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ResourceQuota), err -} - -func (c *FakeResourceQuotas) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(resourcequotasResource, c.ns, name), &api.ResourceQuota{}) - - return err -} - -func (c *FakeResourceQuotas) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(resourcequotasResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.ResourceQuotaList{}) - return err -} - -func (c *FakeResourceQuotas) Get(name string) (result *api.ResourceQuota, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(resourcequotasResource, c.ns, name), &api.ResourceQuota{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ResourceQuota), err -} - -func (c *FakeResourceQuotas) List(opts api.ListOptions) (result *api.ResourceQuotaList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(resourcequotasResource, c.ns, opts), &api.ResourceQuotaList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.ResourceQuotaList{} - for _, item := range obj.(*api.ResourceQuotaList).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 resourceQuotas. -func (c *FakeResourceQuotas) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(resourcequotasResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_secret.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_secret.go deleted file mode 100644 index 0caaa47cf..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_secret.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeSecrets implements SecretInterface -type FakeSecrets struct { - Fake *FakeCore - ns string -} - -var secretsResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "secrets"} - -func (c *FakeSecrets) Create(secret *api.Secret) (result *api.Secret, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(secretsResource, c.ns, secret), &api.Secret{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Secret), err -} - -func (c *FakeSecrets) Update(secret *api.Secret) (result *api.Secret, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(secretsResource, c.ns, secret), &api.Secret{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Secret), err -} - -func (c *FakeSecrets) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(secretsResource, c.ns, name), &api.Secret{}) - - return err -} - -func (c *FakeSecrets) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(secretsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.SecretList{}) - return err -} - -func (c *FakeSecrets) Get(name string) (result *api.Secret, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(secretsResource, c.ns, name), &api.Secret{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Secret), err -} - -func (c *FakeSecrets) List(opts api.ListOptions) (result *api.SecretList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(secretsResource, c.ns, opts), &api.SecretList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.SecretList{} - for _, item := range obj.(*api.SecretList).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 secrets. -func (c *FakeSecrets) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(secretsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_service.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_service.go deleted file mode 100644 index 62eae6481..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_service.go +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeServices implements ServiceInterface -type FakeServices struct { - Fake *FakeCore - ns string -} - -var servicesResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "services"} - -func (c *FakeServices) Create(service *api.Service) (result *api.Service, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(servicesResource, c.ns, service), &api.Service{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Service), err -} - -func (c *FakeServices) Update(service *api.Service) (result *api.Service, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(servicesResource, c.ns, service), &api.Service{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Service), err -} - -func (c *FakeServices) UpdateStatus(service *api.Service) (*api.Service, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(servicesResource, "status", c.ns, service), &api.Service{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Service), err -} - -func (c *FakeServices) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(servicesResource, c.ns, name), &api.Service{}) - - return err -} - -func (c *FakeServices) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(servicesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.ServiceList{}) - return err -} - -func (c *FakeServices) Get(name string) (result *api.Service, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(servicesResource, c.ns, name), &api.Service{}) - - if obj == nil { - return nil, err - } - return obj.(*api.Service), err -} - -func (c *FakeServices) List(opts api.ListOptions) (result *api.ServiceList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(servicesResource, c.ns, opts), &api.ServiceList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.ServiceList{} - for _, item := range obj.(*api.ServiceList).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 services. -func (c *FakeServices) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(servicesResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_service_expansion.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_service_expansion.go deleted file mode 100644 index 3494b8737..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_service_expansion.go +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 fake - -import ( - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" -) - -func (c *FakeServices) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper { - return c.Fake.InvokesProxy(core.NewProxyGetAction(servicesResource, c.ns, scheme, name, port, path, params)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_serviceaccount.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_serviceaccount.go deleted file mode 100644 index fbce964a1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned/fake/fake_serviceaccount.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeServiceAccounts implements ServiceAccountInterface -type FakeServiceAccounts struct { - Fake *FakeCore - ns string -} - -var serviceaccountsResource = unversioned.GroupVersionResource{Group: "", Version: "", Resource: "serviceaccounts"} - -func (c *FakeServiceAccounts) Create(serviceAccount *api.ServiceAccount) (result *api.ServiceAccount, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(serviceaccountsResource, c.ns, serviceAccount), &api.ServiceAccount{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ServiceAccount), err -} - -func (c *FakeServiceAccounts) Update(serviceAccount *api.ServiceAccount) (result *api.ServiceAccount, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(serviceaccountsResource, c.ns, serviceAccount), &api.ServiceAccount{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ServiceAccount), err -} - -func (c *FakeServiceAccounts) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(serviceaccountsResource, c.ns, name), &api.ServiceAccount{}) - - return err -} - -func (c *FakeServiceAccounts) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(serviceaccountsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &api.ServiceAccountList{}) - return err -} - -func (c *FakeServiceAccounts) Get(name string) (result *api.ServiceAccount, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(serviceaccountsResource, c.ns, name), &api.ServiceAccount{}) - - if obj == nil { - return nil, err - } - return obj.(*api.ServiceAccount), err -} - -func (c *FakeServiceAccounts) List(opts api.ListOptions) (result *api.ServiceAccountList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(serviceaccountsResource, c.ns, opts), &api.ServiceAccountList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.ServiceAccountList{} - for _, item := range obj.(*api.ServiceAccountList).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 serviceAccounts. -func (c *FakeServiceAccounts) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(serviceaccountsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/doc.go deleted file mode 100644 index eb358c26c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This package is generated by client-gen with the default arguments. - -// Package fake has the automatically generated clients. -package fake diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_daemonset.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_daemonset.go deleted file mode 100644 index d53fa797a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_daemonset.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeDaemonSets implements DaemonSetInterface -type FakeDaemonSets struct { - Fake *FakeExtensions - ns string -} - -var daemonsetsResource = unversioned.GroupVersionResource{Group: "extensions", Version: "", Resource: "daemonsets"} - -func (c *FakeDaemonSets) Create(daemonSet *extensions.DaemonSet) (result *extensions.DaemonSet, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(daemonsetsResource, c.ns, daemonSet), &extensions.DaemonSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) Update(daemonSet *extensions.DaemonSet) (result *extensions.DaemonSet, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(daemonsetsResource, c.ns, daemonSet), &extensions.DaemonSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) UpdateStatus(daemonSet *extensions.DaemonSet) (*extensions.DaemonSet, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(daemonsetsResource, "status", c.ns, daemonSet), &extensions.DaemonSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(daemonsetsResource, c.ns, name), &extensions.DaemonSet{}) - - return err -} - -func (c *FakeDaemonSets) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(daemonsetsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &extensions.DaemonSetList{}) - return err -} - -func (c *FakeDaemonSets) Get(name string) (result *extensions.DaemonSet, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(daemonsetsResource, c.ns, name), &extensions.DaemonSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) List(opts api.ListOptions) (result *extensions.DaemonSetList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(daemonsetsResource, c.ns, opts), &extensions.DaemonSetList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.DaemonSetList{} - for _, item := range obj.(*extensions.DaemonSetList).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 daemonSets. -func (c *FakeDaemonSets) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(daemonsetsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_deployment.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_deployment.go deleted file mode 100644 index c70a3a81d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_deployment.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeDeployments implements DeploymentInterface -type FakeDeployments struct { - Fake *FakeExtensions - ns string -} - -var deploymentsResource = unversioned.GroupVersionResource{Group: "extensions", Version: "", Resource: "deployments"} - -func (c *FakeDeployments) Create(deployment *extensions.Deployment) (result *extensions.Deployment, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(deploymentsResource, c.ns, deployment), &extensions.Deployment{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) Update(deployment *extensions.Deployment) (result *extensions.Deployment, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(deploymentsResource, c.ns, deployment), &extensions.Deployment{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) UpdateStatus(deployment *extensions.Deployment) (*extensions.Deployment, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(deploymentsResource, "status", c.ns, deployment), &extensions.Deployment{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(deploymentsResource, c.ns, name), &extensions.Deployment{}) - - return err -} - -func (c *FakeDeployments) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(deploymentsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &extensions.DeploymentList{}) - return err -} - -func (c *FakeDeployments) Get(name string) (result *extensions.Deployment, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(deploymentsResource, c.ns, name), &extensions.Deployment{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) List(opts api.ListOptions) (result *extensions.DeploymentList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(deploymentsResource, c.ns, opts), &extensions.DeploymentList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.DeploymentList{} - for _, item := range obj.(*extensions.DeploymentList).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 deployments. -func (c *FakeDeployments) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(deploymentsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_deployment_expansion.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_deployment_expansion.go deleted file mode 100644 index 3a7c06e50..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_deployment_expansion.go +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 fake - -import ( - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/testing/core" -) - -func (c *FakeDeployments) Rollback(deploymentRollback *extensions.DeploymentRollback) error { - action := core.CreateActionImpl{} - action.Verb = "create" - action.Resource = deploymentsResource - action.Subresource = "rollback" - action.Object = deploymentRollback - - _, err := c.Fake.Invokes(action, deploymentRollback) - return err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_extensions_client.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_extensions_client.go deleted file mode 100644 index dfddee1c7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_extensions_client.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - unversioned "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned" - restclient "k8s.io/kubernetes/pkg/client/restclient" - core "k8s.io/kubernetes/pkg/client/testing/core" -) - -type FakeExtensions struct { - *core.Fake -} - -func (c *FakeExtensions) DaemonSets(namespace string) unversioned.DaemonSetInterface { - return &FakeDaemonSets{c, namespace} -} - -func (c *FakeExtensions) Deployments(namespace string) unversioned.DeploymentInterface { - return &FakeDeployments{c, namespace} -} - -func (c *FakeExtensions) HorizontalPodAutoscalers(namespace string) unversioned.HorizontalPodAutoscalerInterface { - return &FakeHorizontalPodAutoscalers{c, namespace} -} - -func (c *FakeExtensions) Ingresses(namespace string) unversioned.IngressInterface { - return &FakeIngresses{c, namespace} -} - -func (c *FakeExtensions) ReplicaSets(namespace string) unversioned.ReplicaSetInterface { - return &FakeReplicaSets{c, namespace} -} - -func (c *FakeExtensions) Scales(namespace string) unversioned.ScaleInterface { - return &FakeScales{c, namespace} -} - -func (c *FakeExtensions) ThirdPartyResources() unversioned.ThirdPartyResourceInterface { - return &FakeThirdPartyResources{c} -} - -// GetRESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *FakeExtensions) GetRESTClient() *restclient.RESTClient { - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_horizontalpodautoscaler.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_horizontalpodautoscaler.go deleted file mode 100644 index 29000bef0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_horizontalpodautoscaler.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface -type FakeHorizontalPodAutoscalers struct { - Fake *FakeExtensions - ns string -} - -var horizontalpodautoscalersResource = unversioned.GroupVersionResource{Group: "extensions", Version: "", Resource: "horizontalpodautoscalers"} - -func (c *FakeHorizontalPodAutoscalers) Create(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &extensions.HorizontalPodAutoscaler{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) Update(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(horizontalpodautoscalersResource, c.ns, horizontalPodAutoscaler), &extensions.HorizontalPodAutoscaler{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) UpdateStatus(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(horizontalpodautoscalersResource, "status", c.ns, horizontalPodAutoscaler), &extensions.HorizontalPodAutoscaler{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(horizontalpodautoscalersResource, c.ns, name), &extensions.HorizontalPodAutoscaler{}) - - return err -} - -func (c *FakeHorizontalPodAutoscalers) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(horizontalpodautoscalersResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &extensions.HorizontalPodAutoscalerList{}) - return err -} - -func (c *FakeHorizontalPodAutoscalers) Get(name string) (result *extensions.HorizontalPodAutoscaler, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(horizontalpodautoscalersResource, c.ns, name), &extensions.HorizontalPodAutoscaler{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) List(opts api.ListOptions) (result *extensions.HorizontalPodAutoscalerList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(horizontalpodautoscalersResource, c.ns, opts), &extensions.HorizontalPodAutoscalerList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.HorizontalPodAutoscalerList{} - for _, item := range obj.(*extensions.HorizontalPodAutoscalerList).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 horizontalPodAutoscalers. -func (c *FakeHorizontalPodAutoscalers) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(horizontalpodautoscalersResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_ingress.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_ingress.go deleted file mode 100644 index 68578ce12..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_ingress.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeIngresses implements IngressInterface -type FakeIngresses struct { - Fake *FakeExtensions - ns string -} - -var ingressesResource = unversioned.GroupVersionResource{Group: "extensions", Version: "", Resource: "ingresses"} - -func (c *FakeIngresses) Create(ingress *extensions.Ingress) (result *extensions.Ingress, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(ingressesResource, c.ns, ingress), &extensions.Ingress{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Ingress), err -} - -func (c *FakeIngresses) Update(ingress *extensions.Ingress) (result *extensions.Ingress, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(ingressesResource, c.ns, ingress), &extensions.Ingress{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Ingress), err -} - -func (c *FakeIngresses) UpdateStatus(ingress *extensions.Ingress) (*extensions.Ingress, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(ingressesResource, "status", c.ns, ingress), &extensions.Ingress{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Ingress), err -} - -func (c *FakeIngresses) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(ingressesResource, c.ns, name), &extensions.Ingress{}) - - return err -} - -func (c *FakeIngresses) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(ingressesResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &extensions.IngressList{}) - return err -} - -func (c *FakeIngresses) Get(name string) (result *extensions.Ingress, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(ingressesResource, c.ns, name), &extensions.Ingress{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.Ingress), err -} - -func (c *FakeIngresses) List(opts api.ListOptions) (result *extensions.IngressList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(ingressesResource, c.ns, opts), &extensions.IngressList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.IngressList{} - for _, item := range obj.(*extensions.IngressList).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 ingresses. -func (c *FakeIngresses) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(ingressesResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_replicaset.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_replicaset.go deleted file mode 100644 index 9d7241ca4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_replicaset.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeReplicaSets implements ReplicaSetInterface -type FakeReplicaSets struct { - Fake *FakeExtensions - ns string -} - -var replicasetsResource = unversioned.GroupVersionResource{Group: "extensions", Version: "", Resource: "replicasets"} - -func (c *FakeReplicaSets) Create(replicaSet *extensions.ReplicaSet) (result *extensions.ReplicaSet, err error) { - obj, err := c.Fake. - Invokes(core.NewCreateAction(replicasetsResource, c.ns, replicaSet), &extensions.ReplicaSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.ReplicaSet), err -} - -func (c *FakeReplicaSets) Update(replicaSet *extensions.ReplicaSet) (result *extensions.ReplicaSet, err error) { - obj, err := c.Fake. - Invokes(core.NewUpdateAction(replicasetsResource, c.ns, replicaSet), &extensions.ReplicaSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.ReplicaSet), err -} - -func (c *FakeReplicaSets) UpdateStatus(replicaSet *extensions.ReplicaSet) (*extensions.ReplicaSet, error) { - obj, err := c.Fake. - Invokes(core.NewUpdateSubresourceAction(replicasetsResource, "status", c.ns, replicaSet), &extensions.ReplicaSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.ReplicaSet), err -} - -func (c *FakeReplicaSets) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewDeleteAction(replicasetsResource, c.ns, name), &extensions.ReplicaSet{}) - - return err -} - -func (c *FakeReplicaSets) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewDeleteCollectionAction(replicasetsResource, c.ns, listOptions) - - _, err := c.Fake.Invokes(action, &extensions.ReplicaSetList{}) - return err -} - -func (c *FakeReplicaSets) Get(name string) (result *extensions.ReplicaSet, err error) { - obj, err := c.Fake. - Invokes(core.NewGetAction(replicasetsResource, c.ns, name), &extensions.ReplicaSet{}) - - if obj == nil { - return nil, err - } - return obj.(*extensions.ReplicaSet), err -} - -func (c *FakeReplicaSets) List(opts api.ListOptions) (result *extensions.ReplicaSetList, err error) { - obj, err := c.Fake. - Invokes(core.NewListAction(replicasetsResource, c.ns, opts), &extensions.ReplicaSetList{}) - - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.ReplicaSetList{} - for _, item := range obj.(*extensions.ReplicaSetList).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 replicaSets. -func (c *FakeReplicaSets) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewWatchAction(replicasetsResource, c.ns, opts)) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_scale.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_scale.go deleted file mode 100644 index d2cfc5f7b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_scale.go +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -// FakeScales implements ScaleInterface -type FakeScales struct { - Fake *FakeExtensions - ns string -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_scale_expansion.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_scale_expansion.go deleted file mode 100644 index 949836afe..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_scale_expansion.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 fake - -import ( - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/testing/core" -) - -func (c *FakeScales) Get(kind string, name string) (result *extensions.Scale, err error) { - action := core.GetActionImpl{} - action.Verb = "get" - action.Namespace = c.ns - action.Resource = unversioned.GroupVersionResource{Resource: kind} - action.Subresource = "scale" - action.Name = name - obj, err := c.Fake.Invokes(action, &extensions.Scale{}) - result = obj.(*extensions.Scale) - return -} - -func (c *FakeScales) Update(kind string, scale *extensions.Scale) (result *extensions.Scale, err error) { - action := core.UpdateActionImpl{} - action.Verb = "update" - action.Namespace = c.ns - action.Resource = unversioned.GroupVersionResource{Resource: kind} - action.Subresource = "scale" - action.Object = scale - obj, err := c.Fake.Invokes(action, scale) - result = obj.(*extensions.Scale) - return -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_thirdpartyresource.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_thirdpartyresource.go deleted file mode 100644 index 37cbca979..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned/fake/fake_thirdpartyresource.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - api "k8s.io/kubernetes/pkg/api" - unversioned "k8s.io/kubernetes/pkg/api/unversioned" - extensions "k8s.io/kubernetes/pkg/apis/extensions" - core "k8s.io/kubernetes/pkg/client/testing/core" - labels "k8s.io/kubernetes/pkg/labels" - watch "k8s.io/kubernetes/pkg/watch" -) - -// FakeThirdPartyResources implements ThirdPartyResourceInterface -type FakeThirdPartyResources struct { - Fake *FakeExtensions -} - -var thirdpartyresourcesResource = unversioned.GroupVersionResource{Group: "extensions", Version: "", Resource: "thirdpartyresources"} - -func (c *FakeThirdPartyResources) Create(thirdPartyResource *extensions.ThirdPartyResource) (result *extensions.ThirdPartyResource, err error) { - obj, err := c.Fake. - Invokes(core.NewRootCreateAction(thirdpartyresourcesResource, thirdPartyResource), &extensions.ThirdPartyResource{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResource), err -} - -func (c *FakeThirdPartyResources) Update(thirdPartyResource *extensions.ThirdPartyResource) (result *extensions.ThirdPartyResource, err error) { - obj, err := c.Fake. - Invokes(core.NewRootUpdateAction(thirdpartyresourcesResource, thirdPartyResource), &extensions.ThirdPartyResource{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResource), err -} - -func (c *FakeThirdPartyResources) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake. - Invokes(core.NewRootDeleteAction(thirdpartyresourcesResource, name), &extensions.ThirdPartyResource{}) - return err -} - -func (c *FakeThirdPartyResources) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := core.NewRootDeleteCollectionAction(thirdpartyresourcesResource, listOptions) - - _, err := c.Fake.Invokes(action, &extensions.ThirdPartyResourceList{}) - return err -} - -func (c *FakeThirdPartyResources) Get(name string) (result *extensions.ThirdPartyResource, err error) { - obj, err := c.Fake. - Invokes(core.NewRootGetAction(thirdpartyresourcesResource, name), &extensions.ThirdPartyResource{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResource), err -} - -func (c *FakeThirdPartyResources) List(opts api.ListOptions) (result *extensions.ThirdPartyResourceList, err error) { - obj, err := c.Fake. - Invokes(core.NewRootListAction(thirdpartyresourcesResource, opts), &extensions.ThirdPartyResourceList{}) - if obj == nil { - return nil, err - } - - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.ThirdPartyResourceList{} - for _, item := range obj.(*extensions.ThirdPartyResourceList).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 thirdPartyResources. -func (c *FakeThirdPartyResources) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(core.NewRootWatchAction(thirdpartyresourcesResource, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/record/event_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/record/event_test.go deleted file mode 100644 index ba7005abf..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/record/event_test.go +++ /dev/null @@ -1,926 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 record - -import ( - "encoding/json" - "fmt" - "math/rand" - "strconv" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - _ "k8s.io/kubernetes/pkg/api/install" // To register api.Pod used in tests below - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - k8sruntime "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/strategicpatch" - "net/http" -) - -type testEventSink struct { - OnCreate func(e *api.Event) (*api.Event, error) - OnUpdate func(e *api.Event) (*api.Event, error) - OnPatch func(e *api.Event, p []byte) (*api.Event, error) -} - -// CreateEvent records the event for testing. -func (t *testEventSink) Create(e *api.Event) (*api.Event, error) { - if t.OnCreate != nil { - return t.OnCreate(e) - } - return e, nil -} - -// UpdateEvent records the event for testing. -func (t *testEventSink) Update(e *api.Event) (*api.Event, error) { - if t.OnUpdate != nil { - return t.OnUpdate(e) - } - return e, nil -} - -// PatchEvent records the event for testing. -func (t *testEventSink) Patch(e *api.Event, p []byte) (*api.Event, error) { - if t.OnPatch != nil { - return t.OnPatch(e, p) - } - return e, nil -} - -type OnCreateFunc func(*api.Event) (*api.Event, error) - -func OnCreateFactory(testCache map[string]*api.Event, createEvent chan<- *api.Event) OnCreateFunc { - return func(event *api.Event) (*api.Event, error) { - testCache[getEventKey(event)] = event - createEvent <- event - return event, nil - } -} - -type OnPatchFunc func(*api.Event, []byte) (*api.Event, error) - -func OnPatchFactory(testCache map[string]*api.Event, patchEvent chan<- *api.Event) OnPatchFunc { - return func(event *api.Event, patch []byte) (*api.Event, error) { - cachedEvent, found := testCache[getEventKey(event)] - if !found { - return nil, fmt.Errorf("unexpected error: couldn't find Event in testCache.") - } - originalData, err := json.Marshal(cachedEvent) - if err != nil { - return nil, fmt.Errorf("unexpected error: %v", err) - } - patched, err := strategicpatch.StrategicMergePatch(originalData, patch, event) - if err != nil { - return nil, fmt.Errorf("unexpected error: %v", err) - } - patchedObj := &api.Event{} - err = json.Unmarshal(patched, patchedObj) - if err != nil { - return nil, fmt.Errorf("unexpected error: %v", err) - } - patchEvent <- patchedObj - return patchedObj, nil - } -} - -func TestEventf(t *testing.T) { - testPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - SelfLink: "/api/version/pods/foo", - Name: "foo", - Namespace: "baz", - UID: "bar", - }, - } - testPod2 := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - SelfLink: "/api/version/pods/foo", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - }, - } - testRef, err := api.GetPartialReference(testPod, "spec.containers[2]") - testRef2, err := api.GetPartialReference(testPod2, "spec.containers[3]") - if err != nil { - t.Fatal(err) - } - table := []struct { - obj k8sruntime.Object - eventtype string - reason string - messageFmt string - elements []interface{} - expect *api.Event - expectLog string - expectUpdate bool - }{ - { - obj: testRef, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - FieldPath: "spec.containers[2]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: false, - }, - { - obj: testPod, - eventtype: api.EventTypeNormal, - reason: "Killed", - messageFmt: "some other verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - }, - Reason: "Killed", - Message: "some other verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`, - expectUpdate: false, - }, - { - obj: testRef, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - FieldPath: "spec.containers[2]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 2, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: true, - }, - { - obj: testRef2, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - APIVersion: "version", - FieldPath: "spec.containers[3]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: false, - }, - { - obj: testRef, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - FieldPath: "spec.containers[2]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 3, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: true, - }, - { - obj: testRef2, - eventtype: api.EventTypeNormal, - reason: "Stopped", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - APIVersion: "version", - FieldPath: "spec.containers[3]", - }, - Reason: "Stopped", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`, - expectUpdate: false, - }, - { - obj: testRef2, - eventtype: api.EventTypeNormal, - reason: "Stopped", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - APIVersion: "version", - FieldPath: "spec.containers[3]", - }, - Reason: "Stopped", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 2, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`, - expectUpdate: true, - }, - } - - testCache := map[string]*api.Event{} - logCalled := make(chan struct{}) - createEvent := make(chan *api.Event) - updateEvent := make(chan *api.Event) - patchEvent := make(chan *api.Event) - testEvents := testEventSink{ - OnCreate: OnCreateFactory(testCache, createEvent), - OnUpdate: func(event *api.Event) (*api.Event, error) { - updateEvent <- event - return event, nil - }, - OnPatch: OnPatchFactory(testCache, patchEvent), - } - eventBroadcaster := NewBroadcasterForTests(0) - sinkWatcher := eventBroadcaster.StartRecordingToSink(&testEvents) - - clock := util.NewFakeClock(time.Now()) - recorder := recorderWithFakeClock(api.EventSource{Component: "eventTest"}, eventBroadcaster, clock) - for index, item := range table { - clock.Step(1 * time.Second) - // TODO: uncomment this after we upgrade to Go 1.6.1. - // testing.(*common).log() is racing with testing.(*T).report() in Go 1.6. - // See #23533 for more details. - // logWatcher1 := eventBroadcaster.StartLogging(t.Logf) // Prove that it is useful - logWatcher2 := eventBroadcaster.StartLogging(func(formatter string, args ...interface{}) { - if e, a := item.expectLog, fmt.Sprintf(formatter, args...); e != a { - t.Errorf("Expected '%v', got '%v'", e, a) - } - logCalled <- struct{}{} - }) - recorder.Eventf(item.obj, item.eventtype, item.reason, item.messageFmt, item.elements...) - - <-logCalled - - // validate event - if item.expectUpdate { - actualEvent := <-patchEvent - validateEvent(string(index), actualEvent, item.expect, t) - } else { - actualEvent := <-createEvent - validateEvent(string(index), actualEvent, item.expect, t) - } - // TODO: uncomment this after we upgrade to Go 1.6.1. - // logWatcher1.Stop() - logWatcher2.Stop() - } - sinkWatcher.Stop() -} - -func recorderWithFakeClock(eventSource api.EventSource, eventBroadcaster EventBroadcaster, clock util.Clock) EventRecorder { - return &recorderImpl{eventSource, eventBroadcaster.(*eventBroadcasterImpl).Broadcaster, clock} -} - -func TestWriteEventError(t *testing.T) { - type entry struct { - timesToSendError int - attemptsWanted int - err error - } - table := map[string]*entry{ - "giveUp1": { - timesToSendError: 1000, - attemptsWanted: 1, - err: &restclient.RequestConstructionError{}, - }, - "giveUp2": { - timesToSendError: 1000, - attemptsWanted: 1, - err: &errors.StatusError{}, - }, - "retry1": { - timesToSendError: 1000, - attemptsWanted: 12, - err: &errors.UnexpectedObjectError{}, - }, - "retry2": { - timesToSendError: 1000, - attemptsWanted: 12, - err: fmt.Errorf("A weird error"), - }, - "succeedEventually": { - timesToSendError: 2, - attemptsWanted: 2, - err: fmt.Errorf("A weird error"), - }, - } - - eventCorrelator := NewEventCorrelator(util.RealClock{}) - randGen := rand.New(rand.NewSource(time.Now().UnixNano())) - - for caseName, ent := range table { - attempts := 0 - sink := &testEventSink{ - OnCreate: func(event *api.Event) (*api.Event, error) { - attempts++ - if attempts < ent.timesToSendError { - return nil, ent.err - } - return event, nil - }, - } - ev := &api.Event{} - recordToSink(sink, ev, eventCorrelator, randGen, 0) - if attempts != ent.attemptsWanted { - t.Errorf("case %v: wanted %d, got %d attempts", caseName, ent.attemptsWanted, attempts) - } - } -} - -func TestUpdateExpiredEvent(t *testing.T) { - eventCorrelator := NewEventCorrelator(util.RealClock{}) - randGen := rand.New(rand.NewSource(time.Now().UnixNano())) - - var createdEvent *api.Event - - sink := &testEventSink{ - OnPatch: func(*api.Event, []byte) (*api.Event, error) { - return nil, &errors.StatusError{ - ErrStatus: unversioned.Status{ - Code: http.StatusNotFound, - Reason: unversioned.StatusReasonNotFound, - }} - }, - OnCreate: func(event *api.Event) (*api.Event, error) { - createdEvent = event - return event, nil - }, - } - - ev := &api.Event{} - ev.ResourceVersion = "updated-resource-version" - ev.Count = 2 - recordToSink(sink, ev, eventCorrelator, randGen, 0) - - if createdEvent == nil { - t.Error("Event did not get created after patch failed") - return - } - - if createdEvent.ResourceVersion != "" { - t.Errorf("Event did not have its resource version cleared, was %s", createdEvent.ResourceVersion) - } -} - -func TestLotsOfEvents(t *testing.T) { - recorderCalled := make(chan struct{}) - loggerCalled := make(chan struct{}) - - // Fail each event a few times to ensure there's some load on the tested code. - var counts [1000]int - testEvents := testEventSink{ - OnCreate: func(event *api.Event) (*api.Event, error) { - num, err := strconv.Atoi(event.Message) - if err != nil { - t.Error(err) - return event, nil - } - counts[num]++ - if counts[num] < 5 { - return nil, fmt.Errorf("fake error") - } - recorderCalled <- struct{}{} - return event, nil - }, - } - - eventBroadcaster := NewBroadcasterForTests(0) - sinkWatcher := eventBroadcaster.StartRecordingToSink(&testEvents) - logWatcher := eventBroadcaster.StartLogging(func(formatter string, args ...interface{}) { - loggerCalled <- struct{}{} - }) - recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "eventTest"}) - ref := &api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - } - for i := 0; i < maxQueuedEvents; i++ { - // we need to vary the reason to prevent aggregation - go recorder.Eventf(ref, api.EventTypeNormal, "Reason-"+string(i), strconv.Itoa(i)) - } - // Make sure no events were dropped by either of the listeners. - for i := 0; i < maxQueuedEvents; i++ { - <-recorderCalled - <-loggerCalled - } - // Make sure that every event was attempted 5 times - for i := 0; i < maxQueuedEvents; i++ { - if counts[i] < 5 { - t.Errorf("Only attempted to record event '%d' %d times.", i, counts[i]) - } - } - sinkWatcher.Stop() - logWatcher.Stop() -} - -func TestEventfNoNamespace(t *testing.T) { - testPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - SelfLink: "/api/version/pods/foo", - Name: "foo", - UID: "bar", - }, - } - testRef, err := api.GetPartialReference(testPod, "spec.containers[2]") - if err != nil { - t.Fatal(err) - } - table := []struct { - obj k8sruntime.Object - eventtype string - reason string - messageFmt string - elements []interface{} - expect *api.Event - expectLog string - expectUpdate bool - }{ - { - obj: testRef, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "", - UID: "bar", - APIVersion: "version", - FieldPath: "spec.containers[2]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: false, - }, - } - - testCache := map[string]*api.Event{} - logCalled := make(chan struct{}) - createEvent := make(chan *api.Event) - updateEvent := make(chan *api.Event) - patchEvent := make(chan *api.Event) - testEvents := testEventSink{ - OnCreate: OnCreateFactory(testCache, createEvent), - OnUpdate: func(event *api.Event) (*api.Event, error) { - updateEvent <- event - return event, nil - }, - OnPatch: OnPatchFactory(testCache, patchEvent), - } - eventBroadcaster := NewBroadcasterForTests(0) - sinkWatcher := eventBroadcaster.StartRecordingToSink(&testEvents) - - clock := util.NewFakeClock(time.Now()) - recorder := recorderWithFakeClock(api.EventSource{Component: "eventTest"}, eventBroadcaster, clock) - - for index, item := range table { - clock.Step(1 * time.Second) - // TODO: uncomment this after we upgrade to Go 1.6.1. - // testing.(*common).log() is racing with testing.(*T).report() in Go 1.6. - // See #23533 for more details. - // logWatcher1 := eventBroadcaster.StartLogging(t.Logf) // Prove that it is useful - logWatcher2 := eventBroadcaster.StartLogging(func(formatter string, args ...interface{}) { - if e, a := item.expectLog, fmt.Sprintf(formatter, args...); e != a { - t.Errorf("Expected '%v', got '%v'", e, a) - } - logCalled <- struct{}{} - }) - recorder.Eventf(item.obj, item.eventtype, item.reason, item.messageFmt, item.elements...) - - <-logCalled - - // validate event - if item.expectUpdate { - actualEvent := <-patchEvent - validateEvent(string(index), actualEvent, item.expect, t) - } else { - actualEvent := <-createEvent - validateEvent(string(index), actualEvent, item.expect, t) - } - - // TODO: uncomment this after we upgrade to Go 1.6.1. - // logWatcher1.Stop() - logWatcher2.Stop() - } - sinkWatcher.Stop() -} - -func TestMultiSinkCache(t *testing.T) { - testPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - SelfLink: "/api/version/pods/foo", - Name: "foo", - Namespace: "baz", - UID: "bar", - }, - } - testPod2 := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - SelfLink: "/api/version/pods/foo", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - }, - } - testRef, err := api.GetPartialReference(testPod, "spec.containers[2]") - testRef2, err := api.GetPartialReference(testPod2, "spec.containers[3]") - if err != nil { - t.Fatal(err) - } - table := []struct { - obj k8sruntime.Object - eventtype string - reason string - messageFmt string - elements []interface{} - expect *api.Event - expectLog string - expectUpdate bool - }{ - { - obj: testRef, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - FieldPath: "spec.containers[2]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: false, - }, - { - obj: testPod, - eventtype: api.EventTypeNormal, - reason: "Killed", - messageFmt: "some other verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - }, - Reason: "Killed", - Message: "some other verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`, - expectUpdate: false, - }, - { - obj: testRef, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - FieldPath: "spec.containers[2]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 2, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: true, - }, - { - obj: testRef2, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - APIVersion: "version", - FieldPath: "spec.containers[3]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: false, - }, - { - obj: testRef, - eventtype: api.EventTypeNormal, - reason: "Started", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "bar", - APIVersion: "version", - FieldPath: "spec.containers[2]", - }, - Reason: "Started", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 3, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`, - expectUpdate: true, - }, - { - obj: testRef2, - eventtype: api.EventTypeNormal, - reason: "Stopped", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - APIVersion: "version", - FieldPath: "spec.containers[3]", - }, - Reason: "Stopped", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 1, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`, - expectUpdate: false, - }, - { - obj: testRef2, - eventtype: api.EventTypeNormal, - reason: "Stopped", - messageFmt: "some verbose message: %v", - elements: []interface{}{1}, - expect: &api.Event{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - }, - InvolvedObject: api.ObjectReference{ - Kind: "Pod", - Name: "foo", - Namespace: "baz", - UID: "differentUid", - APIVersion: "version", - FieldPath: "spec.containers[3]", - }, - Reason: "Stopped", - Message: "some verbose message: 1", - Source: api.EventSource{Component: "eventTest"}, - Count: 2, - Type: api.EventTypeNormal, - }, - expectLog: `Event(api.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`, - expectUpdate: true, - }, - } - - testCache := map[string]*api.Event{} - createEvent := make(chan *api.Event) - updateEvent := make(chan *api.Event) - patchEvent := make(chan *api.Event) - testEvents := testEventSink{ - OnCreate: OnCreateFactory(testCache, createEvent), - OnUpdate: func(event *api.Event) (*api.Event, error) { - updateEvent <- event - return event, nil - }, - OnPatch: OnPatchFactory(testCache, patchEvent), - } - - testCache2 := map[string]*api.Event{} - createEvent2 := make(chan *api.Event) - updateEvent2 := make(chan *api.Event) - patchEvent2 := make(chan *api.Event) - testEvents2 := testEventSink{ - OnCreate: OnCreateFactory(testCache2, createEvent2), - OnUpdate: func(event *api.Event) (*api.Event, error) { - updateEvent2 <- event - return event, nil - }, - OnPatch: OnPatchFactory(testCache2, patchEvent2), - } - - eventBroadcaster := NewBroadcasterForTests(0) - clock := util.NewFakeClock(time.Now()) - recorder := recorderWithFakeClock(api.EventSource{Component: "eventTest"}, eventBroadcaster, clock) - - sinkWatcher := eventBroadcaster.StartRecordingToSink(&testEvents) - for index, item := range table { - clock.Step(1 * time.Second) - recorder.Eventf(item.obj, item.eventtype, item.reason, item.messageFmt, item.elements...) - - // validate event - if item.expectUpdate { - actualEvent := <-patchEvent - validateEvent(string(index), actualEvent, item.expect, t) - } else { - actualEvent := <-createEvent - validateEvent(string(index), actualEvent, item.expect, t) - } - } - - // Another StartRecordingToSink call should start to record events with new clean cache. - sinkWatcher2 := eventBroadcaster.StartRecordingToSink(&testEvents2) - for index, item := range table { - clock.Step(1 * time.Second) - recorder.Eventf(item.obj, item.eventtype, item.reason, item.messageFmt, item.elements...) - - // validate event - if item.expectUpdate { - actualEvent := <-patchEvent2 - validateEvent(string(index), actualEvent, item.expect, t) - } else { - actualEvent := <-createEvent2 - validateEvent(string(index), actualEvent, item.expect, t) - } - } - - sinkWatcher.Stop() - sinkWatcher2.Stop() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/record/events_cache_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/record/events_cache_test.go deleted file mode 100644 index 166550783..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/record/events_cache_test.go +++ /dev/null @@ -1,254 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 record - -import ( - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/diff" -) - -func makeObjectReference(kind, name, namespace string) api.ObjectReference { - return api.ObjectReference{ - Kind: kind, - Name: name, - Namespace: namespace, - UID: "C934D34AFB20242", - APIVersion: "version", - } -} - -func makeEvent(reason, message string, involvedObject api.ObjectReference) api.Event { - eventTime := unversioned.Now() - event := api.Event{ - Reason: reason, - Message: message, - InvolvedObject: involvedObject, - Source: api.EventSource{ - Component: "kubelet", - Host: "kublet.node1", - }, - Count: 1, - FirstTimestamp: eventTime, - LastTimestamp: eventTime, - Type: api.EventTypeNormal, - } - return event -} - -func makeEvents(num int, template api.Event) []api.Event { - events := []api.Event{} - for i := 0; i < num; i++ { - events = append(events, template) - } - return events -} - -func makeUniqueEvents(num int) []api.Event { - events := []api.Event{} - kind := "Pod" - for i := 0; i < num; i++ { - reason := strings.Join([]string{"reason", string(i)}, "-") - message := strings.Join([]string{"message", string(i)}, "-") - name := strings.Join([]string{"pod", string(i)}, "-") - namespace := strings.Join([]string{"ns", string(i)}, "-") - involvedObject := makeObjectReference(kind, name, namespace) - events = append(events, makeEvent(reason, message, involvedObject)) - } - return events -} - -func makeSimilarEvents(num int, template api.Event, messagePrefix string) []api.Event { - events := makeEvents(num, template) - for i := range events { - events[i].Message = strings.Join([]string{messagePrefix, string(i), events[i].Message}, "-") - } - return events -} - -func setCount(event api.Event, count int) api.Event { - event.Count = int32(count) - return event -} - -func validateEvent(messagePrefix string, actualEvent *api.Event, expectedEvent *api.Event, t *testing.T) (*api.Event, error) { - recvEvent := *actualEvent - expectCompression := expectedEvent.Count > 1 - t.Logf("%v - expectedEvent.Count is %d\n", messagePrefix, expectedEvent.Count) - // Just check that the timestamp was set. - if recvEvent.FirstTimestamp.IsZero() || recvEvent.LastTimestamp.IsZero() { - t.Errorf("%v - timestamp wasn't set: %#v", messagePrefix, recvEvent) - } - actualFirstTimestamp := recvEvent.FirstTimestamp - actualLastTimestamp := recvEvent.LastTimestamp - if actualFirstTimestamp.Equal(actualLastTimestamp) { - if expectCompression { - t.Errorf("%v - FirstTimestamp (%q) and LastTimestamp (%q) must be different to indicate event compression happened, but were the same. Actual Event: %#v", messagePrefix, actualFirstTimestamp, actualLastTimestamp, recvEvent) - } - } else { - if expectedEvent.Count == 1 { - t.Errorf("%v - FirstTimestamp (%q) and LastTimestamp (%q) must be equal to indicate only one occurrence of the event, but were different. Actual Event: %#v", messagePrefix, actualFirstTimestamp, actualLastTimestamp, recvEvent) - } - } - // Temp clear time stamps for comparison because actual values don't matter for comparison - recvEvent.FirstTimestamp = expectedEvent.FirstTimestamp - recvEvent.LastTimestamp = expectedEvent.LastTimestamp - // Check that name has the right prefix. - if n, en := recvEvent.Name, expectedEvent.Name; !strings.HasPrefix(n, en) { - t.Errorf("%v - Name '%v' does not contain prefix '%v'", messagePrefix, n, en) - } - recvEvent.Name = expectedEvent.Name - if e, a := expectedEvent, &recvEvent; !reflect.DeepEqual(e, a) { - t.Errorf("%v - diff: %s", messagePrefix, diff.ObjectGoPrintDiff(e, a)) - } - recvEvent.FirstTimestamp = actualFirstTimestamp - recvEvent.LastTimestamp = actualLastTimestamp - return actualEvent, nil -} - -// TestDefaultEventFilterFunc ensures that no events are filtered -func TestDefaultEventFilterFunc(t *testing.T) { - event := makeEvent("end-of-world", "it was fun", makeObjectReference("Pod", "pod1", "other")) - if DefaultEventFilterFunc(&event) { - t.Fatalf("DefaultEventFilterFunc should always return false") - } -} - -// TestEventAggregatorByReasonFunc ensures that two events are aggregated if they vary only by event.message -func TestEventAggregatorByReasonFunc(t *testing.T) { - event1 := makeEvent("end-of-world", "it was fun", makeObjectReference("Pod", "pod1", "other")) - event2 := makeEvent("end-of-world", "it was awful", makeObjectReference("Pod", "pod1", "other")) - event3 := makeEvent("nevermind", "it was a bug", makeObjectReference("Pod", "pod1", "other")) - - aggKey1, localKey1 := EventAggregatorByReasonFunc(&event1) - aggKey2, localKey2 := EventAggregatorByReasonFunc(&event2) - aggKey3, _ := EventAggregatorByReasonFunc(&event3) - - if aggKey1 != aggKey2 { - t.Errorf("Expected %v equal %v", aggKey1, aggKey2) - } - if localKey1 == localKey2 { - t.Errorf("Expected %v to not equal %v", aggKey1, aggKey3) - } - if aggKey1 == aggKey3 { - t.Errorf("Expected %v to not equal %v", aggKey1, aggKey3) - } -} - -// TestEventAggregatorByReasonMessageFunc validates the proper output for an aggregate message -func TestEventAggregatorByReasonMessageFunc(t *testing.T) { - expected := "(events with common reason combined)" - event1 := makeEvent("end-of-world", "it was fun", makeObjectReference("Pod", "pod1", "other")) - if actual := EventAggregatorByReasonMessageFunc(&event1); expected != actual { - t.Errorf("Expected %v got %v", expected, actual) - } -} - -// TestEventCorrelator validates proper counting, aggregation of events -func TestEventCorrelator(t *testing.T) { - firstEvent := makeEvent("first", "i am first", makeObjectReference("Pod", "my-pod", "my-ns")) - duplicateEvent := makeEvent("duplicate", "me again", makeObjectReference("Pod", "my-pod", "my-ns")) - uniqueEvent := makeEvent("unique", "snowflake", makeObjectReference("Pod", "my-pod", "my-ns")) - similarEvent := makeEvent("similar", "similar message", makeObjectReference("Pod", "my-pod", "my-ns")) - aggregateEvent := makeEvent(similarEvent.Reason, EventAggregatorByReasonMessageFunc(&similarEvent), similarEvent.InvolvedObject) - scenario := map[string]struct { - previousEvents []api.Event - newEvent api.Event - expectedEvent api.Event - intervalSeconds int - }{ - "create-a-single-event": { - previousEvents: []api.Event{}, - newEvent: firstEvent, - expectedEvent: setCount(firstEvent, 1), - intervalSeconds: 5, - }, - "the-same-event-should-just-count": { - previousEvents: makeEvents(1, duplicateEvent), - newEvent: duplicateEvent, - expectedEvent: setCount(duplicateEvent, 2), - intervalSeconds: 5, - }, - "the-same-event-should-just-count-even-if-more-than-aggregate": { - previousEvents: makeEvents(defaultAggregateMaxEvents, duplicateEvent), - newEvent: duplicateEvent, - expectedEvent: setCount(duplicateEvent, defaultAggregateMaxEvents+1), - intervalSeconds: 5, - }, - "create-many-unique-events": { - previousEvents: makeUniqueEvents(30), - newEvent: uniqueEvent, - expectedEvent: setCount(uniqueEvent, 1), - intervalSeconds: 5, - }, - "similar-events-should-aggregate-event": { - previousEvents: makeSimilarEvents(defaultAggregateMaxEvents-1, similarEvent, similarEvent.Message), - newEvent: similarEvent, - expectedEvent: setCount(aggregateEvent, 1), - intervalSeconds: 5, - }, - "similar-events-many-times-should-count-the-aggregate": { - previousEvents: makeSimilarEvents(defaultAggregateMaxEvents, similarEvent, similarEvent.Message), - newEvent: similarEvent, - expectedEvent: setCount(aggregateEvent, 2), - intervalSeconds: 5, - }, - "similar-events-whose-interval-is-greater-than-aggregate-interval-do-not-aggregate": { - previousEvents: makeSimilarEvents(defaultAggregateMaxEvents-1, similarEvent, similarEvent.Message), - newEvent: similarEvent, - expectedEvent: setCount(similarEvent, 1), - intervalSeconds: defaultAggregateIntervalInSeconds, - }, - } - - for testScenario, testInput := range scenario { - eventInterval := time.Duration(testInput.intervalSeconds) * time.Second - clock := util.IntervalClock{Time: time.Now(), Duration: eventInterval} - correlator := NewEventCorrelator(&clock) - for i := range testInput.previousEvents { - event := testInput.previousEvents[i] - now := unversioned.NewTime(clock.Now()) - event.FirstTimestamp = now - event.LastTimestamp = now - result, err := correlator.EventCorrelate(&event) - if err != nil { - t.Errorf("scenario %v: unexpected error playing back prevEvents %v", testScenario, err) - } - correlator.UpdateState(result.Event) - } - - // update the input to current clock value - now := unversioned.NewTime(clock.Now()) - testInput.newEvent.FirstTimestamp = now - testInput.newEvent.LastTimestamp = now - result, err := correlator.EventCorrelate(&testInput.newEvent) - if err != nil { - t.Errorf("scenario %v: unexpected error correlating input event %v", testScenario, err) - } - - _, err = validateEvent(testScenario, result.Event, &testInput.expectedEvent, t) - if err != nil { - t.Errorf("scenario %v: unexpected error validating result %v", testScenario, err) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/client_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/client_test.go deleted file mode 100644 index e1cc1f9fa..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/client_test.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 restclient - -import ( - "net/http" - "net/http/httptest" - "net/url" - "os" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/diff" - utiltesting "k8s.io/kubernetes/pkg/util/testing" -) - -func TestDoRequestSuccess(t *testing.T) { - status := &unversioned.Status{Status: unversioned.StatusSuccess} - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), status) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c, err := RESTClientFor(&Config{ - Host: testServer.URL, - ContentConfig: ContentConfig{ - GroupVersion: testapi.Default.GroupVersion(), - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), - }, - Username: "user", - Password: "pass", - }) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - body, err := c.Get().Prefix("test").Do().Raw() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if fakeHandler.RequestReceived.Header["Authorization"] == nil { - t.Errorf("Request is missing authorization header: %#v", fakeHandler.RequestReceived) - } - statusOut, err := runtime.Decode(testapi.Default.Codec(), body) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - if !reflect.DeepEqual(status, statusOut) { - t.Errorf("Unexpected mis-match. Expected %#v. Saw %#v", status, statusOut) - } - fakeHandler.ValidateRequest(t, "/"+testapi.Default.GroupVersion().String()+"/test", "GET", nil) -} - -func TestDoRequestFailed(t *testing.T) { - status := &unversioned.Status{ - Code: http.StatusNotFound, - Status: unversioned.StatusFailure, - Reason: unversioned.StatusReasonNotFound, - Message: " \"\" not found", - Details: &unversioned.StatusDetails{}, - } - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), status) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 404, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c, err := RESTClientFor(&Config{ - Host: testServer.URL, - ContentConfig: ContentConfig{ - GroupVersion: testapi.Default.GroupVersion(), - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), - }, - }) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - body, err := c.Get().Do().Raw() - if err == nil || body != nil { - t.Errorf("unexpected non-error: %#v", body) - } - ss, ok := err.(errors.APIStatus) - if !ok { - t.Errorf("unexpected error type %v", err) - } - actual := ss.Status() - expected := *status - // The decoder will apply the default Version and Kind to the Status. - expected.APIVersion = "v1" - expected.Kind = "Status" - if !reflect.DeepEqual(&expected, &actual) { - t.Errorf("Unexpected mis-match: %s", diff.ObjectDiff(status, &actual)) - } -} - -func TestDoRequestCreated(t *testing.T) { - status := &unversioned.Status{Status: unversioned.StatusSuccess} - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), status) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 201, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c, err := RESTClientFor(&Config{ - Host: testServer.URL, - ContentConfig: ContentConfig{ - GroupVersion: testapi.Default.GroupVersion(), - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), - }, - Username: "user", - Password: "pass", - }) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - created := false - body, err := c.Get().Prefix("test").Do().WasCreated(&created).Raw() - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - if !created { - t.Errorf("Expected object to be created") - } - statusOut, err := runtime.Decode(testapi.Default.Codec(), body) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - if !reflect.DeepEqual(status, statusOut) { - t.Errorf("Unexpected mis-match. Expected %#v. Saw %#v", status, statusOut) - } - fakeHandler.ValidateRequest(t, "/"+testapi.Default.GroupVersion().String()+"/test", "GET", nil) -} - -func TestCreateBackoffManager(t *testing.T) { - - theUrl, _ := url.Parse("http://localhost") - - // 1 second base backoff + duration of 2 seconds -> exponential backoff for requests. - os.Setenv(envBackoffBase, "1") - os.Setenv(envBackoffDuration, "2") - backoff := readExpBackoffConfig() - backoff.UpdateBackoff(theUrl, nil, 500) - backoff.UpdateBackoff(theUrl, nil, 500) - if backoff.CalculateBackoff(theUrl)/time.Second != 2 { - t.Errorf("Backoff env not working.") - } - - // 0 duration -> no backoff. - os.Setenv(envBackoffBase, "1") - os.Setenv(envBackoffDuration, "0") - backoff.UpdateBackoff(theUrl, nil, 500) - backoff.UpdateBackoff(theUrl, nil, 500) - backoff = readExpBackoffConfig() - if backoff.CalculateBackoff(theUrl)/time.Second != 0 { - t.Errorf("Zero backoff duration, but backoff still occuring.") - } - - // No env -> No backoff. - os.Setenv(envBackoffBase, "") - os.Setenv(envBackoffDuration, "") - backoff = readExpBackoffConfig() - backoff.UpdateBackoff(theUrl, nil, 500) - backoff.UpdateBackoff(theUrl, nil, 500) - if backoff.CalculateBackoff(theUrl)/time.Second != 0 { - t.Errorf("Backoff should have been 0.") - } - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/config_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/config_test.go deleted file mode 100644 index a9c71e19d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/config_test.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 restclient - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/testapi" -) - -func TestIsConfigTransportTLS(t *testing.T) { - testCases := []struct { - Config *Config - TransportTLS bool - }{ - { - Config: &Config{}, - TransportTLS: false, - }, - { - Config: &Config{ - Host: "https://localhost", - }, - TransportTLS: true, - }, - { - Config: &Config{ - Host: "localhost", - TLSClientConfig: TLSClientConfig{ - CertFile: "foo", - }, - }, - TransportTLS: true, - }, - { - Config: &Config{ - Host: "///:://localhost", - TLSClientConfig: TLSClientConfig{ - CertFile: "foo", - }, - }, - TransportTLS: false, - }, - { - Config: &Config{ - Host: "1.2.3.4:567", - Insecure: true, - }, - TransportTLS: true, - }, - } - for _, testCase := range testCases { - if err := SetKubernetesDefaults(testCase.Config); err != nil { - t.Errorf("setting defaults failed for %#v: %v", testCase.Config, err) - continue - } - useTLS := IsConfigTransportTLS(*testCase.Config) - if testCase.TransportTLS != useTLS { - t.Errorf("expected %v for %#v", testCase.TransportTLS, testCase.Config) - } - } -} - -func TestSetKubernetesDefaultsUserAgent(t *testing.T) { - config := &Config{} - if err := SetKubernetesDefaults(config); err != nil { - t.Errorf("unexpected error: %v", err) - } - if !strings.Contains(config.UserAgent, "kubernetes/") { - t.Errorf("no user agent set: %#v", config) - } -} - -func TestRESTClientRequires(t *testing.T) { - if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{NegotiatedSerializer: testapi.Default.NegotiatedSerializer()}}); err == nil { - t.Errorf("unexpected non-error") - } - if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}); err == nil { - t.Errorf("unexpected non-error") - } - if _, err := RESTClientFor(&Config{Host: "127.0.0.1", ContentConfig: ContentConfig{GroupVersion: testapi.Default.GroupVersion(), NegotiatedSerializer: testapi.Default.NegotiatedSerializer()}}); err != nil { - t.Errorf("unexpected error: %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/plugin_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/plugin_test.go deleted file mode 100644 index 3419ecb8a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/plugin_test.go +++ /dev/null @@ -1,311 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 restclient - -import ( - "fmt" - "net/http" - "reflect" - "strconv" - "testing" - - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" -) - -func TestAuthPluginWrapTransport(t *testing.T) { - if err := RegisterAuthProviderPlugin("pluginA", pluginAProvider); err != nil { - t.Errorf("Unexpected error: failed to register pluginA: %v", err) - } - if err := RegisterAuthProviderPlugin("pluginB", pluginBProvider); err != nil { - t.Errorf("Unexpected error: failed to register pluginB: %v", err) - } - if err := RegisterAuthProviderPlugin("pluginFail", pluginFailProvider); err != nil { - t.Errorf("Unexpected error: failed to register pluginFail: %v", err) - } - testCases := []struct { - useWrapTransport bool - plugin string - expectErr bool - expectPluginA bool - expectPluginB bool - }{ - {false, "", false, false, false}, - {false, "pluginA", false, true, false}, - {false, "pluginB", false, false, true}, - {false, "pluginFail", true, false, false}, - {false, "pluginUnknown", true, false, false}, - } - for i, tc := range testCases { - c := Config{} - if tc.useWrapTransport { - // Specify an existing WrapTransport in the config to make sure that - // plugins play nicely. - c.WrapTransport = func(rt http.RoundTripper) http.RoundTripper { - return &wrapTransport{rt} - } - } - if len(tc.plugin) != 0 { - c.AuthProvider = &clientcmdapi.AuthProviderConfig{Name: tc.plugin} - } - tConfig, err := c.transportConfig() - if err != nil { - // Unknown/bad plugins are expected to fail here. - if !tc.expectErr { - t.Errorf("%d. Did not expect errors loading Auth Plugin: %q. Got: %v", i, tc.plugin, err) - } - continue - } - var fullyWrappedTransport http.RoundTripper - fullyWrappedTransport = &emptyTransport{} - if tConfig.WrapTransport != nil { - fullyWrappedTransport = tConfig.WrapTransport(&emptyTransport{}) - } - res, err := fullyWrappedTransport.RoundTrip(&http.Request{}) - if err != nil { - t.Errorf("%d. Unexpected error in RoundTrip: %v", i, err) - continue - } - hasWrapTransport := res.Header.Get("wrapTransport") == "Y" - hasPluginA := res.Header.Get("pluginA") == "Y" - hasPluginB := res.Header.Get("pluginB") == "Y" - if hasWrapTransport != tc.useWrapTransport { - t.Errorf("%d. Expected Existing config.WrapTransport: %t; Got: %t", i, tc.useWrapTransport, hasWrapTransport) - } - if hasPluginA != tc.expectPluginA { - t.Errorf("%d. Expected Plugin A: %t; Got: %t", i, tc.expectPluginA, hasPluginA) - } - if hasPluginB != tc.expectPluginB { - t.Errorf("%d. Expected Plugin B: %t; Got: %t", i, tc.expectPluginB, hasPluginB) - } - } -} - -func TestAuthPluginPersist(t *testing.T) { - // register pluginA by a different name so we don't collide across tests. - if err := RegisterAuthProviderPlugin("pluginA2", pluginAProvider); err != nil { - t.Errorf("Unexpected error: failed to register pluginA: %v", err) - } - if err := RegisterAuthProviderPlugin("pluginPersist", pluginPersistProvider); err != nil { - t.Errorf("Unexpected error: failed to register pluginPersist: %v", err) - } - fooBarConfig := map[string]string{"foo": "bar"} - testCases := []struct { - plugin string - startingConfig map[string]string - expectedConfigAfterLogin map[string]string - expectedConfigAfterRoundTrip map[string]string - }{ - // non-persisting plugins should work fine without modifying config. - {"pluginA2", map[string]string{}, map[string]string{}, map[string]string{}}, - {"pluginA2", fooBarConfig, fooBarConfig, fooBarConfig}, - // plugins that persist config should be able to persist when they want. - { - "pluginPersist", - map[string]string{}, - map[string]string{ - "login": "Y", - }, - map[string]string{ - "login": "Y", - "roundTrips": "1", - }, - }, - { - "pluginPersist", - map[string]string{ - "login": "Y", - "roundTrips": "123", - }, - map[string]string{ - "login": "Y", - "roundTrips": "123", - }, - map[string]string{ - "login": "Y", - "roundTrips": "124", - }, - }, - } - for i, tc := range testCases { - cfg := &clientcmdapi.AuthProviderConfig{ - Name: tc.plugin, - Config: tc.startingConfig, - } - persister := &inMemoryPersister{make(map[string]string)} - persister.Persist(tc.startingConfig) - plugin, err := GetAuthProvider("127.0.0.1", cfg, persister) - if err != nil { - t.Errorf("%d. Unexpected error: failed to get plugin %q: %v", i, tc.plugin, err) - } - if err := plugin.Login(); err != nil { - t.Errorf("%d. Unexpected error calling Login() w/ plugin %q: %v", i, tc.plugin, err) - } - // Make sure the plugin persisted what we expect after Login(). - if !reflect.DeepEqual(persister.savedConfig, tc.expectedConfigAfterLogin) { - t.Errorf("%d. Unexpected persisted config after calling %s.Login(): \nGot:\n%v\nExpected:\n%v", - i, tc.plugin, persister.savedConfig, tc.expectedConfigAfterLogin) - } - if _, err := plugin.WrapTransport(&emptyTransport{}).RoundTrip(&http.Request{}); err != nil { - t.Errorf("%d. Unexpected error round-tripping w/ plugin %q: %v", i, tc.plugin, err) - } - // Make sure the plugin persisted what we expect after RoundTrip(). - if !reflect.DeepEqual(persister.savedConfig, tc.expectedConfigAfterRoundTrip) { - t.Errorf("%d. Unexpected persisted config after calling %s.WrapTransport.RoundTrip(): \nGot:\n%v\nExpected:\n%v", - i, tc.plugin, persister.savedConfig, tc.expectedConfigAfterLogin) - } - } - -} - -// emptyTransport provides an empty http.Response with an initialized header -// to allow wrapping RoundTrippers to set header values. -type emptyTransport struct{} - -func (*emptyTransport) RoundTrip(req *http.Request) (*http.Response, error) { - res := &http.Response{ - Header: make(map[string][]string), - } - return res, nil -} - -// wrapTransport sets "wrapTransport" = "Y" on the response. -type wrapTransport struct { - rt http.RoundTripper -} - -func (w *wrapTransport) RoundTrip(req *http.Request) (*http.Response, error) { - res, err := w.rt.RoundTrip(req) - if err != nil { - return nil, err - } - res.Header.Add("wrapTransport", "Y") - return res, nil -} - -// wrapTransportA sets "pluginA" = "Y" on the response. -type wrapTransportA struct { - rt http.RoundTripper -} - -func (w *wrapTransportA) RoundTrip(req *http.Request) (*http.Response, error) { - res, err := w.rt.RoundTrip(req) - if err != nil { - return nil, err - } - res.Header.Add("pluginA", "Y") - return res, nil -} - -type pluginA struct{} - -func (*pluginA) WrapTransport(rt http.RoundTripper) http.RoundTripper { - return &wrapTransportA{rt} -} - -func (*pluginA) Login() error { return nil } - -func pluginAProvider(string, map[string]string, AuthProviderConfigPersister) (AuthProvider, error) { - return &pluginA{}, nil -} - -// wrapTransportB sets "pluginB" = "Y" on the response. -type wrapTransportB struct { - rt http.RoundTripper -} - -func (w *wrapTransportB) RoundTrip(req *http.Request) (*http.Response, error) { - res, err := w.rt.RoundTrip(req) - if err != nil { - return nil, err - } - res.Header.Add("pluginB", "Y") - return res, nil -} - -type pluginB struct{} - -func (*pluginB) WrapTransport(rt http.RoundTripper) http.RoundTripper { - return &wrapTransportB{rt} -} - -func (*pluginB) Login() error { return nil } - -func pluginBProvider(string, map[string]string, AuthProviderConfigPersister) (AuthProvider, error) { - return &pluginB{}, nil -} - -// pluginFailProvider simulates a registered AuthPlugin that fails to load. -func pluginFailProvider(string, map[string]string, AuthProviderConfigPersister) (AuthProvider, error) { - return nil, fmt.Errorf("Failed to load AuthProvider") -} - -type inMemoryPersister struct { - savedConfig map[string]string -} - -func (i *inMemoryPersister) Persist(config map[string]string) error { - i.savedConfig = make(map[string]string) - for k, v := range config { - i.savedConfig[k] = v - } - return nil -} - -// wrapTransportPersist increments the "roundTrips" entry from the config when -// roundTrip is called. -type wrapTransportPersist struct { - rt http.RoundTripper - config map[string]string - persister AuthProviderConfigPersister -} - -func (w *wrapTransportPersist) RoundTrip(req *http.Request) (*http.Response, error) { - roundTrips := 0 - if rtVal, ok := w.config["roundTrips"]; ok { - var err error - roundTrips, err = strconv.Atoi(rtVal) - if err != nil { - return nil, err - } - } - roundTrips++ - w.config["roundTrips"] = fmt.Sprintf("%d", roundTrips) - if err := w.persister.Persist(w.config); err != nil { - return nil, err - } - return w.rt.RoundTrip(req) -} - -type pluginPersist struct { - config map[string]string - persister AuthProviderConfigPersister -} - -func (p *pluginPersist) WrapTransport(rt http.RoundTripper) http.RoundTripper { - return &wrapTransportPersist{rt, p.config, p.persister} -} - -// Login sets the config entry "login" to "Y". -func (p *pluginPersist) Login() error { - p.config["login"] = "Y" - p.persister.Persist(p.config) - return nil -} - -func pluginPersistProvider(_ string, config map[string]string, persister AuthProviderConfigPersister) (AuthProvider, error) { - return &pluginPersist{config, persister}, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/request_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/request_test.go deleted file mode 100644 index b7cb6a2ac..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/request_test.go +++ /dev/null @@ -1,1343 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 restclient - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "os" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - apierrors "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/streaming" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/flowcontrol" - "k8s.io/kubernetes/pkg/util/httpstream" - "k8s.io/kubernetes/pkg/util/intstr" - utiltesting "k8s.io/kubernetes/pkg/util/testing" - "k8s.io/kubernetes/pkg/watch" - "k8s.io/kubernetes/pkg/watch/versioned" -) - -func TestNewRequestSetsAccept(t *testing.T) { - r := NewRequest(nil, "get", &url.URL{Path: "/path/"}, "", ContentConfig{}, Serializers{}, nil, nil) - if r.headers.Get("Accept") != "" { - t.Errorf("unexpected headers: %#v", r.headers) - } - r = NewRequest(nil, "get", &url.URL{Path: "/path/"}, "", ContentConfig{ContentType: "application/other"}, Serializers{}, nil, nil) - if r.headers.Get("Accept") != "application/other, */*" { - t.Errorf("unexpected headers: %#v", r.headers) - } -} - -func TestRequestWithErrorWontChange(t *testing.T) { - original := Request{ - err: errors.New("test"), - content: ContentConfig{GroupVersion: testapi.Default.GroupVersion()}, - } - r := original - changed := r.Param("foo", "bar"). - LabelsSelectorParam(labels.Set{"a": "b"}.AsSelector()). - UintParam("uint", 1). - AbsPath("/abs"). - Prefix("test"). - Suffix("testing"). - Namespace("new"). - Resource("foos"). - Name("bars"). - Body("foo"). - Timeout(time.Millisecond) - if changed != &r { - t.Errorf("returned request should point to the same object") - } - if !reflect.DeepEqual(changed, &original) { - t.Errorf("expected %#v, got %#v", &original, changed) - } -} - -func TestRequestPreservesBaseTrailingSlash(t *testing.T) { - r := &Request{baseURL: &url.URL{}, pathPrefix: "/path/"} - if s := r.URL().String(); s != "/path/" { - t.Errorf("trailing slash should be preserved: %s", s) - } -} - -func TestRequestAbsPathPreservesTrailingSlash(t *testing.T) { - r := (&Request{baseURL: &url.URL{}}).AbsPath("/foo/") - if s := r.URL().String(); s != "/foo/" { - t.Errorf("trailing slash should be preserved: %s", s) - } - - r = (&Request{baseURL: &url.URL{}}).AbsPath("/foo/") - if s := r.URL().String(); s != "/foo/" { - t.Errorf("trailing slash should be preserved: %s", s) - } -} - -func TestRequestAbsPathJoins(t *testing.T) { - r := (&Request{baseURL: &url.URL{}}).AbsPath("foo/bar", "baz") - if s := r.URL().String(); s != "foo/bar/baz" { - t.Errorf("trailing slash should be preserved: %s", s) - } -} - -func TestRequestSetsNamespace(t *testing.T) { - r := (&Request{ - baseURL: &url.URL{ - Path: "/", - }, - }).Namespace("foo") - if r.namespace == "" { - t.Errorf("namespace should be set: %#v", r) - } - - if s := r.URL().String(); s != "namespaces/foo" { - t.Errorf("namespace should be in path: %s", s) - } -} - -func TestRequestOrdersNamespaceInPath(t *testing.T) { - r := (&Request{ - baseURL: &url.URL{}, - pathPrefix: "/test/", - }).Name("bar").Resource("baz").Namespace("foo") - if s := r.URL().String(); s != "/test/namespaces/foo/baz/bar" { - t.Errorf("namespace should be in order in path: %s", s) - } -} - -func TestRequestOrdersSubResource(t *testing.T) { - r := (&Request{ - baseURL: &url.URL{}, - pathPrefix: "/test/", - }).Name("bar").Resource("baz").Namespace("foo").Suffix("test").SubResource("a", "b") - if s := r.URL().String(); s != "/test/namespaces/foo/baz/bar/a/b/test" { - t.Errorf("namespace should be in order in path: %s", s) - } -} - -func TestRequestSetTwiceError(t *testing.T) { - if (&Request{}).Name("bar").Name("baz").err == nil { - t.Errorf("setting name twice should result in error") - } - if (&Request{}).Namespace("bar").Namespace("baz").err == nil { - t.Errorf("setting namespace twice should result in error") - } - if (&Request{}).Resource("bar").Resource("baz").err == nil { - t.Errorf("setting resource twice should result in error") - } - if (&Request{}).SubResource("bar").SubResource("baz").err == nil { - t.Errorf("setting subresource twice should result in error") - } -} - -func TestInvalidSegments(t *testing.T) { - invalidSegments := []string{".", "..", "test/segment", "test%2bsegment"} - setters := map[string]func(string, *Request){ - "namespace": func(s string, r *Request) { r.Namespace(s) }, - "resource": func(s string, r *Request) { r.Resource(s) }, - "name": func(s string, r *Request) { r.Name(s) }, - "subresource": func(s string, r *Request) { r.SubResource(s) }, - } - for _, invalidSegment := range invalidSegments { - for setterName, setter := range setters { - r := &Request{} - setter(invalidSegment, r) - if r.err == nil { - t.Errorf("%s: %s: expected error, got none", setterName, invalidSegment) - } - } - } -} - -func TestRequestParam(t *testing.T) { - r := (&Request{}).Param("foo", "a") - if !reflect.DeepEqual(r.params, url.Values{"foo": []string{"a"}}) { - t.Errorf("should have set a param: %#v", r) - } - - r.Param("bar", "1") - r.Param("bar", "2") - if !reflect.DeepEqual(r.params, url.Values{"foo": []string{"a"}, "bar": []string{"1", "2"}}) { - t.Errorf("should have set a param: %#v", r) - } -} - -func TestRequestVersionedParams(t *testing.T) { - r := (&Request{content: ContentConfig{GroupVersion: &v1.SchemeGroupVersion}}).Param("foo", "a") - if !reflect.DeepEqual(r.params, url.Values{"foo": []string{"a"}}) { - t.Errorf("should have set a param: %#v", r) - } - r.VersionedParams(&api.PodLogOptions{Follow: true, Container: "bar"}, api.ParameterCodec) - - if !reflect.DeepEqual(r.params, url.Values{ - "foo": []string{"a"}, - "container": []string{"bar"}, - "follow": []string{"true"}, - }) { - t.Errorf("should have set a param: %#v", r) - } -} - -func TestRequestVersionedParamsFromListOptions(t *testing.T) { - r := &Request{content: ContentConfig{GroupVersion: &v1.SchemeGroupVersion}} - r.VersionedParams(&api.ListOptions{ResourceVersion: "1"}, api.ParameterCodec) - if !reflect.DeepEqual(r.params, url.Values{ - "resourceVersion": []string{"1"}, - }) { - t.Errorf("should have set a param: %#v", r) - } - - var timeout int64 = 10 - r.VersionedParams(&api.ListOptions{ResourceVersion: "2", TimeoutSeconds: &timeout}, api.ParameterCodec) - if !reflect.DeepEqual(r.params, url.Values{ - "resourceVersion": []string{"1", "2"}, - "timeoutSeconds": []string{"10"}, - }) { - t.Errorf("should have set a param: %#v", r) - } -} - -func TestRequestURI(t *testing.T) { - r := (&Request{}).Param("foo", "a") - r.Prefix("other") - r.RequestURI("/test?foo=b&a=b&c=1&c=2") - if r.pathPrefix != "/test" { - t.Errorf("path is wrong: %#v", r) - } - if !reflect.DeepEqual(r.params, url.Values{"a": []string{"b"}, "foo": []string{"b"}, "c": []string{"1", "2"}}) { - t.Errorf("should have set a param: %#v", r) - } -} - -type NotAnAPIObject struct{} - -func (obj NotAnAPIObject) GroupVersionKind() *unversioned.GroupVersionKind { return nil } -func (obj NotAnAPIObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) {} - -func defaultContentConfig() ContentConfig { - return ContentConfig{ - GroupVersion: testapi.Default.GroupVersion(), - Codec: testapi.Default.Codec(), - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), - } -} - -func defaultSerializers() Serializers { - return Serializers{ - Encoder: testapi.Default.Codec(), - Decoder: testapi.Default.Codec(), - StreamingSerializer: testapi.Default.Codec(), - Framer: runtime.DefaultFramer, - } -} - -func TestRequestBody(t *testing.T) { - // test unknown type - r := (&Request{}).Body([]string{"test"}) - if r.err == nil || r.body != nil { - t.Errorf("should have set err and left body nil: %#v", r) - } - - // test error set when failing to read file - f, err := ioutil.TempFile("", "test") - if err != nil { - t.Fatalf("unable to create temp file") - } - defer f.Close() - os.Remove(f.Name()) - r = (&Request{}).Body(f.Name()) - if r.err == nil || r.body != nil { - t.Errorf("should have set err and left body nil: %#v", r) - } - - // test unencodable api object - r = (&Request{content: defaultContentConfig()}).Body(&NotAnAPIObject{}) - if r.err == nil || r.body != nil { - t.Errorf("should have set err and left body nil: %#v", r) - } -} - -func TestResultIntoWithErrReturnsErr(t *testing.T) { - res := Result{err: errors.New("test")} - if err := res.Into(&api.Pod{}); err != res.err { - t.Errorf("should have returned exact error from result") - } -} - -func TestURLTemplate(t *testing.T) { - uri, _ := url.Parse("http://localhost") - r := NewRequest(nil, "POST", uri, "", ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "test"}}, Serializers{}, nil, nil) - r.Prefix("pre1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0") - full := r.URL() - if full.String() != "http://localhost/pre1/namespaces/ns/r1/nm?p0=v0" { - t.Errorf("unexpected initial URL: %s", full) - } - actual := r.finalURLTemplate() - expected := "http://localhost/pre1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D?p0=%7Bvalue%7D" - if actual != expected { - t.Errorf("unexpected URL template: %s %s", actual, expected) - } - if r.URL().String() != full.String() { - t.Errorf("creating URL template changed request: %s -> %s", full.String(), r.URL().String()) - } -} - -func TestTransformResponse(t *testing.T) { - invalid := []byte("aaaaa") - uri, _ := url.Parse("http://localhost") - testCases := []struct { - Response *http.Response - Data []byte - Created bool - Error bool - ErrFn func(err error) bool - }{ - {Response: &http.Response{StatusCode: 200}, Data: []byte{}}, - {Response: &http.Response{StatusCode: 201}, Data: []byte{}, Created: true}, - {Response: &http.Response{StatusCode: 199}, Error: true}, - {Response: &http.Response{StatusCode: 500}, Error: true}, - {Response: &http.Response{StatusCode: 422}, Error: true}, - {Response: &http.Response{StatusCode: 409}, Error: true}, - {Response: &http.Response{StatusCode: 404}, Error: true}, - {Response: &http.Response{StatusCode: 401}, Error: true}, - { - Response: &http.Response{ - StatusCode: 401, - Header: http.Header{"Content-Type": []string{"application/json"}}, - Body: ioutil.NopCloser(bytes.NewReader(invalid)), - }, - Error: true, - ErrFn: func(err error) bool { - return err.Error() != "aaaaa" && apierrors.IsUnauthorized(err) - }, - }, - { - Response: &http.Response{ - StatusCode: 401, - Header: http.Header{"Content-Type": []string{"text/any"}}, - Body: ioutil.NopCloser(bytes.NewReader(invalid)), - }, - Error: true, - ErrFn: func(err error) bool { - return strings.Contains(err.Error(), "server has asked for the client to provide") && apierrors.IsUnauthorized(err) - }, - }, - {Response: &http.Response{StatusCode: 403}, Error: true}, - {Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid}, - {Response: &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewReader(invalid))}, Data: invalid}, - } - for i, test := range testCases { - r := NewRequest(nil, "", uri, "", defaultContentConfig(), defaultSerializers(), nil, nil) - if test.Response.Body == nil { - test.Response.Body = ioutil.NopCloser(bytes.NewReader([]byte{})) - } - result := r.transformResponse(test.Response, &http.Request{}) - response, created, err := result.body, result.statusCode == http.StatusCreated, result.err - hasErr := err != nil - if hasErr != test.Error { - t.Errorf("%d: unexpected error: %t %v", i, test.Error, err) - } else if hasErr && test.Response.StatusCode > 399 { - status, ok := err.(apierrors.APIStatus) - if !ok { - t.Errorf("%d: response should have been transformable into APIStatus: %v", i, err) - continue - } - if int(status.Status().Code) != test.Response.StatusCode { - t.Errorf("%d: status code did not match response: %#v", i, status.Status()) - } - } - if test.ErrFn != nil && !test.ErrFn(err) { - t.Errorf("%d: error function did not match: %v", i, err) - } - if !(test.Data == nil && response == nil) && !api.Semantic.DeepDerivative(test.Data, response) { - t.Errorf("%d: unexpected response: %#v %#v", i, test.Data, response) - } - if test.Created != created { - t.Errorf("%d: expected created %t, got %t", i, test.Created, created) - } - } -} - -func TestTransformUnstructuredError(t *testing.T) { - testCases := []struct { - Req *http.Request - Res *http.Response - - Resource string - Name string - - ErrFn func(error) bool - }{ - { - Resource: "foo", - Name: "bar", - Req: &http.Request{ - Method: "POST", - }, - Res: &http.Response{ - StatusCode: http.StatusConflict, - Body: ioutil.NopCloser(bytes.NewReader(nil)), - }, - ErrFn: apierrors.IsAlreadyExists, - }, - { - Resource: "foo", - Name: "bar", - Req: &http.Request{ - Method: "PUT", - }, - Res: &http.Response{ - StatusCode: http.StatusConflict, - Body: ioutil.NopCloser(bytes.NewReader(nil)), - }, - ErrFn: apierrors.IsConflict, - }, - { - Resource: "foo", - Name: "bar", - Req: &http.Request{}, - Res: &http.Response{ - StatusCode: http.StatusNotFound, - Body: ioutil.NopCloser(bytes.NewReader(nil)), - }, - ErrFn: apierrors.IsNotFound, - }, - { - Req: &http.Request{}, - Res: &http.Response{ - StatusCode: http.StatusBadRequest, - Body: ioutil.NopCloser(bytes.NewReader(nil)), - }, - ErrFn: apierrors.IsBadRequest, - }, - } - - for _, testCase := range testCases { - r := &Request{ - content: defaultContentConfig(), - serializers: defaultSerializers(), - resourceName: testCase.Name, - resource: testCase.Resource, - } - result := r.transformResponse(testCase.Res, testCase.Req) - err := result.err - if !testCase.ErrFn(err) { - t.Errorf("unexpected error: %v", err) - continue - } - if len(testCase.Name) != 0 && !strings.Contains(err.Error(), testCase.Name) { - t.Errorf("unexpected error string: %s", err) - } - if len(testCase.Resource) != 0 && !strings.Contains(err.Error(), testCase.Resource) { - t.Errorf("unexpected error string: %s", err) - } - } -} - -type clientFunc func(req *http.Request) (*http.Response, error) - -func (f clientFunc) Do(req *http.Request) (*http.Response, error) { - return f(req) -} - -func TestRequestWatch(t *testing.T) { - testCases := []struct { - Request *Request - Err bool - ErrFn func(error) bool - Empty bool - }{ - { - Request: &Request{err: errors.New("bail")}, - Err: true, - }, - { - Request: &Request{baseURL: &url.URL{}, pathPrefix: "%"}, - Err: true, - }, - { - Request: &Request{ - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return nil, errors.New("err") - }), - baseURL: &url.URL{}, - }, - Err: true, - }, - { - Request: &Request{ - content: defaultContentConfig(), - serializers: defaultSerializers(), - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusForbidden, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), - }, nil - }), - baseURL: &url.URL{}, - }, - Err: true, - ErrFn: func(err error) bool { - return apierrors.IsForbidden(err) - }, - }, - { - Request: &Request{ - content: defaultContentConfig(), - serializers: defaultSerializers(), - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusUnauthorized, - Body: ioutil.NopCloser(bytes.NewReader([]byte{})), - }, nil - }), - baseURL: &url.URL{}, - }, - Err: true, - ErrFn: func(err error) bool { - return apierrors.IsUnauthorized(err) - }, - }, - { - Request: &Request{ - content: defaultContentConfig(), - serializers: defaultSerializers(), - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusUnauthorized, - Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &unversioned.Status{ - Status: unversioned.StatusFailure, - Reason: unversioned.StatusReasonUnauthorized, - })))), - }, nil - }), - baseURL: &url.URL{}, - }, - Err: true, - ErrFn: func(err error) bool { - return apierrors.IsUnauthorized(err) - }, - }, - { - Request: &Request{ - serializers: defaultSerializers(), - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return nil, io.EOF - }), - baseURL: &url.URL{}, - }, - Empty: true, - }, - { - Request: &Request{ - serializers: defaultSerializers(), - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return nil, &url.Error{Err: io.EOF} - }), - baseURL: &url.URL{}, - }, - Empty: true, - }, - { - Request: &Request{ - serializers: defaultSerializers(), - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return nil, errors.New("http: can't write HTTP request on broken connection") - }), - baseURL: &url.URL{}, - }, - Empty: true, - }, - { - Request: &Request{ - serializers: defaultSerializers(), - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return nil, errors.New("foo: connection reset by peer") - }), - baseURL: &url.URL{}, - }, - Empty: true, - }, - } - for i, testCase := range testCases { - t.Logf("testcase %v", testCase.Request) - testCase.Request.backoffMgr = &NoBackoff{} - watch, err := testCase.Request.Watch() - hasErr := err != nil - if hasErr != testCase.Err { - t.Errorf("%d: expected %t, got %t: %v", i, testCase.Err, hasErr, err) - continue - } - if testCase.ErrFn != nil && !testCase.ErrFn(err) { - t.Errorf("%d: error not valid: %v", i, err) - } - if hasErr && watch != nil { - t.Errorf("%d: watch should be nil when error is returned", i) - continue - } - if testCase.Empty { - _, ok := <-watch.ResultChan() - if ok { - t.Errorf("%d: expected the watch to be empty: %#v", i, watch) - } - } - } -} - -func TestRequestStream(t *testing.T) { - testCases := []struct { - Request *Request - Err bool - }{ - { - Request: &Request{err: errors.New("bail")}, - Err: true, - }, - { - Request: &Request{baseURL: &url.URL{}, pathPrefix: "%"}, - Err: true, - }, - { - Request: &Request{ - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return nil, errors.New("err") - }), - baseURL: &url.URL{}, - }, - Err: true, - }, - { - Request: &Request{ - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return &http.Response{ - StatusCode: http.StatusUnauthorized, - Body: ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &unversioned.Status{ - Status: unversioned.StatusFailure, - Reason: unversioned.StatusReasonUnauthorized, - })))), - }, nil - }), - content: defaultContentConfig(), - serializers: defaultSerializers(), - baseURL: &url.URL{}, - }, - Err: true, - }, - } - for i, testCase := range testCases { - testCase.Request.backoffMgr = &NoBackoff{} - body, err := testCase.Request.Stream() - hasErr := err != nil - if hasErr != testCase.Err { - t.Errorf("%d: expected %t, got %t: %v", i, testCase.Err, hasErr, err) - } - if hasErr && body != nil { - t.Errorf("%d: body should be nil when error is returned", i) - } - } -} - -type fakeUpgradeConnection struct{} - -func (c *fakeUpgradeConnection) CreateStream(headers http.Header) (httpstream.Stream, error) { - return nil, nil -} -func (c *fakeUpgradeConnection) Close() error { - return nil -} -func (c *fakeUpgradeConnection) CloseChan() <-chan bool { - return make(chan bool) -} -func (c *fakeUpgradeConnection) SetIdleTimeout(timeout time.Duration) { -} - -type fakeUpgradeRoundTripper struct { - req *http.Request - conn httpstream.Connection -} - -func (f *fakeUpgradeRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - f.req = req - b := []byte{} - body := ioutil.NopCloser(bytes.NewReader(b)) - resp := &http.Response{ - StatusCode: 101, - Body: body, - } - return resp, nil -} - -func (f *fakeUpgradeRoundTripper) NewConnection(resp *http.Response) (httpstream.Connection, error) { - return f.conn, nil -} - -func TestRequestDo(t *testing.T) { - testCases := []struct { - Request *Request - Err bool - }{ - { - Request: &Request{err: errors.New("bail")}, - Err: true, - }, - { - Request: &Request{baseURL: &url.URL{}, pathPrefix: "%"}, - Err: true, - }, - { - Request: &Request{ - client: clientFunc(func(req *http.Request) (*http.Response, error) { - return nil, errors.New("err") - }), - baseURL: &url.URL{}, - }, - Err: true, - }, - } - for i, testCase := range testCases { - testCase.Request.backoffMgr = &NoBackoff{} - body, err := testCase.Request.Do().Raw() - hasErr := err != nil - if hasErr != testCase.Err { - t.Errorf("%d: expected %t, got %t: %v", i, testCase.Err, hasErr, err) - } - if hasErr && body != nil { - t.Errorf("%d: body should be nil when error is returned", i) - } - } -} - -func TestDoRequestNewWay(t *testing.T) { - reqBody := "request body" - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ - Protocol: "TCP", - Port: 12345, - TargetPort: intstr.FromInt(12345), - }}}} - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := testRESTClient(t, testServer) - obj, err := c.Verb("POST"). - Prefix("foo", "bar"). - Suffix("baz"). - Timeout(time.Second). - Body([]byte(reqBody)). - Do().Get() - if err != nil { - t.Errorf("Unexpected error: %v %#v", err, err) - return - } - if obj == nil { - t.Error("nil obj") - } else if !api.Semantic.DeepDerivative(expectedObj, obj) { - t.Errorf("Expected: %#v, got %#v", expectedObj, obj) - } - requestURL := testapi.Default.ResourcePathWithPrefix("foo/bar", "", "", "baz") - requestURL += "?timeout=1s" - fakeHandler.ValidateRequest(t, requestURL, "POST", &reqBody) -} - -// This test assumes that the client implementation backs off exponentially, for an individual request. -func TestBackoffLifecycle(t *testing.T) { - count := 0 - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - count++ - t.Logf("Attempt %d", count) - if count == 5 || count == 9 { - w.WriteHeader(http.StatusOK) - return - } else { - w.WriteHeader(http.StatusGatewayTimeout) - return - } - })) - defer testServer.Close() - c := testRESTClient(t, testServer) - - // Test backoff recovery and increase. This correlates to the constants - // which are used in the server implementation returning StatusOK above. - seconds := []int{0, 1, 2, 4, 8, 0, 1, 2, 4, 0} - request := c.Verb("POST").Prefix("backofftest").Suffix("abc") - clock := util.FakeClock{} - request.backoffMgr = &URLBackoff{ - // Use a fake backoff here to avoid flakes and speed the test up. - Backoff: flowcontrol.NewFakeBackOff( - time.Duration(1)*time.Second, - time.Duration(200)*time.Second, - &clock, - )} - - for _, sec := range seconds { - thisBackoff := request.backoffMgr.CalculateBackoff(request.URL()) - t.Logf("Current backoff %v", thisBackoff) - if thisBackoff != time.Duration(sec)*time.Second { - t.Errorf("Backoff is %v instead of %v", thisBackoff, sec) - } - now := clock.Now() - request.DoRaw() - elapsed := clock.Since(now) - if clock.Since(now) != thisBackoff { - t.Errorf("CalculatedBackoff not honored by clock: Expected time of %v, but got %v ", thisBackoff, elapsed) - } - } -} - -func TestCheckRetryClosesBody(t *testing.T) { - count := 0 - ch := make(chan struct{}) - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - count++ - t.Logf("attempt %d", count) - if count >= 5 { - w.WriteHeader(http.StatusOK) - close(ch) - return - } - w.Header().Set("Retry-After", "0") - w.WriteHeader(apierrors.StatusTooManyRequests) - })) - defer testServer.Close() - - c := testRESTClient(t, testServer) - _, err := c.Verb("POST"). - Prefix("foo", "bar"). - Suffix("baz"). - Timeout(time.Second). - Body([]byte(strings.Repeat("abcd", 1000))). - DoRaw() - if err != nil { - t.Fatalf("Unexpected error: %v %#v", err, err) - } - <-ch - if count != 5 { - t.Errorf("unexpected retries: %d", count) - } -} - -func TestCheckRetryHandles429And5xx(t *testing.T) { - count := 0 - ch := make(chan struct{}) - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - t.Logf("attempt %d", count) - if count >= 4 { - w.WriteHeader(http.StatusOK) - close(ch) - return - } - w.Header().Set("Retry-After", "0") - w.WriteHeader([]int{apierrors.StatusTooManyRequests, 500, 501, 504}[count]) - count++ - })) - defer testServer.Close() - - c := testRESTClient(t, testServer) - _, err := c.Verb("POST"). - Prefix("foo", "bar"). - Suffix("baz"). - Timeout(time.Second). - Body([]byte(strings.Repeat("abcd", 1000))). - DoRaw() - if err != nil { - t.Fatalf("Unexpected error: %v %#v", err, err) - } - <-ch - if count != 4 { - t.Errorf("unexpected retries: %d", count) - } -} - -func BenchmarkCheckRetryClosesBody(b *testing.B) { - count := 0 - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - count++ - if count%3 == 0 { - w.WriteHeader(http.StatusOK) - return - } - w.Header().Set("Retry-After", "0") - w.WriteHeader(apierrors.StatusTooManyRequests) - })) - defer testServer.Close() - - c := testRESTClient(b, testServer) - r := c.Verb("POST"). - Prefix("foo", "bar"). - Suffix("baz"). - Timeout(time.Second). - Body([]byte(strings.Repeat("abcd", 1000))) - - for i := 0; i < b.N; i++ { - if _, err := r.DoRaw(); err != nil { - b.Fatalf("Unexpected error: %v %#v", err, err) - } - } -} - -func TestDoRequestNewWayReader(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - reqBodyExpected, _ := runtime.Encode(testapi.Default.Codec(), reqObj) - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ - Protocol: "TCP", - Port: 12345, - TargetPort: intstr.FromInt(12345), - }}}} - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := testRESTClient(t, testServer) - obj, err := c.Verb("POST"). - Resource("bar"). - Name("baz"). - Prefix("foo"). - LabelsSelectorParam(labels.Set{"name": "foo"}.AsSelector()). - Timeout(time.Second). - Body(bytes.NewBuffer(reqBodyExpected)). - Do().Get() - if err != nil { - t.Errorf("Unexpected error: %v %#v", err, err) - return - } - if obj == nil { - t.Error("nil obj") - } else if !api.Semantic.DeepDerivative(expectedObj, obj) { - t.Errorf("Expected: %#v, got %#v", expectedObj, obj) - } - tmpStr := string(reqBodyExpected) - requestURL := testapi.Default.ResourcePathWithPrefix("foo", "bar", "", "baz") - requestURL += "?" + unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) + "=name%3Dfoo&timeout=1s" - fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) -} - -func TestDoRequestNewWayObj(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - reqBodyExpected, _ := runtime.Encode(testapi.Default.Codec(), reqObj) - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ - Protocol: "TCP", - Port: 12345, - TargetPort: intstr.FromInt(12345), - }}}} - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := testRESTClient(t, testServer) - obj, err := c.Verb("POST"). - Suffix("baz"). - Name("bar"). - Resource("foo"). - LabelsSelectorParam(labels.Set{"name": "foo"}.AsSelector()). - Timeout(time.Second). - Body(reqObj). - Do().Get() - if err != nil { - t.Errorf("Unexpected error: %v %#v", err, err) - return - } - if obj == nil { - t.Error("nil obj") - } else if !api.Semantic.DeepDerivative(expectedObj, obj) { - t.Errorf("Expected: %#v, got %#v", expectedObj, obj) - } - tmpStr := string(reqBodyExpected) - requestURL := testapi.Default.ResourcePath("foo", "", "bar/baz") - requestURL += "?" + unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) + "=name%3Dfoo&timeout=1s" - fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) -} - -func TestDoRequestNewWayFile(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - reqBodyExpected, err := runtime.Encode(testapi.Default.Codec(), reqObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - file, err := ioutil.TempFile("", "foo") - if err != nil { - t.Errorf("unexpected error: %v", err) - } - defer file.Close() - - _, err = file.Write(reqBodyExpected) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ - Protocol: "TCP", - Port: 12345, - TargetPort: intstr.FromInt(12345), - }}}} - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := testRESTClient(t, testServer) - wasCreated := true - obj, err := c.Verb("POST"). - Prefix("foo/bar", "baz"). - Timeout(time.Second). - Body(file.Name()). - Do().WasCreated(&wasCreated).Get() - if err != nil { - t.Errorf("Unexpected error: %v %#v", err, err) - return - } - if obj == nil { - t.Error("nil obj") - } else if !api.Semantic.DeepDerivative(expectedObj, obj) { - t.Errorf("Expected: %#v, got %#v", expectedObj, obj) - } - if wasCreated { - t.Errorf("expected object was not created") - } - tmpStr := string(reqBodyExpected) - requestURL := testapi.Default.ResourcePathWithPrefix("foo/bar/baz", "", "", "") - requestURL += "?timeout=1s" - fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) -} - -func TestWasCreated(t *testing.T) { - reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - reqBodyExpected, err := runtime.Encode(testapi.Default.Codec(), reqObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ - Protocol: "TCP", - Port: 12345, - TargetPort: intstr.FromInt(12345), - }}}} - expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 201, - ResponseBody: string(expectedBody), - T: t, - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := testRESTClient(t, testServer) - wasCreated := false - obj, err := c.Verb("PUT"). - Prefix("foo/bar", "baz"). - Timeout(time.Second). - Body(reqBodyExpected). - Do().WasCreated(&wasCreated).Get() - if err != nil { - t.Errorf("Unexpected error: %v %#v", err, err) - return - } - if obj == nil { - t.Error("nil obj") - } else if !api.Semantic.DeepDerivative(expectedObj, obj) { - t.Errorf("Expected: %#v, got %#v", expectedObj, obj) - } - if !wasCreated { - t.Errorf("Expected object was created") - } - - tmpStr := string(reqBodyExpected) - requestURL := testapi.Default.ResourcePathWithPrefix("foo/bar/baz", "", "", "") - requestURL += "?timeout=1s" - fakeHandler.ValidateRequest(t, requestURL, "PUT", &tmpStr) -} - -func TestVerbs(t *testing.T) { - c := testRESTClient(t, nil) - if r := c.Post(); r.verb != "POST" { - t.Errorf("Post verb is wrong") - } - if r := c.Put(); r.verb != "PUT" { - t.Errorf("Put verb is wrong") - } - if r := c.Get(); r.verb != "GET" { - t.Errorf("Get verb is wrong") - } - if r := c.Delete(); r.verb != "DELETE" { - t.Errorf("Delete verb is wrong") - } -} - -func TestAbsPath(t *testing.T) { - for i, tc := range []struct { - configPrefix string - resourcePrefix string - absPath string - wantsAbsPath string - }{ - {"/", "", "", "/"}, - {"", "", "/", "/"}, - {"", "", "/api", "/api"}, - {"", "", "/api/", "/api/"}, - {"", "", "/apis", "/apis"}, - {"", "/foo", "/bar/foo", "/bar/foo"}, - {"", "/api/foo/123", "/bar/foo", "/bar/foo"}, - {"/p1", "", "", "/p1"}, - {"/p1", "", "/", "/p1/"}, - {"/p1", "", "/api", "/p1/api"}, - {"/p1", "", "/apis", "/p1/apis"}, - {"/p1", "/r1", "/apis", "/p1/apis"}, - {"/p1", "/api/r1", "/apis", "/p1/apis"}, - {"/p1/api/p2", "", "", "/p1/api/p2"}, - {"/p1/api/p2", "", "/", "/p1/api/p2/"}, - {"/p1/api/p2", "", "/api", "/p1/api/p2/api"}, - {"/p1/api/p2", "", "/api/", "/p1/api/p2/api/"}, - {"/p1/api/p2", "/r1", "/api/", "/p1/api/p2/api/"}, - {"/p1/api/p2", "/api/r1", "/api/", "/p1/api/p2/api/"}, - } { - u, _ := url.Parse("http://localhost:123" + tc.configPrefix) - r := NewRequest(nil, "POST", u, "", ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "test"}}, Serializers{}, nil, nil).Prefix(tc.resourcePrefix).AbsPath(tc.absPath) - if r.pathPrefix != tc.wantsAbsPath { - t.Errorf("test case %d failed, unexpected path: %q, expected %q", i, r.pathPrefix, tc.wantsAbsPath) - } - } -} - -func TestUintParam(t *testing.T) { - table := []struct { - name string - testVal uint64 - expectStr string - }{ - {"foo", 31415, "http://localhost?foo=31415"}, - {"bar", 42, "http://localhost?bar=42"}, - {"baz", 0, "http://localhost?baz=0"}, - } - - for _, item := range table { - u, _ := url.Parse("http://localhost") - r := NewRequest(nil, "GET", u, "", ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "test"}}, Serializers{}, nil, nil).AbsPath("").UintParam(item.name, item.testVal) - if e, a := item.expectStr, r.URL().String(); e != a { - t.Errorf("expected %v, got %v", e, a) - } - } -} - -func TestUnacceptableParamNames(t *testing.T) { - table := []struct { - name string - testVal string - expectSuccess bool - }{ - {"timeout", "42", false}, - } - - for _, item := range table { - c := testRESTClient(t, nil) - r := c.Get().setParam(item.name, item.testVal) - if e, a := item.expectSuccess, r.err == nil; e != a { - t.Errorf("expected %v, got %v (%v)", e, a, r.err) - } - } -} - -func TestBody(t *testing.T) { - const data = "test payload" - - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - bodyExpected, _ := runtime.Encode(testapi.Default.Codec(), obj) - - f, err := ioutil.TempFile("", "test_body") - if err != nil { - t.Fatalf("TempFile error: %v", err) - } - if _, err := f.WriteString(data); err != nil { - t.Fatalf("TempFile.WriteString error: %v", err) - } - f.Close() - - var nilObject *api.DeleteOptions - typedObject := interface{}(nilObject) - c := testRESTClient(t, nil) - tests := []struct { - input interface{} - expected string - headers map[string]string - }{ - {[]byte(data), data, nil}, - {f.Name(), data, nil}, - {strings.NewReader(data), data, nil}, - {obj, string(bodyExpected), map[string]string{"Content-Type": "application/json"}}, - {typedObject, "", nil}, - } - for i, tt := range tests { - r := c.Post().Body(tt.input) - if r.err != nil { - t.Errorf("%d: r.Body(%#v) error: %v", i, tt, r.err) - continue - } - if tt.headers != nil { - for k, v := range tt.headers { - if r.headers.Get(k) != v { - t.Errorf("%d: r.headers[%q] = %q; want %q", i, k, v, v) - } - } - } - - if r.body == nil { - if len(tt.expected) != 0 { - t.Errorf("%d: r.body = %q; want %q", i, r.body, tt.expected) - } - continue - } - buf := make([]byte, len(tt.expected)) - if _, err := r.body.Read(buf); err != nil { - t.Errorf("%d: r.body.Read error: %v", i, err) - continue - } - body := string(buf) - if body != tt.expected { - t.Errorf("%d: r.body = %q; want %q", i, body, tt.expected) - } - } -} - -func TestWatch(t *testing.T) { - var table = []struct { - t watch.EventType - obj runtime.Object - }{ - {watch.Added, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "first"}}}, - {watch.Modified, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "second"}}}, - {watch.Deleted, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "last"}}}, - } - - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - flusher, ok := w.(http.Flusher) - if !ok { - panic("need flusher!") - } - - w.Header().Set("Transfer-Encoding", "chunked") - w.WriteHeader(http.StatusOK) - flusher.Flush() - - encoder := versioned.NewEncoder(streaming.NewEncoder(w, testapi.Default.Codec()), testapi.Default.Codec()) - for _, item := range table { - if err := encoder.Encode(&watch.Event{Type: item.t, Object: item.obj}); err != nil { - panic(err) - } - flusher.Flush() - } - })) - defer testServer.Close() - - s := testRESTClient(t, testServer) - watching, err := s.Get().Prefix("path/to/watch/thing").Watch() - if err != nil { - t.Fatalf("Unexpected error") - } - - for _, item := range table { - got, ok := <-watching.ResultChan() - if !ok { - t.Fatalf("Unexpected early close") - } - if e, a := item.t, got.Type; e != a { - t.Errorf("Expected %v, got %v", e, a) - } - if e, a := item.obj, got.Object; !api.Semantic.DeepDerivative(e, a) { - t.Errorf("Expected %v, got %v", e, a) - } - } - - _, ok := <-watching.ResultChan() - if ok { - t.Fatal("Unexpected non-close") - } -} - -func TestStream(t *testing.T) { - expectedBody := "expected body" - - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - flusher, ok := w.(http.Flusher) - if !ok { - panic("need flusher!") - } - w.Header().Set("Transfer-Encoding", "chunked") - w.WriteHeader(http.StatusOK) - w.Write([]byte(expectedBody)) - flusher.Flush() - })) - defer testServer.Close() - - s := testRESTClient(t, testServer) - readCloser, err := s.Get().Prefix("path/to/stream/thing").Stream() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - defer readCloser.Close() - buf := new(bytes.Buffer) - buf.ReadFrom(readCloser) - resultBody := buf.String() - - if expectedBody != resultBody { - t.Errorf("Expected %s, got %s", expectedBody, resultBody) - } -} - -func testRESTClient(t testing.TB, srv *httptest.Server) *RESTClient { - baseURL, _ := url.Parse("http://localhost") - if srv != nil { - var err error - baseURL, err = url.Parse(srv.URL) - if err != nil { - t.Fatalf("failed to parse test URL: %v", err) - } - } - versionedAPIPath := testapi.Default.ResourcePath("", "", "") - client, err := NewRESTClient(baseURL, versionedAPIPath, defaultContentConfig(), 0, 0, nil, nil) - if err != nil { - t.Fatalf("failed to create a client: %v", err) - } - return client -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/url_utils_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/url_utils_test.go deleted file mode 100644 index 4bf8c5423..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/url_utils_test.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 restclient - -import ( - "path" - "testing" - - "k8s.io/kubernetes/pkg/api/testapi" -) - -func TestValidatesHostParameter(t *testing.T) { - testCases := []struct { - Host string - APIPath string - - URL string - Err bool - }{ - {"127.0.0.1", "", "http://127.0.0.1/" + testapi.Default.GroupVersion().Version, false}, - {"127.0.0.1:8080", "", "http://127.0.0.1:8080/" + testapi.Default.GroupVersion().Version, false}, - {"foo.bar.com", "", "http://foo.bar.com/" + testapi.Default.GroupVersion().Version, false}, - {"http://host/prefix", "", "http://host/prefix/" + testapi.Default.GroupVersion().Version, false}, - {"http://host", "", "http://host/" + testapi.Default.GroupVersion().Version, false}, - {"http://host", "/", "http://host/" + testapi.Default.GroupVersion().Version, false}, - {"http://host", "/other", "http://host/other/" + testapi.Default.GroupVersion().Version, false}, - {"host/server", "", "", true}, - } - for i, testCase := range testCases { - u, versionedAPIPath, err := DefaultServerURL(testCase.Host, testCase.APIPath, *testapi.Default.GroupVersion(), false) - switch { - case err == nil && testCase.Err: - t.Errorf("expected error but was nil") - continue - case err != nil && !testCase.Err: - t.Errorf("unexpected error %v", err) - continue - case err != nil: - continue - } - u.Path = path.Join(u.Path, versionedAPIPath) - if e, a := testCase.URL, u.String(); e != a { - t.Errorf("%d: expected host %s, got %s", i, e, a) - continue - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/urlbackoff_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/urlbackoff_test.go deleted file mode 100644 index 5b370dbe5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/restclient/urlbackoff_test.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 restclient - -import ( - "net/url" - "testing" - "time" - - "k8s.io/kubernetes/pkg/util/flowcontrol" -) - -func parse(raw string) *url.URL { - theUrl, _ := url.Parse(raw) - return theUrl -} - -func TestURLBackoffFunctionalityCollisions(t *testing.T) { - myBackoff := &URLBackoff{ - Backoff: flowcontrol.NewBackOff(1*time.Second, 60*time.Second), - } - - // Add some noise and make sure backoff for a clean URL is zero. - myBackoff.UpdateBackoff(parse("http://100.200.300.400:8080"), nil, 500) - - myBackoff.UpdateBackoff(parse("http://1.2.3.4:8080"), nil, 500) - - if myBackoff.CalculateBackoff(parse("http://1.2.3.4:100")) > 0 { - t.Errorf("URLs are colliding in the backoff map!") - } -} - -// TestURLBackoffFunctionality generally tests the URLBackoff wrapper. We avoid duplicating tests from backoff and request. -func TestURLBackoffFunctionality(t *testing.T) { - myBackoff := &URLBackoff{ - Backoff: flowcontrol.NewBackOff(1*time.Second, 60*time.Second), - } - - // Now test that backoff increases, then recovers. - // 200 and 300 should both result in clearing the backoff. - // all others like 429 should result in increased backoff. - seconds := []int{0, - 1, 2, 4, 8, 0, - 1, 2} - returnCodes := []int{ - 429, 500, 501, 502, 300, - 500, 501, 502, - } - - if len(seconds) != len(returnCodes) { - t.Fatalf("responseCode to backoff arrays should be the same length... sanity check failed.") - } - - for i, sec := range seconds { - backoffSec := myBackoff.CalculateBackoff(parse("http://1.2.3.4:100")) - if backoffSec < time.Duration(sec)*time.Second || backoffSec > time.Duration(sec+5)*time.Second { - t.Errorf("Backoff out of range %v: %v %v", i, sec, backoffSec) - } - myBackoff.UpdateBackoff(parse("http://1.2.3.4:100/responseCodeForFuncTest"), nil, returnCodes[i]) - } - - if myBackoff.CalculateBackoff(parse("http://1.2.3.4:100")) == 0 { - t.Errorf("The final return code %v should have resulted in a backoff ! ", returnCodes[7]) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/cache_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/cache_test.go deleted file mode 100644 index 8a602c147..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/cache_test.go +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 transport - -import ( - "net/http" - "testing" -) - -func TestTLSConfigKey(t *testing.T) { - // Make sure config fields that don't affect the tls config don't affect the cache key - identicalConfigurations := map[string]*Config{ - "empty": {}, - "basic": {Username: "bob", Password: "password"}, - "bearer": {BearerToken: "token"}, - "user agent": {UserAgent: "useragent"}, - "transport": {Transport: http.DefaultTransport}, - "wrap transport": {WrapTransport: func(http.RoundTripper) http.RoundTripper { return nil }}, - } - for nameA, valueA := range identicalConfigurations { - for nameB, valueB := range identicalConfigurations { - keyA, err := tlsConfigKey(valueA) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameA, err) - continue - } - keyB, err := tlsConfigKey(valueB) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameB, err) - continue - } - if keyA != keyB { - t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB) - continue - } - } - } - - // Make sure config fields that affect the tls config affect the cache key - uniqueConfigurations := map[string]*Config{ - "no tls": {}, - "insecure": {TLS: TLSConfig{Insecure: true}}, - "cadata 1": {TLS: TLSConfig{CAData: []byte{1}}}, - "cadata 2": {TLS: TLSConfig{CAData: []byte{2}}}, - "cert 1, key 1": { - TLS: TLSConfig{ - CertData: []byte{1}, - KeyData: []byte{1}, - }, - }, - "cert 1, key 2": { - TLS: TLSConfig{ - CertData: []byte{1}, - KeyData: []byte{2}, - }, - }, - "cert 2, key 1": { - TLS: TLSConfig{ - CertData: []byte{2}, - KeyData: []byte{1}, - }, - }, - "cert 2, key 2": { - TLS: TLSConfig{ - CertData: []byte{2}, - KeyData: []byte{2}, - }, - }, - "cadata 1, cert 1, key 1": { - TLS: TLSConfig{ - CAData: []byte{1}, - CertData: []byte{1}, - KeyData: []byte{1}, - }, - }, - } - for nameA, valueA := range uniqueConfigurations { - for nameB, valueB := range uniqueConfigurations { - // Don't compare to ourselves - if nameA == nameB { - continue - } - - keyA, err := tlsConfigKey(valueA) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameA, err) - continue - } - keyB, err := tlsConfigKey(valueB) - if err != nil { - t.Errorf("Unexpected error for %q: %v", nameB, err) - continue - } - if keyA == keyB { - t.Errorf("Expected unique cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB) - continue - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/round_trippers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/round_trippers_test.go deleted file mode 100644 index 6e8e52f7d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/round_trippers_test.go +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 transport - -import ( - "net/http" - "testing" -) - -type testRoundTripper struct { - Request *http.Request - Response *http.Response - Err error -} - -func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - rt.Request = req - return rt.Response, rt.Err -} - -func TestBearerAuthRoundTripper(t *testing.T) { - rt := &testRoundTripper{} - req := &http.Request{} - NewBearerAuthRoundTripper("test", rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("unexpected nil request: %v", rt) - } - if rt.Request == req { - t.Fatalf("round tripper should have copied request object: %#v", rt.Request) - } - if rt.Request.Header.Get("Authorization") != "Bearer test" { - t.Errorf("unexpected authorization header: %#v", rt.Request) - } -} - -func TestBasicAuthRoundTripper(t *testing.T) { - for n, tc := range map[string]struct { - user string - pass string - }{ - "basic": {user: "user", pass: "pass"}, - "no pass": {user: "user"}, - } { - rt := &testRoundTripper{} - req := &http.Request{} - NewBasicAuthRoundTripper(tc.user, tc.pass, rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("%s: unexpected nil request: %v", n, rt) - } - if rt.Request == req { - t.Fatalf("%s: round tripper should have copied request object: %#v", n, rt.Request) - } - if user, pass, found := rt.Request.BasicAuth(); !found || user != tc.user || pass != tc.pass { - t.Errorf("%s: unexpected authorization header: %#v", n, rt.Request) - } - } -} - -func TestUserAgentRoundTripper(t *testing.T) { - rt := &testRoundTripper{} - req := &http.Request{ - Header: make(http.Header), - } - req.Header.Set("User-Agent", "other") - NewUserAgentRoundTripper("test", rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("unexpected nil request: %v", rt) - } - if rt.Request != req { - t.Fatalf("round tripper should not have copied request object: %#v", rt.Request) - } - if rt.Request.Header.Get("User-Agent") != "other" { - t.Errorf("unexpected user agent header: %#v", rt.Request) - } - - req = &http.Request{} - NewUserAgentRoundTripper("test", rt).RoundTrip(req) - if rt.Request == nil { - t.Fatalf("unexpected nil request: %v", rt) - } - if rt.Request == req { - t.Fatalf("round tripper should have copied request object: %#v", rt.Request) - } - if rt.Request.Header.Get("User-Agent") != "test" { - t.Errorf("unexpected user agent header: %#v", rt.Request) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/transport_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/transport_test.go deleted file mode 100644 index ca04172d2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/transport/transport_test.go +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 transport - -import ( - "net/http" - "testing" -) - -const ( - rootCACert = `-----BEGIN CERTIFICATE----- -MIIC4DCCAcqgAwIBAgIBATALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu -MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIxNTczN1oXDTE2MDExNTIxNTcz -OFowIzEhMB8GA1UEAwwYMTAuMTMuMTI5LjEwNkAxNDIxMzU5MDU4MIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunDRXGwsiYWGFDlWH6kjGun+PshDGeZX -xtx9lUnL8pIRWH3wX6f13PO9sktaOWW0T0mlo6k2bMlSLlSZgG9H6og0W6gLS3vq -s4VavZ6DbXIwemZG2vbRwsvR+t4G6Nbwelm6F8RFnA1Fwt428pavmNQ/wgYzo+T1 -1eS+HiN4ACnSoDSx3QRWcgBkB1g6VReofVjx63i0J+w8Q/41L9GUuLqquFxu6ZnH -60vTB55lHgFiDLjA1FkEz2dGvGh/wtnFlRvjaPC54JH2K1mPYAUXTreoeJtLJKX0 -ycoiyB24+zGCniUmgIsmQWRPaOPircexCp1BOeze82BT1LCZNTVaxQIDAQABoyMw -ITAOBgNVHQ8BAf8EBAMCAKQwDwYDVR0TAQH/BAUwAwEB/zALBgkqhkiG9w0BAQsD -ggEBADMxsUuAFlsYDpF4fRCzXXwrhbtj4oQwcHpbu+rnOPHCZupiafzZpDu+rw4x -YGPnCb594bRTQn4pAu3Ac18NbLD5pV3uioAkv8oPkgr8aUhXqiv7KdDiaWm6sbAL -EHiXVBBAFvQws10HMqMoKtO8f1XDNAUkWduakR/U6yMgvOPwS7xl0eUTqyRB6zGb -K55q2dejiFWaFqB/y78txzvz6UlOZKE44g2JAVoJVM6kGaxh33q8/FmrL4kuN3ut -W+MmJCVDvd4eEqPwbp7146ZWTqpIJ8lvA6wuChtqV8lhAPka2hD/LMqY8iXNmfXD -uml0obOEy+ON91k+SWTJ3ggmF/U= ------END CERTIFICATE-----` - - certData = `-----BEGIN CERTIFICATE----- -MIIC6jCCAdSgAwIBAgIBCzALBgkqhkiG9w0BAQswIzEhMB8GA1UEAwwYMTAuMTMu -MTI5LjEwNkAxNDIxMzU5MDU4MB4XDTE1MDExNTIyMDEzMVoXDTE2MDExNTIyMDEz -MlowGzEZMBcGA1UEAxMQb3BlbnNoaWZ0LWNsaWVudDCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKtdhz0+uCLXw5cSYns9rU/XifFSpb/x24WDdrm72S/v -b9BPYsAStiP148buylr1SOuNi8sTAZmlVDDIpIVwMLff+o2rKYDicn9fjbrTxTOj -lI4pHJBH+JU3AJ0tbajupioh70jwFS0oYpwtneg2zcnE2Z4l6mhrj2okrc5Q1/X2 -I2HChtIU4JYTisObtin10QKJX01CLfYXJLa8upWzKZ4/GOcHG+eAV3jXWoXidtjb -1Usw70amoTZ6mIVCkiu1QwCoa8+ycojGfZhvqMsAp1536ZcCul+Na+AbCv4zKS7F -kQQaImVrXdUiFansIoofGlw/JNuoKK6ssVpS5Ic3pgcCAwEAAaM1MDMwDgYDVR0P -AQH/BAQDAgCgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCwYJ -KoZIhvcNAQELA4IBAQCKLREH7bXtXtZ+8vI6cjD7W3QikiArGqbl36bAhhWsJLp/ -p/ndKz39iFNaiZ3GlwIURWOOKx3y3GA0x9m8FR+Llthf0EQ8sUjnwaknWs0Y6DQ3 -jjPFZOpV3KPCFrdMJ3++E3MgwFC/Ih/N2ebFX9EcV9Vcc6oVWMdwT0fsrhu683rq -6GSR/3iVX1G/pmOiuaR0fNUaCyCfYrnI4zHBDgSfnlm3vIvN2lrsR/DQBakNL8DJ -HBgKxMGeUPoneBv+c8DMXIL0EhaFXRlBv9QW45/GiAIOuyFJ0i6hCtGZpJjq4OpQ -BRjCI+izPzFTjsxD4aORE+WOkyWFCGPWKfNejfw0 ------END CERTIFICATE-----` - - keyData = `-----BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAq12HPT64ItfDlxJiez2tT9eJ8VKlv/HbhYN2ubvZL+9v0E9i -wBK2I/Xjxu7KWvVI642LyxMBmaVUMMikhXAwt9/6jaspgOJyf1+NutPFM6OUjikc -kEf4lTcAnS1tqO6mKiHvSPAVLShinC2d6DbNycTZniXqaGuPaiStzlDX9fYjYcKG -0hTglhOKw5u2KfXRAolfTUIt9hcktry6lbMpnj8Y5wcb54BXeNdaheJ22NvVSzDv -RqahNnqYhUKSK7VDAKhrz7JyiMZ9mG+oywCnXnfplwK6X41r4BsK/jMpLsWRBBoi -ZWtd1SIVqewiih8aXD8k26gorqyxWlLkhzemBwIDAQABAoIBAD2XYRs3JrGHQUpU -FkdbVKZkvrSY0vAZOqBTLuH0zUv4UATb8487anGkWBjRDLQCgxH+jucPTrztekQK -aW94clo0S3aNtV4YhbSYIHWs1a0It0UdK6ID7CmdWkAj6s0T8W8lQT7C46mWYVLm -5mFnCTHi6aB42jZrqmEpC7sivWwuU0xqj3Ml8kkxQCGmyc9JjmCB4OrFFC8NNt6M -ObvQkUI6Z3nO4phTbpxkE1/9dT0MmPIF7GhHVzJMS+EyyRYUDllZ0wvVSOM3qZT0 -JMUaBerkNwm9foKJ1+dv2nMKZZbJajv7suUDCfU44mVeaEO+4kmTKSGCGjjTBGkr -7L1ySDECgYEA5ElIMhpdBzIivCuBIH8LlUeuzd93pqssO1G2Xg0jHtfM4tz7fyeI -cr90dc8gpli24dkSxzLeg3Tn3wIj/Bu64m2TpZPZEIlukYvgdgArmRIPQVxerYey -OkrfTNkxU1HXsYjLCdGcGXs5lmb+K/kuTcFxaMOs7jZi7La+jEONwf8CgYEAwCs/ -rUOOA0klDsWWisbivOiNPII79c9McZCNBqncCBfMUoiGe8uWDEO4TFHN60vFuVk9 -8PkwpCfvaBUX+ajvbafIfHxsnfk1M04WLGCeqQ/ym5Q4sQoQOcC1b1y9qc/xEWfg -nIUuia0ukYRpl7qQa3tNg+BNFyjypW8zukUAC/kCgYB1/Kojuxx5q5/oQVPrx73k -2bevD+B3c+DYh9MJqSCNwFtUpYIWpggPxoQan4LwdsmO0PKzocb/ilyNFj4i/vII -NToqSc/WjDFpaDIKyuu9oWfhECye45NqLWhb/6VOuu4QA/Nsj7luMhIBehnEAHW+ -GkzTKM8oD1PxpEG3nPKXYQKBgQC6AuMPRt3XBl1NkCrpSBy/uObFlFaP2Enpf39S -3OZ0Gv0XQrnSaL1kP8TMcz68rMrGX8DaWYsgytstR4W+jyy7WvZwsUu+GjTJ5aMG -77uEcEBpIi9CBzivfn7hPccE8ZgqPf+n4i6q66yxBJflW5xhvafJqDtW2LcPNbW/ -bvzdmQKBgExALRUXpq+5dbmkdXBHtvXdRDZ6rVmrnjy4nI5bPw+1GqQqk6uAR6B/ -F6NmLCQOO4PDG/cuatNHIr2FrwTmGdEL6ObLUGWn9Oer9gJhHVqqsY5I4sEPo4XX -stR0Yiw0buV6DL/moUO0HIM9Bjh96HJp+LxiIS6UCdIhMPp5HoQa ------END RSA PRIVATE KEY-----` -) - -func TestNew(t *testing.T) { - testCases := map[string]struct { - Config *Config - Err bool - TLS bool - Default bool - }{ - "default transport": { - Default: true, - Config: &Config{}, - }, - - "ca transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - }, - }, - }, - "bad ca file transport": { - Err: true, - Config: &Config{ - TLS: TLSConfig{ - CAFile: "invalid file", - }, - }, - }, - "ca data overriding bad ca file transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CAFile: "invalid file", - }, - }, - }, - - "cert transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyData: []byte(keyData), - }, - }, - }, - "bad cert data transport": { - Err: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyData: []byte("bad key data"), - }, - }, - }, - "bad file cert transport": { - Err: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyFile: "invalid file", - }, - }, - }, - "key data overriding bad file cert transport": { - TLS: true, - Config: &Config{ - TLS: TLSConfig{ - CAData: []byte(rootCACert), - CertData: []byte(certData), - KeyData: []byte(keyData), - KeyFile: "invalid file", - }, - }, - }, - } - for k, testCase := range testCases { - transport, err := New(testCase.Config) - switch { - case testCase.Err && err == nil: - t.Errorf("%s: unexpected non-error", k) - continue - case !testCase.Err && err != nil: - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - - switch { - case testCase.Default && transport != http.DefaultTransport: - t.Errorf("%s: expected the default transport, got %#v", k, transport) - continue - case !testCase.Default && transport == http.DefaultTransport: - t.Errorf("%s: expected non-default transport, got %#v", k, transport) - continue - } - - // We only know how to check TLSConfig on http.Transports - if transport, ok := transport.(*http.Transport); ok { - switch { - case testCase.TLS && transport.TLSClientConfig == nil: - t.Errorf("%s: expected TLSClientConfig, got %#v", k, transport) - continue - case !testCase.TLS && transport.TLSClientConfig != nil: - t.Errorf("%s: expected no TLSClientConfig, got %#v", k, transport) - continue - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/typed/discovery/client_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/typed/discovery/client_test.go deleted file mode 100644 index 674b92f0f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/typed/discovery/client_test.go +++ /dev/null @@ -1,303 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 discovery - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "reflect" - "testing" - - "github.com/emicklei/go-restful/swagger" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/version" -) - -func TestGetServerVersion(t *testing.T) { - expect := version.Info{ - Major: "foo", - Minor: "bar", - GitCommit: "baz", - } - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - output, err := json.Marshal(expect) - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - return - } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(output) - })) - defer server.Close() - client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) - - got, err := client.ServerVersion() - if err != nil { - t.Fatalf("unexpected encoding error: %v", err) - } - if e, a := expect, *got; !reflect.DeepEqual(e, a) { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetServerGroupsWithV1Server(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var obj interface{} - switch req.URL.Path { - case "/api": - obj = &unversioned.APIVersions{ - Versions: []string{ - "v1", - }, - } - default: - w.WriteHeader(http.StatusNotFound) - return - } - output, err := json.Marshal(obj) - if err != nil { - t.Fatalf("unexpected encoding error: %v", err) - return - } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(output) - })) - defer server.Close() - client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) - // ServerGroups should not return an error even if server returns error at /api and /apis - apiGroupList, err := client.ServerGroups() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - groupVersions := unversioned.ExtractGroupVersions(apiGroupList) - if !reflect.DeepEqual(groupVersions, []string{"v1"}) { - t.Errorf("expected: %q, got: %q", []string{"v1"}, groupVersions) - } -} - -func TestGetServerResourcesWithV1Server(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var obj interface{} - switch req.URL.Path { - case "/api": - obj = &unversioned.APIVersions{ - Versions: []string{ - "v1", - }, - } - default: - w.WriteHeader(http.StatusNotFound) - return - } - output, err := json.Marshal(obj) - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - return - } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(output) - })) - defer server.Close() - client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) - // ServerResources should not return an error even if server returns error at /api/v1. - resourceMap, err := client.ServerResources() - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if _, found := resourceMap["v1"]; !found { - t.Errorf("missing v1 in resource map") - } - -} - -func TestGetServerResources(t *testing.T) { - stable := unversioned.APIResourceList{ - GroupVersion: "v1", - APIResources: []unversioned.APIResource{ - {"pods", true, "Pod"}, - {"services", true, "Service"}, - {"namespaces", false, "Namespace"}, - }, - } - beta := unversioned.APIResourceList{ - GroupVersion: "extensions/v1", - APIResources: []unversioned.APIResource{ - {"deployments", true, "Deployment"}, - {"ingresses", true, "Ingress"}, - {"jobs", true, "Job"}, - }, - } - tests := []struct { - resourcesList *unversioned.APIResourceList - path string - request string - expectErr bool - }{ - { - resourcesList: &stable, - path: "/api/v1", - request: "v1", - expectErr: false, - }, - { - resourcesList: &beta, - path: "/apis/extensions/v1beta1", - request: "extensions/v1beta1", - expectErr: false, - }, - { - resourcesList: &stable, - path: "/api/v1", - request: "foobar", - expectErr: true, - }, - } - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var list interface{} - switch req.URL.Path { - case "/api/v1": - list = &stable - case "/apis/extensions/v1beta1": - list = &beta - case "/api": - list = &unversioned.APIVersions{ - Versions: []string{ - "v1", - }, - } - case "/apis": - list = &unversioned.APIGroupList{ - Groups: []unversioned.APIGroup{ - { - Versions: []unversioned.GroupVersionForDiscovery{ - {GroupVersion: "extensions/v1beta1"}, - }, - }, - }, - } - default: - t.Logf("unexpected request: %s", req.URL.Path) - w.WriteHeader(http.StatusNotFound) - return - } - output, err := json.Marshal(list) - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - return - } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(output) - })) - defer server.Close() - client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) - for _, test := range tests { - got, err := client.ServerResourcesForGroupVersion(test.request) - if test.expectErr { - if err == nil { - t.Error("unexpected non-error") - } - continue - } - if err != nil { - t.Errorf("unexpected error: %v", err) - continue - } - if !reflect.DeepEqual(got, test.resourcesList) { - t.Errorf("expected:\n%v\ngot:\n%v\n", test.resourcesList, got) - } - } - - resourceMap, err := client.ServerResources() - if err != nil { - t.Errorf("unexpected error: %v", err) - } - for _, api := range []string{"v1", "extensions/v1beta1"} { - if _, found := resourceMap[api]; !found { - t.Errorf("missing expected api: %s", api) - } - } -} - -func swaggerSchemaFakeServer() (*httptest.Server, error) { - request := 1 - var sErr error - - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var resp interface{} - if request == 1 { - resp = unversioned.APIVersions{Versions: []string{"v1", "v2", "v3"}} - request++ - } else { - resp = swagger.ApiDeclaration{} - } - output, err := json.Marshal(resp) - if err != nil { - sErr = err - return - } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(output) - })) - return server, sErr -} - -func TestGetSwaggerSchema(t *testing.T) { - expect := swagger.ApiDeclaration{} - - server, err := swaggerSchemaFakeServer() - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - } - defer server.Close() - - client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) - got, err := client.SwaggerSchema(v1.SchemeGroupVersion) - if err != nil { - t.Fatalf("unexpected encoding error: %v", err) - } - if e, a := expect, *got; !reflect.DeepEqual(e, a) { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestGetSwaggerSchemaFail(t *testing.T) { - expErr := "API version: api.group/v4 is not supported by the server. Use one of: [v1 v2 v3]" - - server, err := swaggerSchemaFakeServer() - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - } - defer server.Close() - - client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL}) - got, err := client.SwaggerSchema(unversioned.GroupVersion{Group: "api.group", Version: "v4"}) - if got != nil { - t.Fatalf("unexpected response: %v", got) - } - if err.Error() != expErr { - t.Errorf("expected an error, got %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/typed/discovery/fake/discovery.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/typed/discovery/fake/discovery.go deleted file mode 100644 index 0a2bb9af9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/typed/discovery/fake/discovery.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 fake - -import ( - "github.com/emicklei/go-restful/swagger" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/version" -) - -type FakeDiscovery struct { - *core.Fake -} - -func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*unversioned.APIResourceList, error) { - action := core.ActionImpl{ - Verb: "get", - Resource: unversioned.GroupVersionResource{Resource: "resource"}, - } - c.Invokes(action, nil) - return c.Resources[groupVersion], nil -} - -func (c *FakeDiscovery) ServerResources() (map[string]*unversioned.APIResourceList, error) { - action := core.ActionImpl{ - Verb: "get", - Resource: unversioned.GroupVersionResource{Resource: "resource"}, - } - c.Invokes(action, nil) - return c.Resources, nil -} - -func (c *FakeDiscovery) ServerGroups() (*unversioned.APIGroupList, error) { - return nil, nil -} - -func (c *FakeDiscovery) ServerVersion() (*version.Info, error) { - action := core.ActionImpl{} - action.Verb = "get" - action.Resource = unversioned.GroupVersionResource{Resource: "version"} - - c.Invokes(action, nil) - versionInfo := version.Get() - return &versionInfo, nil -} - -func (c *FakeDiscovery) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) { - action := core.ActionImpl{} - action.Verb = "get" - if version == v1.SchemeGroupVersion { - action.Resource = unversioned.GroupVersionResource{Resource: "/swaggerapi/api/" + version.Version} - } else { - action.Resource = unversioned.GroupVersionResource{Resource: "/swaggerapi/apis/" + version.Group + "/" + version.Version} - } - - c.Invokes(action, nil) - return &swagger.ApiDeclaration{}, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_2/clientset_adaption.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_2/clientset_adaption.go deleted file mode 100644 index 9e33ccd19..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_2/clientset_adaption.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 release_1_2 - -import ( - "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2" - v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2/typed/core/v1" - v1beta1extensions "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2/typed/extensions/v1beta1" - "k8s.io/kubernetes/pkg/client/typed/discovery" - "k8s.io/kubernetes/pkg/client/unversioned" -) - -// FromUnversionedClient adapts a unversioned.Client to a release_1_2.Clientset. -// This function is temporary. We will remove it when everyone has moved to using -// Clientset. New code should NOT use this function. -func FromUnversionedClient(c *unversioned.Client) *release_1_2.Clientset { - var clientset release_1_2.Clientset - if c != nil { - clientset.CoreClient = v1core.New(c.RESTClient) - } else { - clientset.CoreClient = v1core.New(nil) - } - if c != nil && c.ExtensionsClient != nil { - clientset.ExtensionsClient = v1beta1extensions.New(c.ExtensionsClient.RESTClient) - } else { - clientset.ExtensionsClient = v1beta1extensions.New(nil) - } - - if c != nil && c.DiscoveryClient != nil { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(c.DiscoveryClient.RESTClient) - } else { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(nil) - } - - return &clientset -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go deleted file mode 100644 index 3f4b86fb4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/adapters/release_1_3/clientset_adaption.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 release_1_3 - -import ( - "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3" - v1core "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3/typed/core/v1" - v1beta1extensions "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_3/typed/extensions/v1beta1" - "k8s.io/kubernetes/pkg/client/typed/discovery" - "k8s.io/kubernetes/pkg/client/unversioned" -) - -// FromUnversionedClient adapts a unversioned.Client to a release_1_3.Clientset. -// This function is temporary. We will remove it when everyone has moved to using -// Clientset. New code should NOT use this function. -func FromUnversionedClient(c *unversioned.Client) *release_1_3.Clientset { - var clientset release_1_3.Clientset - if c != nil { - clientset.CoreClient = v1core.New(c.RESTClient) - } else { - clientset.CoreClient = v1core.New(nil) - } - if c != nil && c.ExtensionsClient != nil { - clientset.ExtensionsClient = v1beta1extensions.New(c.ExtensionsClient.RESTClient) - } else { - clientset.ExtensionsClient = v1beta1extensions.New(nil) - } - - if c != nil && c.DiscoveryClient != nil { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(c.DiscoveryClient.RESTClient) - } else { - clientset.DiscoveryClient = discovery.NewDiscoveryClient(nil) - } - - return &clientset -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/auth/clientauth_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/auth/clientauth_test.go deleted file mode 100644 index a99c5d94a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/auth/clientauth_test.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 auth_test - -import ( - "io/ioutil" - "os" - "reflect" - "testing" - - clientauth "k8s.io/kubernetes/pkg/client/unversioned/auth" -) - -func TestLoadFromFile(t *testing.T) { - loadAuthInfoTests := []struct { - authData string - authInfo *clientauth.Info - expectErr bool - }{ - { - `{"user": "user", "password": "pass"}`, - &clientauth.Info{User: "user", Password: "pass"}, - false, - }, - { - "", nil, true, - }, - } - for _, loadAuthInfoTest := range loadAuthInfoTests { - tt := loadAuthInfoTest - aifile, err := ioutil.TempFile("", "testAuthInfo") - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if tt.authData != "missing" { - defer os.Remove(aifile.Name()) - defer aifile.Close() - _, err = aifile.WriteString(tt.authData) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - } else { - aifile.Close() - os.Remove(aifile.Name()) - } - authInfo, err := clientauth.LoadFromFile(aifile.Name()) - gotErr := err != nil - if gotErr != tt.expectErr { - t.Errorf("expected errorness: %v, actual errorness: %v", tt.expectErr, gotErr) - } - if !reflect.DeepEqual(authInfo, tt.authInfo) { - t.Errorf("Expected %v, got %v", tt.authInfo, authInfo) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/helpers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/helpers_test.go deleted file mode 100644 index 6952524c6..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/helpers_test.go +++ /dev/null @@ -1,301 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 api - -import ( - "fmt" - "io/ioutil" - "os" - "reflect" - "testing" - - "github.com/ghodss/yaml" -) - -func newMergedConfig(certFile, certContent, keyFile, keyContent, caFile, caContent string, t *testing.T) Config { - if err := ioutil.WriteFile(certFile, []byte(certContent), 0644); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := ioutil.WriteFile(keyFile, []byte(keyContent), 0600); err != nil { - t.Errorf("unexpected error: %v", err) - } - if err := ioutil.WriteFile(caFile, []byte(caContent), 0644); err != nil { - t.Errorf("unexpected error: %v", err) - } - - return Config{ - AuthInfos: map[string]*AuthInfo{ - "red-user": {Token: "red-token", ClientCertificateData: []byte(certContent), ClientKeyData: []byte(keyContent)}, - "blue-user": {Token: "blue-token", ClientCertificate: certFile, ClientKey: keyFile}}, - Clusters: map[string]*Cluster{ - "cow-cluster": {Server: "http://cow.org:8080", CertificateAuthorityData: []byte(caContent)}, - "chicken-cluster": {Server: "http://chicken.org:8080", CertificateAuthority: caFile}}, - Contexts: map[string]*Context{ - "federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"}, - "shaker-context": {AuthInfo: "blue-user", Cluster: "chicken-cluster"}}, - CurrentContext: "federal-context", - } -} - -func TestMinifySuccess(t *testing.T) { - certFile, _ := ioutil.TempFile("", "") - defer os.Remove(certFile.Name()) - keyFile, _ := ioutil.TempFile("", "") - defer os.Remove(keyFile.Name()) - caFile, _ := ioutil.TempFile("", "") - defer os.Remove(caFile.Name()) - - mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t) - - if err := MinifyConfig(&mutatingConfig); err != nil { - t.Errorf("unexpected error: %v", err) - } - - if len(mutatingConfig.Contexts) > 1 { - t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts) - } - if _, exists := mutatingConfig.Contexts["federal-context"]; !exists { - t.Errorf("missing context") - } - - if len(mutatingConfig.Clusters) > 1 { - t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters) - } - if _, exists := mutatingConfig.Clusters["cow-cluster"]; !exists { - t.Errorf("missing cluster") - } - - if len(mutatingConfig.AuthInfos) > 1 { - t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos) - } - if _, exists := mutatingConfig.AuthInfos["red-user"]; !exists { - t.Errorf("missing user") - } -} - -func TestMinifyMissingContext(t *testing.T) { - certFile, _ := ioutil.TempFile("", "") - defer os.Remove(certFile.Name()) - keyFile, _ := ioutil.TempFile("", "") - defer os.Remove(keyFile.Name()) - caFile, _ := ioutil.TempFile("", "") - defer os.Remove(caFile.Name()) - - mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t) - mutatingConfig.CurrentContext = "missing" - - errMsg := "cannot locate context missing" - - if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg { - t.Errorf("expected %v, got %v", errMsg, err) - } -} - -func TestMinifyMissingCluster(t *testing.T) { - certFile, _ := ioutil.TempFile("", "") - defer os.Remove(certFile.Name()) - keyFile, _ := ioutil.TempFile("", "") - defer os.Remove(keyFile.Name()) - caFile, _ := ioutil.TempFile("", "") - defer os.Remove(caFile.Name()) - - mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t) - delete(mutatingConfig.Clusters, mutatingConfig.Contexts[mutatingConfig.CurrentContext].Cluster) - - errMsg := "cannot locate cluster cow-cluster" - - if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg { - t.Errorf("expected %v, got %v", errMsg, err) - } -} - -func TestMinifyMissingAuthInfo(t *testing.T) { - certFile, _ := ioutil.TempFile("", "") - defer os.Remove(certFile.Name()) - keyFile, _ := ioutil.TempFile("", "") - defer os.Remove(keyFile.Name()) - caFile, _ := ioutil.TempFile("", "") - defer os.Remove(caFile.Name()) - - mutatingConfig := newMergedConfig(certFile.Name(), "cert", keyFile.Name(), "key", caFile.Name(), "ca", t) - delete(mutatingConfig.AuthInfos, mutatingConfig.Contexts[mutatingConfig.CurrentContext].AuthInfo) - - errMsg := "cannot locate user red-user" - - if err := MinifyConfig(&mutatingConfig); err == nil || err.Error() != errMsg { - t.Errorf("expected %v, got %v", errMsg, err) - } -} - -func TestFlattenSuccess(t *testing.T) { - certFile, _ := ioutil.TempFile("", "") - defer os.Remove(certFile.Name()) - keyFile, _ := ioutil.TempFile("", "") - defer os.Remove(keyFile.Name()) - caFile, _ := ioutil.TempFile("", "") - defer os.Remove(caFile.Name()) - - certData := "cert" - keyData := "key" - caData := "ca" - - unchangingCluster := "cow-cluster" - unchangingAuthInfo := "red-user" - changingCluster := "chicken-cluster" - changingAuthInfo := "blue-user" - - startingConfig := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, t) - mutatingConfig := startingConfig - - if err := FlattenConfig(&mutatingConfig); err != nil { - t.Errorf("unexpected error: %v", err) - } - - if len(mutatingConfig.Contexts) != 2 { - t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts) - } - if !reflect.DeepEqual(startingConfig.Contexts, mutatingConfig.Contexts) { - t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts) - } - - if len(mutatingConfig.Clusters) != 2 { - t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters) - } - if !reflect.DeepEqual(startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) { - t.Errorf("expected %v, got %v", startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) - } - if len(mutatingConfig.Clusters[changingCluster].CertificateAuthority) != 0 { - t.Errorf("unexpected caFile") - } - if string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData) != caData { - t.Errorf("expected %v, got %v", caData, string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData)) - } - - if len(mutatingConfig.AuthInfos) != 2 { - t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos) - } - if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) { - t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) - } - if len(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificate) != 0 { - t.Errorf("unexpected caFile") - } - if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != certData { - t.Errorf("expected %v, got %v", certData, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData)) - } - if len(mutatingConfig.AuthInfos[changingAuthInfo].ClientKey) != 0 { - t.Errorf("unexpected caFile") - } - if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != keyData { - t.Errorf("expected %v, got %v", keyData, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData)) - } - -} - -func Example_minifyAndShorten() { - certFile, _ := ioutil.TempFile("", "") - defer os.Remove(certFile.Name()) - keyFile, _ := ioutil.TempFile("", "") - defer os.Remove(keyFile.Name()) - caFile, _ := ioutil.TempFile("", "") - defer os.Remove(caFile.Name()) - - certData := "cert" - keyData := "key" - caData := "ca" - - config := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, nil) - - MinifyConfig(&config) - ShortenConfig(&config) - - output, _ := yaml.Marshal(config) - fmt.Printf("%s", string(output)) - // Output: - // clusters: - // cow-cluster: - // LocationOfOrigin: "" - // certificate-authority-data: REDACTED - // server: http://cow.org:8080 - // contexts: - // federal-context: - // LocationOfOrigin: "" - // cluster: cow-cluster - // user: red-user - // current-context: federal-context - // preferences: {} - // users: - // red-user: - // LocationOfOrigin: "" - // client-certificate-data: REDACTED - // client-key-data: REDACTED - // token: red-token -} - -func TestShortenSuccess(t *testing.T) { - certFile, _ := ioutil.TempFile("", "") - defer os.Remove(certFile.Name()) - keyFile, _ := ioutil.TempFile("", "") - defer os.Remove(keyFile.Name()) - caFile, _ := ioutil.TempFile("", "") - defer os.Remove(caFile.Name()) - - certData := "cert" - keyData := "key" - caData := "ca" - - unchangingCluster := "chicken-cluster" - unchangingAuthInfo := "blue-user" - changingCluster := "cow-cluster" - changingAuthInfo := "red-user" - - startingConfig := newMergedConfig(certFile.Name(), certData, keyFile.Name(), keyData, caFile.Name(), caData, t) - mutatingConfig := startingConfig - - ShortenConfig(&mutatingConfig) - - if len(mutatingConfig.Contexts) != 2 { - t.Errorf("unexpected contexts: %v", mutatingConfig.Contexts) - } - if !reflect.DeepEqual(startingConfig.Contexts, mutatingConfig.Contexts) { - t.Errorf("expected %v, got %v", startingConfig.Contexts, mutatingConfig.Contexts) - } - - redacted := string(redactedBytes) - if len(mutatingConfig.Clusters) != 2 { - t.Errorf("unexpected clusters: %v", mutatingConfig.Clusters) - } - if !reflect.DeepEqual(startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) { - t.Errorf("expected %v, got %v", startingConfig.Clusters[unchangingCluster], mutatingConfig.Clusters[unchangingCluster]) - } - if string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData) != redacted { - t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.Clusters[changingCluster].CertificateAuthorityData)) - } - - if len(mutatingConfig.AuthInfos) != 2 { - t.Errorf("unexpected users: %v", mutatingConfig.AuthInfos) - } - if !reflect.DeepEqual(startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) { - t.Errorf("expected %v, got %v", startingConfig.AuthInfos[unchangingAuthInfo], mutatingConfig.AuthInfos[unchangingAuthInfo]) - } - if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData) != redacted { - t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientCertificateData)) - } - if string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData) != redacted { - t.Errorf("expected %v, got %v", redacted, string(mutatingConfig.AuthInfos[changingAuthInfo].ClientKeyData)) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/types_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/types_test.go deleted file mode 100644 index 6c79728f4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/types_test.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 api - -import ( - "fmt" - - "github.com/ghodss/yaml" -) - -func Example_emptyConfig() { - defaultConfig := NewConfig() - - output, err := yaml.Marshal(defaultConfig) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - - fmt.Printf("%v", string(output)) - // Output: - // clusters: {} - // contexts: {} - // current-context: "" - // preferences: {} - // users: {} -} - -func Example_ofOptionsConfig() { - defaultConfig := NewConfig() - defaultConfig.Preferences.Colors = true - defaultConfig.Clusters["alfa"] = &Cluster{ - Server: "https://alfa.org:8080", - InsecureSkipTLSVerify: true, - CertificateAuthority: "path/to/my/cert-ca-filename", - } - defaultConfig.Clusters["bravo"] = &Cluster{ - Server: "https://bravo.org:8080", - InsecureSkipTLSVerify: false, - } - defaultConfig.AuthInfos["white-mage-via-cert"] = &AuthInfo{ - ClientCertificate: "path/to/my/client-cert-filename", - ClientKey: "path/to/my/client-key-filename", - } - defaultConfig.AuthInfos["red-mage-via-token"] = &AuthInfo{ - Token: "my-secret-token", - } - defaultConfig.AuthInfos["black-mage-via-auth-provider"] = &AuthInfo{ - AuthProvider: &AuthProviderConfig{ - Name: "gcp", - Config: map[string]string{ - "foo": "bar", - "token": "s3cr3t-t0k3n", - }, - }, - } - defaultConfig.Contexts["bravo-as-black-mage"] = &Context{ - Cluster: "bravo", - AuthInfo: "black-mage-via-auth-provider", - Namespace: "yankee", - } - defaultConfig.Contexts["alfa-as-black-mage"] = &Context{ - Cluster: "alfa", - AuthInfo: "black-mage-via-auth-provider", - Namespace: "zulu", - } - defaultConfig.Contexts["alfa-as-white-mage"] = &Context{ - Cluster: "alfa", - AuthInfo: "white-mage-via-cert", - } - defaultConfig.CurrentContext = "alfa-as-white-mage" - - output, err := yaml.Marshal(defaultConfig) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - - fmt.Printf("%v", string(output)) - // Output: - // clusters: - // alfa: - // LocationOfOrigin: "" - // certificate-authority: path/to/my/cert-ca-filename - // insecure-skip-tls-verify: true - // server: https://alfa.org:8080 - // bravo: - // LocationOfOrigin: "" - // server: https://bravo.org:8080 - // contexts: - // alfa-as-black-mage: - // LocationOfOrigin: "" - // cluster: alfa - // namespace: zulu - // user: black-mage-via-auth-provider - // alfa-as-white-mage: - // LocationOfOrigin: "" - // cluster: alfa - // user: white-mage-via-cert - // bravo-as-black-mage: - // LocationOfOrigin: "" - // cluster: bravo - // namespace: yankee - // user: black-mage-via-auth-provider - // current-context: alfa-as-white-mage - // preferences: - // colors: true - // users: - // black-mage-via-auth-provider: - // LocationOfOrigin: "" - // auth-provider: - // config: - // foo: bar - // token: s3cr3t-t0k3n - // name: gcp - // red-mage-via-token: - // LocationOfOrigin: "" - // token: my-secret-token - // white-mage-via-cert: - // LocationOfOrigin: "" - // client-certificate: path/to/my/client-cert-filename - // client-key: path/to/my/client-key-filename -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/client_config_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/client_config_test.go deleted file mode 100644 index 1e9b5b8b3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/client_config_test.go +++ /dev/null @@ -1,290 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 clientcmd - -import ( - "reflect" - "testing" - - "github.com/imdario/mergo" - "k8s.io/kubernetes/pkg/client/restclient" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" -) - -func TestOldMergoLib(t *testing.T) { - type T struct { - X string - } - dst := T{X: "one"} - src := T{X: "two"} - mergo.Merge(&dst, &src) - if dst.X != "two" { - // mergo.Merge changed in an incompatible way with - // - // https://github.com/imdario/mergo/commit/d304790b2ed594794496464fadd89d2bb266600a - // - // We have to stay with the old version which still does eager - // copying from src to dst in structs. - t.Errorf("mergo.Merge library found with incompatible, new behavior") - } -} - -func createValidTestConfig() *clientcmdapi.Config { - const ( - server = "https://anything.com:8080" - token = "the-token" - ) - - config := clientcmdapi.NewConfig() - config.Clusters["clean"] = &clientcmdapi.Cluster{ - Server: server, - } - config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ - Token: token, - } - config.Contexts["clean"] = &clientcmdapi.Context{ - Cluster: "clean", - AuthInfo: "clean", - } - config.CurrentContext = "clean" - - return config -} - -func createCAValidTestConfig() *clientcmdapi.Config { - - config := createValidTestConfig() - config.Clusters["clean"].CertificateAuthorityData = []byte{0, 0} - return config -} - -func TestInsecureOverridesCA(t *testing.T) { - config := createCAValidTestConfig() - clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{ - ClusterInfo: clientcmdapi.Cluster{ - InsecureSkipTLSVerify: true, - }, - }, nil) - - actualCfg, err := clientBuilder.ClientConfig() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - matchBoolArg(true, actualCfg.Insecure, t) - matchStringArg("", actualCfg.TLSClientConfig.CAFile, t) - matchByteArg(nil, actualCfg.TLSClientConfig.CAData, t) -} - -func TestMergeContext(t *testing.T) { - const namespace = "overriden-namespace" - - config := createValidTestConfig() - clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil) - - _, overridden, err := clientBuilder.Namespace() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if overridden { - t.Error("Expected namespace to not be overridden") - } - - clientBuilder = NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{ - Context: clientcmdapi.Context{ - Namespace: namespace, - }, - }, nil) - - actual, overridden, err := clientBuilder.Namespace() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if !overridden { - t.Error("Expected namespace to be overridden") - } - - matchStringArg(namespace, actual, t) -} - -func TestCertificateData(t *testing.T) { - caData := []byte("ca-data") - certData := []byte("cert-data") - keyData := []byte("key-data") - - config := clientcmdapi.NewConfig() - config.Clusters["clean"] = &clientcmdapi.Cluster{ - Server: "https://localhost:8443", - CertificateAuthorityData: caData, - } - config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ - ClientCertificateData: certData, - ClientKeyData: keyData, - } - config.Contexts["clean"] = &clientcmdapi.Context{ - Cluster: "clean", - AuthInfo: "clean", - } - config.CurrentContext = "clean" - - clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil) - - clientConfig, err := clientBuilder.ClientConfig() - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - // Make sure cert data gets into config (will override file paths) - matchByteArg(caData, clientConfig.TLSClientConfig.CAData, t) - matchByteArg(certData, clientConfig.TLSClientConfig.CertData, t) - matchByteArg(keyData, clientConfig.TLSClientConfig.KeyData, t) -} - -func TestBasicAuthData(t *testing.T) { - username := "myuser" - password := "mypass" - - config := clientcmdapi.NewConfig() - config.Clusters["clean"] = &clientcmdapi.Cluster{ - Server: "https://localhost:8443", - } - config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ - Username: username, - Password: password, - } - config.Contexts["clean"] = &clientcmdapi.Context{ - Cluster: "clean", - AuthInfo: "clean", - } - config.CurrentContext = "clean" - - clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil) - - clientConfig, err := clientBuilder.ClientConfig() - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - // Make sure basic auth data gets into config - matchStringArg(username, clientConfig.Username, t) - matchStringArg(password, clientConfig.Password, t) -} - -func TestCreateClean(t *testing.T) { - config := createValidTestConfig() - clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil) - - clientConfig, err := clientBuilder.ClientConfig() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - matchStringArg(config.Clusters["clean"].Server, clientConfig.Host, t) - matchStringArg("", clientConfig.APIPath, t) - matchBoolArg(config.Clusters["clean"].InsecureSkipTLSVerify, clientConfig.Insecure, t) - matchStringArg(config.AuthInfos["clean"].Token, clientConfig.BearerToken, t) -} - -func TestCreateCleanWithPrefix(t *testing.T) { - tt := []struct { - server string - host string - }{ - {"https://anything.com:8080/foo/bar", "https://anything.com:8080/foo/bar"}, - {"http://anything.com:8080/foo/bar", "http://anything.com:8080/foo/bar"}, - {"http://anything.com:8080/foo/bar/", "http://anything.com:8080/foo/bar/"}, - {"http://anything.com:8080/", "http://anything.com:8080/"}, - {"http://anything.com:8080//", "http://anything.com:8080//"}, - {"anything.com:8080/foo/bar", "anything.com:8080/foo/bar"}, - {"anything.com:8080", "anything.com:8080"}, - {"anything.com", "anything.com"}, - {"anything", "anything"}, - } - - // WARNING: EnvVarCluster.Server is set during package loading time and can not be overriden by os.Setenv inside this test - EnvVarCluster.Server = "" - tt = append(tt, struct{ server, host string }{"", "http://localhost:8080"}) - - for _, tc := range tt { - config := createValidTestConfig() - - cleanConfig := config.Clusters["clean"] - cleanConfig.Server = tc.server - config.Clusters["clean"] = cleanConfig - - clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{}, nil) - - clientConfig, err := clientBuilder.ClientConfig() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - matchStringArg(tc.host, clientConfig.Host, t) - } -} - -func TestCreateCleanDefault(t *testing.T) { - config := createValidTestConfig() - clientBuilder := NewDefaultClientConfig(*config, &ConfigOverrides{}) - - clientConfig, err := clientBuilder.ClientConfig() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - matchStringArg(config.Clusters["clean"].Server, clientConfig.Host, t) - matchBoolArg(config.Clusters["clean"].InsecureSkipTLSVerify, clientConfig.Insecure, t) - matchStringArg(config.AuthInfos["clean"].Token, clientConfig.BearerToken, t) -} - -func TestCreateMissingContext(t *testing.T) { - const expectedErrorContains = "Context was not found for specified context" - config := createValidTestConfig() - clientBuilder := NewNonInteractiveClientConfig(*config, "not-present", &ConfigOverrides{}, nil) - - clientConfig, err := clientBuilder.ClientConfig() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - expectedConfig := &restclient.Config{Host: clientConfig.Host} - - if !reflect.DeepEqual(expectedConfig, clientConfig) { - t.Errorf("Expected %#v, got %#v", expectedConfig, clientConfig) - } - -} - -func matchBoolArg(expected, got bool, t *testing.T) { - if expected != got { - t.Errorf("Expected %v, got %v", expected, got) - } -} - -func matchStringArg(expected, got string, t *testing.T) { - if expected != got { - t.Errorf("Expected %q, got %q", expected, got) - } -} - -func matchByteArg(expected, got []byte, t *testing.T) { - if !reflect.DeepEqual(expected, got) { - t.Errorf("Expected %v, got %v", expected, got) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/loader_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/loader_test.go deleted file mode 100644 index ad79c7b81..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/loader_test.go +++ /dev/null @@ -1,562 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 clientcmd - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "path/filepath" - "reflect" - "strings" - "testing" - - "github.com/ghodss/yaml" - - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - clientcmdlatest "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/latest" - "k8s.io/kubernetes/pkg/runtime" -) - -var ( - testConfigAlfa = clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "red-user": {Token: "red-token"}}, - Clusters: map[string]*clientcmdapi.Cluster{ - "cow-cluster": {Server: "http://cow.org:8080"}}, - Contexts: map[string]*clientcmdapi.Context{ - "federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster", Namespace: "hammer-ns"}}, - } - testConfigBravo = clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "black-user": {Token: "black-token"}}, - Clusters: map[string]*clientcmdapi.Cluster{ - "pig-cluster": {Server: "http://pig.org:8080"}}, - Contexts: map[string]*clientcmdapi.Context{ - "queen-anne-context": {AuthInfo: "black-user", Cluster: "pig-cluster", Namespace: "saw-ns"}}, - } - testConfigCharlie = clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "green-user": {Token: "green-token"}}, - Clusters: map[string]*clientcmdapi.Cluster{ - "horse-cluster": {Server: "http://horse.org:8080"}}, - Contexts: map[string]*clientcmdapi.Context{ - "shaker-context": {AuthInfo: "green-user", Cluster: "horse-cluster", Namespace: "chisel-ns"}}, - } - testConfigDelta = clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "blue-user": {Token: "blue-token"}}, - Clusters: map[string]*clientcmdapi.Cluster{ - "chicken-cluster": {Server: "http://chicken.org:8080"}}, - Contexts: map[string]*clientcmdapi.Context{ - "gothic-context": {AuthInfo: "blue-user", Cluster: "chicken-cluster", Namespace: "plane-ns"}}, - } - - testConfigConflictAlfa = clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "red-user": {Token: "a-different-red-token"}, - "yellow-user": {Token: "yellow-token"}}, - Clusters: map[string]*clientcmdapi.Cluster{ - "cow-cluster": {Server: "http://a-different-cow.org:8080", InsecureSkipTLSVerify: true}, - "donkey-cluster": {Server: "http://donkey.org:8080", InsecureSkipTLSVerify: true}}, - CurrentContext: "federal-context", - } -) - -func TestNonExistentCommandLineFile(t *testing.T) { - loadingRules := ClientConfigLoadingRules{ - ExplicitPath: "bogus_file", - } - - _, err := loadingRules.Load() - if err == nil { - t.Fatalf("Expected error for missing command-line file, got none") - } - if !strings.Contains(err.Error(), "bogus_file") { - t.Fatalf("Expected error about 'bogus_file', got %s", err.Error()) - } -} - -func TestToleratingMissingFiles(t *testing.T) { - loadingRules := ClientConfigLoadingRules{ - Precedence: []string{"bogus1", "bogus2", "bogus3"}, - } - - _, err := loadingRules.Load() - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } -} - -func TestErrorReadingFile(t *testing.T) { - commandLineFile, _ := ioutil.TempFile("", "") - defer os.Remove(commandLineFile.Name()) - - if err := ioutil.WriteFile(commandLineFile.Name(), []byte("bogus value"), 0644); err != nil { - t.Fatalf("Error creating tempfile: %v", err) - } - - loadingRules := ClientConfigLoadingRules{ - ExplicitPath: commandLineFile.Name(), - } - - _, err := loadingRules.Load() - if err == nil { - t.Fatalf("Expected error for unloadable file, got none") - } - if !strings.Contains(err.Error(), commandLineFile.Name()) { - t.Fatalf("Expected error about '%s', got %s", commandLineFile.Name(), err.Error()) - } -} - -func TestErrorReadingNonFile(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "") - if err != nil { - t.Fatalf("Couldn't create tmpdir") - } - defer os.Remove(tmpdir) - - loadingRules := ClientConfigLoadingRules{ - ExplicitPath: tmpdir, - } - - _, err = loadingRules.Load() - if err == nil { - t.Fatalf("Expected error for non-file, got none") - } - if !strings.Contains(err.Error(), tmpdir) { - t.Fatalf("Expected error about '%s', got %s", tmpdir, err.Error()) - } -} - -func TestConflictingCurrentContext(t *testing.T) { - commandLineFile, _ := ioutil.TempFile("", "") - defer os.Remove(commandLineFile.Name()) - envVarFile, _ := ioutil.TempFile("", "") - defer os.Remove(envVarFile.Name()) - - mockCommandLineConfig := clientcmdapi.Config{ - CurrentContext: "any-context-value", - } - mockEnvVarConfig := clientcmdapi.Config{ - CurrentContext: "a-different-context", - } - - WriteToFile(mockCommandLineConfig, commandLineFile.Name()) - WriteToFile(mockEnvVarConfig, envVarFile.Name()) - - loadingRules := ClientConfigLoadingRules{ - ExplicitPath: commandLineFile.Name(), - Precedence: []string{envVarFile.Name()}, - } - - mergedConfig, err := loadingRules.Load() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if mergedConfig.CurrentContext != mockCommandLineConfig.CurrentContext { - t.Errorf("expected %v, got %v", mockCommandLineConfig.CurrentContext, mergedConfig.CurrentContext) - } -} - -func TestLoadingEmptyMaps(t *testing.T) { - configFile, _ := ioutil.TempFile("", "") - defer os.Remove(configFile.Name()) - - mockConfig := clientcmdapi.Config{ - CurrentContext: "any-context-value", - } - - WriteToFile(mockConfig, configFile.Name()) - - config, err := LoadFromFile(configFile.Name()) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if config.Clusters == nil { - t.Error("expected config.Clusters to be non-nil") - } - if config.AuthInfos == nil { - t.Error("expected config.AuthInfos to be non-nil") - } - if config.Contexts == nil { - t.Error("expected config.Contexts to be non-nil") - } -} - -func TestResolveRelativePaths(t *testing.T) { - pathResolutionConfig1 := clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "relative-user-1": {ClientCertificate: "relative/client/cert", ClientKey: "../relative/client/key"}, - "absolute-user-1": {ClientCertificate: "/absolute/client/cert", ClientKey: "/absolute/client/key"}, - }, - Clusters: map[string]*clientcmdapi.Cluster{ - "relative-server-1": {CertificateAuthority: "../relative/ca"}, - "absolute-server-1": {CertificateAuthority: "/absolute/ca"}, - }, - } - pathResolutionConfig2 := clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "relative-user-2": {ClientCertificate: "relative/client/cert2", ClientKey: "../relative/client/key2"}, - "absolute-user-2": {ClientCertificate: "/absolute/client/cert2", ClientKey: "/absolute/client/key2"}, - }, - Clusters: map[string]*clientcmdapi.Cluster{ - "relative-server-2": {CertificateAuthority: "../relative/ca2"}, - "absolute-server-2": {CertificateAuthority: "/absolute/ca2"}, - }, - } - - configDir1, _ := ioutil.TempDir("", "") - configFile1 := path.Join(configDir1, ".kubeconfig") - configDir1, _ = filepath.Abs(configDir1) - defer os.Remove(configFile1) - configDir2, _ := ioutil.TempDir("", "") - configDir2, _ = ioutil.TempDir(configDir2, "") - configFile2 := path.Join(configDir2, ".kubeconfig") - configDir2, _ = filepath.Abs(configDir2) - defer os.Remove(configFile2) - - WriteToFile(pathResolutionConfig1, configFile1) - WriteToFile(pathResolutionConfig2, configFile2) - - loadingRules := ClientConfigLoadingRules{ - Precedence: []string{configFile1, configFile2}, - } - - mergedConfig, err := loadingRules.Load() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - foundClusterCount := 0 - for key, cluster := range mergedConfig.Clusters { - if key == "relative-server-1" { - foundClusterCount++ - matchStringArg(path.Join(configDir1, pathResolutionConfig1.Clusters["relative-server-1"].CertificateAuthority), cluster.CertificateAuthority, t) - } - if key == "relative-server-2" { - foundClusterCount++ - matchStringArg(path.Join(configDir2, pathResolutionConfig2.Clusters["relative-server-2"].CertificateAuthority), cluster.CertificateAuthority, t) - } - if key == "absolute-server-1" { - foundClusterCount++ - matchStringArg(pathResolutionConfig1.Clusters["absolute-server-1"].CertificateAuthority, cluster.CertificateAuthority, t) - } - if key == "absolute-server-2" { - foundClusterCount++ - matchStringArg(pathResolutionConfig2.Clusters["absolute-server-2"].CertificateAuthority, cluster.CertificateAuthority, t) - } - } - if foundClusterCount != 4 { - t.Errorf("Expected 4 clusters, found %v: %v", foundClusterCount, mergedConfig.Clusters) - } - - foundAuthInfoCount := 0 - for key, authInfo := range mergedConfig.AuthInfos { - if key == "relative-user-1" { - foundAuthInfoCount++ - matchStringArg(path.Join(configDir1, pathResolutionConfig1.AuthInfos["relative-user-1"].ClientCertificate), authInfo.ClientCertificate, t) - matchStringArg(path.Join(configDir1, pathResolutionConfig1.AuthInfos["relative-user-1"].ClientKey), authInfo.ClientKey, t) - } - if key == "relative-user-2" { - foundAuthInfoCount++ - matchStringArg(path.Join(configDir2, pathResolutionConfig2.AuthInfos["relative-user-2"].ClientCertificate), authInfo.ClientCertificate, t) - matchStringArg(path.Join(configDir2, pathResolutionConfig2.AuthInfos["relative-user-2"].ClientKey), authInfo.ClientKey, t) - } - if key == "absolute-user-1" { - foundAuthInfoCount++ - matchStringArg(pathResolutionConfig1.AuthInfos["absolute-user-1"].ClientCertificate, authInfo.ClientCertificate, t) - matchStringArg(pathResolutionConfig1.AuthInfos["absolute-user-1"].ClientKey, authInfo.ClientKey, t) - } - if key == "absolute-user-2" { - foundAuthInfoCount++ - matchStringArg(pathResolutionConfig2.AuthInfos["absolute-user-2"].ClientCertificate, authInfo.ClientCertificate, t) - matchStringArg(pathResolutionConfig2.AuthInfos["absolute-user-2"].ClientKey, authInfo.ClientKey, t) - } - } - if foundAuthInfoCount != 4 { - t.Errorf("Expected 4 users, found %v: %v", foundAuthInfoCount, mergedConfig.AuthInfos) - } - -} - -func TestMigratingFile(t *testing.T) { - sourceFile, _ := ioutil.TempFile("", "") - defer os.Remove(sourceFile.Name()) - destinationFile, _ := ioutil.TempFile("", "") - // delete the file so that we'll write to it - os.Remove(destinationFile.Name()) - - WriteToFile(testConfigAlfa, sourceFile.Name()) - - loadingRules := ClientConfigLoadingRules{ - MigrationRules: map[string]string{destinationFile.Name(): sourceFile.Name()}, - } - - if _, err := loadingRules.Load(); err != nil { - t.Errorf("unexpected error %v", err) - } - - // the load should have recreated this file - defer os.Remove(destinationFile.Name()) - - sourceContent, err := ioutil.ReadFile(sourceFile.Name()) - if err != nil { - t.Errorf("unexpected error %v", err) - } - destinationContent, err := ioutil.ReadFile(destinationFile.Name()) - if err != nil { - t.Errorf("unexpected error %v", err) - } - - if !reflect.DeepEqual(sourceContent, destinationContent) { - t.Errorf("source and destination do not match") - } -} - -func TestMigratingFileLeaveExistingFileAlone(t *testing.T) { - sourceFile, _ := ioutil.TempFile("", "") - defer os.Remove(sourceFile.Name()) - destinationFile, _ := ioutil.TempFile("", "") - defer os.Remove(destinationFile.Name()) - - WriteToFile(testConfigAlfa, sourceFile.Name()) - - loadingRules := ClientConfigLoadingRules{ - MigrationRules: map[string]string{destinationFile.Name(): sourceFile.Name()}, - } - - if _, err := loadingRules.Load(); err != nil { - t.Errorf("unexpected error %v", err) - } - - destinationContent, err := ioutil.ReadFile(destinationFile.Name()) - if err != nil { - t.Errorf("unexpected error %v", err) - } - - if len(destinationContent) > 0 { - t.Errorf("destination should not have been touched") - } -} - -func TestMigratingFileSourceMissingSkip(t *testing.T) { - sourceFilename := "some-missing-file" - destinationFile, _ := ioutil.TempFile("", "") - // delete the file so that we'll write to it - os.Remove(destinationFile.Name()) - - loadingRules := ClientConfigLoadingRules{ - MigrationRules: map[string]string{destinationFile.Name(): sourceFilename}, - } - - if _, err := loadingRules.Load(); err != nil { - t.Errorf("unexpected error %v", err) - } - - if _, err := os.Stat(destinationFile.Name()); !os.IsNotExist(err) { - t.Errorf("destination should not exist") - } -} - -func Example_noMergingOnExplicitPaths() { - commandLineFile, _ := ioutil.TempFile("", "") - defer os.Remove(commandLineFile.Name()) - envVarFile, _ := ioutil.TempFile("", "") - defer os.Remove(envVarFile.Name()) - - WriteToFile(testConfigAlfa, commandLineFile.Name()) - WriteToFile(testConfigConflictAlfa, envVarFile.Name()) - - loadingRules := ClientConfigLoadingRules{ - ExplicitPath: commandLineFile.Name(), - Precedence: []string{envVarFile.Name()}, - } - - mergedConfig, err := loadingRules.Load() - - json, err := runtime.Encode(clientcmdlatest.Codec, mergedConfig) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - output, err := yaml.JSONToYAML(json) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - - fmt.Printf("%v", string(output)) - // Output: - // apiVersion: v1 - // clusters: - // - cluster: - // server: http://cow.org:8080 - // name: cow-cluster - // contexts: - // - context: - // cluster: cow-cluster - // namespace: hammer-ns - // user: red-user - // name: federal-context - // current-context: "" - // kind: Config - // preferences: {} - // users: - // - name: red-user - // user: - // token: red-token -} - -func Example_mergingSomeWithConflict() { - commandLineFile, _ := ioutil.TempFile("", "") - defer os.Remove(commandLineFile.Name()) - envVarFile, _ := ioutil.TempFile("", "") - defer os.Remove(envVarFile.Name()) - - WriteToFile(testConfigAlfa, commandLineFile.Name()) - WriteToFile(testConfigConflictAlfa, envVarFile.Name()) - - loadingRules := ClientConfigLoadingRules{ - Precedence: []string{commandLineFile.Name(), envVarFile.Name()}, - } - - mergedConfig, err := loadingRules.Load() - - json, err := runtime.Encode(clientcmdlatest.Codec, mergedConfig) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - output, err := yaml.JSONToYAML(json) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - - fmt.Printf("%v", string(output)) - // Output: - // apiVersion: v1 - // clusters: - // - cluster: - // server: http://cow.org:8080 - // name: cow-cluster - // - cluster: - // insecure-skip-tls-verify: true - // server: http://donkey.org:8080 - // name: donkey-cluster - // contexts: - // - context: - // cluster: cow-cluster - // namespace: hammer-ns - // user: red-user - // name: federal-context - // current-context: federal-context - // kind: Config - // preferences: {} - // users: - // - name: red-user - // user: - // token: red-token - // - name: yellow-user - // user: - // token: yellow-token -} - -func Example_mergingEverythingNoConflicts() { - commandLineFile, _ := ioutil.TempFile("", "") - defer os.Remove(commandLineFile.Name()) - envVarFile, _ := ioutil.TempFile("", "") - defer os.Remove(envVarFile.Name()) - currentDirFile, _ := ioutil.TempFile("", "") - defer os.Remove(currentDirFile.Name()) - homeDirFile, _ := ioutil.TempFile("", "") - defer os.Remove(homeDirFile.Name()) - - WriteToFile(testConfigAlfa, commandLineFile.Name()) - WriteToFile(testConfigBravo, envVarFile.Name()) - WriteToFile(testConfigCharlie, currentDirFile.Name()) - WriteToFile(testConfigDelta, homeDirFile.Name()) - - loadingRules := ClientConfigLoadingRules{ - Precedence: []string{commandLineFile.Name(), envVarFile.Name(), currentDirFile.Name(), homeDirFile.Name()}, - } - - mergedConfig, err := loadingRules.Load() - - json, err := runtime.Encode(clientcmdlatest.Codec, mergedConfig) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - output, err := yaml.JSONToYAML(json) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - - fmt.Printf("%v", string(output)) - // Output: - // apiVersion: v1 - // clusters: - // - cluster: - // server: http://chicken.org:8080 - // name: chicken-cluster - // - cluster: - // server: http://cow.org:8080 - // name: cow-cluster - // - cluster: - // server: http://horse.org:8080 - // name: horse-cluster - // - cluster: - // server: http://pig.org:8080 - // name: pig-cluster - // contexts: - // - context: - // cluster: cow-cluster - // namespace: hammer-ns - // user: red-user - // name: federal-context - // - context: - // cluster: chicken-cluster - // namespace: plane-ns - // user: blue-user - // name: gothic-context - // - context: - // cluster: pig-cluster - // namespace: saw-ns - // user: black-user - // name: queen-anne-context - // - context: - // cluster: horse-cluster - // namespace: chisel-ns - // user: green-user - // name: shaker-context - // current-context: "" - // kind: Config - // preferences: {} - // users: - // - name: black-user - // user: - // token: black-token - // - name: blue-user - // user: - // token: blue-token - // - name: green-user - // user: - // token: green-token - // - name: red-user - // user: - // token: red-token -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/validation_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/validation_test.go deleted file mode 100644 index ca4843a87..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/clientcmd/validation_test.go +++ /dev/null @@ -1,432 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 clientcmd - -import ( - "io/ioutil" - "os" - "strings" - "testing" - - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - utilerrors "k8s.io/kubernetes/pkg/util/errors" -) - -func TestConfirmUsableBadInfoButOkConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - config.Clusters["missing ca"] = &clientcmdapi.Cluster{ - Server: "anything", - CertificateAuthority: "missing", - } - config.AuthInfos["error"] = &clientcmdapi.AuthInfo{ - Username: "anything", - Token: "here", - } - config.Contexts["dirty"] = &clientcmdapi.Context{ - Cluster: "missing ca", - AuthInfo: "error", - } - config.Clusters["clean"] = &clientcmdapi.Cluster{ - Server: "anything", - } - config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ - Token: "here", - } - config.Contexts["clean"] = &clientcmdapi.Context{ - Cluster: "clean", - AuthInfo: "clean", - } - - badValidation := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"unable to read certificate-authority"}, - } - okTest := configValidationTest{ - config: config, - } - - okTest.testConfirmUsable("clean", t) - badValidation.testConfig(t) -} -func TestConfirmUsableBadInfoConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - config.Clusters["missing ca"] = &clientcmdapi.Cluster{ - Server: "anything", - CertificateAuthority: "missing", - } - config.AuthInfos["error"] = &clientcmdapi.AuthInfo{ - Username: "anything", - Token: "here", - } - config.Contexts["first"] = &clientcmdapi.Context{ - Cluster: "missing ca", - AuthInfo: "error", - } - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"unable to read certificate-authority"}, - } - - test.testConfirmUsable("first", t) -} -func TestConfirmUsableEmptyConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"invalid configuration: no configuration has been provided"}, - } - - test.testConfirmUsable("", t) -} -func TestConfirmUsableMissingConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"invalid configuration: no configuration has been provided"}, - } - - test.testConfirmUsable("not-here", t) -} -func TestValidateEmptyConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"invalid configuration: no configuration has been provided"}, - } - - test.testConfig(t) -} -func TestValidateMissingCurrentContextConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - config.CurrentContext = "anything" - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"context was not found for specified "}, - } - - test.testConfig(t) -} -func TestIsContextNotFound(t *testing.T) { - config := clientcmdapi.NewConfig() - config.CurrentContext = "anything" - - err := Validate(*config) - if !IsContextNotFound(err) { - t.Errorf("Expected context not found, but got %v", err) - } - if !IsConfigurationInvalid(err) { - t.Errorf("Expected configuration invalid, but got %v", err) - } -} - -func TestIsEmptyConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - - err := Validate(*config) - if !IsEmptyConfig(err) { - t.Errorf("Expected context not found, but got %v", err) - } - if !IsConfigurationInvalid(err) { - t.Errorf("Expected configuration invalid, but got %v", err) - } -} - -func TestIsConfigurationInvalid(t *testing.T) { - if newErrConfigurationInvalid([]error{}) != nil { - t.Errorf("unexpected error") - } - if newErrConfigurationInvalid([]error{ErrNoContext}) == ErrNoContext { - t.Errorf("unexpected error") - } - if newErrConfigurationInvalid([]error{ErrNoContext, ErrNoContext}) == nil { - t.Errorf("unexpected error") - } - if !IsConfigurationInvalid(newErrConfigurationInvalid([]error{ErrNoContext, ErrNoContext})) { - t.Errorf("unexpected error") - } -} - -func TestValidateMissingReferencesConfig(t *testing.T) { - config := clientcmdapi.NewConfig() - config.CurrentContext = "anything" - config.Contexts["anything"] = &clientcmdapi.Context{Cluster: "missing", AuthInfo: "missing"} - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"user \"missing\" was not found for context \"anything\"", "cluster \"missing\" was not found for context \"anything\""}, - } - - test.testContext("anything", t) - test.testConfig(t) -} -func TestValidateEmptyContext(t *testing.T) { - config := clientcmdapi.NewConfig() - config.CurrentContext = "anything" - config.Contexts["anything"] = &clientcmdapi.Context{} - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"user was not specified for context \"anything\"", "cluster was not specified for context \"anything\""}, - } - - test.testContext("anything", t) - test.testConfig(t) -} - -func TestValidateEmptyClusterInfo(t *testing.T) { - config := clientcmdapi.NewConfig() - config.Clusters["empty"] = &clientcmdapi.Cluster{} - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"cluster has no server defined"}, - } - - test.testCluster("empty", t) - test.testConfig(t) -} -func TestValidateMissingCAFileClusterInfo(t *testing.T) { - config := clientcmdapi.NewConfig() - config.Clusters["missing ca"] = &clientcmdapi.Cluster{ - Server: "anything", - CertificateAuthority: "missing", - } - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"unable to read certificate-authority"}, - } - - test.testCluster("missing ca", t) - test.testConfig(t) -} -func TestValidateCleanClusterInfo(t *testing.T) { - config := clientcmdapi.NewConfig() - config.Clusters["clean"] = &clientcmdapi.Cluster{ - Server: "anything", - } - test := configValidationTest{ - config: config, - } - - test.testCluster("clean", t) - test.testConfig(t) -} -func TestValidateCleanWithCAClusterInfo(t *testing.T) { - tempFile, _ := ioutil.TempFile("", "") - defer os.Remove(tempFile.Name()) - - config := clientcmdapi.NewConfig() - config.Clusters["clean"] = &clientcmdapi.Cluster{ - Server: "anything", - CertificateAuthority: tempFile.Name(), - } - test := configValidationTest{ - config: config, - } - - test.testCluster("clean", t) - test.testConfig(t) -} - -func TestValidateEmptyAuthInfo(t *testing.T) { - config := clientcmdapi.NewConfig() - config.AuthInfos["error"] = &clientcmdapi.AuthInfo{} - test := configValidationTest{ - config: config, - } - - test.testAuthInfo("error", t) - test.testConfig(t) -} -func TestValidateCertFilesNotFoundAuthInfo(t *testing.T) { - config := clientcmdapi.NewConfig() - config.AuthInfos["error"] = &clientcmdapi.AuthInfo{ - ClientCertificate: "missing", - ClientKey: "missing", - } - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"unable to read client-cert", "unable to read client-key"}, - } - - test.testAuthInfo("error", t) - test.testConfig(t) -} -func TestValidateCertDataOverridesFiles(t *testing.T) { - tempFile, _ := ioutil.TempFile("", "") - defer os.Remove(tempFile.Name()) - - config := clientcmdapi.NewConfig() - config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ - ClientCertificate: tempFile.Name(), - ClientCertificateData: []byte("certdata"), - ClientKey: tempFile.Name(), - ClientKeyData: []byte("keydata"), - } - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"client-cert-data and client-cert are both specified", "client-key-data and client-key are both specified"}, - } - - test.testAuthInfo("clean", t) - test.testConfig(t) -} -func TestValidateCleanCertFilesAuthInfo(t *testing.T) { - tempFile, _ := ioutil.TempFile("", "") - defer os.Remove(tempFile.Name()) - - config := clientcmdapi.NewConfig() - config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ - ClientCertificate: tempFile.Name(), - ClientKey: tempFile.Name(), - } - test := configValidationTest{ - config: config, - } - - test.testAuthInfo("clean", t) - test.testConfig(t) -} -func TestValidateCleanTokenAuthInfo(t *testing.T) { - config := clientcmdapi.NewConfig() - config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{ - Token: "any-value", - } - test := configValidationTest{ - config: config, - } - - test.testAuthInfo("clean", t) - test.testConfig(t) -} - -func TestValidateMultipleMethodsAuthInfo(t *testing.T) { - config := clientcmdapi.NewConfig() - config.AuthInfos["error"] = &clientcmdapi.AuthInfo{ - Token: "token", - Username: "username", - } - test := configValidationTest{ - config: config, - expectedErrorSubstring: []string{"more than one authentication method", "token", "basicAuth"}, - } - - test.testAuthInfo("error", t) - test.testConfig(t) -} - -type configValidationTest struct { - config *clientcmdapi.Config - expectedErrorSubstring []string -} - -func (c configValidationTest) testContext(contextName string, t *testing.T) { - errs := validateContext(contextName, *c.config.Contexts[contextName], *c.config) - - if len(c.expectedErrorSubstring) != 0 { - if len(errs) == 0 { - t.Errorf("Expected error containing: %v", c.expectedErrorSubstring) - } - for _, curr := range c.expectedErrorSubstring { - if len(errs) != 0 && !strings.Contains(utilerrors.NewAggregate(errs).Error(), curr) { - t.Errorf("Expected error containing: %v, but got %v", c.expectedErrorSubstring, utilerrors.NewAggregate(errs)) - } - } - - } else { - if len(errs) != 0 { - t.Errorf("Unexpected error: %v", utilerrors.NewAggregate(errs)) - } - } -} -func (c configValidationTest) testConfirmUsable(contextName string, t *testing.T) { - err := ConfirmUsable(*c.config, contextName) - - if len(c.expectedErrorSubstring) != 0 { - if err == nil { - t.Errorf("Expected error containing: %v", c.expectedErrorSubstring) - } else { - for _, curr := range c.expectedErrorSubstring { - if err != nil && !strings.Contains(err.Error(), curr) { - t.Errorf("Expected error containing: %v, but got %v", c.expectedErrorSubstring, err) - } - } - } - } else { - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - } -} -func (c configValidationTest) testConfig(t *testing.T) { - err := Validate(*c.config) - - if len(c.expectedErrorSubstring) != 0 { - if err == nil { - t.Errorf("Expected error containing: %v", c.expectedErrorSubstring) - } else { - for _, curr := range c.expectedErrorSubstring { - if err != nil && !strings.Contains(err.Error(), curr) { - t.Errorf("Expected error containing: %v, but got %v", c.expectedErrorSubstring, err) - } - } - if !IsConfigurationInvalid(err) { - t.Errorf("all errors should be configuration invalid: %v", err) - } - } - } else { - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - } -} -func (c configValidationTest) testCluster(clusterName string, t *testing.T) { - errs := validateClusterInfo(clusterName, *c.config.Clusters[clusterName]) - - if len(c.expectedErrorSubstring) != 0 { - if len(errs) == 0 { - t.Errorf("Expected error containing: %v", c.expectedErrorSubstring) - } - for _, curr := range c.expectedErrorSubstring { - if len(errs) != 0 && !strings.Contains(utilerrors.NewAggregate(errs).Error(), curr) { - t.Errorf("Expected error containing: %v, but got %v", c.expectedErrorSubstring, utilerrors.NewAggregate(errs)) - } - } - - } else { - if len(errs) != 0 { - t.Errorf("Unexpected error: %v", utilerrors.NewAggregate(errs)) - } - } -} - -func (c configValidationTest) testAuthInfo(authInfoName string, t *testing.T) { - errs := validateAuthInfo(authInfoName, *c.config.AuthInfos[authInfoName]) - - if len(c.expectedErrorSubstring) != 0 { - if len(errs) == 0 { - t.Errorf("Expected error containing: %v", c.expectedErrorSubstring) - } - for _, curr := range c.expectedErrorSubstring { - if len(errs) != 0 && !strings.Contains(utilerrors.NewAggregate(errs).Error(), curr) { - t.Errorf("Expected error containing: %v, but got %v", c.expectedErrorSubstring, utilerrors.NewAggregate(errs)) - } - } - - } else { - if len(errs) != 0 { - t.Errorf("Unexpected error: %v", utilerrors.NewAggregate(errs)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/conditions_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/conditions_test.go deleted file mode 100644 index 1042461c0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/conditions_test.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned - -import ( - "fmt" - "testing" - - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/util/wait" -) - -func TestRetryOnConflict(t *testing.T) { - opts := wait.Backoff{Factor: 1.0, Steps: 3} - conflictErr := errors.NewConflict(unversioned.GroupResource{Resource: "test"}, "other", nil) - - // never returns - err := RetryOnConflict(opts, func() error { - return conflictErr - }) - if err != conflictErr { - t.Errorf("unexpected error: %v", err) - } - - // returns immediately - i := 0 - err = RetryOnConflict(opts, func() error { - i++ - return nil - }) - if err != nil || i != 1 { - t.Errorf("unexpected error: %v", err) - } - - // returns immediately on error - testErr := fmt.Errorf("some other error") - err = RetryOnConflict(opts, func() error { - return testErr - }) - if err != testErr { - t.Errorf("unexpected error: %v", err) - } - - // keeps retrying - i = 0 - err = RetryOnConflict(opts, func() error { - if i < 2 { - i++ - return errors.NewConflict(unversioned.GroupResource{Resource: "test"}, "other", nil) - } - return nil - }) - if err != nil || i != 2 { - t.Errorf("unexpected error: %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/containerinfo_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/containerinfo_test.go deleted file mode 100644 index 797ad5139..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/containerinfo_test.go +++ /dev/null @@ -1,198 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "net/url" - "path" - "reflect" - "strconv" - "strings" - "testing" - "time" - - cadvisorapi "github.com/google/cadvisor/info/v1" - cadvisorapitest "github.com/google/cadvisor/info/v1/test" -) - -func testHTTPContainerInfoGetter( - req *cadvisorapi.ContainerInfoRequest, - cinfo *cadvisorapi.ContainerInfo, - podID string, - containerID string, - status int, - t *testing.T, -) { - expectedPath := "/stats" - if len(podID) > 0 && len(containerID) > 0 { - expectedPath = path.Join(expectedPath, podID, containerID) - } - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if status != 0 { - w.WriteHeader(status) - } - if strings.TrimRight(r.URL.Path, "/") != strings.TrimRight(expectedPath, "/") { - t.Fatalf("Received request to an invalid path. Should be %v. got %v", - expectedPath, r.URL.Path) - } - - var receivedReq cadvisorapi.ContainerInfoRequest - err := json.NewDecoder(r.Body).Decode(&receivedReq) - if err != nil { - t.Fatal(err) - } - // Note: This will not make a deep copy of req. - // So changing req after Get*Info would be a race. - expectedReq := req - // Fill any empty fields with default value - if !expectedReq.Equals(receivedReq) { - t.Errorf("received wrong request") - } - err = json.NewEncoder(w).Encode(cinfo) - if err != nil { - t.Fatal(err) - } - })) - defer ts.Close() - hostURL, err := url.Parse(ts.URL) - if err != nil { - t.Fatal(err) - } - parts := strings.Split(hostURL.Host, ":") - - port, err := strconv.Atoi(parts[1]) - if err != nil { - t.Fatal(err) - } - - containerInfoGetter := &HTTPContainerInfoGetter{ - Client: http.DefaultClient, - Port: port, - } - - var receivedContainerInfo *cadvisorapi.ContainerInfo - if len(podID) > 0 && len(containerID) > 0 { - receivedContainerInfo, err = containerInfoGetter.GetContainerInfo(parts[0], podID, containerID, req) - } else { - receivedContainerInfo, err = containerInfoGetter.GetRootInfo(parts[0], req) - } - if status == 0 || status == http.StatusOK { - if err != nil { - t.Errorf("received unexpected error: %v", err) - } - - if !receivedContainerInfo.Eq(cinfo) { - t.Error("received unexpected container info") - } - } else { - if err == nil { - t.Error("did not receive expected error.") - } - } -} - -func TestHTTPContainerInfoGetterGetContainerInfoSuccessfully(t *testing.T) { - req := &cadvisorapi.ContainerInfoRequest{ - NumStats: 10, - } - cinfo := cadvisorapitest.GenerateRandomContainerInfo( - "dockerIDWhichWillNotBeChecked", // docker ID - 2, // Number of cores - req, - 1*time.Second, - ) - testHTTPContainerInfoGetter(req, cinfo, "somePodID", "containerNameInK8S", 0, t) -} - -func TestHTTPContainerInfoGetterGetRootInfoSuccessfully(t *testing.T) { - req := &cadvisorapi.ContainerInfoRequest{ - NumStats: 10, - } - cinfo := cadvisorapitest.GenerateRandomContainerInfo( - "dockerIDWhichWillNotBeChecked", // docker ID - 2, // Number of cores - req, - 1*time.Second, - ) - testHTTPContainerInfoGetter(req, cinfo, "", "", 0, t) -} - -func TestHTTPContainerInfoGetterGetContainerInfoWithError(t *testing.T) { - req := &cadvisorapi.ContainerInfoRequest{ - NumStats: 10, - } - cinfo := cadvisorapitest.GenerateRandomContainerInfo( - "dockerIDWhichWillNotBeChecked", // docker ID - 2, // Number of cores - req, - 1*time.Second, - ) - testHTTPContainerInfoGetter(req, cinfo, "somePodID", "containerNameInK8S", http.StatusNotFound, t) -} - -func TestHTTPContainerInfoGetterGetRootInfoWithError(t *testing.T) { - req := &cadvisorapi.ContainerInfoRequest{ - NumStats: 10, - } - cinfo := cadvisorapitest.GenerateRandomContainerInfo( - "dockerIDWhichWillNotBeChecked", // docker ID - 2, // Number of cores - req, - 1*time.Second, - ) - testHTTPContainerInfoGetter(req, cinfo, "", "", http.StatusNotFound, t) -} - -func TestHTTPGetMachineInfo(t *testing.T) { - mspec := &cadvisorapi.MachineInfo{ - NumCores: 4, - MemoryCapacity: 2048, - } - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - err := json.NewEncoder(w).Encode(mspec) - if err != nil { - t.Fatal(err) - } - })) - defer ts.Close() - hostURL, err := url.Parse(ts.URL) - if err != nil { - t.Fatal(err) - } - parts := strings.Split(hostURL.Host, ":") - - port, err := strconv.Atoi(parts[1]) - if err != nil { - t.Fatal(err) - } - - containerInfoGetter := &HTTPContainerInfoGetter{ - Client: http.DefaultClient, - Port: port, - } - - received, err := containerInfoGetter.GetMachineInfo(parts[0]) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(received, mspec) { - t.Errorf("received wrong machine spec") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/daemon_sets_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/daemon_sets_test.go deleted file mode 100644 index f453a9138..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/daemon_sets_test.go +++ /dev/null @@ -1,198 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/extensions" -) - -func getDSResourceName() string { - return "daemonsets" -} - -func TestListDaemonSets(t *testing.T) { - ns := api.NamespaceAll - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getDSResourceName(), ns, ""), - }, - Response: simple.Response{StatusCode: 200, - Body: &extensions.DaemonSetList{ - Items: []extensions.DaemonSet{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.DaemonSetSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - }, - }, - } - receivedDSs, err := c.Setup(t).Extensions().DaemonSets(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, receivedDSs, err) - -} - -func TestGetDaemonSet(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Extensions.ResourcePath(getDSResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.DaemonSetSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedDaemonSet, err := c.Setup(t).Extensions().DaemonSets(ns).Get("foo") - defer c.Close() - c.Validate(t, receivedDaemonSet, err) -} - -func TestGetDaemonSetWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).Extensions().DaemonSets(ns).Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} - -func TestUpdateDaemonSet(t *testing.T) { - ns := api.NamespaceDefault - requestDaemonSet := &extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getDSResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.DaemonSetSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedDaemonSet, err := c.Setup(t).Extensions().DaemonSets(ns).Update(requestDaemonSet) - defer c.Close() - c.Validate(t, receivedDaemonSet, err) -} - -func TestUpdateDaemonSetUpdateStatus(t *testing.T) { - ns := api.NamespaceDefault - requestDaemonSet := &extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getDSResourceName(), ns, "foo") + "/status", Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.DaemonSetSpec{ - Template: api.PodTemplateSpec{}, - }, - Status: extensions.DaemonSetStatus{}, - }, - }, - } - receivedDaemonSet, err := c.Setup(t).Extensions().DaemonSets(ns).UpdateStatus(requestDaemonSet) - defer c.Close() - c.Validate(t, receivedDaemonSet, err) -} - -func TestDeleteDaemon(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Extensions.ResourcePath(getDSResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Extensions().DaemonSets(ns).Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestCreateDaemonSet(t *testing.T) { - ns := api.NamespaceDefault - requestDaemonSet := &extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "POST", Path: testapi.Extensions.ResourcePath(getDSResourceName(), ns, ""), Body: requestDaemonSet, Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.DaemonSetSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedDaemonSet, err := c.Setup(t).Extensions().DaemonSets(ns).Create(requestDaemonSet) - defer c.Close() - c.Validate(t, receivedDaemonSet, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/deployment_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/deployment_test.go deleted file mode 100644 index c530411a7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/deployment_test.go +++ /dev/null @@ -1,236 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "net/http" - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" - "k8s.io/kubernetes/pkg/labels" -) - -func getDeploymentsResourceName() string { - return "deployments" -} - -func TestDeploymentCreate(t *testing.T) { - ns := api.NamespaceDefault - deployment := extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Extensions.ResourcePath(getDeploymentsResourceName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: &deployment, - }, - Response: simple.Response{StatusCode: 200, Body: &deployment}, - } - - response, err := c.Setup(t).Deployments(ns).Create(&deployment) - defer c.Close() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - c.Validate(t, response, err) -} - -func TestDeploymentGet(t *testing.T) { - ns := api.NamespaceDefault - deployment := &extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getDeploymentsResourceName(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: deployment}, - } - - response, err := c.Setup(t).Deployments(ns).Get("abc") - defer c.Close() - c.Validate(t, response, err) -} - -func TestDeploymentList(t *testing.T) { - ns := api.NamespaceDefault - deploymentList := &extensions.DeploymentList{ - Items: []extensions.Deployment{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getDeploymentsResourceName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: deploymentList}, - } - response, err := c.Setup(t).Deployments(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestDeploymentUpdate(t *testing.T) { - ns := api.NamespaceDefault - deployment := &extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Extensions.ResourcePath(getDeploymentsResourceName(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{StatusCode: 200, Body: deployment}, - } - response, err := c.Setup(t).Deployments(ns).Update(deployment) - defer c.Close() - c.Validate(t, response, err) -} - -func TestDeploymentUpdateStatus(t *testing.T) { - ns := api.NamespaceDefault - deployment := &extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Extensions.ResourcePath(getDeploymentsResourceName(), ns, "abc") + "/status", - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{StatusCode: 200, Body: deployment}, - } - response, err := c.Setup(t).Deployments(ns).UpdateStatus(deployment) - defer c.Close() - c.Validate(t, response, err) -} - -func TestDeploymentDelete(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "DELETE", - Path: testapi.Extensions.ResourcePath(getDeploymentsResourceName(), ns, "foo"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Deployments(ns).Delete("foo", nil) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestDeploymentWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePathWithPrefix("watch", getDeploymentsResourceName(), "", ""), - Query: url.Values{"resourceVersion": []string{}}, - }, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).Deployments(api.NamespaceAll).Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestListDeploymentsLabels(t *testing.T) { - ns := api.NamespaceDefault - labelSelectorQueryParamName := unversioned.LabelSelectorQueryParam(testapi.Extensions.GroupVersion().String()) - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath("deployments", ns, ""), - Query: simple.BuildQueryValues(url.Values{labelSelectorQueryParamName: []string{"foo=bar,name=baz"}})}, - Response: simple.Response{ - StatusCode: http.StatusOK, - Body: &extensions.DeploymentList{ - Items: []extensions.Deployment{ - { - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - }, - }, - }, - }, - } - c.Setup(t) - defer c.Close() - c.QueryValidator[labelSelectorQueryParamName] = simple.ValidateLabels - selector := labels.Set{"foo": "bar", "name": "baz"}.AsSelector() - options := api.ListOptions{LabelSelector: selector} - receivedPodList, err := c.Deployments(ns).List(options) - c.Validate(t, receivedPodList, err) -} - -func TestDeploymentRollback(t *testing.T) { - ns := api.NamespaceDefault - deploymentRollback := &extensions.DeploymentRollback{ - Name: "abc", - UpdatedAnnotations: map[string]string{}, - RollbackTo: extensions.RollbackConfig{Revision: 1}, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Extensions.ResourcePath(getDeploymentsResourceName(), ns, "abc") + "/rollback", - Query: simple.BuildQueryValues(nil), - Body: deploymentRollback, - }, - Response: simple.Response{StatusCode: http.StatusOK}, - } - err := c.Setup(t).Deployments(ns).Rollback(deploymentRollback) - defer c.Close() - c.ValidateCommon(t, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/endpoints_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/endpoints_test.go deleted file mode 100644 index 59bc869b8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/endpoints_test.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func TestListEndpoints(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Default.ResourcePath("endpoints", ns, ""), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, - Body: &api.EndpointsList{ - Items: []api.Endpoints{ - { - ObjectMeta: api.ObjectMeta{Name: "endpoint-1"}, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "10.245.1.2"}, {IP: "10.245.1.3"}}, - Ports: []api.EndpointPort{{Port: 8080}}, - }}, - }, - }, - }, - }, - } - receivedEndpointsList, err := c.Setup(t).Endpoints(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, receivedEndpointsList, err) -} - -func TestGetEndpoints(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Default.ResourcePath("endpoints", ns, "endpoint-1"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: &api.Endpoints{ObjectMeta: api.ObjectMeta{Name: "endpoint-1"}}}, - } - response, err := c.Setup(t).Endpoints(ns).Get("endpoint-1") - defer c.Close() - c.Validate(t, response, err) -} - -func TestGetEndpointWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).Endpoints(ns).Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/events_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/events_test.go deleted file mode 100644 index 371c7544e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/events_test.go +++ /dev/null @@ -1,205 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - . "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -import ( - "net/url" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -func TestEventSearch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("events", "baz", ""), - Query: url.Values{ - unversioned.FieldSelectorQueryParam(testapi.Default.GroupVersion().String()): []string{ - GetInvolvedObjectNameFieldLabel(testapi.Default.GroupVersion().String()) + "=foo,", - "involvedObject.namespace=baz,", - "involvedObject.kind=Pod", - }, - unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()): []string{}, - }, - }, - Response: simple.Response{StatusCode: 200, Body: &api.EventList{}}, - } - eventList, err := c.Setup(t).Events("baz").Search( - &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "baz", - SelfLink: testapi.Default.SelfLink("pods", ""), - }, - }, - ) - defer c.Close() - c.Validate(t, eventList, err) -} - -func TestEventCreate(t *testing.T) { - objReference := &api.ObjectReference{ - Kind: "foo", - Namespace: "nm", - Name: "objref1", - UID: "uid", - APIVersion: "apiv1", - ResourceVersion: "1", - } - timeStamp := unversioned.Now() - event := &api.Event{ - ObjectMeta: api.ObjectMeta{ - Namespace: api.NamespaceDefault, - }, - InvolvedObject: *objReference, - FirstTimestamp: timeStamp, - LastTimestamp: timeStamp, - Count: 1, - Type: api.EventTypeNormal, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath("events", api.NamespaceDefault, ""), - Body: event, - }, - Response: simple.Response{StatusCode: 200, Body: event}, - } - - response, err := c.Setup(t).Events(api.NamespaceDefault).Create(event) - defer c.Close() - - if err != nil { - t.Fatalf("%v should be nil.", err) - } - - if e, a := *objReference, response.InvolvedObject; !reflect.DeepEqual(e, a) { - t.Errorf("%#v != %#v.", e, a) - } -} - -func TestEventGet(t *testing.T) { - objReference := &api.ObjectReference{ - Kind: "foo", - Namespace: "nm", - Name: "objref1", - UID: "uid", - APIVersion: "apiv1", - ResourceVersion: "1", - } - timeStamp := unversioned.Now() - event := &api.Event{ - ObjectMeta: api.ObjectMeta{ - Namespace: "other", - }, - InvolvedObject: *objReference, - FirstTimestamp: timeStamp, - LastTimestamp: timeStamp, - Count: 1, - Type: api.EventTypeNormal, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("events", "other", "1"), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: event}, - } - - response, err := c.Setup(t).Events("other").Get("1") - defer c.Close() - - if err != nil { - t.Fatalf("%v should be nil.", err) - } - - if e, r := event.InvolvedObject, response.InvolvedObject; !reflect.DeepEqual(e, r) { - t.Errorf("%#v != %#v.", e, r) - } -} - -func TestEventList(t *testing.T) { - ns := api.NamespaceDefault - objReference := &api.ObjectReference{ - Kind: "foo", - Namespace: ns, - Name: "objref1", - UID: "uid", - APIVersion: "apiv1", - ResourceVersion: "1", - } - timeStamp := unversioned.Now() - eventList := &api.EventList{ - Items: []api.Event{ - { - InvolvedObject: *objReference, - FirstTimestamp: timeStamp, - LastTimestamp: timeStamp, - Count: 1, - Type: api.EventTypeNormal, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("events", ns, ""), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: eventList}, - } - response, err := c.Setup(t).Events(ns).List(api.ListOptions{}) - defer c.Close() - - if err != nil { - t.Errorf("%#v should be nil.", err) - } - - if len(response.Items) != 1 { - t.Errorf("%#v response.Items should have len 1.", response.Items) - } - - responseEvent := response.Items[0] - if e, r := eventList.Items[0].InvolvedObject, - responseEvent.InvolvedObject; !reflect.DeepEqual(e, r) { - t.Errorf("%#v != %#v.", e, r) - } -} - -func TestEventDelete(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "DELETE", - Path: testapi.Default.ResourcePath("events", ns, "foo"), - }, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Events(ns).Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/fake/fake.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/fake/fake.go deleted file mode 100644 index df7824251..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/fake/fake.go +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This is made a separate package and should only be imported by tests, because -// it imports testapi -package fake - -import ( - "net/http" - "net/url" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/runtime" -) - -func CreateHTTPClient(roundTripper func(*http.Request) (*http.Response, error)) *http.Client { - return &http.Client{ - Transport: roundTripperFunc(roundTripper), - } -} - -type roundTripperFunc func(*http.Request) (*http.Response, error) - -func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) { - return f(req) -} - -// RESTClient provides a fake RESTClient interface. -type RESTClient struct { - Client *http.Client - Codec runtime.Codec - Req *http.Request - Resp *http.Response - Err error -} - -func (c *RESTClient) Get() *restclient.Request { - return c.request("GET") -} - -func (c *RESTClient) Put() *restclient.Request { - return c.request("PUT") -} - -func (c *RESTClient) Patch(_ api.PatchType) *restclient.Request { - return c.request("PATCH") -} - -func (c *RESTClient) Post() *restclient.Request { - return c.request("POST") -} - -func (c *RESTClient) Delete() *restclient.Request { - return c.request("DELETE") -} - -func (c *RESTClient) request(verb string) *restclient.Request { - config := restclient.ContentConfig{ - GroupVersion: testapi.Default.GroupVersion(), - Codec: c.Codec, - } - serializers := restclient.Serializers{ - Encoder: c.Codec, - Decoder: c.Codec, - StreamingSerializer: c.Codec, - Framer: runtime.DefaultFramer, - } - return restclient.NewRequest(c, verb, &url.URL{Host: "localhost"}, "", config, serializers, nil, nil) -} - -func (c *RESTClient) Do(req *http.Request) (*http.Response, error) { - if c.Err != nil { - return nil, c.Err - } - c.Req = req - if c.Client != nil { - return c.Client.Do(req) - } - return c.Resp, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/flags_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/flags_test.go deleted file mode 100644 index ab0f94d04..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/flags_test.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned - -import ( - "testing" - "time" - - "k8s.io/kubernetes/pkg/util/sets" -) - -type fakeFlagSet struct { - t *testing.T - set sets.String -} - -func (f *fakeFlagSet) StringVar(p *string, name, value, usage string) { - if p == nil { - f.t.Errorf("unexpected nil pointer") - } - if usage == "" { - f.t.Errorf("unexpected empty usage") - } - f.set.Insert(name) -} - -func (f *fakeFlagSet) BoolVar(p *bool, name string, value bool, usage string) { - if p == nil { - f.t.Errorf("unexpected nil pointer") - } - if usage == "" { - f.t.Errorf("unexpected empty usage") - } - f.set.Insert(name) -} - -func (f *fakeFlagSet) UintVar(p *uint, name string, value uint, usage string) { - if p == nil { - f.t.Errorf("unexpected nil pointer") - } - if usage == "" { - f.t.Errorf("unexpected empty usage") - } - f.set.Insert(name) -} - -func (f *fakeFlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) { - if p == nil { - f.t.Errorf("unexpected nil pointer") - } - if usage == "" { - f.t.Errorf("unexpected empty usage") - } - f.set.Insert(name) -} - -func (f *fakeFlagSet) IntVar(p *int, name string, value int, usage string) { - if p == nil { - f.t.Errorf("unexpected nil pointer") - } - if usage == "" { - f.t.Errorf("unexpected empty usage") - } - f.set.Insert(name) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/helper_blackbox_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/helper_blackbox_test.go deleted file mode 100644 index c4860a12f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/helper_blackbox_test.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "bytes" - "encoding/json" - "errors" - "io" - "io/ioutil" - "net/http" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/testapi" - uapi "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func objBody(object interface{}) io.ReadCloser { - output, err := json.MarshalIndent(object, "", "") - if err != nil { - panic(err) - } - return ioutil.NopCloser(bytes.NewReader([]byte(output))) -} - -func TestNegotiateVersion(t *testing.T) { - tests := []struct { - name string - version *uapi.GroupVersion - expectedVersion *uapi.GroupVersion - serverVersions []string - clientVersions []uapi.GroupVersion - config *restclient.Config - expectErr func(err error) bool - sendErr error - }{ - { - name: "server supports client default", - version: &uapi.GroupVersion{Version: "version1"}, - config: &restclient.Config{}, - serverVersions: []string{"version1", testapi.Default.GroupVersion().String()}, - clientVersions: []uapi.GroupVersion{{Version: "version1"}, *testapi.Default.GroupVersion()}, - expectedVersion: &uapi.GroupVersion{Version: "version1"}, - }, - { - name: "server falls back to client supported", - version: testapi.Default.GroupVersion(), - config: &restclient.Config{}, - serverVersions: []string{"version1"}, - clientVersions: []uapi.GroupVersion{{Version: "version1"}, *testapi.Default.GroupVersion()}, - expectedVersion: &uapi.GroupVersion{Version: "version1"}, - }, - { - name: "explicit version supported", - config: &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}, - serverVersions: []string{"/version1", testapi.Default.GroupVersion().String()}, - clientVersions: []uapi.GroupVersion{{Version: "version1"}, *testapi.Default.GroupVersion()}, - expectedVersion: testapi.Default.GroupVersion(), - }, - { - name: "explicit version not supported", - config: &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}, - serverVersions: []string{"version1"}, - clientVersions: []uapi.GroupVersion{{Version: "version1"}, *testapi.Default.GroupVersion()}, - expectErr: func(err error) bool { return strings.Contains(err.Error(), `server does not support API version "v1"`) }, - }, - { - name: "connection refused error", - config: &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}, - serverVersions: []string{"version1"}, - clientVersions: []uapi.GroupVersion{{Version: "version1"}, *testapi.Default.GroupVersion()}, - sendErr: errors.New("connection refused"), - expectErr: func(err error) bool { return strings.Contains(err.Error(), "connection refused") }, - }, - } - codec := testapi.Default.Codec() - - for _, test := range tests { - fakeClient := &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{ - StatusCode: 200, - Body: objBody(&uapi.APIVersions{Versions: test.serverVersions}), - }, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if test.sendErr != nil { - return nil, test.sendErr - } - return &http.Response{StatusCode: 200, Body: objBody(&uapi.APIVersions{Versions: test.serverVersions})}, nil - }), - } - c := unversioned.NewOrDie(test.config) - c.DiscoveryClient.Client = fakeClient.Client - response, err := unversioned.NegotiateVersion(c, test.config, test.version, test.clientVersions) - if err == nil && test.expectErr != nil { - t.Errorf("expected error, got nil for [%s].", test.name) - } - if err != nil { - if test.expectErr == nil || !test.expectErr(err) { - t.Errorf("unexpected error for [%s]: %v.", test.name, err) - } - continue - } - if *response != *test.expectedVersion { - t.Errorf("%s: expected version %s, got %s.", test.name, test.expectedVersion, response) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/helper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/helper_test.go deleted file mode 100644 index 0e186e4c7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/helper_test.go +++ /dev/null @@ -1,179 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestSetKubernetesDefaults(t *testing.T) { - testCases := []struct { - Config restclient.Config - After restclient.Config - Err bool - }{ - { - restclient.Config{}, - restclient.Config{ - APIPath: "/api", - ContentConfig: restclient.ContentConfig{ - GroupVersion: testapi.Default.GroupVersion(), - Codec: testapi.Default.Codec(), - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), - }, - QPS: 5, - Burst: 10, - }, - false, - }, - // Add this test back when we fixed config and SetKubernetesDefaults - // { - // restclient.Config{ - // GroupVersion: &unversioned.GroupVersion{Group: "not.a.group", Version: "not_an_api"}, - // }, - // restclient.Config{}, - // true, - // }, - } - for _, testCase := range testCases { - val := &testCase.Config - err := SetKubernetesDefaults(val) - val.UserAgent = "" - switch { - case err == nil && testCase.Err: - t.Errorf("expected error but was nil") - continue - case err != nil && !testCase.Err: - t.Errorf("unexpected error %v", err) - continue - case err != nil: - continue - } - if !reflect.DeepEqual(*val, testCase.After) { - t.Errorf("unexpected result object: %#v", val) - } - } -} - -func TestHelperGetServerAPIVersions(t *testing.T) { - expect := []string{"v1", "v2", "v3"} - APIVersions := unversioned.APIVersions{Versions: expect} - expect = append(expect, "group1/v1", "group1/v2", "group2/v1", "group2/v2") - APIGroupList := unversioned.APIGroupList{ - Groups: []unversioned.APIGroup{ - { - Versions: []unversioned.GroupVersionForDiscovery{ - { - GroupVersion: "group1/v1", - }, - { - GroupVersion: "group1/v2", - }, - }, - }, - { - Versions: []unversioned.GroupVersionForDiscovery{ - { - GroupVersion: "group2/v1", - }, - { - GroupVersion: "group2/v2", - }, - }, - }, - }, - } - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - var output []byte - var err error - switch req.URL.Path { - case "/api": - output, err = json.Marshal(APIVersions) - - case "/apis": - output, err = json.Marshal(APIGroupList) - } - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - return - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write(output) - })) - defer server.Close() - got, err := restclient.ServerAPIVersions(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Group: "invalid version", Version: "one"}, NegotiatedSerializer: testapi.Default.NegotiatedSerializer()}}) - if err != nil { - t.Fatalf("unexpected encoding error: %v", err) - } - if e, a := expect, got; !reflect.DeepEqual(e, a) { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestSetsCodec(t *testing.T) { - testCases := map[string]struct { - Err bool - Prefix string - Codec runtime.Codec - }{ - testapi.Default.GroupVersion().Version: {false, "/api/" + testapi.Default.GroupVersion().Version, testapi.Default.Codec()}, - // Add this test back when we fixed config and SetKubernetesDefaults - // "invalidVersion": {true, "", nil}, - } - for version, expected := range testCases { - conf := &restclient.Config{ - Host: "127.0.0.1", - ContentConfig: restclient.ContentConfig{ - GroupVersion: &unversioned.GroupVersion{Version: version}, - }, - } - - var versionedPath string - err := SetKubernetesDefaults(conf) - if err == nil { - _, versionedPath, err = restclient.DefaultServerURL(conf.Host, conf.APIPath, *conf.GroupVersion, false) - } - - switch { - case err == nil && expected.Err: - t.Errorf("expected error but was nil") - continue - case err != nil && !expected.Err: - t.Errorf("unexpected error %v", err) - continue - case err != nil: - continue - } - if e, a := expected.Prefix, versionedPath; e != a { - t.Errorf("expected %#v, got %#v", e, a) - } - if e, a := expected.Codec, conf.Codec; !reflect.DeepEqual(e, a) { - t.Errorf("expected %#v, got %#v", e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/horizontalpodautoscaler_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/horizontalpodautoscaler_test.go deleted file mode 100644 index 550dae6ec..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/horizontalpodautoscaler_test.go +++ /dev/null @@ -1,222 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/autoscaling" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getHorizontalPodAutoscalersResoureName() string { - return "horizontalpodautoscalers" -} - -func getHPAClient(t *testing.T, c *simple.Client, ns, resourceGroup string) unversioned.HorizontalPodAutoscalerInterface { - switch resourceGroup { - case autoscaling.GroupName: - return c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns) - case extensions.GroupName: - return c.Setup(t).Extensions().HorizontalPodAutoscalers(ns) - default: - t.Fatalf("Unknown group %v", resourceGroup) - } - return nil -} - -func testHorizontalPodAutoscalerCreate(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - horizontalPodAutoscaler := extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: &horizontalPodAutoscaler, - }, - Response: simple.Response{StatusCode: 200, Body: &horizontalPodAutoscaler}, - ResourceGroup: resourceGroup, - } - - response, err := getHPAClient(t, c, ns, resourceGroup).Create(&horizontalPodAutoscaler) - defer c.Close() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - c.Validate(t, response, err) -} - -func TestHorizontalPodAutoscalerCreate(t *testing.T) { - testHorizontalPodAutoscalerCreate(t, testapi.Extensions, extensions.GroupName) - testHorizontalPodAutoscalerCreate(t, testapi.Autoscaling, autoscaling.GroupName) -} - -func testHorizontalPodAutoscalerGet(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler}, - ResourceGroup: resourceGroup, - } - - response, err := getHPAClient(t, c, ns, resourceGroup).Get("abc") - defer c.Close() - c.Validate(t, response, err) -} - -func TestHorizontalPodAutoscalerGet(t *testing.T) { - testHorizontalPodAutoscalerGet(t, testapi.Extensions, extensions.GroupName) - testHorizontalPodAutoscalerGet(t, testapi.Autoscaling, autoscaling.GroupName) -} - -func testHorizontalPodAutoscalerList(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - horizontalPodAutoscalerList := &extensions.HorizontalPodAutoscalerList{ - Items: []extensions.HorizontalPodAutoscaler{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscalerList}, - ResourceGroup: resourceGroup, - } - response, err := getHPAClient(t, c, ns, resourceGroup).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestHorizontalPodAutoscalerList(t *testing.T) { - testHorizontalPodAutoscalerList(t, testapi.Extensions, extensions.GroupName) - testHorizontalPodAutoscalerList(t, testapi.Autoscaling, autoscaling.GroupName) -} - -func testHorizontalPodAutoscalerUpdate(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler}, - ResourceGroup: resourceGroup, - } - response, err := getHPAClient(t, c, ns, resourceGroup).Update(horizontalPodAutoscaler) - defer c.Close() - c.Validate(t, response, err) -} - -func TestHorizontalPodAutoscalerUpdate(t *testing.T) { - testHorizontalPodAutoscalerUpdate(t, testapi.Extensions, extensions.GroupName) - testHorizontalPodAutoscalerUpdate(t, testapi.Autoscaling, autoscaling.GroupName) -} - -func testHorizontalPodAutoscalerUpdateStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc") + "/status", Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler}, - ResourceGroup: resourceGroup, - } - response, err := getHPAClient(t, c, ns, resourceGroup).UpdateStatus(horizontalPodAutoscaler) - defer c.Close() - c.Validate(t, response, err) -} - -func TestHorizontalPodAutoscalerUpdateStatus(t *testing.T) { - testHorizontalPodAutoscalerUpdateStatus(t, testapi.Extensions, extensions.GroupName) - testHorizontalPodAutoscalerUpdateStatus(t, testapi.Autoscaling, autoscaling.GroupName) -} - -func testHorizontalPodAutoscalerDelete(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - ResourceGroup: resourceGroup, - } - err := getHPAClient(t, c, ns, resourceGroup).Delete("foo", nil) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestHorizontalPodAutoscalerDelete(t *testing.T) { - testHorizontalPodAutoscalerDelete(t, testapi.Extensions, extensions.GroupName) - testHorizontalPodAutoscalerDelete(t, testapi.Autoscaling, autoscaling.GroupName) -} - -func testHorizontalPodAutoscalerWatch(t *testing.T, group testapi.TestGroup, resourceGroup string) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: group.ResourcePathWithPrefix("watch", getHorizontalPodAutoscalersResoureName(), "", ""), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - ResourceGroup: resourceGroup, - } - _, err := getHPAClient(t, c, api.NamespaceAll, resourceGroup).Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestHorizontalPodAutoscalerWatch(t *testing.T) { - testHorizontalPodAutoscalerWatch(t, testapi.Extensions, extensions.GroupName) - testHorizontalPodAutoscalerWatch(t, testapi.Autoscaling, autoscaling.GroupName) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/ingress_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/ingress_test.go deleted file mode 100644 index dfec482ea..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/ingress_test.go +++ /dev/null @@ -1,236 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getIngressResourceName() string { - return "ingresses" -} - -func TestListIngress(t *testing.T) { - ns := api.NamespaceAll - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getIngressResourceName(), ns, ""), - }, - Response: simple.Response{StatusCode: 200, - Body: &extensions.IngressList{ - Items: []extensions.Ingress{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.IngressSpec{ - Rules: []extensions.IngressRule{}, - }, - }, - }, - }, - }, - } - receivedIngressList, err := c.Setup(t).Extensions().Ingress(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, receivedIngressList, err) -} - -func TestGetIngress(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getIngressResourceName(), ns, "foo"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.IngressSpec{ - Rules: []extensions.IngressRule{}, - }, - }, - }, - } - receivedIngress, err := c.Setup(t).Extensions().Ingress(ns).Get("foo") - defer c.Close() - c.Validate(t, receivedIngress, err) -} - -func TestGetIngressWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedIngress, err := c.Setup(t).Extensions().Ingress(ns).Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedIngress, err) -} - -func TestUpdateIngress(t *testing.T) { - ns := api.NamespaceDefault - requestIngress := &extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Extensions.ResourcePath(getIngressResourceName(), ns, "foo"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.IngressSpec{ - Rules: []extensions.IngressRule{}, - }, - }, - }, - } - receivedIngress, err := c.Setup(t).Extensions().Ingress(ns).Update(requestIngress) - defer c.Close() - c.Validate(t, receivedIngress, err) -} - -func TestUpdateIngressStatus(t *testing.T) { - ns := api.NamespaceDefault - lbStatus := api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - {IP: "127.0.0.1"}, - }, - } - requestIngress := &extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Status: extensions.IngressStatus{ - LoadBalancer: lbStatus, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Extensions.ResourcePath(getIngressResourceName(), ns, "foo") + "/status", - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.IngressSpec{ - Rules: []extensions.IngressRule{}, - }, - Status: extensions.IngressStatus{ - LoadBalancer: lbStatus, - }, - }, - }, - } - receivedIngress, err := c.Setup(t).Extensions().Ingress(ns).UpdateStatus(requestIngress) - defer c.Close() - c.Validate(t, receivedIngress, err) -} - -func TestDeleteIngress(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "DELETE", - Path: testapi.Extensions.ResourcePath(getIngressResourceName(), ns, "foo"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Extensions().Ingress(ns).Delete("foo", nil) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestCreateIngress(t *testing.T) { - ns := api.NamespaceDefault - requestIngress := &extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Extensions.ResourcePath(getIngressResourceName(), ns, ""), - Body: requestIngress, - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.IngressSpec{ - Rules: []extensions.IngressRule{}, - }, - }, - }, - } - receivedIngress, err := c.Setup(t).Extensions().Ingress(ns).Create(requestIngress) - defer c.Close() - c.Validate(t, receivedIngress, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/jobs_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/jobs_test.go deleted file mode 100644 index e47d49d51..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/jobs_test.go +++ /dev/null @@ -1,269 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getJobsResourceName() string { - return "jobs" -} - -func getJobClient(t *testing.T, c *simple.Client, ns, resourceGroup string) unversioned.JobInterface { - switch resourceGroup { - case batch.GroupName: - return c.Setup(t).Batch().Jobs(ns) - case extensions.GroupName: - return c.Setup(t).Extensions().Jobs(ns) - default: - t.Fatalf("Unknown group %v", resourceGroup) - } - return nil -} - -func testListJob(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceAll - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: group.ResourcePath(getJobsResourceName(), ns, ""), - }, - Response: simple.Response{StatusCode: 200, - Body: &batch.JobList{ - Items: []batch.Job{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: batch.JobSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - }, - }, - ResourceGroup: resourceGroup, - } - receivedJobList, err := getJobClient(t, c, ns, resourceGroup).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, receivedJobList, err) -} - -func TestListJob(t *testing.T) { - testListJob(t, testapi.Extensions, extensions.GroupName) - testListJob(t, testapi.Batch, batch.GroupName) -} - -func testGetJob(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: group.ResourcePath(getJobsResourceName(), ns, "foo"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: batch.JobSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - ResourceGroup: resourceGroup, - } - receivedJob, err := getJobClient(t, c, ns, resourceGroup).Get("foo") - defer c.Close() - c.Validate(t, receivedJob, err) -} - -func TestGetJob(t *testing.T) { - testGetJob(t, testapi.Extensions, extensions.GroupName) - testGetJob(t, testapi.Batch, batch.GroupName) -} - -func testUpdateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - requestJob := &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: group.ResourcePath(getJobsResourceName(), ns, "foo"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: batch.JobSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - ResourceGroup: resourceGroup, - } - receivedJob, err := getJobClient(t, c, ns, resourceGroup).Update(requestJob) - defer c.Close() - c.Validate(t, receivedJob, err) -} - -func TestUpdateJob(t *testing.T) { - testUpdateJob(t, testapi.Extensions, extensions.GroupName) - testUpdateJob(t, testapi.Batch, batch.GroupName) -} - -func testUpdateJobStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - requestJob := &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: group.ResourcePath(getJobsResourceName(), ns, "foo") + "/status", - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: batch.JobSpec{ - Template: api.PodTemplateSpec{}, - }, - Status: batch.JobStatus{ - Active: 1, - }, - }, - }, - ResourceGroup: resourceGroup, - } - receivedJob, err := getJobClient(t, c, ns, resourceGroup).UpdateStatus(requestJob) - defer c.Close() - c.Validate(t, receivedJob, err) -} - -func TestUpdateJobStatus(t *testing.T) { - testUpdateJobStatus(t, testapi.Extensions, extensions.GroupName) - testUpdateJobStatus(t, testapi.Batch, batch.GroupName) -} - -func testDeleteJob(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "DELETE", - Path: group.ResourcePath(getJobsResourceName(), ns, "foo"), - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{StatusCode: 200}, - ResourceGroup: resourceGroup, - } - err := getJobClient(t, c, ns, resourceGroup).Delete("foo", nil) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestDeleteJob(t *testing.T) { - testDeleteJob(t, testapi.Extensions, extensions.GroupName) - testDeleteJob(t, testapi.Batch, batch.GroupName) -} - -func testCreateJob(t *testing.T, group testapi.TestGroup, resourceGroup string) { - ns := api.NamespaceDefault - requestJob := &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: group.ResourcePath(getJobsResourceName(), ns, ""), - Body: requestJob, - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: batch.JobSpec{ - Template: api.PodTemplateSpec{}, - }, - }, - }, - ResourceGroup: resourceGroup, - } - receivedJob, err := getJobClient(t, c, ns, resourceGroup).Create(requestJob) - defer c.Close() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - c.Validate(t, receivedJob, err) -} - -func TestCreateJob(t *testing.T) { - testCreateJob(t, testapi.Extensions, extensions.GroupName) - testCreateJob(t, testapi.Batch, batch.GroupName) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/limit_ranges_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/limit_ranges_test.go deleted file mode 100644 index 445310291..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/limit_ranges_test.go +++ /dev/null @@ -1,185 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getLimitRangesResourceName() string { - return "limitranges" -} - -func TestLimitRangeCreate(t *testing.T) { - ns := api.NamespaceDefault - limitRange := &api.LimitRange{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - }, - Min: api.ResourceList{ - api.ResourceCPU: resource.MustParse("0"), - api.ResourceMemory: resource.MustParse("100"), - }, - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath(getLimitRangesResourceName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: limitRange, - }, - Response: simple.Response{StatusCode: 200, Body: limitRange}, - } - - response, err := c.Setup(t).LimitRanges(ns).Create(limitRange) - defer c.Close() - c.Validate(t, response, err) -} - -func TestLimitRangeGet(t *testing.T) { - ns := api.NamespaceDefault - limitRange := &api.LimitRange{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - }, - Min: api.ResourceList{ - api.ResourceCPU: resource.MustParse("0"), - api.ResourceMemory: resource.MustParse("100"), - }, - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getLimitRangesResourceName(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: limitRange}, - } - - response, err := c.Setup(t).LimitRanges(ns).Get("abc") - defer c.Close() - c.Validate(t, response, err) -} - -func TestLimitRangeList(t *testing.T) { - ns := api.NamespaceDefault - - limitRangeList := &api.LimitRangeList{ - Items: []api.LimitRange{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getLimitRangesResourceName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: limitRangeList}, - } - response, err := c.Setup(t).LimitRanges(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestLimitRangeUpdate(t *testing.T) { - ns := api.NamespaceDefault - limitRange := &api.LimitRange{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - ResourceVersion: "1", - }, - Spec: api.LimitRangeSpec{ - Limits: []api.LimitRangeItem{ - { - Type: api.LimitTypePod, - Max: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - }, - Min: api.ResourceList{ - api.ResourceCPU: resource.MustParse("0"), - api.ResourceMemory: resource.MustParse("100"), - }, - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getLimitRangesResourceName(), ns, "abc"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: limitRange}, - } - response, err := c.Setup(t).LimitRanges(ns).Update(limitRange) - defer c.Close() - c.Validate(t, response, err) -} - -func TestLimitRangeDelete(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath(getLimitRangesResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).LimitRanges(ns).Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestLimitRangeWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePathWithPrefix("watch", getLimitRangesResourceName(), "", ""), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).LimitRanges(api.NamespaceAll).Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/namespaces_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/namespaces_test.go deleted file mode 100644 index 8e38c935b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/namespaces_test.go +++ /dev/null @@ -1,185 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func TestNamespaceCreate(t *testing.T) { - // we create a namespace relative to another namespace - namespace := &api.Namespace{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath("namespaces", "", ""), - Body: namespace, - }, - Response: simple.Response{StatusCode: 200, Body: namespace}, - } - - // from the source ns, provision a new global namespace "foo" - response, err := c.Setup(t).Namespaces().Create(namespace) - defer c.Close() - - if err != nil { - t.Errorf("%#v should be nil.", err) - } - - if e, a := response.Name, namespace.Name; e != a { - t.Errorf("%#v != %#v.", e, a) - } -} - -func TestNamespaceGet(t *testing.T) { - namespace := &api.Namespace{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("namespaces", "", "foo"), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: namespace}, - } - - response, err := c.Setup(t).Namespaces().Get("foo") - defer c.Close() - - if err != nil { - t.Errorf("%#v should be nil.", err) - } - - if e, r := response.Name, namespace.Name; e != r { - t.Errorf("%#v != %#v.", e, r) - } -} - -func TestNamespaceList(t *testing.T) { - namespaceList := &api.NamespaceList{ - Items: []api.Namespace{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("namespaces", "", ""), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: namespaceList}, - } - response, err := c.Setup(t).Namespaces().List(api.ListOptions{}) - defer c.Close() - - if err != nil { - t.Errorf("%#v should be nil.", err) - } - - if len(response.Items) != 1 { - t.Errorf("%#v response.Items should have len 1.", response.Items) - } - - responseNamespace := response.Items[0] - if e, r := responseNamespace.Name, "foo"; e != r { - t.Errorf("%#v != %#v.", e, r) - } -} - -func TestNamespaceUpdate(t *testing.T) { - requestNamespace := &api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - ResourceVersion: "1", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{api.FinalizerKubernetes}, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Default.ResourcePath("namespaces", "", "foo")}, - Response: simple.Response{StatusCode: 200, Body: requestNamespace}, - } - receivedNamespace, err := c.Setup(t).Namespaces().Update(requestNamespace) - defer c.Close() - c.Validate(t, receivedNamespace, err) -} - -func TestNamespaceFinalize(t *testing.T) { - requestNamespace := &api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - ResourceVersion: "1", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{api.FinalizerKubernetes}, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Default.ResourcePath("namespaces", "", "foo") + "/finalize", - }, - Response: simple.Response{StatusCode: 200, Body: requestNamespace}, - } - receivedNamespace, err := c.Setup(t).Namespaces().Finalize(requestNamespace) - defer c.Close() - c.Validate(t, receivedNamespace, err) -} - -func TestNamespaceDelete(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath("namespaces", "", "foo")}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Namespaces().Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestNamespaceWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePathWithPrefix("watch", "namespaces", "", ""), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).Namespaces().Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/nodes_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/nodes_test.go deleted file mode 100644 index d20656d49..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/nodes_test.go +++ /dev/null @@ -1,173 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" - "k8s.io/kubernetes/pkg/labels" -) - -func getNodesResourceName() string { - return "nodes" -} - -func TestListNodes(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getNodesResourceName(), "", ""), - }, - Response: simple.Response{StatusCode: 200, Body: &api.NodeList{ListMeta: unversioned.ListMeta{ResourceVersion: "1"}}}, - } - response, err := c.Setup(t).Nodes().List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestListNodesLabels(t *testing.T) { - labelSelectorQueryParamName := unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getNodesResourceName(), "", ""), - Query: simple.BuildQueryValues(url.Values{labelSelectorQueryParamName: []string{"foo=bar,name=baz"}})}, - Response: simple.Response{ - StatusCode: 200, - Body: &api.NodeList{ - Items: []api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - }, - }, - }, - }, - } - c.Setup(t) - defer c.Close() - c.QueryValidator[labelSelectorQueryParamName] = simple.ValidateLabels - selector := labels.Set{"foo": "bar", "name": "baz"}.AsSelector() - options := api.ListOptions{LabelSelector: selector} - receivedNodeList, err := c.Nodes().List(options) - c.Validate(t, receivedNodeList, err) -} - -func TestGetNode(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getNodesResourceName(), "", "1"), - }, - Response: simple.Response{StatusCode: 200, Body: &api.Node{ObjectMeta: api.ObjectMeta{Name: "node-1"}}}, - } - response, err := c.Setup(t).Nodes().Get("1") - defer c.Close() - c.Validate(t, response, err) -} - -func TestGetNodeWithNoName(t *testing.T) { - c := &simple.Client{Error: true} - receivedNode, err := c.Setup(t).Nodes().Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedNode, err) -} - -func TestCreateNode(t *testing.T) { - requestNode := &api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "node-1", - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceCPU: resource.MustParse("1000m"), - api.ResourceMemory: resource.MustParse("1Mi"), - }, - }, - Spec: api.NodeSpec{ - Unschedulable: false, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath(getNodesResourceName(), "", ""), - Body: requestNode}, - Response: simple.Response{ - StatusCode: 200, - Body: requestNode, - }, - } - receivedNode, err := c.Setup(t).Nodes().Create(requestNode) - defer c.Close() - c.Validate(t, receivedNode, err) -} - -func TestDeleteNode(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "DELETE", - Path: testapi.Default.ResourcePath(getNodesResourceName(), "", "foo"), - }, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Nodes().Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestUpdateNode(t *testing.T) { - requestNode := &api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - ResourceVersion: "1", - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceCPU: resource.MustParse("1000m"), - api.ResourceMemory: resource.MustParse("1Mi"), - }, - }, - Spec: api.NodeSpec{ - Unschedulable: true, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Default.ResourcePath(getNodesResourceName(), "", "foo"), - }, - Response: simple.Response{StatusCode: 200, Body: requestNode}, - } - response, err := c.Setup(t).Nodes().Update(requestNode) - defer c.Close() - c.Validate(t, response, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/persistentvolume_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/persistentvolume_test.go deleted file mode 100644 index 03ebed7e7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/persistentvolume_test.go +++ /dev/null @@ -1,191 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getPersistentVolumesResoureName() string { - return "persistentvolumes" -} - -func TestPersistentVolumeCreate(t *testing.T) { - pv := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }, - } - - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath(getPersistentVolumesResoureName(), "", ""), - Query: simple.BuildQueryValues(nil), - Body: pv, - }, - Response: simple.Response{StatusCode: 200, Body: pv}, - } - - response, err := c.Setup(t).PersistentVolumes().Create(pv) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeGet(t *testing.T) { - persistentVolume := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getPersistentVolumesResoureName(), "", "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: persistentVolume}, - } - - response, err := c.Setup(t).PersistentVolumes().Get("abc") - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeList(t *testing.T) { - persistentVolumeList := &api.PersistentVolumeList{ - Items: []api.PersistentVolume{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getPersistentVolumesResoureName(), "", ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: persistentVolumeList}, - } - response, err := c.Setup(t).PersistentVolumes().List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeUpdate(t *testing.T) { - persistentVolume := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - ResourceVersion: "1", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getPersistentVolumesResoureName(), "", "abc"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: persistentVolume}, - } - response, err := c.Setup(t).PersistentVolumes().Update(persistentVolume) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeStatusUpdate(t *testing.T) { - persistentVolume := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - ResourceVersion: "1", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{Path: "/foo"}, - }, - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - Message: "foo", - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Default.ResourcePath(getPersistentVolumesResoureName(), "", "abc") + "/status", - Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: persistentVolume}, - } - response, err := c.Setup(t).PersistentVolumes().UpdateStatus(persistentVolume) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeDelete(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath(getPersistentVolumesResoureName(), "", "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).PersistentVolumes().Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestPersistentVolumeWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePathWithPrefix("watch", getPersistentVolumesResoureName(), "", ""), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).PersistentVolumes().Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/persistentvolumeclaim_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/persistentvolumeclaim_test.go deleted file mode 100644 index 901f510df..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/persistentvolumeclaim_test.go +++ /dev/null @@ -1,208 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getPersistentVolumeClaimsResoureName() string { - return "persistentvolumeclaims" -} - -func TestPersistentVolumeClaimCreate(t *testing.T) { - ns := api.NamespaceDefault - pv := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }, - } - - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath(getPersistentVolumeClaimsResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: pv, - }, - Response: simple.Response{StatusCode: 200, Body: pv}, - } - - response, err := c.Setup(t).PersistentVolumeClaims(ns).Create(pv) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeClaimGet(t *testing.T) { - ns := api.NamespaceDefault - persistentVolumeClaim := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getPersistentVolumeClaimsResoureName(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: persistentVolumeClaim}, - } - - response, err := c.Setup(t).PersistentVolumeClaims(ns).Get("abc") - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeClaimList(t *testing.T) { - ns := api.NamespaceDefault - persistentVolumeList := &api.PersistentVolumeClaimList{ - Items: []api.PersistentVolumeClaim{ - { - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "ns"}, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getPersistentVolumeClaimsResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: persistentVolumeList}, - } - response, err := c.Setup(t).PersistentVolumeClaims(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeClaimUpdate(t *testing.T) { - ns := api.NamespaceDefault - persistentVolumeClaim := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - ResourceVersion: "1", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getPersistentVolumeClaimsResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: persistentVolumeClaim}, - } - response, err := c.Setup(t).PersistentVolumeClaims(ns).Update(persistentVolumeClaim) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeClaimStatusUpdate(t *testing.T) { - ns := api.NamespaceDefault - persistentVolumeClaim := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - ResourceVersion: "1", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - }, - }, - Status: api.PersistentVolumeClaimStatus{ - Phase: api.ClaimBound, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Default.ResourcePath(getPersistentVolumeClaimsResoureName(), ns, "abc") + "/status", - Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: persistentVolumeClaim}, - } - response, err := c.Setup(t).PersistentVolumeClaims(ns).UpdateStatus(persistentVolumeClaim) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPersistentVolumeClaimDelete(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath(getPersistentVolumeClaimsResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).PersistentVolumeClaims(ns).Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestPersistentVolumeClaimWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePathWithPrefix("watch", getPersistentVolumeClaimsResoureName(), "", ""), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).PersistentVolumeClaims(api.NamespaceAll).Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pet_sets_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pet_sets_test.go deleted file mode 100644 index 879aa5ce7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pet_sets_test.go +++ /dev/null @@ -1,165 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 unversioned_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getPetSetResourceName() string { - return "petsets" -} - -func TestListPetSets(t *testing.T) { - ns := api.NamespaceAll - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Apps.ResourcePath(getPetSetResourceName(), ns, ""), - }, - Response: simple.Response{StatusCode: 200, - Body: &apps.PetSetList{ - Items: []apps.PetSet{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: apps.PetSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - }, - }, - } - receivedRSList, err := c.Setup(t).Apps().PetSets(ns).List(api.ListOptions{}) - c.Validate(t, receivedRSList, err) -} - -func TestGetPetSet(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Apps.ResourcePath(getPetSetResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &apps.PetSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: apps.PetSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedRS, err := c.Setup(t).Apps().PetSets(ns).Get("foo") - c.Validate(t, receivedRS, err) -} - -func TestGetPetSetWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).Apps().PetSets(ns).Get("") - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} - -func TestUpdatePetSet(t *testing.T) { - ns := api.NamespaceDefault - requestRS := &apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Apps.ResourcePath(getPetSetResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &apps.PetSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: apps.PetSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedRS, err := c.Setup(t).Apps().PetSets(ns).Update(requestRS) - c.Validate(t, receivedRS, err) -} - -func TestDeletePetSet(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Apps.ResourcePath(getPetSetResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Apps().PetSets(ns).Delete("foo", nil) - c.Validate(t, nil, err) -} - -func TestCreatePetSet(t *testing.T) { - ns := api.NamespaceDefault - requestRS := &apps.PetSet{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "POST", Path: testapi.Apps.ResourcePath(getPetSetResourceName(), ns, ""), Body: requestRS, Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &apps.PetSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: apps.PetSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedRS, err := c.Setup(t).Apps().PetSets(ns).Create(requestRS) - c.Validate(t, receivedRS, err) -} - -// TODO: Test Status actions. diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pod_templates_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pod_templates_test.go deleted file mode 100644 index c72f0a21c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pod_templates_test.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getPodTemplatesResoureName() string { - return "podtemplates" -} - -func TestPodTemplateCreate(t *testing.T) { - ns := api.NamespaceDefault - podTemplate := api.PodTemplate{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - }, - Template: api.PodTemplateSpec{}, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath(getPodTemplatesResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: &podTemplate, - }, - Response: simple.Response{StatusCode: 200, Body: &podTemplate}, - } - - response, err := c.Setup(t).PodTemplates(ns).Create(&podTemplate) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPodTemplateGet(t *testing.T) { - ns := api.NamespaceDefault - podTemplate := &api.PodTemplate{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - }, - Template: api.PodTemplateSpec{}, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getPodTemplatesResoureName(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: podTemplate}, - } - - response, err := c.Setup(t).PodTemplates(ns).Get("abc") - defer c.Close() - c.Validate(t, response, err) -} - -func TestPodTemplateList(t *testing.T) { - ns := api.NamespaceDefault - podTemplateList := &api.PodTemplateList{ - Items: []api.PodTemplate{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getPodTemplatesResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: podTemplateList}, - } - response, err := c.Setup(t).PodTemplates(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPodTemplateUpdate(t *testing.T) { - ns := api.NamespaceDefault - podTemplate := &api.PodTemplate{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: ns, - ResourceVersion: "1", - }, - Template: api.PodTemplateSpec{}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getPodTemplatesResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: podTemplate}, - } - response, err := c.Setup(t).PodTemplates(ns).Update(podTemplate) - defer c.Close() - c.Validate(t, response, err) -} - -func TestPodTemplateDelete(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath(getPodTemplatesResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).PodTemplates(ns).Delete("foo", nil) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestPodTemplateWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePathWithPrefix("watch", getPodTemplatesResoureName(), "", ""), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).PodTemplates(api.NamespaceAll).Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pods_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pods_test.go deleted file mode 100644 index 42a806502..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/pods_test.go +++ /dev/null @@ -1,226 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "net/http" - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" - "k8s.io/kubernetes/pkg/labels" -) - -func TestListEmptyPods(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Default.ResourcePath("pods", ns, ""), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: http.StatusOK, Body: &api.PodList{}}, - } - podList, err := c.Setup(t).Pods(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, podList, err) -} - -func TestListPods(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Default.ResourcePath("pods", ns, ""), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: http.StatusOK, - Body: &api.PodList{ - Items: []api.Pod{ - { - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - }, - }, - }, - }, - } - receivedPodList, err := c.Setup(t).Pods(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, receivedPodList, err) -} - -func TestListPodsLabels(t *testing.T) { - ns := api.NamespaceDefault - labelSelectorQueryParamName := unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("pods", ns, ""), - Query: simple.BuildQueryValues(url.Values{labelSelectorQueryParamName: []string{"foo=bar,name=baz"}})}, - Response: simple.Response{ - StatusCode: http.StatusOK, - Body: &api.PodList{ - Items: []api.Pod{ - { - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - }, - }, - }, - }, - } - c.Setup(t) - defer c.Close() - c.QueryValidator[labelSelectorQueryParamName] = simple.ValidateLabels - selector := labels.Set{"foo": "bar", "name": "baz"}.AsSelector() - options := api.ListOptions{LabelSelector: selector} - receivedPodList, err := c.Pods(ns).List(options) - c.Validate(t, receivedPodList, err) -} - -func TestGetPod(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Default.ResourcePath("pods", ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: http.StatusOK, - Body: &api.Pod{ - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - }, - }, - } - receivedPod, err := c.Setup(t).Pods(ns).Get("foo") - defer c.Close() - c.Validate(t, receivedPod, err) -} - -func TestGetPodWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).Pods(ns).Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} - -func TestDeletePod(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath("pods", ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: http.StatusOK}, - } - err := c.Setup(t).Pods(ns).Delete("foo", nil) - defer c.Close() - c.Validate(t, nil, err) -} - -func TestCreatePod(t *testing.T) { - ns := api.NamespaceDefault - requestPod := &api.Pod{ - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "POST", Path: testapi.Default.ResourcePath("pods", ns, ""), Query: simple.BuildQueryValues(nil), Body: requestPod}, - Response: simple.Response{ - StatusCode: http.StatusOK, - Body: requestPod, - }, - } - receivedPod, err := c.Setup(t).Pods(ns).Create(requestPod) - defer c.Close() - c.Validate(t, receivedPod, err) -} - -func TestUpdatePod(t *testing.T) { - ns := api.NamespaceDefault - requestPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - ResourceVersion: "1", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath("pods", ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: http.StatusOK, Body: requestPod}, - } - receivedPod, err := c.Setup(t).Pods(ns).Update(requestPod) - defer c.Close() - c.Validate(t, receivedPod, err) -} - -func TestPodGetLogs(t *testing.T) { - ns := api.NamespaceDefault - opts := &api.PodLogOptions{ - Follow: true, - Timestamps: true, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("pods", ns, "podName") + "/log", - Query: url.Values{ - "follow": []string{"true"}, - "timestamps": []string{"true"}, - }, - }, - Response: simple.Response{StatusCode: http.StatusOK}, - } - - body, err := c.Setup(t).Pods(ns).GetLogs("podName", opts).Stream() - defer c.Close() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - defer body.Close() - c.ValidateCommon(t, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/podsecuritypolicy_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/podsecuritypolicy_test.go deleted file mode 100644 index d51e2c5a0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/podsecuritypolicy_test.go +++ /dev/null @@ -1,137 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "fmt" - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func TestPodSecurityPolicyCreate(t *testing.T) { - ns := api.NamespaceNone - scc := &extensions.PodSecurityPolicy{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - } - - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: scc, - }, - Response: simple.Response{StatusCode: 200, Body: scc}, - } - - response, err := c.Setup(t).PodSecurityPolicies().Create(scc) - c.Validate(t, response, err) -} - -func TestPodSecurityPolicyGet(t *testing.T) { - ns := api.NamespaceNone - scc := &extensions.PodSecurityPolicy{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: scc}, - } - - response, err := c.Setup(t).PodSecurityPolicies().Get("abc") - c.Validate(t, response, err) -} - -func TestPodSecurityPolicyList(t *testing.T) { - ns := api.NamespaceNone - sccList := &extensions.PodSecurityPolicyList{ - Items: []extensions.PodSecurityPolicy{ - { - ObjectMeta: api.ObjectMeta{ - Name: "abc", - }, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: sccList}, - } - response, err := c.Setup(t).PodSecurityPolicies().List(api.ListOptions{}) - c.Validate(t, response, err) -} - -func TestPodSecurityPolicyUpdate(t *testing.T) { - ns := api.NamespaceNone - scc := &extensions.PodSecurityPolicy{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - ResourceVersion: "1", - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, "abc"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: scc}, - } - response, err := c.Setup(t).PodSecurityPolicies().Update(scc) - c.Validate(t, response, err) -} - -func TestPodSecurityPolicyDelete(t *testing.T) { - ns := api.NamespaceNone - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).PodSecurityPolicies().Delete("foo") - c.Validate(t, nil, err) -} - -func TestPodSecurityPolicyWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: fmt.Sprintf("%s/watch/%s", testapi.Extensions.ResourcePath("", "", ""), getPSPResourcename()), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).PodSecurityPolicies().Watch(api.ListOptions{}) - c.Validate(t, nil, err) -} - -func getPSPResourcename() string { - return "podsecuritypolicies" -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/doc.go deleted file mode 100644 index 032f180f9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 portforward adds support for SSH-like port forwarding from the client's -// local host to remote containers. -package portforward diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/portforward.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/portforward.go deleted file mode 100644 index a5ce32d34..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/portforward.go +++ /dev/null @@ -1,338 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 portforward - -import ( - "errors" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "strconv" - "strings" - "sync" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/kubelet/server/portforward" - "k8s.io/kubernetes/pkg/util/httpstream" - "k8s.io/kubernetes/pkg/util/runtime" -) - -// PortForwarder knows how to listen for local connections and forward them to -// a remote pod via an upgraded HTTP request. -type PortForwarder struct { - ports []ForwardedPort - stopChan <-chan struct{} - - dialer httpstream.Dialer - streamConn httpstream.Connection - listeners []io.Closer - Ready chan struct{} - requestIDLock sync.Mutex - requestID int - out io.Writer - errOut io.Writer -} - -// ForwardedPort contains a Local:Remote port pairing. -type ForwardedPort struct { - Local uint16 - Remote uint16 -} - -/* - valid port specifications: - - 5000 - - forwards from localhost:5000 to pod:5000 - - 8888:5000 - - forwards from localhost:8888 to pod:5000 - - 0:5000 - :5000 - - selects a random available local port, - forwards from localhost: to pod:5000 -*/ -func parsePorts(ports []string) ([]ForwardedPort, error) { - var forwards []ForwardedPort - for _, portString := range ports { - parts := strings.Split(portString, ":") - var localString, remoteString string - if len(parts) == 1 { - localString = parts[0] - remoteString = parts[0] - } else if len(parts) == 2 { - localString = parts[0] - if localString == "" { - // support :5000 - localString = "0" - } - remoteString = parts[1] - } else { - return nil, fmt.Errorf("Invalid port format '%s'", portString) - } - - localPort, err := strconv.ParseUint(localString, 10, 16) - if err != nil { - return nil, fmt.Errorf("Error parsing local port '%s': %s", localString, err) - } - - remotePort, err := strconv.ParseUint(remoteString, 10, 16) - if err != nil { - return nil, fmt.Errorf("Error parsing remote port '%s': %s", remoteString, err) - } - if remotePort == 0 { - return nil, fmt.Errorf("Remote port must be > 0") - } - - forwards = append(forwards, ForwardedPort{uint16(localPort), uint16(remotePort)}) - } - - return forwards, nil -} - -// New creates a new PortForwarder. -func New(dialer httpstream.Dialer, ports []string, stopChan <-chan struct{}, out, errOut io.Writer) (*PortForwarder, error) { - if len(ports) == 0 { - return nil, errors.New("You must specify at least 1 port") - } - parsedPorts, err := parsePorts(ports) - if err != nil { - return nil, err - } - return &PortForwarder{ - dialer: dialer, - ports: parsedPorts, - stopChan: stopChan, - Ready: make(chan struct{}), - out: out, - errOut: errOut, - }, nil -} - -// ForwardPorts formats and executes a port forwarding request. The connection will remain -// open until stopChan is closed. -func (pf *PortForwarder) ForwardPorts() error { - defer pf.Close() - - var err error - pf.streamConn, _, err = pf.dialer.Dial(portforward.PortForwardProtocolV1Name) - if err != nil { - return fmt.Errorf("error upgrading connection: %s", err) - } - defer pf.streamConn.Close() - - return pf.forward() -} - -// forward dials the remote host specific in req, upgrades the request, starts -// listeners for each port specified in ports, and forwards local connections -// to the remote host via streams. -func (pf *PortForwarder) forward() error { - var err error - - listenSuccess := false - for _, port := range pf.ports { - err = pf.listenOnPort(&port) - switch { - case err == nil: - listenSuccess = true - default: - if pf.errOut != nil { - fmt.Fprintf(pf.errOut, "Unable to listen on port %d: %v\n", port.Local, err) - } - } - } - - if !listenSuccess { - return fmt.Errorf("Unable to listen on any of the requested ports: %v", pf.ports) - } - - close(pf.Ready) - - // wait for interrupt or conn closure - select { - case <-pf.stopChan: - case <-pf.streamConn.CloseChan(): - runtime.HandleError(errors.New("lost connection to pod")) - } - - return nil -} - -// listenOnPort delegates tcp4 and tcp6 listener creation and waits for connections on both of these addresses. -// If both listener creation fail, an error is raised. -func (pf *PortForwarder) listenOnPort(port *ForwardedPort) error { - errTcp4 := pf.listenOnPortAndAddress(port, "tcp4", "127.0.0.1") - errTcp6 := pf.listenOnPortAndAddress(port, "tcp6", "[::1]") - if errTcp4 != nil && errTcp6 != nil { - return fmt.Errorf("All listeners failed to create with the following errors: %s, %s", errTcp4, errTcp6) - } - return nil -} - -// listenOnPortAndAddress delegates listener creation and waits for new connections -// in the background f -func (pf *PortForwarder) listenOnPortAndAddress(port *ForwardedPort, protocol string, address string) error { - listener, err := pf.getListener(protocol, address, port) - if err != nil { - return err - } - pf.listeners = append(pf.listeners, listener) - go pf.waitForConnection(listener, *port) - return nil -} - -// getListener creates a listener on the interface targeted by the given hostname on the given port with -// the given protocol. protocol is in net.Listen style which basically admits values like tcp, tcp4, tcp6 -func (pf *PortForwarder) getListener(protocol string, hostname string, port *ForwardedPort) (net.Listener, error) { - listener, err := net.Listen(protocol, fmt.Sprintf("%s:%d", hostname, port.Local)) - if err != nil { - runtime.HandleError(fmt.Errorf("Unable to create listener: Error %s", err)) - return nil, err - } - listenerAddress := listener.Addr().String() - host, localPort, _ := net.SplitHostPort(listenerAddress) - localPortUInt, err := strconv.ParseUint(localPort, 10, 16) - - if err != nil { - return nil, fmt.Errorf("Error parsing local port: %s from %s (%s)", err, listenerAddress, host) - } - port.Local = uint16(localPortUInt) - if pf.out != nil { - fmt.Fprintf(pf.out, "Forwarding from %s:%d -> %d\n", hostname, localPortUInt, port.Remote) - } - - return listener, nil -} - -// waitForConnection waits for new connections to listener and handles them in -// the background. -func (pf *PortForwarder) waitForConnection(listener net.Listener, port ForwardedPort) { - for { - conn, err := listener.Accept() - if err != nil { - // TODO consider using something like https://github.com/hydrogen18/stoppableListener? - if !strings.Contains(strings.ToLower(err.Error()), "use of closed network connection") { - runtime.HandleError(fmt.Errorf("Error accepting connection on port %d: %v", port.Local, err)) - } - return - } - go pf.handleConnection(conn, port) - } -} - -func (pf *PortForwarder) nextRequestID() int { - pf.requestIDLock.Lock() - defer pf.requestIDLock.Unlock() - id := pf.requestID - pf.requestID++ - return id -} - -// handleConnection copies data between the local connection and the stream to -// the remote server. -func (pf *PortForwarder) handleConnection(conn net.Conn, port ForwardedPort) { - defer conn.Close() - - if pf.out != nil { - fmt.Fprintf(pf.out, "Handling connection for %d\n", port.Local) - } - - requestID := pf.nextRequestID() - - // create error stream - headers := http.Header{} - headers.Set(api.StreamType, api.StreamTypeError) - headers.Set(api.PortHeader, fmt.Sprintf("%d", port.Remote)) - headers.Set(api.PortForwardRequestIDHeader, strconv.Itoa(requestID)) - errorStream, err := pf.streamConn.CreateStream(headers) - if err != nil { - runtime.HandleError(fmt.Errorf("error creating error stream for port %d -> %d: %v", port.Local, port.Remote, err)) - return - } - // we're not writing to this stream - errorStream.Close() - - errorChan := make(chan error) - go func() { - message, err := ioutil.ReadAll(errorStream) - switch { - case err != nil: - errorChan <- fmt.Errorf("error reading from error stream for port %d -> %d: %v", port.Local, port.Remote, err) - case len(message) > 0: - errorChan <- fmt.Errorf("an error occurred forwarding %d -> %d: %v", port.Local, port.Remote, string(message)) - } - close(errorChan) - }() - - // create data stream - headers.Set(api.StreamType, api.StreamTypeData) - dataStream, err := pf.streamConn.CreateStream(headers) - if err != nil { - runtime.HandleError(fmt.Errorf("error creating forwarding stream for port %d -> %d: %v", port.Local, port.Remote, err)) - return - } - - localError := make(chan struct{}) - remoteDone := make(chan struct{}) - - go func() { - // Copy from the remote side to the local port. - if _, err := io.Copy(conn, dataStream); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { - runtime.HandleError(fmt.Errorf("error copying from remote stream to local connection: %v", err)) - } - - // inform the select below that the remote copy is done - close(remoteDone) - }() - - go func() { - // inform server we're not sending any more data after copy unblocks - defer dataStream.Close() - - // Copy from the local port to the remote side. - if _, err := io.Copy(dataStream, conn); err != nil && !strings.Contains(err.Error(), "use of closed network connection") { - runtime.HandleError(fmt.Errorf("error copying from local connection to remote stream: %v", err)) - // break out of the select below without waiting for the other copy to finish - close(localError) - } - }() - - // wait for either a local->remote error or for copying from remote->local to finish - select { - case <-remoteDone: - case <-localError: - } - - // always expect something on errorChan (it may be nil) - err = <-errorChan - if err != nil { - runtime.HandleError(err) - } -} - -func (pf *PortForwarder) Close() { - // stop all listeners - for _, l := range pf.listeners { - if err := l.Close(); err != nil { - runtime.HandleError(fmt.Errorf("error closing listener: %v", err)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/portforward_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/portforward_test.go deleted file mode 100644 index 31689eed2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/portforward/portforward_test.go +++ /dev/null @@ -1,394 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 portforward - -import ( - "bytes" - "fmt" - "io" - "net" - "net/http" - "net/http/httptest" - "net/url" - "os" - "reflect" - "strings" - "sync" - "testing" - "time" - - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/remotecommand" - kubeletserver "k8s.io/kubernetes/pkg/kubelet/server" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/httpstream" -) - -type fakeDialer struct { - dialed bool - conn httpstream.Connection - err error - negotiatedProtocol string -} - -func (d *fakeDialer) Dial(protocols ...string) (httpstream.Connection, string, error) { - d.dialed = true - return d.conn, d.negotiatedProtocol, d.err -} - -func TestParsePortsAndNew(t *testing.T) { - tests := []struct { - input []string - expected []ForwardedPort - expectParseError bool - expectNewError bool - }{ - {input: []string{}, expectNewError: true}, - {input: []string{"a"}, expectParseError: true, expectNewError: true}, - {input: []string{":a"}, expectParseError: true, expectNewError: true}, - {input: []string{"-1"}, expectParseError: true, expectNewError: true}, - {input: []string{"65536"}, expectParseError: true, expectNewError: true}, - {input: []string{"0"}, expectParseError: true, expectNewError: true}, - {input: []string{"0:0"}, expectParseError: true, expectNewError: true}, - {input: []string{"a:5000"}, expectParseError: true, expectNewError: true}, - {input: []string{"5000:a"}, expectParseError: true, expectNewError: true}, - { - input: []string{"5000", "5000:5000", "8888:5000", "5000:8888", ":5000", "0:5000"}, - expected: []ForwardedPort{ - {5000, 5000}, - {5000, 5000}, - {8888, 5000}, - {5000, 8888}, - {0, 5000}, - {0, 5000}, - }, - }, - } - - for i, test := range tests { - parsed, err := parsePorts(test.input) - haveError := err != nil - if e, a := test.expectParseError, haveError; e != a { - t.Fatalf("%d: parsePorts: error expected=%t, got %t: %s", i, e, a, err) - } - - dialer := &fakeDialer{} - expectedStopChan := make(chan struct{}) - pf, err := New(dialer, test.input, expectedStopChan, os.Stdout, os.Stderr) - haveError = err != nil - if e, a := test.expectNewError, haveError; e != a { - t.Fatalf("%d: New: error expected=%t, got %t: %s", i, e, a, err) - } - - if test.expectParseError || test.expectNewError { - continue - } - - for pi, expectedPort := range test.expected { - if e, a := expectedPort.Local, parsed[pi].Local; e != a { - t.Fatalf("%d: local expected: %d, got: %d", i, e, a) - } - if e, a := expectedPort.Remote, parsed[pi].Remote; e != a { - t.Fatalf("%d: remote expected: %d, got: %d", i, e, a) - } - } - - if dialer.dialed { - t.Fatalf("%d: expected not dialed", i) - } - if e, a := test.expected, pf.ports; !reflect.DeepEqual(e, a) { - t.Fatalf("%d: ports: expected %#v, got %#v", i, e, a) - } - if e, a := expectedStopChan, pf.stopChan; e != a { - t.Fatalf("%d: stopChan: expected %#v, got %#v", i, e, a) - } - if pf.Ready == nil { - t.Fatalf("%d: Ready should be non-nil", i) - } - } -} - -type GetListenerTestCase struct { - Hostname string - Protocol string - ShouldRaiseError bool - ExpectedListenerAddress string -} - -func TestGetListener(t *testing.T) { - var pf PortForwarder - testCases := []GetListenerTestCase{ - { - Hostname: "localhost", - Protocol: "tcp4", - ShouldRaiseError: false, - ExpectedListenerAddress: "127.0.0.1", - }, - { - Hostname: "127.0.0.1", - Protocol: "tcp4", - ShouldRaiseError: false, - ExpectedListenerAddress: "127.0.0.1", - }, - { - Hostname: "[::1]", - Protocol: "tcp6", - ShouldRaiseError: false, - ExpectedListenerAddress: "::1", - }, - { - Hostname: "[::1]", - Protocol: "tcp4", - ShouldRaiseError: true, - }, - { - Hostname: "127.0.0.1", - Protocol: "tcp6", - ShouldRaiseError: true, - }, - { - // IPv6 address must be put into brackets. This test reveals this. - Hostname: "::1", - Protocol: "tcp6", - ShouldRaiseError: true, - }, - } - - for i, testCase := range testCases { - expectedListenerPort := "12345" - listener, err := pf.getListener(testCase.Protocol, testCase.Hostname, &ForwardedPort{12345, 12345}) - if err != nil && strings.Contains(err.Error(), "cannot assign requested address") { - t.Logf("Can't test #%d: %v", i, err) - continue - } - errorRaised := err != nil - - if testCase.ShouldRaiseError != errorRaised { - t.Errorf("Test case #%d failed: Data %v an error has been raised(%t) where it should not (or reciprocally): %v", i, testCase, testCase.ShouldRaiseError, err) - continue - } - if errorRaised { - continue - } - - if listener == nil { - t.Errorf("Test case #%d did not raise an error but failed in initializing listener", i) - continue - } - - host, port, _ := net.SplitHostPort(listener.Addr().String()) - t.Logf("Asked a %s forward for: %s:%v, got listener %s:%s, expected: %s", testCase.Protocol, testCase.Hostname, 12345, host, port, expectedListenerPort) - if host != testCase.ExpectedListenerAddress { - t.Errorf("Test case #%d failed: Listener does not listen on exepected address: asked %v got %v", i, testCase.ExpectedListenerAddress, host) - } - if port != expectedListenerPort { - t.Errorf("Test case #%d failed: Listener does not listen on exepected port: asked %v got %v", i, expectedListenerPort, port) - - } - listener.Close() - - } -} - -// fakePortForwarder simulates port forwarding for testing. It implements -// kubeletserver.PortForwarder. -type fakePortForwarder struct { - lock sync.Mutex - // stores data expected from the stream per port - expected map[uint16]string - // stores data received from the stream per port - received map[uint16]string - // data to be sent to the stream per port - send map[uint16]string -} - -var _ kubeletserver.PortForwarder = &fakePortForwarder{} - -func (pf *fakePortForwarder) PortForward(name string, uid types.UID, port uint16, stream io.ReadWriteCloser) error { - defer stream.Close() - - // read from the client - received := make([]byte, len(pf.expected[port])) - n, err := stream.Read(received) - if err != nil { - return fmt.Errorf("error reading from client for port %d: %v", port, err) - } - if n != len(pf.expected[port]) { - return fmt.Errorf("unexpected length read from client for port %d: got %d, expected %d. data=%q", port, n, len(pf.expected[port]), string(received)) - } - - // store the received content - pf.lock.Lock() - pf.received[port] = string(received) - pf.lock.Unlock() - - // send the hardcoded data to the client - io.Copy(stream, strings.NewReader(pf.send[port])) - - return nil -} - -// fakePortForwardServer creates an HTTP server that can handle port forwarding -// requests. -func fakePortForwardServer(t *testing.T, testName string, serverSends, expectedFromClient map[uint16]string) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - pf := &fakePortForwarder{ - expected: expectedFromClient, - received: make(map[uint16]string), - send: serverSends, - } - kubeletserver.ServePortForward(w, req, pf, "pod", "uid", 0, 10*time.Second) - - for port, expected := range expectedFromClient { - actual, ok := pf.received[port] - if !ok { - t.Errorf("%s: server didn't receive any data for port %d", testName, port) - continue - } - - if expected != actual { - t.Errorf("%s: server expected to receive %q, got %q for port %d", testName, expected, actual, port) - } - } - - for port, actual := range pf.received { - if _, ok := expectedFromClient[port]; !ok { - t.Errorf("%s: server unexpectedly received %q for port %d", testName, actual, port) - } - } - }) -} - -func TestForwardPorts(t *testing.T) { - tests := map[string]struct { - ports []string - clientSends map[uint16]string - serverSends map[uint16]string - }{ - "forward 1 port with no data either direction": { - ports: []string{"5000"}, - }, - "forward 2 ports with bidirectional data": { - ports: []string{"5001", "6000"}, - clientSends: map[uint16]string{ - 5001: "abcd", - 6000: "ghij", - }, - serverSends: map[uint16]string{ - 5001: "1234", - 6000: "5678", - }, - }, - } - - for testName, test := range tests { - server := httptest.NewServer(fakePortForwardServer(t, testName, test.serverSends, test.clientSends)) - - url, _ := url.Parse(server.URL) - exec, err := remotecommand.NewExecutor(&restclient.Config{}, "POST", url) - if err != nil { - t.Fatal(err) - } - - stopChan := make(chan struct{}, 1) - - pf, err := New(exec, test.ports, stopChan, os.Stdout, os.Stderr) - if err != nil { - t.Fatalf("%s: unexpected error calling New: %v", testName, err) - } - - doneChan := make(chan error) - go func() { - doneChan <- pf.ForwardPorts() - }() - <-pf.Ready - - for port, data := range test.clientSends { - clientConn, err := net.Dial("tcp", fmt.Sprintf("localhost:%d", port)) - if err != nil { - t.Errorf("%s: error dialing %d: %s", testName, port, err) - server.Close() - continue - } - defer clientConn.Close() - - n, err := clientConn.Write([]byte(data)) - if err != nil && err != io.EOF { - t.Errorf("%s: Error sending data '%s': %s", testName, data, err) - server.Close() - continue - } - if n == 0 { - t.Errorf("%s: unexpected write of 0 bytes", testName) - server.Close() - continue - } - b := make([]byte, 4) - n, err = clientConn.Read(b) - if err != nil && err != io.EOF { - t.Errorf("%s: Error reading data: %s", testName, err) - server.Close() - continue - } - if !bytes.Equal([]byte(test.serverSends[port]), b) { - t.Errorf("%s: expected to read '%s', got '%s'", testName, test.serverSends[port], b) - server.Close() - continue - } - } - // tell r.ForwardPorts to stop - close(stopChan) - - // wait for r.ForwardPorts to actually return - err = <-doneChan - if err != nil { - t.Errorf("%s: unexpected error: %s", testName, err) - } - server.Close() - } - -} - -func TestForwardPortsReturnsErrorWhenAllBindsFailed(t *testing.T) { - server := httptest.NewServer(fakePortForwardServer(t, "allBindsFailed", nil, nil)) - defer server.Close() - - url, _ := url.Parse(server.URL) - exec, err := remotecommand.NewExecutor(&restclient.Config{}, "POST", url) - if err != nil { - t.Fatal(err) - } - - stopChan1 := make(chan struct{}, 1) - defer close(stopChan1) - - pf1, err := New(exec, []string{"5555"}, stopChan1, os.Stdout, os.Stderr) - if err != nil { - t.Fatalf("error creating pf1: %v", err) - } - go pf1.ForwardPorts() - <-pf1.Ready - - stopChan2 := make(chan struct{}, 1) - pf2, err := New(exec, []string{"5555"}, stopChan2, os.Stdout, os.Stderr) - if err != nil { - t.Fatalf("error creating pf2: %v", err) - } - if err := pf2.ForwardPorts(); err == nil { - t.Fatal("expected non-nil error for pf2.ForwardPorts") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/doc.go deleted file mode 100644 index 88197ed0d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 remotecommand adds support for executing commands in containers, -// with support for separate stdin, stdout, and stderr streams, as well as -// TTY. -package remotecommand diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/remotecommand.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/remotecommand.go deleted file mode 100644 index 7144f3093..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/remotecommand.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 remotecommand - -import ( - "fmt" - "io" - "net/http" - "net/url" - - "github.com/golang/glog" - - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/transport" - "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" - "k8s.io/kubernetes/pkg/util/httpstream" - "k8s.io/kubernetes/pkg/util/httpstream/spdy" -) - -// Executor is an interface for transporting shell-style streams. -type Executor interface { - // Stream initiates the transport of the standard shell streams. It will transport any - // non-nil stream to a remote system, and return an error if a problem occurs. If tty - // is set, the stderr stream is not used (raw TTY manages stdout and stderr over the - // stdout stream). - Stream(supportedProtocols []string, stdin io.Reader, stdout, stderr io.Writer, tty bool) error -} - -// StreamExecutor supports the ability to dial an httpstream connection and the ability to -// run a command line stream protocol over that dialer. -type StreamExecutor interface { - Executor - httpstream.Dialer -} - -// streamExecutor handles transporting standard shell streams over an httpstream connection. -type streamExecutor struct { - upgrader httpstream.UpgradeRoundTripper - transport http.RoundTripper - - method string - url *url.URL -} - -// NewExecutor connects to the provided server and upgrades the connection to -// multiplexed bidirectional streams. The current implementation uses SPDY, -// but this could be replaced with HTTP/2 once it's available, or something else. -// TODO: the common code between this and portforward could be abstracted. -func NewExecutor(config *restclient.Config, method string, url *url.URL) (StreamExecutor, error) { - tlsConfig, err := restclient.TLSConfigFor(config) - if err != nil { - return nil, err - } - - upgradeRoundTripper := spdy.NewRoundTripper(tlsConfig) - wrapper, err := restclient.HTTPWrappersForConfig(config, upgradeRoundTripper) - if err != nil { - return nil, err - } - - return &streamExecutor{ - upgrader: upgradeRoundTripper, - transport: wrapper, - method: method, - url: url, - }, nil -} - -// NewStreamExecutor upgrades the request so that it supports multiplexed bidirectional -// streams. This method takes a stream upgrader and an optional function that is invoked -// to wrap the round tripper. This method may be used by clients that are lower level than -// Kubernetes clients or need to provide their own upgrade round tripper. -func NewStreamExecutor(upgrader httpstream.UpgradeRoundTripper, fn func(http.RoundTripper) http.RoundTripper, method string, url *url.URL) (StreamExecutor, error) { - var rt http.RoundTripper = upgrader - if fn != nil { - rt = fn(rt) - } - return &streamExecutor{ - upgrader: upgrader, - transport: rt, - method: method, - url: url, - }, nil -} - -// Dial opens a connection to a remote server and attempts to negotiate a SPDY -// connection. Upon success, it returns the connection and the protocol -// selected by the server. -func (e *streamExecutor) Dial(protocols ...string) (httpstream.Connection, string, error) { - rt := transport.DebugWrappers(e.transport) - - // TODO the client probably shouldn't be created here, as it doesn't allow - // flexibility to allow callers to configure it. - client := &http.Client{Transport: rt} - - req, err := http.NewRequest(e.method, e.url.String(), nil) - if err != nil { - return nil, "", fmt.Errorf("error creating request: %v", err) - } - for i := range protocols { - req.Header.Add(httpstream.HeaderProtocolVersion, protocols[i]) - } - - resp, err := client.Do(req) - if err != nil { - return nil, "", fmt.Errorf("error sending request: %v", err) - } - defer resp.Body.Close() - - conn, err := e.upgrader.NewConnection(resp) - if err != nil { - return nil, "", err - } - - return conn, resp.Header.Get(httpstream.HeaderProtocolVersion), nil -} - -type streamProtocolHandler interface { - stream(httpstream.Connection) error -} - -// Stream opens a protocol streamer to the server and streams until a client closes -// the connection or the server disconnects. -func (e *streamExecutor) Stream(supportedProtocols []string, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { - conn, protocol, err := e.Dial(supportedProtocols...) - if err != nil { - return err - } - defer conn.Close() - - var streamer streamProtocolHandler - - switch protocol { - case remotecommand.StreamProtocolV2Name: - streamer = &streamProtocolV2{ - stdin: stdin, - stdout: stdout, - stderr: stderr, - tty: tty, - } - case "": - glog.V(4).Infof("The server did not negotiate a streaming protocol version. Falling back to %s", remotecommand.StreamProtocolV1Name) - fallthrough - case remotecommand.StreamProtocolV1Name: - streamer = &streamProtocolV1{ - stdin: stdin, - stdout: stdout, - stderr: stderr, - tty: tty, - } - } - - return streamer.stream(conn) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/remotecommand_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/remotecommand_test.go deleted file mode 100644 index f231a7f49..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/remotecommand_test.go +++ /dev/null @@ -1,357 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 remotecommand - -import ( - "bytes" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/httpstream" -) - -type fakeExecutor struct { - t *testing.T - testName string - errorData string - stdoutData string - stderrData string - expectStdin bool - stdinReceived bytes.Buffer - tty bool - messageCount int - command []string - exec bool -} - -func (ex *fakeExecutor) ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool) error { - return ex.run(name, uid, container, cmd, in, out, err, tty) -} - -func (ex *fakeExecutor) AttachContainer(name string, uid types.UID, container string, in io.Reader, out, err io.WriteCloser, tty bool) error { - return ex.run(name, uid, container, nil, in, out, err, tty) -} - -func (ex *fakeExecutor) run(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool) error { - ex.command = cmd - ex.tty = tty - - if e, a := "pod", name; e != a { - ex.t.Errorf("%s: pod: expected %q, got %q", ex.testName, e, a) - } - if e, a := "uid", uid; e != string(a) { - ex.t.Errorf("%s: uid: expected %q, got %q", ex.testName, e, a) - } - if ex.exec { - if e, a := "ls /", strings.Join(ex.command, " "); e != a { - ex.t.Errorf("%s: command: expected %q, got %q", ex.testName, e, a) - } - } else { - if len(ex.command) > 0 { - ex.t.Errorf("%s: command: expected nothing, got %v", ex.testName, ex.command) - } - } - - if len(ex.errorData) > 0 { - return errors.New(ex.errorData) - } - - if len(ex.stdoutData) > 0 { - for i := 0; i < ex.messageCount; i++ { - fmt.Fprint(out, ex.stdoutData) - } - } - - if len(ex.stderrData) > 0 { - for i := 0; i < ex.messageCount; i++ { - fmt.Fprint(err, ex.stderrData) - } - } - - if ex.expectStdin { - io.Copy(&ex.stdinReceived, in) - } - - return nil -} - -func fakeServer(t *testing.T, testName string, exec bool, stdinData, stdoutData, stderrData, errorData string, tty bool, messageCount int, serverProtocols []string) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - executor := &fakeExecutor{ - t: t, - testName: testName, - errorData: errorData, - stdoutData: stdoutData, - stderrData: stderrData, - expectStdin: len(stdinData) > 0, - tty: tty, - messageCount: messageCount, - exec: exec, - } - - if exec { - remotecommand.ServeExec(w, req, executor, "pod", "uid", "container", 0, 10*time.Second, serverProtocols) - } else { - remotecommand.ServeAttach(w, req, executor, "pod", "uid", "container", 0, 10*time.Second, serverProtocols) - } - - if e, a := strings.Repeat(stdinData, messageCount), executor.stdinReceived.String(); e != a { - t.Errorf("%s: stdin: expected %q, got %q", testName, e, a) - } - }) -} - -func TestStream(t *testing.T) { - testCases := []struct { - TestName string - Stdin string - Stdout string - Stderr string - Error string - Tty bool - MessageCount int - ClientProtocols []string - ServerProtocols []string - }{ - { - TestName: "error", - Error: "bail", - Stdout: "a", - ClientProtocols: []string{remotecommand.StreamProtocolV2Name}, - ServerProtocols: []string{remotecommand.StreamProtocolV2Name}, - }, - { - TestName: "in/out/err", - Stdin: "a", - Stdout: "b", - Stderr: "c", - MessageCount: 100, - ClientProtocols: []string{remotecommand.StreamProtocolV2Name}, - ServerProtocols: []string{remotecommand.StreamProtocolV2Name}, - }, - { - TestName: "in/out/tty", - Stdin: "a", - Stdout: "b", - Tty: true, - MessageCount: 100, - ClientProtocols: []string{remotecommand.StreamProtocolV2Name}, - ServerProtocols: []string{remotecommand.StreamProtocolV2Name}, - }, - { - // 1.0 kubectl, 1.0 kubelet - TestName: "unversioned client, unversioned server", - Stdout: "b", - Stderr: "c", - MessageCount: 1, - ClientProtocols: []string{}, - ServerProtocols: []string{}, - }, - { - // 1.0 kubectl, 1.1+ kubelet - TestName: "unversioned client, versioned server", - Stdout: "b", - Stderr: "c", - MessageCount: 1, - ClientProtocols: []string{}, - ServerProtocols: []string{remotecommand.StreamProtocolV2Name, remotecommand.StreamProtocolV1Name}, - }, - { - // 1.1+ kubectl, 1.0 kubelet - TestName: "versioned client, unversioned server", - Stdout: "b", - Stderr: "c", - MessageCount: 1, - ClientProtocols: []string{remotecommand.StreamProtocolV2Name, remotecommand.StreamProtocolV1Name}, - ServerProtocols: []string{}, - }, - } - - for _, testCase := range testCases { - for _, exec := range []bool{true, false} { - var name string - if exec { - name = testCase.TestName + " (exec)" - } else { - name = testCase.TestName + " (attach)" - } - var ( - streamIn io.Reader - streamOut, streamErr io.Writer - ) - localOut := &bytes.Buffer{} - localErr := &bytes.Buffer{} - - server := httptest.NewServer(fakeServer(t, name, exec, testCase.Stdin, testCase.Stdout, testCase.Stderr, testCase.Error, testCase.Tty, testCase.MessageCount, testCase.ServerProtocols)) - - url, _ := url.ParseRequestURI(server.URL) - config := restclient.ContentConfig{ - GroupVersion: &unversioned.GroupVersion{Group: "x"}, - NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), - } - c, err := restclient.NewRESTClient(url, "", config, -1, -1, nil, nil) - if err != nil { - t.Fatalf("failed to create a client: %v", err) - } - req := c.Post().Resource("testing") - - if exec { - req.Param("command", "ls") - req.Param("command", "/") - } - - if len(testCase.Stdin) > 0 { - req.Param(api.ExecStdinParam, "1") - streamIn = strings.NewReader(strings.Repeat(testCase.Stdin, testCase.MessageCount)) - } - - if len(testCase.Stdout) > 0 { - req.Param(api.ExecStdoutParam, "1") - streamOut = localOut - } - - if testCase.Tty { - req.Param(api.ExecTTYParam, "1") - } else if len(testCase.Stderr) > 0 { - req.Param(api.ExecStderrParam, "1") - streamErr = localErr - } - - conf := &restclient.Config{ - Host: server.URL, - } - e, err := NewExecutor(conf, "POST", req.URL()) - if err != nil { - t.Errorf("%s: unexpected error: %v", name, err) - continue - } - err = e.Stream(testCase.ClientProtocols, streamIn, streamOut, streamErr, testCase.Tty) - hasErr := err != nil - - if len(testCase.Error) > 0 { - if !hasErr { - t.Errorf("%s: expected an error", name) - } else { - if e, a := testCase.Error, err.Error(); !strings.Contains(a, e) { - t.Errorf("%s: expected error stream read %q, got %q", name, e, a) - } - } - - server.Close() - continue - } - - if hasErr { - t.Errorf("%s: unexpected error: %v", name, err) - server.Close() - continue - } - - if len(testCase.Stdout) > 0 { - if e, a := strings.Repeat(testCase.Stdout, testCase.MessageCount), localOut; e != a.String() { - t.Errorf("%s: expected stdout data '%s', got '%s'", name, e, a) - } - } - - if testCase.Stderr != "" { - if e, a := strings.Repeat(testCase.Stderr, testCase.MessageCount), localErr; e != a.String() { - t.Errorf("%s: expected stderr data '%s', got '%s'", name, e, a) - } - } - - server.Close() - } - } -} - -type fakeUpgrader struct { - req *http.Request - resp *http.Response - conn httpstream.Connection - err, connErr error - checkResponse bool - - t *testing.T -} - -func (u *fakeUpgrader) RoundTrip(req *http.Request) (*http.Response, error) { - u.req = req - return u.resp, u.err -} - -func (u *fakeUpgrader) NewConnection(resp *http.Response) (httpstream.Connection, error) { - if u.checkResponse && u.resp != resp { - u.t.Errorf("response objects passed did not match: %#v", resp) - } - return u.conn, u.connErr -} - -type fakeConnection struct { - httpstream.Connection -} - -// Dial is the common functionality between any stream based upgrader, regardless of protocol. -// This method ensures that someone can use a generic stream executor without being dependent -// on the core Kube client config behavior. -func TestDial(t *testing.T) { - upgrader := &fakeUpgrader{ - t: t, - checkResponse: true, - conn: &fakeConnection{}, - resp: &http.Response{ - StatusCode: http.StatusSwitchingProtocols, - Body: ioutil.NopCloser(&bytes.Buffer{}), - }, - } - var called bool - testFn := func(rt http.RoundTripper) http.RoundTripper { - if rt != upgrader { - t.Fatalf("unexpected round tripper: %#v", rt) - } - called = true - return rt - } - exec, err := NewStreamExecutor(upgrader, testFn, "POST", &url.URL{Host: "something.com", Scheme: "https"}) - if err != nil { - t.Fatal(err) - } - conn, protocol, err := exec.Dial("protocol1") - if err != nil { - t.Fatal(err) - } - if conn != upgrader.conn { - t.Errorf("unexpected connection: %#v", conn) - } - if !called { - t.Errorf("wrapper not called") - } - _ = protocol -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/v1.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/v1.go deleted file mode 100644 index f5428e0f9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/v1.go +++ /dev/null @@ -1,156 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 remotecommand - -import ( - "fmt" - "io" - "io/ioutil" - "net/http" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/util/httpstream" -) - -// streamProtocolV1 implements the first version of the streaming exec & attach -// protocol. This version has some bugs, such as not being able to detecte when -// non-interactive stdin data has ended. See http://issues.k8s.io/13394 and -// http://issues.k8s.io/13395 for more details. -type streamProtocolV1 struct { - stdin io.Reader - stdout io.Writer - stderr io.Writer - tty bool -} - -var _ streamProtocolHandler = &streamProtocolV1{} - -func (e *streamProtocolV1) stream(conn httpstream.Connection) error { - doneChan := make(chan struct{}, 2) - errorChan := make(chan error) - - cp := func(s string, dst io.Writer, src io.Reader) { - glog.V(6).Infof("Copying %s", s) - defer glog.V(6).Infof("Done copying %s", s) - if _, err := io.Copy(dst, src); err != nil && err != io.EOF { - glog.Errorf("Error copying %s: %v", s, err) - } - if s == api.StreamTypeStdout || s == api.StreamTypeStderr { - doneChan <- struct{}{} - } - } - - var ( - err error - errorStream, remoteStdin, remoteStdout, remoteStderr httpstream.Stream - ) - - // set up all the streams first - headers := http.Header{} - headers.Set(api.StreamType, api.StreamTypeError) - errorStream, err = conn.CreateStream(headers) - if err != nil { - return err - } - defer errorStream.Reset() - - // Create all the streams first, then start the copy goroutines. The server doesn't start its copy - // goroutines until it's received all of the streams. If the client creates the stdin stream and - // immediately begins copying stdin data to the server, it's possible to overwhelm and wedge the - // spdy frame handler in the server so that it is full of unprocessed frames. The frames aren't - // getting processed because the server hasn't started its copying, and it won't do that until it - // gets all the streams. By creating all the streams first, we ensure that the server is ready to - // process data before the client starts sending any. See https://issues.k8s.io/16373 for more info. - if e.stdin != nil { - headers.Set(api.StreamType, api.StreamTypeStdin) - remoteStdin, err = conn.CreateStream(headers) - if err != nil { - return err - } - defer remoteStdin.Reset() - } - - if e.stdout != nil { - headers.Set(api.StreamType, api.StreamTypeStdout) - remoteStdout, err = conn.CreateStream(headers) - if err != nil { - return err - } - defer remoteStdout.Reset() - } - - if e.stderr != nil && !e.tty { - headers.Set(api.StreamType, api.StreamTypeStderr) - remoteStderr, err = conn.CreateStream(headers) - if err != nil { - return err - } - defer remoteStderr.Reset() - } - - // now that all the streams have been created, proceed with reading & copying - - // always read from errorStream - go func() { - message, err := ioutil.ReadAll(errorStream) - if err != nil && err != io.EOF { - errorChan <- fmt.Errorf("Error reading from error stream: %s", err) - return - } - if len(message) > 0 { - errorChan <- fmt.Errorf("Error executing remote command: %s", message) - return - } - }() - - if e.stdin != nil { - // TODO this goroutine will never exit cleanly (the io.Copy never unblocks) - // because stdin is not closed until the process exits. If we try to call - // stdin.Close(), it returns no error but doesn't unblock the copy. It will - // exit when the process exits, instead. - go cp(api.StreamTypeStdin, remoteStdin, e.stdin) - } - - waitCount := 0 - completedStreams := 0 - - if e.stdout != nil { - waitCount++ - go cp(api.StreamTypeStdout, e.stdout, remoteStdout) - } - - if e.stderr != nil && !e.tty { - waitCount++ - go cp(api.StreamTypeStderr, e.stderr, remoteStderr) - } - -Loop: - for { - select { - case <-doneChan: - completedStreams++ - if completedStreams == waitCount { - break Loop - } - case err := <-errorChan: - return err - } - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/v2.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/v2.go deleted file mode 100644 index 67e8637cf..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/remotecommand/v2.go +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 remotecommand - -import ( - "fmt" - "io" - "io/ioutil" - "net/http" - "sync" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/util/httpstream" - "k8s.io/kubernetes/pkg/util/runtime" -) - -// streamProtocolV2 implements version 2 of the streaming protocol for attach -// and exec. The original streaming protocol was unversioned. As a result, this -// version is referred to as version 2, even though it is the first actual -// numbered version. -type streamProtocolV2 struct { - stdin io.Reader - stdout io.Writer - stderr io.Writer - tty bool -} - -var _ streamProtocolHandler = &streamProtocolV2{} - -func (e *streamProtocolV2) stream(conn httpstream.Connection) error { - var ( - err error - errorStream, remoteStdin, remoteStdout, remoteStderr httpstream.Stream - ) - - headers := http.Header{} - - // set up all the streams first - // set up error stream - errorChan := make(chan error) - headers.Set(api.StreamType, api.StreamTypeError) - errorStream, err = conn.CreateStream(headers) - if err != nil { - return err - } - - // set up stdin stream - if e.stdin != nil { - headers.Set(api.StreamType, api.StreamTypeStdin) - remoteStdin, err = conn.CreateStream(headers) - if err != nil { - return err - } - } - - // set up stdout stream - if e.stdout != nil { - headers.Set(api.StreamType, api.StreamTypeStdout) - remoteStdout, err = conn.CreateStream(headers) - if err != nil { - return err - } - } - - // set up stderr stream - if e.stderr != nil && !e.tty { - headers.Set(api.StreamType, api.StreamTypeStderr) - remoteStderr, err = conn.CreateStream(headers) - if err != nil { - return err - } - } - - // now that all the streams have been created, proceed with reading & copying - - // always read from errorStream - go func() { - message, err := ioutil.ReadAll(errorStream) - switch { - case err != nil && err != io.EOF: - errorChan <- fmt.Errorf("error reading from error stream: %s", err) - case len(message) > 0: - errorChan <- fmt.Errorf("error executing remote command: %s", message) - default: - errorChan <- nil - } - close(errorChan) - }() - - var wg sync.WaitGroup - var once sync.Once - - if e.stdin != nil { - // copy from client's stdin to container's stdin - go func() { - // if e.stdin is noninteractive, e.g. `echo abc | kubectl exec -i -- cat`, make sure - // we close remoteStdin as soon as the copy from e.stdin to remoteStdin finishes. Otherwise - // the executed command will remain running. - defer once.Do(func() { remoteStdin.Close() }) - - if _, err := io.Copy(remoteStdin, e.stdin); err != nil { - runtime.HandleError(err) - } - }() - - // read from remoteStdin until the stream is closed. this is essential to - // be able to exit interactive sessions cleanly and not leak goroutines or - // hang the client's terminal. - // - // go-dockerclient's current hijack implementation - // (https://github.com/fsouza/go-dockerclient/blob/89f3d56d93788dfe85f864a44f85d9738fca0670/client.go#L564) - // waits for all three streams (stdin/stdout/stderr) to finish copying - // before returning. When hijack finishes copying stdout/stderr, it calls - // Close() on its side of remoteStdin, which allows this copy to complete. - // When that happens, we must Close() on our side of remoteStdin, to - // allow the copy in hijack to complete, and hijack to return. - go func() { - defer once.Do(func() { remoteStdin.Close() }) - // this "copy" doesn't actually read anything - it's just here to wait for - // the server to close remoteStdin. - if _, err := io.Copy(ioutil.Discard, remoteStdin); err != nil { - runtime.HandleError(err) - } - }() - } - - if e.stdout != nil { - wg.Add(1) - go func() { - defer wg.Done() - if _, err := io.Copy(e.stdout, remoteStdout); err != nil { - runtime.HandleError(err) - } - }() - } - - if e.stderr != nil && !e.tty { - wg.Add(1) - go func() { - defer wg.Done() - if _, err := io.Copy(e.stderr, remoteStderr); err != nil { - runtime.HandleError(err) - } - }() - } - - // we're waiting for stdout/stderr to finish copying - wg.Wait() - - // waits for errorStream to finish reading with an error or nil - return <-errorChan -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/replica_sets_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/replica_sets_test.go deleted file mode 100644 index 2a0e8142c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/replica_sets_test.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 unversioned_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getReplicaSetResourceName() string { - return "replicasets" -} - -func TestListReplicaSets(t *testing.T) { - ns := api.NamespaceAll - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getReplicaSetResourceName(), ns, ""), - }, - Response: simple.Response{StatusCode: 200, - Body: &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - }, - }, - } - receivedRSList, err := c.Setup(t).Extensions().ReplicaSets(ns).List(api.ListOptions{}) - c.Validate(t, receivedRSList, err) -} - -func TestGetReplicaSet(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Extensions.ResourcePath(getReplicaSetResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedRS, err := c.Setup(t).Extensions().ReplicaSets(ns).Get("foo") - c.Validate(t, receivedRS, err) -} - -func TestGetReplicaSetWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).Extensions().ReplicaSets(ns).Get("") - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} - -func TestUpdateReplicaSet(t *testing.T) { - ns := api.NamespaceDefault - requestRS := &extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getReplicaSetResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedRS, err := c.Setup(t).Extensions().ReplicaSets(ns).Update(requestRS) - c.Validate(t, receivedRS, err) -} - -func TestUpdateStatusReplicaSet(t *testing.T) { - ns := api.NamespaceDefault - requestRS := &extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getReplicaSetResourceName(), ns, "foo") + "/status", Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - Status: extensions.ReplicaSetStatus{ - Replicas: 2, - }, - }, - }, - } - receivedRS, err := c.Setup(t).Extensions().ReplicaSets(ns).UpdateStatus(requestRS) - c.Validate(t, receivedRS, err) -} -func TestDeleteReplicaSet(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Extensions.ResourcePath(getReplicaSetResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Extensions().ReplicaSets(ns).Delete("foo", nil) - c.Validate(t, nil, err) -} - -func TestCreateReplicaSet(t *testing.T) { - ns := api.NamespaceDefault - requestRS := &extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "POST", Path: testapi.Extensions.ResourcePath(getReplicaSetResourceName(), ns, ""), Body: requestRS, Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 2, - Template: api.PodTemplateSpec{}, - }, - }, - }, - } - receivedRS, err := c.Setup(t).Extensions().ReplicaSets(ns).Create(requestRS) - c.Validate(t, receivedRS, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/replication_controllers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/replication_controllers_test.go deleted file mode 100644 index de0458ce4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/replication_controllers_test.go +++ /dev/null @@ -1,200 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getRCResourceName() string { - return "replicationcontrollers" -} - -func TestListControllers(t *testing.T) { - ns := api.NamespaceAll - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getRCResourceName(), ns, ""), - }, - Response: simple.Response{StatusCode: 200, - Body: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Template: &api.PodTemplateSpec{}, - }, - }, - }, - }, - }, - } - receivedControllerList, err := c.Setup(t).ReplicationControllers(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, receivedControllerList, err) - -} - -func TestGetController(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Default.ResourcePath(getRCResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Template: &api.PodTemplateSpec{}, - }, - }, - }, - } - receivedController, err := c.Setup(t).ReplicationControllers(ns).Get("foo") - defer c.Close() - c.Validate(t, receivedController, err) -} - -func TestGetControllerWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).ReplicationControllers(ns).Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} - -func TestUpdateController(t *testing.T) { - ns := api.NamespaceDefault - requestController := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getRCResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Template: &api.PodTemplateSpec{}, - }, - }, - }, - } - receivedController, err := c.Setup(t).ReplicationControllers(ns).Update(requestController) - defer c.Close() - c.Validate(t, receivedController, err) -} - -func TestUpdateStatusController(t *testing.T) { - ns := api.NamespaceDefault - requestController := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getRCResourceName(), ns, "foo") + "/status", Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Template: &api.PodTemplateSpec{}, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 2, - }, - }, - }, - } - receivedController, err := c.Setup(t).ReplicationControllers(ns).UpdateStatus(requestController) - defer c.Close() - c.Validate(t, receivedController, err) -} -func TestDeleteController(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath(getRCResourceName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).ReplicationControllers(ns).Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestCreateController(t *testing.T) { - ns := api.NamespaceDefault - requestController := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "POST", Path: testapi.Default.ResourcePath(getRCResourceName(), ns, ""), Body: requestController, Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Template: &api.PodTemplateSpec{}, - }, - }, - }, - } - receivedController, err := c.Setup(t).ReplicationControllers(ns).Create(requestController) - defer c.Close() - c.Validate(t, receivedController, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/resource_quotas_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/resource_quotas_test.go deleted file mode 100644 index 73dba8dfb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/resource_quotas_test.go +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getResourceQuotasResoureName() string { - return "resourcequotas" -} - -func TestResourceQuotaCreate(t *testing.T) { - ns := api.NamespaceDefault - resourceQuota := &api.ResourceQuota{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - api.ResourcePods: resource.MustParse("10"), - api.ResourceServices: resource.MustParse("10"), - api.ResourceReplicationControllers: resource.MustParse("10"), - api.ResourceQuotas: resource.MustParse("10"), - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath(getResourceQuotasResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: resourceQuota, - }, - Response: simple.Response{StatusCode: 200, Body: resourceQuota}, - } - - response, err := c.Setup(t).ResourceQuotas(ns).Create(resourceQuota) - defer c.Close() - c.Validate(t, response, err) -} - -func TestResourceQuotaGet(t *testing.T) { - ns := api.NamespaceDefault - resourceQuota := &api.ResourceQuota{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - }, - Spec: api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - api.ResourcePods: resource.MustParse("10"), - api.ResourceServices: resource.MustParse("10"), - api.ResourceReplicationControllers: resource.MustParse("10"), - api.ResourceQuotas: resource.MustParse("10"), - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getResourceQuotasResoureName(), ns, "abc"), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: resourceQuota}, - } - - response, err := c.Setup(t).ResourceQuotas(ns).Get("abc") - defer c.Close() - c.Validate(t, response, err) -} - -func TestResourceQuotaList(t *testing.T) { - ns := api.NamespaceDefault - - resourceQuotaList := &api.ResourceQuotaList{ - Items: []api.ResourceQuota{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath(getResourceQuotasResoureName(), ns, ""), - Query: simple.BuildQueryValues(nil), - Body: nil, - }, - Response: simple.Response{StatusCode: 200, Body: resourceQuotaList}, - } - response, err := c.Setup(t).ResourceQuotas(ns).List(api.ListOptions{}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestResourceQuotaUpdate(t *testing.T) { - ns := api.NamespaceDefault - resourceQuota := &api.ResourceQuota{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - ResourceVersion: "1", - }, - Spec: api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - api.ResourcePods: resource.MustParse("10"), - api.ResourceServices: resource.MustParse("10"), - api.ResourceReplicationControllers: resource.MustParse("10"), - api.ResourceQuotas: resource.MustParse("10"), - }, - }, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath(getResourceQuotasResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: resourceQuota}, - } - response, err := c.Setup(t).ResourceQuotas(ns).Update(resourceQuota) - defer c.Close() - c.Validate(t, response, err) -} - -func TestResourceQuotaStatusUpdate(t *testing.T) { - ns := api.NamespaceDefault - resourceQuota := &api.ResourceQuota{ - ObjectMeta: api.ObjectMeta{ - Name: "abc", - Namespace: "foo", - ResourceVersion: "1", - }, - Status: api.ResourceQuotaStatus{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100"), - api.ResourceMemory: resource.MustParse("10000"), - api.ResourcePods: resource.MustParse("10"), - api.ResourceServices: resource.MustParse("10"), - api.ResourceReplicationControllers: resource.MustParse("10"), - api.ResourceQuotas: resource.MustParse("10"), - }, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Default.ResourcePath(getResourceQuotasResoureName(), ns, "abc") + "/status", - Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: resourceQuota}, - } - response, err := c.Setup(t).ResourceQuotas(ns).UpdateStatus(resourceQuota) - defer c.Close() - c.Validate(t, response, err) -} - -func TestResourceQuotaDelete(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath(getResourceQuotasResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).ResourceQuotas(ns).Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestResourceQuotaWatch(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePathWithPrefix("watch", getResourceQuotasResoureName(), "", ""), - Query: url.Values{"resourceVersion": []string{}}}, - Response: simple.Response{StatusCode: 200}, - } - _, err := c.Setup(t).ResourceQuotas(api.NamespaceAll).Watch(api.ListOptions{}) - defer c.Close() - c.Validate(t, nil, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/services_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/services_test.go deleted file mode 100644 index fadfe2be4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/services_test.go +++ /dev/null @@ -1,238 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "net/url" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" - "k8s.io/kubernetes/pkg/labels" -) - -func TestListServices(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("services", ns, ""), - Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, - Body: &api.ServiceList{ - Items: []api.Service{ - { - ObjectMeta: api.ObjectMeta{ - Name: "name", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "one": "two", - }, - }, - }, - }, - }, - }, - } - receivedServiceList, err := c.Setup(t).Services(ns).List(api.ListOptions{}) - defer c.Close() - t.Logf("received services: %v %#v", err, receivedServiceList) - c.Validate(t, receivedServiceList, err) -} - -func TestListServicesLabels(t *testing.T) { - ns := api.NamespaceDefault - labelSelectorQueryParamName := unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("services", ns, ""), - Query: simple.BuildQueryValues(url.Values{labelSelectorQueryParamName: []string{"foo=bar,name=baz"}})}, - Response: simple.Response{StatusCode: 200, - Body: &api.ServiceList{ - Items: []api.Service{ - { - ObjectMeta: api.ObjectMeta{ - Name: "name", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "one": "two", - }, - }, - }, - }, - }, - }, - } - c.Setup(t) - defer c.Close() - c.QueryValidator[labelSelectorQueryParamName] = simple.ValidateLabels - selector := labels.Set{"foo": "bar", "name": "baz"}.AsSelector() - options := api.ListOptions{LabelSelector: selector} - receivedServiceList, err := c.Services(ns).List(options) - c.Validate(t, receivedServiceList, err) -} - -func TestGetService(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("services", ns, "1"), - Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: &api.Service{ObjectMeta: api.ObjectMeta{Name: "service-1"}}}, - } - response, err := c.Setup(t).Services(ns).Get("1") - defer c.Close() - c.Validate(t, response, err) -} - -func TestGetServiceWithNoName(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).Services(ns).Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} - -func TestCreateService(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "POST", - Path: testapi.Default.ResourcePath("services", ns, ""), - Body: &api.Service{ObjectMeta: api.ObjectMeta{Name: "service-1"}}, - Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: &api.Service{ObjectMeta: api.ObjectMeta{Name: "service-1"}}}, - } - response, err := c.Setup(t).Services(ns).Create(&api.Service{ObjectMeta: api.ObjectMeta{Name: "service-1"}}) - defer c.Close() - c.Validate(t, response, err) -} - -func TestUpdateService(t *testing.T) { - ns := api.NamespaceDefault - svc := &api.Service{ObjectMeta: api.ObjectMeta{Name: "service-1", ResourceVersion: "1"}} - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Default.ResourcePath("services", ns, "service-1"), Body: svc, Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200, Body: svc}, - } - response, err := c.Setup(t).Services(ns).Update(svc) - defer c.Close() - c.Validate(t, response, err) -} - -func TestDeleteService(t *testing.T) { - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Default.ResourcePath("services", ns, "1"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Services(ns).Delete("1") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestUpdateServiceStatus(t *testing.T) { - ns := api.NamespaceDefault - lbStatus := api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - {IP: "127.0.0.1"}, - }, - } - requestService := &api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Status: api.ServiceStatus{ - LoadBalancer: lbStatus, - }, - } - c := &simple.Client{ - Request: simple.Request{ - Method: "PUT", - Path: testapi.Default.ResourcePath("services", ns, "foo") + "/status", - Query: simple.BuildQueryValues(nil), - }, - Response: simple.Response{ - StatusCode: 200, - Body: &api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Spec: api.ServiceSpec{}, - Status: api.ServiceStatus{ - LoadBalancer: lbStatus, - }, - }, - }, - } - receivedService, err := c.Setup(t).Services(ns).UpdateStatus(requestService) - defer c.Close() - c.Validate(t, receivedService, err) -} - -func TestServiceProxyGet(t *testing.T) { - body := "OK" - ns := api.NamespaceDefault - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("services", ns, "service-1") + "/proxy/foo", - Query: simple.BuildQueryValues(url.Values{"param-name": []string{"param-value"}}), - }, - Response: simple.Response{StatusCode: 200, RawBody: &body}, - } - response, err := c.Setup(t).Services(ns).ProxyGet("", "service-1", "", "foo", map[string]string{"param-name": "param-value"}).DoRaw() - defer c.Close() - c.ValidateRaw(t, response, err) - - // With scheme and port specified - c = &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Default.ResourcePath("services", ns, "https:service-1:my-port") + "/proxy/foo", - Query: simple.BuildQueryValues(url.Values{"param-name": []string{"param-value"}}), - }, - Response: simple.Response{StatusCode: 200, RawBody: &body}, - } - response, err = c.Setup(t).Services(ns).ProxyGet("https", "service-1", "my-port", "foo", map[string]string{"param-name": "param-value"}).DoRaw() - defer c.Close() - c.ValidateRaw(t, response, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/actions.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/actions.go deleted file mode 100644 index 1e5a5e470..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/actions.go +++ /dev/null @@ -1,446 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "strings" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" -) - -func NewRootGetAction(resource, name string) GetActionImpl { - action := GetActionImpl{} - action.Verb = "get" - action.Resource = resource - action.Name = name - - return action -} - -func NewGetAction(resource, namespace, name string) GetActionImpl { - action := GetActionImpl{} - action.Verb = "get" - action.Resource = resource - action.Namespace = namespace - action.Name = name - - return action -} - -func NewRootListAction(resource string, opts api.ListOptions) ListActionImpl { - action := ListActionImpl{} - action.Verb = "list" - action.Resource = resource - labelSelector := opts.LabelSelector - if labelSelector == nil { - labelSelector = labels.Everything() - } - fieldSelector := opts.FieldSelector - if fieldSelector == nil { - fieldSelector = fields.Everything() - } - action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} - - return action -} - -func NewListAction(resource, namespace string, opts api.ListOptions) ListActionImpl { - action := ListActionImpl{} - action.Verb = "list" - action.Resource = resource - action.Namespace = namespace - labelSelector := opts.LabelSelector - if labelSelector == nil { - labelSelector = labels.Everything() - } - fieldSelector := opts.FieldSelector - if fieldSelector == nil { - fieldSelector = fields.Everything() - } - action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} - - return action -} - -func NewRootCreateAction(resource string, object runtime.Object) CreateActionImpl { - action := CreateActionImpl{} - action.Verb = "create" - action.Resource = resource - action.Object = object - - return action -} - -func NewCreateAction(resource, namespace string, object runtime.Object) CreateActionImpl { - action := CreateActionImpl{} - action.Verb = "create" - action.Resource = resource - action.Namespace = namespace - action.Object = object - - return action -} - -func NewRootUpdateAction(resource string, object runtime.Object) UpdateActionImpl { - action := UpdateActionImpl{} - action.Verb = "update" - action.Resource = resource - action.Object = object - - return action -} - -func NewUpdateAction(resource, namespace string, object runtime.Object) UpdateActionImpl { - action := UpdateActionImpl{} - action.Verb = "update" - action.Resource = resource - action.Namespace = namespace - action.Object = object - - return action -} - -func NewRootPatchAction(resource string, object runtime.Object) PatchActionImpl { - action := PatchActionImpl{} - action.Verb = "patch" - action.Resource = resource - action.Object = object - - return action -} - -func NewPatchAction(resource, namespace string, object runtime.Object) PatchActionImpl { - action := PatchActionImpl{} - action.Verb = "patch" - action.Resource = resource - action.Namespace = namespace - action.Object = object - - return action -} - -func NewUpdateSubresourceAction(resource, subresource, namespace string, object runtime.Object) UpdateActionImpl { - action := UpdateActionImpl{} - action.Verb = "update" - action.Resource = resource - action.Subresource = subresource - action.Namespace = namespace - action.Object = object - - return action -} - -func NewRootDeleteAction(resource, name string) DeleteActionImpl { - action := DeleteActionImpl{} - action.Verb = "delete" - action.Resource = resource - action.Name = name - - return action -} - -func NewDeleteAction(resource, namespace, name string) DeleteActionImpl { - action := DeleteActionImpl{} - action.Verb = "delete" - action.Resource = resource - action.Namespace = namespace - action.Name = name - - return action -} - -func NewRootDeleteCollectionAction(resource string, opts api.ListOptions) DeleteCollectionActionImpl { - action := DeleteCollectionActionImpl{} - action.Verb = "delete-collection" - action.Resource = resource - labelSelector := opts.LabelSelector - if labelSelector == nil { - labelSelector = labels.Everything() - } - fieldSelector := opts.FieldSelector - if fieldSelector == nil { - fieldSelector = fields.Everything() - } - action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} - - return action -} - -func NewDeleteCollectionAction(resource, namespace string, opts api.ListOptions) DeleteCollectionActionImpl { - action := DeleteCollectionActionImpl{} - action.Verb = "delete-collection" - action.Resource = resource - action.Namespace = namespace - labelSelector := opts.LabelSelector - if labelSelector == nil { - labelSelector = labels.Everything() - } - fieldSelector := opts.FieldSelector - if fieldSelector == nil { - fieldSelector = fields.Everything() - } - action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} - - return action -} - -func NewRootWatchAction(resource string, opts api.ListOptions) WatchActionImpl { - action := WatchActionImpl{} - action.Verb = "watch" - action.Resource = resource - labelSelector := opts.LabelSelector - if labelSelector == nil { - labelSelector = labels.Everything() - } - fieldSelector := opts.FieldSelector - if fieldSelector == nil { - fieldSelector = fields.Everything() - } - action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, opts.ResourceVersion} - - return action -} - -func NewWatchAction(resource, namespace string, opts api.ListOptions) WatchActionImpl { - action := WatchActionImpl{} - action.Verb = "watch" - action.Resource = resource - action.Namespace = namespace - labelSelector := opts.LabelSelector - if labelSelector == nil { - labelSelector = labels.Everything() - } - fieldSelector := opts.FieldSelector - if fieldSelector == nil { - fieldSelector = fields.Everything() - } - action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, opts.ResourceVersion} - - return action -} - -func NewProxyGetAction(resource, namespace, scheme, name, port, path string, params map[string]string) ProxyGetActionImpl { - action := ProxyGetActionImpl{} - action.Verb = "get" - action.Resource = resource - action.Namespace = namespace - action.Scheme = scheme - action.Name = name - action.Port = port - action.Path = path - action.Params = params - return action -} - -type ListRestrictions struct { - Labels labels.Selector - Fields fields.Selector -} -type WatchRestrictions struct { - Labels labels.Selector - Fields fields.Selector - ResourceVersion string -} - -type Action interface { - GetNamespace() string - GetVerb() string - GetResource() string - GetSubresource() string - Matches(verb, resource string) bool -} - -type GenericAction interface { - Action - GetValue() interface{} -} - -type GetAction interface { - Action - GetName() string -} - -type ListAction interface { - Action - GetListRestrictions() ListRestrictions -} - -type CreateAction interface { - Action - GetObject() runtime.Object -} - -type UpdateAction interface { - Action - GetObject() runtime.Object -} - -type DeleteAction interface { - Action - GetName() string -} - -type WatchAction interface { - Action - GetWatchRestrictions() WatchRestrictions -} - -type ProxyGetAction interface { - Action - GetScheme() string - GetName() string - GetPort() string - GetPath() string - GetParams() map[string]string -} - -type ActionImpl struct { - Namespace string - Verb string - Resource string - Subresource string -} - -func (a ActionImpl) GetNamespace() string { - return a.Namespace -} -func (a ActionImpl) GetVerb() string { - return a.Verb -} -func (a ActionImpl) GetResource() string { - return a.Resource -} -func (a ActionImpl) GetSubresource() string { - return a.Subresource -} -func (a ActionImpl) Matches(verb, resource string) bool { - return strings.ToLower(verb) == strings.ToLower(a.Verb) && - strings.ToLower(resource) == strings.ToLower(a.Resource) -} - -type GenericActionImpl struct { - ActionImpl - Value interface{} -} - -func (a GenericActionImpl) GetValue() interface{} { - return a.Value -} - -type GetActionImpl struct { - ActionImpl - Name string -} - -func (a GetActionImpl) GetName() string { - return a.Name -} - -type ListActionImpl struct { - ActionImpl - ListRestrictions ListRestrictions -} - -func (a ListActionImpl) GetListRestrictions() ListRestrictions { - return a.ListRestrictions -} - -type CreateActionImpl struct { - ActionImpl - Object runtime.Object -} - -func (a CreateActionImpl) GetObject() runtime.Object { - return a.Object -} - -type UpdateActionImpl struct { - ActionImpl - Object runtime.Object -} - -func (a UpdateActionImpl) GetObject() runtime.Object { - return a.Object -} - -type PatchActionImpl struct { - ActionImpl - Object runtime.Object -} - -func (a PatchActionImpl) GetObject() runtime.Object { - return a.Object -} - -type DeleteActionImpl struct { - ActionImpl - Name string -} - -func (a DeleteActionImpl) GetName() string { - return a.Name -} - -type DeleteCollectionActionImpl struct { - ActionImpl - ListRestrictions ListRestrictions -} - -func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions { - return a.ListRestrictions -} - -type WatchActionImpl struct { - ActionImpl - WatchRestrictions WatchRestrictions -} - -func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions { - return a.WatchRestrictions -} - -type ProxyGetActionImpl struct { - ActionImpl - Scheme string - Name string - Port string - Path string - Params map[string]string -} - -func (a ProxyGetActionImpl) GetScheme() string { - return a.Scheme -} - -func (a ProxyGetActionImpl) GetName() string { - return a.Name -} - -func (a ProxyGetActionImpl) GetPort() string { - return a.Port -} - -func (a ProxyGetActionImpl) GetPath() string { - return a.Path -} - -func (a ProxyGetActionImpl) GetParams() map[string]string { - return a.Params -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_componentstatuses.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_componentstatuses.go deleted file mode 100644 index 34bf210d4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_componentstatuses.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" -) - -// Fake implements ComponentStatusInterface. -type FakeComponentStatuses struct { - Fake *Fake -} - -func (c *FakeComponentStatuses) Get(name string) (*api.ComponentStatus, error) { - obj, err := c.Fake.Invokes(NewRootGetAction("componentstatuses", name), &api.ComponentStatus{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ComponentStatus), err -} - -func (c *FakeComponentStatuses) List(opts api.ListOptions) (result *api.ComponentStatusList, err error) { - obj, err := c.Fake.Invokes(NewRootListAction("componentstatuses", opts), &api.ComponentStatusList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ComponentStatusList), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_configmaps.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_configmaps.go deleted file mode 100644 index 17a5bfeb8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_configmaps.go +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -const ( - configMapResourceName string = "configMaps" -) - -// FakeConfigMaps implements ConfigMapInterface. 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 FakeConfigMaps struct { - Fake *Fake - Namespace string -} - -func (c *FakeConfigMaps) Get(name string) (*api.ConfigMap, error) { - obj, err := c.Fake.Invokes(NewGetAction(configMapResourceName, c.Namespace, name), &api.ConfigMap{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ConfigMap), err -} - -func (c *FakeConfigMaps) List(opts api.ListOptions) (*api.ConfigMapList, error) { - obj, err := c.Fake.Invokes(NewListAction(configMapResourceName, c.Namespace, opts), &api.ConfigMapList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ConfigMapList), err -} - -func (c *FakeConfigMaps) Create(cfg *api.ConfigMap) (*api.ConfigMap, error) { - obj, err := c.Fake.Invokes(NewCreateAction(configMapResourceName, c.Namespace, cfg), cfg) - if obj == nil { - return nil, err - } - - return obj.(*api.ConfigMap), err -} - -func (c *FakeConfigMaps) Update(cfg *api.ConfigMap) (*api.ConfigMap, error) { - obj, err := c.Fake.Invokes(NewUpdateAction(configMapResourceName, c.Namespace, cfg), cfg) - if obj == nil { - return nil, err - } - - return obj.(*api.ConfigMap), err -} - -func (c *FakeConfigMaps) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction(configMapResourceName, c.Namespace, name), &api.ConfigMap{}) - return err -} - -func (c *FakeConfigMaps) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction(configMapResourceName, c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_daemon_sets.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_daemon_sets.go deleted file mode 100644 index d0e1e73e1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_daemon_sets.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - kclientlib "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeDaemonSet implements DaemonInterface. 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 FakeDaemonSets struct { - Fake *FakeExperimental - Namespace string -} - -// Ensure statically that FakeDaemonSets implements DaemonInterface. -var _ kclientlib.DaemonSetInterface = &FakeDaemonSets{} - -func (c *FakeDaemonSets) Get(name string) (*extensions.DaemonSet, error) { - obj, err := c.Fake.Invokes(NewGetAction("daemonsets", c.Namespace, name), &extensions.DaemonSet{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) List(opts api.ListOptions) (*extensions.DaemonSetList, error) { - obj, err := c.Fake.Invokes(NewListAction("daemonsets", c.Namespace, opts), &extensions.DaemonSetList{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSetList), err -} - -func (c *FakeDaemonSets) Create(daemon *extensions.DaemonSet) (*extensions.DaemonSet, error) { - obj, err := c.Fake.Invokes(NewCreateAction("daemonsets", c.Namespace, daemon), &extensions.DaemonSet{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) Update(daemon *extensions.DaemonSet) (*extensions.DaemonSet, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("daemonsets", c.Namespace, daemon), &extensions.DaemonSet{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) UpdateStatus(daemon *extensions.DaemonSet) (*extensions.DaemonSet, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("daemonsets", "status", c.Namespace, daemon), &extensions.DaemonSet{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.DaemonSet), err -} - -func (c *FakeDaemonSets) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("daemonsets", c.Namespace, name), &extensions.DaemonSet{}) - return err -} - -func (c *FakeDaemonSets) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("daemonsets", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_deployments.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_deployments.go deleted file mode 100644 index f53f27198..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_deployments.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeDeployments implements DeploymentsInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakeDeployments struct { - Fake *FakeExperimental - Namespace string -} - -func (c *FakeDeployments) Get(name string) (*extensions.Deployment, error) { - obj, err := c.Fake.Invokes(NewGetAction("deployments", c.Namespace, name), &extensions.Deployment{}) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) List(opts api.ListOptions) (*extensions.DeploymentList, error) { - obj, err := c.Fake.Invokes(NewListAction("deployments", c.Namespace, opts), &extensions.DeploymentList{}) - if obj == nil { - return nil, err - } - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.DeploymentList{} - for _, deployment := range obj.(*extensions.DeploymentList).Items { - if label.Matches(labels.Set(deployment.Labels)) { - list.Items = append(list.Items, deployment) - } - } - return list, err -} - -func (c *FakeDeployments) Create(deployment *extensions.Deployment) (*extensions.Deployment, error) { - obj, err := c.Fake.Invokes(NewCreateAction("deployments", c.Namespace, deployment), deployment) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("deployments", c.Namespace, deployment), deployment) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) UpdateStatus(deployment *extensions.Deployment) (*extensions.Deployment, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("deployments", "status", c.Namespace, deployment), deployment) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Deployment), err -} - -func (c *FakeDeployments) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("deployments", c.Namespace, name), &extensions.Deployment{}) - return err -} - -func (c *FakeDeployments) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("deployments", c.Namespace, opts)) -} - -func (c *FakeDeployments) Rollback(deploymentRollback *extensions.DeploymentRollback) error { - action := CreateActionImpl{} - action.Verb = "create" - action.Resource = "deployments" - action.Subresource = "rollback" - action.Object = deploymentRollback - - _, err := c.Fake.Invokes(action, deploymentRollback) - return err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_endpoints.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_endpoints.go deleted file mode 100644 index 68f6178f7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_endpoints.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeEndpoints implements EndpointInterface. 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 FakeEndpoints struct { - Fake *Fake - Namespace string -} - -func (c *FakeEndpoints) Get(name string) (*api.Endpoints, error) { - obj, err := c.Fake.Invokes(NewGetAction("endpoints", c.Namespace, name), &api.Endpoints{}) - if obj == nil { - return nil, err - } - - return obj.(*api.Endpoints), err -} - -func (c *FakeEndpoints) List(opts api.ListOptions) (*api.EndpointsList, error) { - obj, err := c.Fake.Invokes(NewListAction("endpoints", c.Namespace, opts), &api.EndpointsList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.EndpointsList), err -} - -func (c *FakeEndpoints) Create(endpoints *api.Endpoints) (*api.Endpoints, error) { - obj, err := c.Fake.Invokes(NewCreateAction("endpoints", c.Namespace, endpoints), endpoints) - if obj == nil { - return nil, err - } - - return obj.(*api.Endpoints), err -} - -func (c *FakeEndpoints) Update(endpoints *api.Endpoints) (*api.Endpoints, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("endpoints", c.Namespace, endpoints), endpoints) - if obj == nil { - return nil, err - } - - return obj.(*api.Endpoints), err -} - -func (c *FakeEndpoints) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("endpoints", c.Namespace, name), &api.Endpoints{}) - return err -} - -func (c *FakeEndpoints) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("endpoints", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_events.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_events.go deleted file mode 100644 index 3da2143fc..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_events.go +++ /dev/null @@ -1,151 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeEvents implements EventInterface. 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 FakeEvents struct { - Fake *Fake - Namespace string -} - -// Get returns the given event, or an error. -func (c *FakeEvents) Get(name string) (*api.Event, error) { - action := NewRootGetAction("events", name) - if c.Namespace != "" { - action = NewGetAction("events", c.Namespace, name) - } - obj, err := c.Fake.Invokes(action, &api.Event{}) - if obj == nil { - return nil, err - } - - return obj.(*api.Event), err -} - -// List returns a list of events matching the selectors. -func (c *FakeEvents) List(opts api.ListOptions) (*api.EventList, error) { - action := NewRootListAction("events", opts) - if c.Namespace != "" { - action = NewListAction("events", c.Namespace, opts) - } - obj, err := c.Fake.Invokes(action, &api.EventList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.EventList), err -} - -// Create makes a new event. Returns the copy of the event the server returns, or an error. -func (c *FakeEvents) Create(event *api.Event) (*api.Event, error) { - action := NewRootCreateAction("events", event) - if c.Namespace != "" { - action = NewCreateAction("events", c.Namespace, event) - } - obj, err := c.Fake.Invokes(action, event) - if obj == nil { - return nil, err - } - - return obj.(*api.Event), err -} - -// Update replaces an existing event. Returns the copy of the event the server returns, or an error. -func (c *FakeEvents) Update(event *api.Event) (*api.Event, error) { - action := NewRootUpdateAction("events", event) - if c.Namespace != "" { - action = NewUpdateAction("events", c.Namespace, event) - } - obj, err := c.Fake.Invokes(action, event) - if obj == nil { - return nil, err - } - - return obj.(*api.Event), err -} - -// Patch patches an existing event. Returns the copy of the event the server returns, or an error. -func (c *FakeEvents) Patch(event *api.Event, data []byte) (*api.Event, error) { - action := NewRootPatchAction("events", event) - if c.Namespace != "" { - action = NewPatchAction("events", c.Namespace, event) - } - obj, err := c.Fake.Invokes(action, event) - if obj == nil { - return nil, err - } - - return obj.(*api.Event), err -} - -func (c *FakeEvents) Delete(name string) error { - action := NewRootDeleteAction("events", name) - if c.Namespace != "" { - action = NewDeleteAction("events", c.Namespace, name) - } - _, err := c.Fake.Invokes(action, &api.Event{}) - return err -} - -func (c *FakeEvents) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { - action := NewRootDeleteCollectionAction("events", listOptions) - if c.Namespace != "" { - action = NewDeleteCollectionAction("events", c.Namespace, listOptions) - } - _, err := c.Fake.Invokes(action, &api.EventList{}) - return err -} - -// Watch starts watching for events matching the given selectors. -func (c *FakeEvents) Watch(opts api.ListOptions) (watch.Interface, error) { - action := NewRootWatchAction("events", opts) - if c.Namespace != "" { - action = NewWatchAction("events", c.Namespace, opts) - } - return c.Fake.InvokesWatch(action) -} - -// Search returns a list of events matching the specified object. -func (c *FakeEvents) Search(objOrRef runtime.Object) (*api.EventList, error) { - action := NewRootListAction("events", api.ListOptions{}) - if c.Namespace != "" { - action = NewListAction("events", c.Namespace, api.ListOptions{}) - } - obj, err := c.Fake.Invokes(action, &api.EventList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.EventList), err -} - -func (c *FakeEvents) GetFieldSelector(involvedObjectName, involvedObjectNamespace, involvedObjectKind, involvedObjectUID *string) fields.Selector { - action := GenericActionImpl{} - action.Verb = "get-field-selector" - action.Resource = "events" - - c.Fake.Invokes(action, nil) - return fields.Everything() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_horizontal_pod_autoscalers.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_horizontal_pod_autoscalers.go deleted file mode 100644 index e50b326d9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_horizontal_pod_autoscalers.go +++ /dev/null @@ -1,164 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakeHorizontalPodAutoscalers struct { - Fake *FakeExperimental - Namespace string -} - -func (c *FakeHorizontalPodAutoscalers) Get(name string) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) - if obj == nil { - return nil, err - } - - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error) { - obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &extensions.HorizontalPodAutoscalerList{}) - if obj == nil { - return nil, err - } - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.HorizontalPodAutoscalerList{} - for _, a := range obj.(*extensions.HorizontalPodAutoscalerList).Items { - if label.Matches(labels.Set(a.Labels)) { - list.Items = append(list.Items, a) - } - } - return list, err -} - -func (c *FakeHorizontalPodAutoscalers) Create(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewCreateAction("horizontalpodautoscalers", c.Namespace, a), a) - if obj == nil { - return nil, err - } - - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) Update(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("horizontalpodautoscalers", c.Namespace, a), a) - if obj == nil { - return nil, err - } - - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) UpdateStatus(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &extensions.HorizontalPodAutoscaler{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) - return err -} - -func (c *FakeHorizontalPodAutoscalers) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts)) -} - -// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -// This is a test implementation of HorizontalPodAutoscalersV1 -// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely -type FakeHorizontalPodAutoscalersV1 struct { - Fake *FakeAutoscaling - Namespace string -} - -func (c *FakeHorizontalPodAutoscalersV1) Get(name string) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) - if obj == nil { - return nil, err - } - - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalersV1) List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error) { - obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &extensions.HorizontalPodAutoscalerList{}) - if obj == nil { - return nil, err - } - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &extensions.HorizontalPodAutoscalerList{} - for _, a := range obj.(*extensions.HorizontalPodAutoscalerList).Items { - if label.Matches(labels.Set(a.Labels)) { - list.Items = append(list.Items, a) - } - } - return list, err -} - -func (c *FakeHorizontalPodAutoscalersV1) Create(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewCreateAction("horizontalpodautoscalers", c.Namespace, a), a) - if obj == nil { - return nil, err - } - - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalersV1) Update(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("horizontalpodautoscalers", c.Namespace, a), a) - if obj == nil { - return nil, err - } - - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalersV1) UpdateStatus(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &extensions.HorizontalPodAutoscaler{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.HorizontalPodAutoscaler), err -} - -func (c *FakeHorizontalPodAutoscalersV1) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) - return err -} - -func (c *FakeHorizontalPodAutoscalersV1) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_ingress.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_ingress.go deleted file mode 100644 index b15458997..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_ingress.go +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeIngress implements IngressInterface. 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 FakeIngress struct { - Fake *FakeExperimental - Namespace string -} - -func (c *FakeIngress) Get(name string) (*extensions.Ingress, error) { - obj, err := c.Fake.Invokes(NewGetAction("ingresses", c.Namespace, name), &extensions.Ingress{}) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Ingress), err -} - -func (c *FakeIngress) List(opts api.ListOptions) (*extensions.IngressList, error) { - obj, err := c.Fake.Invokes(NewListAction("ingresses", c.Namespace, opts), &extensions.IngressList{}) - if obj == nil { - return nil, err - } - - return obj.(*extensions.IngressList), err -} - -func (c *FakeIngress) Create(ingress *extensions.Ingress) (*extensions.Ingress, error) { - obj, err := c.Fake.Invokes(NewCreateAction("ingresses", c.Namespace, ingress), ingress) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Ingress), err -} - -func (c *FakeIngress) Update(ingress *extensions.Ingress) (*extensions.Ingress, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("ingresses", c.Namespace, ingress), ingress) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Ingress), err -} - -func (c *FakeIngress) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("ingresses", c.Namespace, name), &extensions.Ingress{}) - return err -} - -func (c *FakeIngress) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("ingresses", c.Namespace, opts)) -} - -func (c *FakeIngress) UpdateStatus(ingress *extensions.Ingress) (result *extensions.Ingress, err error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("ingresses", "status", c.Namespace, ingress), ingress) - if obj == nil { - return nil, err - } - - return obj.(*extensions.Ingress), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_jobs.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_jobs.go deleted file mode 100644 index dedde9dc3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_jobs.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeJobs implements JobInterface. 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 FakeJobs struct { - Fake *FakeExperimental - Namespace string -} - -func (c *FakeJobs) Get(name string) (*batch.Job, error) { - obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &batch.Job{}) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} - -func (c *FakeJobs) List(opts api.ListOptions) (*batch.JobList, error) { - obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &batch.JobList{}) - if obj == nil { - return nil, err - } - - return obj.(*batch.JobList), err -} - -func (c *FakeJobs) Create(job *batch.Job) (*batch.Job, error) { - obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} - -func (c *FakeJobs) Update(job *batch.Job) (*batch.Job, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} - -func (c *FakeJobs) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &batch.Job{}) - return err -} - -func (c *FakeJobs) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts)) -} - -func (c *FakeJobs) UpdateStatus(job *batch.Job) (result *batch.Job, err error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} - -// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -// This is a test implementation of JobsV1 -// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely -type FakeJobsV1 struct { - Fake *FakeBatch - Namespace string -} - -func (c *FakeJobsV1) Get(name string) (*batch.Job, error) { - obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &batch.Job{}) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} - -func (c *FakeJobsV1) List(opts api.ListOptions) (*batch.JobList, error) { - obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &batch.JobList{}) - if obj == nil { - return nil, err - } - - return obj.(*batch.JobList), err -} - -func (c *FakeJobsV1) Create(job *batch.Job) (*batch.Job, error) { - obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} - -func (c *FakeJobsV1) Update(job *batch.Job) (*batch.Job, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} - -func (c *FakeJobsV1) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &batch.Job{}) - return err -} - -func (c *FakeJobsV1) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts)) -} - -func (c *FakeJobsV1) UpdateStatus(job *batch.Job) (result *batch.Job, err error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job) - if obj == nil { - return nil, err - } - - return obj.(*batch.Job), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_limit_ranges.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_limit_ranges.go deleted file mode 100644 index 3669f5ff8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_limit_ranges.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeLimitRanges implements PodsInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakeLimitRanges struct { - Fake *Fake - Namespace string -} - -func (c *FakeLimitRanges) Get(name string) (*api.LimitRange, error) { - obj, err := c.Fake.Invokes(NewGetAction("limitranges", c.Namespace, name), &api.LimitRange{}) - if obj == nil { - return nil, err - } - - return obj.(*api.LimitRange), err -} - -func (c *FakeLimitRanges) List(opts api.ListOptions) (*api.LimitRangeList, error) { - obj, err := c.Fake.Invokes(NewListAction("limitranges", c.Namespace, opts), &api.LimitRangeList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.LimitRangeList), err -} - -func (c *FakeLimitRanges) Create(limitRange *api.LimitRange) (*api.LimitRange, error) { - obj, err := c.Fake.Invokes(NewCreateAction("limitranges", c.Namespace, limitRange), limitRange) - if obj == nil { - return nil, err - } - - return obj.(*api.LimitRange), err -} - -func (c *FakeLimitRanges) Update(limitRange *api.LimitRange) (*api.LimitRange, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("limitranges", c.Namespace, limitRange), limitRange) - if obj == nil { - return nil, err - } - - return obj.(*api.LimitRange), err -} - -func (c *FakeLimitRanges) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("limitranges", c.Namespace, name), &api.LimitRange{}) - return err -} - -func (c *FakeLimitRanges) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("limitranges", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_namespaces.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_namespaces.go deleted file mode 100644 index 8c4ac1ac2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_namespaces.go +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeNamespaces implements NamespacesInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakeNamespaces struct { - Fake *Fake -} - -func (c *FakeNamespaces) Get(name string) (*api.Namespace, error) { - obj, err := c.Fake.Invokes(NewRootGetAction("namespaces", name), &api.Namespace{}) - if obj == nil { - return nil, err - } - - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) List(opts api.ListOptions) (*api.NamespaceList, error) { - obj, err := c.Fake.Invokes(NewRootListAction("namespaces", opts), &api.NamespaceList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.NamespaceList), err -} - -func (c *FakeNamespaces) Create(namespace *api.Namespace) (*api.Namespace, error) { - obj, err := c.Fake.Invokes(NewRootCreateAction("namespaces", namespace), namespace) - if obj == nil { - return nil, err - } - - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) Update(namespace *api.Namespace) (*api.Namespace, error) { - obj, err := c.Fake.Invokes(NewRootUpdateAction("namespaces", namespace), namespace) - if obj == nil { - return nil, err - } - - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) Delete(name string) error { - _, err := c.Fake.Invokes(NewRootDeleteAction("namespaces", name), &api.Namespace{}) - return err -} - -func (c *FakeNamespaces) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewRootWatchAction("namespaces", opts)) -} - -func (c *FakeNamespaces) Finalize(namespace *api.Namespace) (*api.Namespace, error) { - action := CreateActionImpl{} - action.Verb = "create" - action.Resource = "namespaces" - action.Subresource = "finalize" - action.Object = namespace - - obj, err := c.Fake.Invokes(action, namespace) - if obj == nil { - return nil, err - } - - return obj.(*api.Namespace), err -} - -func (c *FakeNamespaces) Status(namespace *api.Namespace) (*api.Namespace, error) { - action := CreateActionImpl{} - action.Verb = "create" - action.Resource = "namespaces" - action.Subresource = "status" - action.Object = namespace - - obj, err := c.Fake.Invokes(action, namespace) - if obj == nil { - return nil, err - } - - return obj.(*api.Namespace), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_nodes.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_nodes.go deleted file mode 100644 index b1943366e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_nodes.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeNodes implements NodeInterface. 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 FakeNodes struct { - Fake *Fake -} - -func (c *FakeNodes) Get(name string) (*api.Node, error) { - obj, err := c.Fake.Invokes(NewRootGetAction("nodes", name), &api.Node{}) - if obj == nil { - return nil, err - } - - return obj.(*api.Node), err -} - -func (c *FakeNodes) List(opts api.ListOptions) (*api.NodeList, error) { - obj, err := c.Fake.Invokes(NewRootListAction("nodes", opts), &api.NodeList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.NodeList), err -} - -func (c *FakeNodes) Create(node *api.Node) (*api.Node, error) { - obj, err := c.Fake.Invokes(NewRootCreateAction("nodes", node), node) - if obj == nil { - return nil, err - } - - return obj.(*api.Node), err -} - -func (c *FakeNodes) Update(node *api.Node) (*api.Node, error) { - obj, err := c.Fake.Invokes(NewRootUpdateAction("nodes", node), node) - if obj == nil { - return nil, err - } - - return obj.(*api.Node), err -} - -func (c *FakeNodes) Delete(name string) error { - _, err := c.Fake.Invokes(NewRootDeleteAction("nodes", name), &api.Node{}) - return err -} - -func (c *FakeNodes) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewRootWatchAction("nodes", opts)) -} - -func (c *FakeNodes) UpdateStatus(node *api.Node) (*api.Node, error) { - action := CreateActionImpl{} - action.Verb = "update" - action.Resource = "nodes" - action.Subresource = "status" - action.Object = node - - obj, err := c.Fake.Invokes(action, node) - if obj == nil { - return nil, err - } - - return obj.(*api.Node), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go deleted file mode 100644 index cadfb084c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -type FakePersistentVolumeClaims struct { - Fake *Fake - Namespace string -} - -func (c *FakePersistentVolumeClaims) Get(name string) (*api.PersistentVolumeClaim, error) { - obj, err := c.Fake.Invokes(NewGetAction("persistentvolumeclaims", c.Namespace, name), &api.PersistentVolumeClaim{}) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolumeClaim), err -} - -func (c *FakePersistentVolumeClaims) List(opts api.ListOptions) (*api.PersistentVolumeClaimList, error) { - obj, err := c.Fake.Invokes(NewListAction("persistentvolumeclaims", c.Namespace, opts), &api.PersistentVolumeClaimList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolumeClaimList), err -} - -func (c *FakePersistentVolumeClaims) Create(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - obj, err := c.Fake.Invokes(NewCreateAction("persistentvolumeclaims", c.Namespace, claim), claim) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolumeClaim), err -} - -func (c *FakePersistentVolumeClaims) Update(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("persistentvolumeclaims", c.Namespace, claim), claim) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolumeClaim), err -} - -func (c *FakePersistentVolumeClaims) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("persistentvolumeclaims", c.Namespace, name), &api.PersistentVolumeClaim{}) - return err -} - -func (c *FakePersistentVolumeClaims) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("persistentvolumeclaims", c.Namespace, opts)) -} - -func (c *FakePersistentVolumeClaims) UpdateStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("persistentvolumeclaims", "status", c.Namespace, claim), claim) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolumeClaim), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volumes.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volumes.go deleted file mode 100644 index cb184bc44..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volumes.go +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -type FakePersistentVolumes struct { - Fake *Fake -} - -func (c *FakePersistentVolumes) Get(name string) (*api.PersistentVolume, error) { - obj, err := c.Fake.Invokes(NewRootGetAction("persistentvolumes", name), &api.PersistentVolume{}) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolume), err -} - -func (c *FakePersistentVolumes) List(opts api.ListOptions) (*api.PersistentVolumeList, error) { - obj, err := c.Fake.Invokes(NewRootListAction("persistentvolumes", opts), &api.PersistentVolumeList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolumeList), err -} - -func (c *FakePersistentVolumes) Create(pv *api.PersistentVolume) (*api.PersistentVolume, error) { - obj, err := c.Fake.Invokes(NewRootCreateAction("persistentvolumes", pv), pv) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolume), err -} - -func (c *FakePersistentVolumes) Update(pv *api.PersistentVolume) (*api.PersistentVolume, error) { - obj, err := c.Fake.Invokes(NewRootUpdateAction("persistentvolumes", pv), pv) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolume), err -} - -func (c *FakePersistentVolumes) Delete(name string) error { - _, err := c.Fake.Invokes(NewRootDeleteAction("persistentvolumes", name), &api.PersistentVolume{}) - return err -} - -func (c *FakePersistentVolumes) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewRootWatchAction("persistentvolumes", opts)) -} - -func (c *FakePersistentVolumes) UpdateStatus(pv *api.PersistentVolume) (*api.PersistentVolume, error) { - action := UpdateActionImpl{} - action.Verb = "update" - action.Resource = "persistentvolumes" - action.Subresource = "status" - action.Object = pv - - obj, err := c.Fake.Invokes(action, pv) - if obj == nil { - return nil, err - } - - return obj.(*api.PersistentVolume), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pod_templates.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pod_templates.go deleted file mode 100644 index 47ff3d8ac..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pod_templates.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakePodTemplates implements PodTemplatesInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakePodTemplates struct { - Fake *Fake - Namespace string -} - -func (c *FakePodTemplates) Get(name string) (*api.PodTemplate, error) { - obj, err := c.Fake.Invokes(NewGetAction("podtemplates", c.Namespace, name), &api.PodTemplate{}) - if obj == nil { - return nil, err - } - - return obj.(*api.PodTemplate), err -} - -func (c *FakePodTemplates) List(opts api.ListOptions) (*api.PodTemplateList, error) { - obj, err := c.Fake.Invokes(NewListAction("podtemplates", c.Namespace, opts), &api.PodTemplateList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.PodTemplateList), err -} - -func (c *FakePodTemplates) Create(pod *api.PodTemplate) (*api.PodTemplate, error) { - obj, err := c.Fake.Invokes(NewCreateAction("podtemplates", c.Namespace, pod), pod) - if obj == nil { - return nil, err - } - - return obj.(*api.PodTemplate), err -} - -func (c *FakePodTemplates) Update(pod *api.PodTemplate) (*api.PodTemplate, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("podtemplates", c.Namespace, pod), pod) - if obj == nil { - return nil, err - } - - return obj.(*api.PodTemplate), err -} - -func (c *FakePodTemplates) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("podtemplates", c.Namespace, name), &api.PodTemplate{}) - return err -} - -func (c *FakePodTemplates) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("podtemplates", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pods.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pods.go deleted file mode 100644 index e634030c8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pods.go +++ /dev/null @@ -1,117 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/watch" -) - -// FakePods implements PodsInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakePods struct { - Fake *Fake - Namespace string -} - -func (c *FakePods) Get(name string) (*api.Pod, error) { - obj, err := c.Fake.Invokes(NewGetAction("pods", c.Namespace, name), &api.Pod{}) - if obj == nil { - return nil, err - } - - return obj.(*api.Pod), err -} - -func (c *FakePods) List(opts api.ListOptions) (*api.PodList, error) { - obj, err := c.Fake.Invokes(NewListAction("pods", c.Namespace, opts), &api.PodList{}) - if obj == nil { - return nil, err - } - label := opts.LabelSelector - if label == nil { - label = labels.Everything() - } - list := &api.PodList{} - for _, pod := range obj.(*api.PodList).Items { - if label.Matches(labels.Set(pod.Labels)) { - list.Items = append(list.Items, pod) - } - } - return list, err -} - -func (c *FakePods) Create(pod *api.Pod) (*api.Pod, error) { - obj, err := c.Fake.Invokes(NewCreateAction("pods", c.Namespace, pod), pod) - if obj == nil { - return nil, err - } - - return obj.(*api.Pod), err -} - -func (c *FakePods) Update(pod *api.Pod) (*api.Pod, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("pods", c.Namespace, pod), pod) - if obj == nil { - return nil, err - } - - return obj.(*api.Pod), err -} - -func (c *FakePods) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("pods", c.Namespace, name), &api.Pod{}) - return err -} - -func (c *FakePods) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("pods", c.Namespace, opts)) -} - -func (c *FakePods) Bind(binding *api.Binding) error { - action := CreateActionImpl{} - action.Verb = "create" - action.Resource = "pods" - action.Subresource = "bindings" - action.Object = binding - - _, err := c.Fake.Invokes(action, binding) - return err -} - -func (c *FakePods) UpdateStatus(pod *api.Pod) (*api.Pod, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("pods", "status", c.Namespace, pod), pod) - if obj == nil { - return nil, err - } - - return obj.(*api.Pod), err -} - -func (c *FakePods) GetLogs(name string, opts *api.PodLogOptions) *restclient.Request { - action := GenericActionImpl{} - action.Verb = "get" - action.Namespace = c.Namespace - action.Resource = "pod" - action.Subresource = "logs" - action.Value = opts - - _, _ = c.Fake.Invokes(action, &api.Pod{}) - return &restclient.Request{} -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_podsecuritypolicy.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_podsecuritypolicy.go deleted file mode 100644 index bb611d322..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_podsecuritypolicy.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/watch" -) - -// FakePodSecurityPolicy implements PodSecurityPolicyInterface. 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 FakePodSecurityPolicy struct { - Fake *Fake - Namespace string -} - -func (c *FakePodSecurityPolicy) List(opts api.ListOptions) (*extensions.PodSecurityPolicyList, error) { - obj, err := c.Fake.Invokes(NewListAction("podsecuritypolicies", c.Namespace, opts), &extensions.PodSecurityPolicyList{}) - if obj == nil { - return nil, err - } - - return obj.(*extensions.PodSecurityPolicyList), err -} - -func (c *FakePodSecurityPolicy) Get(name string) (*extensions.PodSecurityPolicy, error) { - obj, err := c.Fake.Invokes(NewGetAction("podsecuritypolicies", c.Namespace, name), &extensions.PodSecurityPolicy{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.PodSecurityPolicy), err -} - -func (c *FakePodSecurityPolicy) Create(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) { - obj, err := c.Fake.Invokes(NewCreateAction("podsecuritypolicies", c.Namespace, scc), &extensions.PodSecurityPolicy{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.PodSecurityPolicy), err -} - -func (c *FakePodSecurityPolicy) Update(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("podsecuritypolicies", c.Namespace, scc), &extensions.PodSecurityPolicy{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.PodSecurityPolicy), err -} - -func (c *FakePodSecurityPolicy) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("podsecuritypolicies", c.Namespace, name), &extensions.PodSecurityPolicy{}) - return err -} - -func (c *FakePodSecurityPolicy) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("podsecuritypolicies", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replica_sets.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replica_sets.go deleted file mode 100644 index 29c985c8c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replica_sets.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeReplicaSets implements ReplicaSetsInterface. 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 FakeReplicaSets struct { - Fake *FakeExperimental - Namespace string -} - -func (c *FakeReplicaSets) Get(name string) (*extensions.ReplicaSet, error) { - obj, err := c.Fake.Invokes(NewGetAction("replicasets", c.Namespace, name), &extensions.ReplicaSet{}) - if obj == nil { - return nil, err - } - - return obj.(*extensions.ReplicaSet), err -} - -func (c *FakeReplicaSets) List(opts api.ListOptions) (*extensions.ReplicaSetList, error) { - obj, err := c.Fake.Invokes(NewListAction("replicasets", c.Namespace, opts), &extensions.ReplicaSetList{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ReplicaSetList), err -} - -func (c *FakeReplicaSets) Create(rs *extensions.ReplicaSet) (*extensions.ReplicaSet, error) { - obj, err := c.Fake.Invokes(NewCreateAction("replicasets", c.Namespace, rs), rs) - if obj == nil { - return nil, err - } - - return obj.(*extensions.ReplicaSet), err -} - -func (c *FakeReplicaSets) Update(rs *extensions.ReplicaSet) (*extensions.ReplicaSet, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("replicasets", c.Namespace, rs), rs) - if obj == nil { - return nil, err - } - - return obj.(*extensions.ReplicaSet), err -} - -func (c *FakeReplicaSets) Delete(name string, options *api.DeleteOptions) error { - _, err := c.Fake.Invokes(NewDeleteAction("replicasets", c.Namespace, name), &extensions.ReplicaSet{}) - return err -} - -func (c *FakeReplicaSets) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("replicasets", c.Namespace, opts)) -} - -func (c *FakeReplicaSets) UpdateStatus(rs *extensions.ReplicaSet) (result *extensions.ReplicaSet, err error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("replicasets", "status", c.Namespace, rs), rs) - if obj == nil { - return nil, err - } - - return obj.(*extensions.ReplicaSet), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replication_controllers.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replication_controllers.go deleted file mode 100644 index e44b82615..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replication_controllers.go +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeReplicationControllers implements ReplicationControllerInterface. 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 FakeReplicationControllers struct { - Fake *Fake - Namespace string -} - -func (c *FakeReplicationControllers) Get(name string) (*api.ReplicationController, error) { - obj, err := c.Fake.Invokes(NewGetAction("replicationcontrollers", c.Namespace, name), &api.ReplicationController{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) List(opts api.ListOptions) (*api.ReplicationControllerList, error) { - obj, err := c.Fake.Invokes(NewListAction("replicationcontrollers", c.Namespace, opts), &api.ReplicationControllerList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ReplicationControllerList), err -} - -func (c *FakeReplicationControllers) Create(controller *api.ReplicationController) (*api.ReplicationController, error) { - obj, err := c.Fake.Invokes(NewCreateAction("replicationcontrollers", c.Namespace, controller), controller) - if obj == nil { - return nil, err - } - - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("replicationcontrollers", c.Namespace, controller), controller) - if obj == nil { - return nil, err - } - - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) UpdateStatus(controller *api.ReplicationController) (*api.ReplicationController, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("replicationcontrollers", "status", c.Namespace, controller), &api.ReplicationController{}) - if obj == nil { - return nil, err - } - return obj.(*api.ReplicationController), err -} - -func (c *FakeReplicationControllers) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("replicationcontrollers", c.Namespace, name), &api.ReplicationController{}) - return err -} - -func (c *FakeReplicationControllers) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("replicationcontrollers", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_resource_quotas.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_resource_quotas.go deleted file mode 100644 index d5090f0d0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_resource_quotas.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeResourceQuotas implements ResourceQuotaInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakeResourceQuotas struct { - Fake *Fake - Namespace string -} - -func (c *FakeResourceQuotas) Get(name string) (*api.ResourceQuota, error) { - obj, err := c.Fake.Invokes(NewGetAction("resourcequotas", c.Namespace, name), &api.ResourceQuota{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ResourceQuota), err -} - -func (c *FakeResourceQuotas) List(opts api.ListOptions) (*api.ResourceQuotaList, error) { - obj, err := c.Fake.Invokes(NewListAction("resourcequotas", c.Namespace, opts), &api.ResourceQuotaList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ResourceQuotaList), err -} - -func (c *FakeResourceQuotas) Create(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { - obj, err := c.Fake.Invokes(NewCreateAction("resourcequotas", c.Namespace, resourceQuota), resourceQuota) - if obj == nil { - return nil, err - } - - return obj.(*api.ResourceQuota), err -} - -func (c *FakeResourceQuotas) Update(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("resourcequotas", c.Namespace, resourceQuota), resourceQuota) - if obj == nil { - return nil, err - } - - return obj.(*api.ResourceQuota), err -} - -func (c *FakeResourceQuotas) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("resourcequotas", c.Namespace, name), &api.ResourceQuota{}) - return err -} - -func (c *FakeResourceQuotas) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("resourcequotas", c.Namespace, opts)) -} - -func (c *FakeResourceQuotas) UpdateStatus(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("resourcequotas", "status", c.Namespace, resourceQuota), resourceQuota) - if obj == nil { - return nil, err - } - - return obj.(*api.ResourceQuota), err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_scales.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_scales.go deleted file mode 100644 index 53ff5f87d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_scales.go +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/apis/extensions" -) - -// FakeScales implements ScaleInterface. Meant to be embedded into a struct to get a default -// implementation. This makes faking out just the methods you want to test easier. -type FakeScales struct { - Fake *FakeExperimental - Namespace string -} - -func (c *FakeScales) Get(kind string, name string) (result *extensions.Scale, err error) { - action := GetActionImpl{} - action.Verb = "get" - action.Namespace = c.Namespace - action.Resource = kind - action.Subresource = "scale" - action.Name = name - obj, err := c.Fake.Invokes(action, &extensions.Scale{}) - result = obj.(*extensions.Scale) - return -} - -func (c *FakeScales) Update(kind string, scale *extensions.Scale) (result *extensions.Scale, err error) { - action := UpdateActionImpl{} - action.Verb = "update" - action.Namespace = c.Namespace - action.Resource = kind - action.Subresource = "scale" - action.Object = scale - obj, err := c.Fake.Invokes(action, scale) - result = obj.(*extensions.Scale) - return -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_secrets.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_secrets.go deleted file mode 100644 index f54cffb87..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_secrets.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// Fake implements SecretInterface. 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 FakeSecrets struct { - Fake *Fake - Namespace string -} - -func (c *FakeSecrets) Get(name string) (*api.Secret, error) { - obj, err := c.Fake.Invokes(NewGetAction("secrets", c.Namespace, name), &api.Secret{}) - if obj == nil { - return nil, err - } - - return obj.(*api.Secret), err -} - -func (c *FakeSecrets) List(opts api.ListOptions) (*api.SecretList, error) { - obj, err := c.Fake.Invokes(NewListAction("secrets", c.Namespace, opts), &api.SecretList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.SecretList), err -} - -func (c *FakeSecrets) Create(secret *api.Secret) (*api.Secret, error) { - obj, err := c.Fake.Invokes(NewCreateAction("secrets", c.Namespace, secret), secret) - if obj == nil { - return nil, err - } - - return obj.(*api.Secret), err -} - -func (c *FakeSecrets) Update(secret *api.Secret) (*api.Secret, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("secrets", c.Namespace, secret), secret) - if obj == nil { - return nil, err - } - - return obj.(*api.Secret), err -} - -func (c *FakeSecrets) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("secrets", c.Namespace, name), &api.Secret{}) - return err -} - -func (c *FakeSecrets) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("secrets", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_service_accounts.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_service_accounts.go deleted file mode 100644 index e40641668..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_service_accounts.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeServiceAccounts implements ServiceAccountsInterface. 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 FakeServiceAccounts struct { - Fake *Fake - Namespace string -} - -func (c *FakeServiceAccounts) Get(name string) (*api.ServiceAccount, error) { - obj, err := c.Fake.Invokes(NewGetAction("serviceaccounts", c.Namespace, name), &api.ServiceAccount{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ServiceAccount), err -} - -func (c *FakeServiceAccounts) List(opts api.ListOptions) (*api.ServiceAccountList, error) { - obj, err := c.Fake.Invokes(NewListAction("serviceaccounts", c.Namespace, opts), &api.ServiceAccountList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ServiceAccountList), err -} - -func (c *FakeServiceAccounts) Create(serviceAccount *api.ServiceAccount) (*api.ServiceAccount, error) { - obj, err := c.Fake.Invokes(NewCreateAction("serviceaccounts", c.Namespace, serviceAccount), serviceAccount) - if obj == nil { - return nil, err - } - - return obj.(*api.ServiceAccount), err -} - -func (c *FakeServiceAccounts) Update(serviceAccount *api.ServiceAccount) (*api.ServiceAccount, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("serviceaccounts", c.Namespace, serviceAccount), serviceAccount) - if obj == nil { - return nil, err - } - - return obj.(*api.ServiceAccount), err -} - -func (c *FakeServiceAccounts) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("serviceaccounts", c.Namespace, name), &api.ServiceAccount{}) - return err -} - -func (c *FakeServiceAccounts) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("serviceaccounts", c.Namespace, opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_services.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_services.go deleted file mode 100644 index fd4861ba1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_services.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/watch" -) - -// Fake implements ServiceInterface. 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 FakeServices struct { - Fake *Fake - Namespace string -} - -func (c *FakeServices) Get(name string) (*api.Service, error) { - obj, err := c.Fake.Invokes(NewGetAction("services", c.Namespace, name), &api.Service{}) - if obj == nil { - return nil, err - } - - return obj.(*api.Service), err -} - -func (c *FakeServices) List(opts api.ListOptions) (*api.ServiceList, error) { - obj, err := c.Fake.Invokes(NewListAction("services", c.Namespace, opts), &api.ServiceList{}) - if obj == nil { - return nil, err - } - - return obj.(*api.ServiceList), err -} - -func (c *FakeServices) Create(service *api.Service) (*api.Service, error) { - obj, err := c.Fake.Invokes(NewCreateAction("services", c.Namespace, service), service) - if obj == nil { - return nil, err - } - - return obj.(*api.Service), err -} - -func (c *FakeServices) Update(service *api.Service) (*api.Service, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("services", c.Namespace, service), service) - if obj == nil { - return nil, err - } - - return obj.(*api.Service), err -} - -func (c *FakeServices) UpdateStatus(service *api.Service) (result *api.Service, err error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("services", "status", c.Namespace, service), service) - if obj == nil { - return nil, err - } - - return obj.(*api.Service), err -} - -func (c *FakeServices) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("services", c.Namespace, name), &api.Service{}) - return err -} - -func (c *FakeServices) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("services", c.Namespace, opts)) -} - -func (c *FakeServices) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper { - return c.Fake.InvokesProxy(NewProxyGetAction("services", c.Namespace, scheme, name, port, path, params)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_test.go deleted file mode 100644 index 303d6d786..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_test.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testclient - -import ( - "testing" - - client "k8s.io/kubernetes/pkg/client/unversioned" -) - -// This test file just ensures that Fake and structs it is embedded in -// implement Interface. - -func TestFakeImplementsInterface(t *testing.T) { - _ = client.Interface(&Fake{}) -} - -type MyFake struct { - *Fake -} - -func TestEmbeddedFakeImplementsInterface(t *testing.T) { - _ = client.Interface(MyFake{&Fake{}}) - _ = client.Interface(&MyFake{&Fake{}}) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_thirdpartyresources.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_thirdpartyresources.go deleted file mode 100644 index cb4a15572..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_thirdpartyresources.go +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - kclientlib "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/watch" -) - -// FakeThirdPartyResources implements ThirdPartyResourceInterface. 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 FakeThirdPartyResources struct { - Fake *FakeExperimental -} - -// Ensure statically that FakeThirdPartyResources implements DaemonInterface. -var _ kclientlib.ThirdPartyResourceInterface = &FakeThirdPartyResources{} - -func (c *FakeThirdPartyResources) Get(name string) (*extensions.ThirdPartyResource, error) { - obj, err := c.Fake.Invokes(NewGetAction("thirdpartyresources", "", name), &extensions.ThirdPartyResource{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResource), err -} - -func (c *FakeThirdPartyResources) List(opts api.ListOptions) (*extensions.ThirdPartyResourceList, error) { - obj, err := c.Fake.Invokes(NewListAction("thirdpartyresources", "", opts), &extensions.ThirdPartyResourceList{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResourceList), err -} - -func (c *FakeThirdPartyResources) Create(daemon *extensions.ThirdPartyResource) (*extensions.ThirdPartyResource, error) { - obj, err := c.Fake.Invokes(NewCreateAction("thirdpartyresources", "", daemon), &extensions.ThirdPartyResource{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResource), err -} - -func (c *FakeThirdPartyResources) Update(daemon *extensions.ThirdPartyResource) (*extensions.ThirdPartyResource, error) { - obj, err := c.Fake.Invokes(NewUpdateAction("thirdpartyresources", "", daemon), &extensions.ThirdPartyResource{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResource), err -} - -func (c *FakeThirdPartyResources) UpdateStatus(daemon *extensions.ThirdPartyResource) (*extensions.ThirdPartyResource, error) { - obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("thirdpartyresources", "status", "", daemon), &extensions.ThirdPartyResource{}) - if obj == nil { - return nil, err - } - return obj.(*extensions.ThirdPartyResource), err -} - -func (c *FakeThirdPartyResources) Delete(name string) error { - _, err := c.Fake.Invokes(NewDeleteAction("thirdpartyresources", "", name), &extensions.ThirdPartyResource{}) - return err -} - -func (c *FakeThirdPartyResources) Watch(opts api.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(NewWatchAction("thirdpartyresources", "", opts)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fixture.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fixture.go deleted file mode 100644 index bb02e96d1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/fixture.go +++ /dev/null @@ -1,313 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "fmt" - "io/ioutil" - "reflect" - "strings" - - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/yaml" - "k8s.io/kubernetes/pkg/watch" -) - -// ObjectRetriever abstracts the implementation for retrieving or setting generic -// objects. It is intended to be used to fake calls to a server by returning -// objects based on their kind and name. -type ObjectRetriever interface { - // Kind should return a resource or a list of resources (depending on the provided kind and - // name). It should return an error if the caller should communicate an error to the server. - Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Object, error) - // Add adds a runtime object for test purposes into this object. - Add(runtime.Object) error -} - -// ObjectScheme abstracts the implementation of common operations on objects. -type ObjectScheme interface { - runtime.ObjectCreater - runtime.ObjectCopier - runtime.ObjectTyper -} - -// ObjectReaction returns a ReactionFunc that takes a generic action string of the form -// - or -- and attempts to return a runtime -// Object or error that matches the requested action. For instance, list-replicationControllers -// should attempt to return a list of replication controllers. This method delegates to the -// ObjectRetriever interface to satisfy retrieval of lists or retrieval of single items. -// TODO: add support for sub resources -func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { - - return func(action Action) (bool, runtime.Object, error) { - kind, err := mapper.KindFor(unversioned.GroupVersionResource{Resource: action.GetResource()}) - if err != nil { - return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) - } - - // TODO: have mapper return a Kind for a subresource? - switch castAction := action.(type) { - case ListAction: - kind.Kind += "List" - resource, err := o.Kind(kind, "") - return true, resource, err - - case GetAction: - resource, err := o.Kind(kind, castAction.GetName()) - return true, resource, err - - case DeleteAction: - resource, err := o.Kind(kind, castAction.GetName()) - return true, resource, err - - case CreateAction: - accessor, err := meta.Accessor(castAction.GetObject()) - if err != nil { - return true, nil, err - } - resource, err := o.Kind(kind, accessor.GetName()) - return true, resource, err - - case UpdateAction: - accessor, err := meta.Accessor(castAction.GetObject()) - if err != nil { - return true, nil, err - } - resource, err := o.Kind(kind, accessor.GetName()) - return true, resource, err - - default: - return false, nil, fmt.Errorf("no reaction implemented for %s", action) - } - } -} - -// AddObjectsFromPath loads the JSON or YAML file containing Kubernetes API resources -// and adds them to the provided ObjectRetriever. -func AddObjectsFromPath(path string, o ObjectRetriever, decoder runtime.Decoder) error { - data, err := ioutil.ReadFile(path) - if err != nil { - return err - } - data, err = yaml.ToJSON(data) - if err != nil { - return err - } - obj, err := runtime.Decode(decoder, data) - if err != nil { - return err - } - if err := o.Add(obj); err != nil { - return err - } - return nil -} - -type objects struct { - types map[string][]runtime.Object - last map[string]int - scheme ObjectScheme - decoder runtime.Decoder -} - -var _ ObjectRetriever = &objects{} - -// NewObjects implements the ObjectRetriever interface by introspecting the -// objects provided to Add() and returning them when the Kind method is invoked. -// If an api.List object is provided to Add(), each child item is added. If an -// object is added that is itself a list (PodList, ServiceList) then that is added -// to the "PodList" kind. If no PodList is added, the retriever will take any loaded -// Pods and return them in a list. If an api.Status is added, and the Details.Kind field -// is set, that status will be returned instead (as an error if Status != Success, or -// as a runtime.Object if Status == Success). If multiple PodLists are provided, they -// will be returned in order by the Kind call, and the last PodList will be reused for -// subsequent calls. -func NewObjects(scheme ObjectScheme, decoder runtime.Decoder) ObjectRetriever { - return objects{ - types: make(map[string][]runtime.Object), - last: make(map[string]int), - scheme: scheme, - decoder: decoder, - } -} - -func (o objects) Kind(kind unversioned.GroupVersionKind, name string) (runtime.Object, error) { - kind.Version = runtime.APIVersionInternal - - empty, _ := o.scheme.New(kind) - nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object) - - arr, ok := o.types[kind.Kind] - if !ok { - if strings.HasSuffix(kind.Kind, "List") { - itemKind := kind.Kind[:len(kind.Kind)-4] - arr, ok := o.types[itemKind] - if !ok { - return empty, nil - } - out, err := o.scheme.New(kind) - if err != nil { - return nilValue, err - } - if err := meta.SetList(out, arr); err != nil { - return nilValue, err - } - if out, err = o.scheme.Copy(out); err != nil { - return nilValue, err - } - return out, nil - } - return nilValue, errors.NewNotFound(unversioned.GroupResource{Group: kind.Group, Resource: kind.Kind}, name) - } - - index := o.last[kind.Kind] - if index >= len(arr) { - index = len(arr) - 1 - } - if index < 0 { - return nilValue, errors.NewNotFound(unversioned.GroupResource{Group: kind.Group, Resource: kind.Kind}, name) - } - out, err := o.scheme.Copy(arr[index]) - if err != nil { - return nilValue, err - } - o.last[kind.Kind] = index + 1 - - if status, ok := out.(*unversioned.Status); ok { - if status.Details != nil { - status.Details.Kind = kind.Kind - } - if status.Status != unversioned.StatusSuccess { - return nilValue, &errors.StatusError{ErrStatus: *status} - } - } - - return out, nil -} - -func (o objects) Add(obj runtime.Object) error { - gvk, err := o.scheme.ObjectKind(obj) - if err != nil { - return err - } - kind := gvk.Kind - - switch { - case meta.IsListType(obj): - if kind != "List" { - o.types[kind] = append(o.types[kind], obj) - } - - list, err := meta.ExtractList(obj) - if err != nil { - return err - } - if errs := runtime.DecodeList(list, o.decoder); len(errs) > 0 { - return errs[0] - } - for _, obj := range list { - if err := o.Add(obj); err != nil { - return err - } - } - default: - if status, ok := obj.(*unversioned.Status); ok && status.Details != nil { - kind = status.Details.Kind - } - o.types[kind] = append(o.types[kind], obj) - } - - return nil -} - -func DefaultWatchReactor(watchInterface watch.Interface, err error) WatchReactionFunc { - return func(action Action) (bool, watch.Interface, error) { - return true, watchInterface, err - } -} - -// SimpleReactor is a Reactor. Each reaction function is attached to a given verb,resource tuple. "*" in either field matches everything for that value. -// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions -type SimpleReactor struct { - Verb string - Resource string - - Reaction ReactionFunc -} - -func (r *SimpleReactor) Handles(action Action) bool { - verbCovers := r.Verb == "*" || r.Verb == action.GetVerb() - if !verbCovers { - return false - } - resourceCovers := r.Resource == "*" || r.Resource == action.GetResource() - if !resourceCovers { - return false - } - - return true -} - -func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) { - return r.Reaction(action) -} - -// SimpleWatchReactor is a WatchReactor. Each reaction function is attached to a given resource. "*" matches everything for that value. -// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions -type SimpleWatchReactor struct { - Resource string - - Reaction WatchReactionFunc -} - -func (r *SimpleWatchReactor) Handles(action Action) bool { - resourceCovers := r.Resource == "*" || r.Resource == action.GetResource() - if !resourceCovers { - return false - } - - return true -} - -func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) { - return r.Reaction(action) -} - -// SimpleProxyReactor is a ProxyReactor. Each reaction function is attached to a given resource. "*" matches everything for that value. -// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions. -type SimpleProxyReactor struct { - Resource string - - Reaction ProxyReactionFunc -} - -func (r *SimpleProxyReactor) Handles(action Action) bool { - resourceCovers := r.Resource == "*" || r.Resource == action.GetResource() - if !resourceCovers { - return false - } - - return true -} - -func (r *SimpleProxyReactor) React(action Action) (bool, restclient.ResponseWrapper, error) { - return r.Reaction(action) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/simple/simple_testclient.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/simple/simple_testclient.go deleted file mode 100644 index b35a34427..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/simple/simple_testclient.go +++ /dev/null @@ -1,244 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 simple - -import ( - "net/http/httptest" - "net/url" - "path" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - utiltesting "k8s.io/kubernetes/pkg/util/testing" -) - -const NameRequiredError = "resource name may not be empty" - -type Request struct { - Method string - Path string - Header string - Query url.Values - Body runtime.Object - RawBody *string -} - -type Response struct { - StatusCode int - Body runtime.Object - RawBody *string -} - -type Client struct { - *client.Client - Clientset *clientset.Clientset - Request Request - Response Response - Error bool - Created bool - server *httptest.Server - handler *utiltesting.FakeHandler - // For query args, an optional function to validate the contents - // useful when the contents can change but still be correct. - // Maps from query arg key to validator. - // If no validator is present, string equality is used. - QueryValidator map[string]func(string, string) bool - - // If your object could exist in multiple groups, set this to - // correspond to the URL you're testing it with. - ResourceGroup string -} - -func (c *Client) Setup(t *testing.T) *Client { - c.handler = &utiltesting.FakeHandler{ - StatusCode: c.Response.StatusCode, - } - if responseBody := c.body(t, c.Response.Body, c.Response.RawBody); responseBody != nil { - c.handler.ResponseBody = *responseBody - } - c.server = httptest.NewServer(c.handler) - if c.Client == nil { - c.Client = client.NewOrDie(&restclient.Config{ - Host: c.server.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}, - }) - - // TODO: caesarxuchao: hacky way to specify version of Experimental client. - // We will fix this by supporting multiple group versions in Config - c.AutoscalingClient = client.NewAutoscalingOrDie(&restclient.Config{ - Host: c.server.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Autoscaling.GroupVersion()}, - }) - c.BatchClient = client.NewBatchOrDie(&restclient.Config{ - Host: c.server.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Batch.GroupVersion()}, - }) - c.ExtensionsClient = client.NewExtensionsOrDie(&restclient.Config{ - Host: c.server.URL, - ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Extensions.GroupVersion()}, - }) - - c.Clientset = clientset.NewForConfigOrDie(&restclient.Config{Host: c.server.URL}) - } - c.QueryValidator = map[string]func(string, string) bool{} - return c -} - -func (c *Client) Close() { - if c.server != nil { - c.server.Close() - } -} - -func (c *Client) ServerURL() string { - return c.server.URL -} - -func (c *Client) Validate(t *testing.T, received runtime.Object, err error) { - c.ValidateCommon(t, err) - - if c.Response.Body != nil && !api.Semantic.DeepDerivative(c.Response.Body, received) { - t.Errorf("bad response for request %#v: \nexpected %#v\ngot %#v\n", c.Request, c.Response.Body, received) - } -} - -func (c *Client) ValidateRaw(t *testing.T, received []byte, err error) { - c.ValidateCommon(t, err) - - if c.Response.Body != nil && !reflect.DeepEqual(c.Response.Body, received) { - t.Errorf("bad response for request %#v: expected %#v, got %#v", c.Request, c.Response.Body, received) - } -} - -func (c *Client) ValidateCommon(t *testing.T, err error) { - if c.Error { - if err == nil { - t.Errorf("error expected for %#v, got none", c.Request) - } - return - } - if err != nil { - t.Errorf("no error expected for %#v, got: %v", c.Request, err) - } - - if c.handler.RequestReceived == nil { - t.Errorf("handler had an empty request, %#v", c) - return - } - - requestBody := c.body(t, c.Request.Body, c.Request.RawBody) - actualQuery := c.handler.RequestReceived.URL.Query() - t.Logf("got query: %v", actualQuery) - t.Logf("path: %v", c.Request.Path) - // We check the query manually, so blank it out so that FakeHandler.ValidateRequest - // won't check it. - c.handler.RequestReceived.URL.RawQuery = "" - c.handler.ValidateRequest(t, path.Join(c.Request.Path), c.Request.Method, requestBody) - for key, values := range c.Request.Query { - validator, ok := c.QueryValidator[key] - if !ok { - switch key { - case unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()): - validator = ValidateLabels - case unversioned.FieldSelectorQueryParam(testapi.Default.GroupVersion().String()): - validator = validateFields - default: - validator = func(a, b string) bool { return a == b } - } - } - observed := actualQuery.Get(key) - wanted := strings.Join(values, "") - if !validator(wanted, observed) { - t.Errorf("Unexpected query arg for key: %s. Expected %s, Received %s", key, wanted, observed) - } - } - if c.Request.Header != "" { - if c.handler.RequestReceived.Header.Get(c.Request.Header) == "" { - t.Errorf("header %q not found in request %#v", c.Request.Header, c.handler.RequestReceived) - } - } - - if expected, received := requestBody, c.handler.RequestBody; expected != nil && *expected != received { - t.Errorf("bad body for request %#v: expected %s, got %s", c.Request, *expected, received) - } -} - -// buildQueryValues is a convenience function for knowing if a namespace should be in a query param or not -func BuildQueryValues(query url.Values) url.Values { - v := url.Values{} - if query != nil { - for key, values := range query { - for _, value := range values { - v.Add(key, value) - } - } - } - return v -} - -func ValidateLabels(a, b string) bool { - sA, eA := labels.Parse(a) - if eA != nil { - return false - } - sB, eB := labels.Parse(b) - if eB != nil { - return false - } - return sA.String() == sB.String() -} - -func validateFields(a, b string) bool { - sA, _ := fields.ParseSelector(a) - sB, _ := fields.ParseSelector(b) - return sA.String() == sB.String() -} - -func (c *Client) body(t *testing.T, obj runtime.Object, raw *string) *string { - if obj != nil { - fqKind, err := api.Scheme.ObjectKind(obj) - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - } - groupName := fqKind.GroupVersion().Group - if c.ResourceGroup != "" { - groupName = c.ResourceGroup - } - var bs []byte - g, found := testapi.Groups[groupName] - if !found { - t.Errorf("Group %s is not registered in testapi", groupName) - } - bs, err = runtime.Encode(g.Codec(), obj) - if err != nil { - t.Errorf("unexpected encoding error: %v", err) - } - body := string(bs) - return &body - } - return raw -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient.go deleted file mode 100644 index 258a0f5af..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient.go +++ /dev/null @@ -1,419 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "fmt" - "sync" - - "github.com/emicklei/go-restful/swagger" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/typed/discovery" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/version" - "k8s.io/kubernetes/pkg/watch" -) - -// NewSimpleFake returns a client that will respond with the provided objects -func NewSimpleFake(objects ...runtime.Object) *Fake { - o := NewObjects(api.Scheme, api.Codecs.UniversalDecoder()) - for _, obj := range objects { - if err := o.Add(obj); err != nil { - panic(err) - } - } - - fakeClient := &Fake{} - fakeClient.AddReactor("*", "*", ObjectReaction(o, registered.RESTMapper())) - - fakeClient.AddWatchReactor("*", DefaultWatchReactor(watch.NewFake(), nil)) - - return fakeClient -} - -// Fake implements client.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 Fake struct { - sync.RWMutex - actions []Action // these may be castable to other types, but "Action" is the minimum - - // ReactionChain is the list of reactors that will be attempted for every request in the order they are tried - ReactionChain []Reactor - // WatchReactionChain is the list of watch reactors that will be attempted for every request in the order they are tried - WatchReactionChain []WatchReactor - // ProxyReactionChain is the list of proxy reactors that will be attempted for every request in the order they are tried - ProxyReactionChain []ProxyReactor - - Resources map[string]*unversioned.APIResourceList -} - -// Reactor is an interface to allow the composition of reaction functions. -type Reactor interface { - // Handles indicates whether or not this Reactor deals with a given action - Handles(action Action) bool - // React handles the action and returns results. It may choose to delegate by indicated handled=false - React(action Action) (handled bool, ret runtime.Object, err error) -} - -// WatchReactor is an interface to allow the composition of watch functions. -type WatchReactor interface { - // Handles indicates whether or not this Reactor deals with a given action - Handles(action Action) bool - // React handles a watch action and returns results. It may choose to delegate by indicated handled=false - React(action Action) (handled bool, ret watch.Interface, err error) -} - -// ProxyReactor is an interface to allow the composition of proxy get functions. -type ProxyReactor interface { - // Handles indicates whether or not this Reactor deals with a given action - Handles(action Action) bool - // React handles a watch action and returns results. It may choose to delegate by indicated handled=false - React(action Action) (handled bool, ret restclient.ResponseWrapper, err error) -} - -// ReactionFunc is a function that returns an object or error for a given Action. If "handled" is false, -// then the test client will continue ignore the results and continue to the next ReactionFunc -type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error) - -// WatchReactionFunc is a function that returns a watch interface. If "handled" is false, -// then the test client will continue ignore the results and continue to the next ReactionFunc -type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error) - -// ProxyReactionFunc is a function that returns a ResponseWrapper interface for a given Action. If "handled" is false, -// then the test client will continue ignore the results and continue to the next ProxyReactionFunc -type ProxyReactionFunc func(action Action) (handled bool, ret restclient.ResponseWrapper, err error) - -// AddReactor appends a reactor to the end of the chain -func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) { - c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction}) -} - -// PrependReactor adds a reactor to the beginning of the chain -func (c *Fake) PrependReactor(verb, resource string, reaction ReactionFunc) { - c.ReactionChain = append([]Reactor{&SimpleReactor{verb, resource, reaction}}, c.ReactionChain...) -} - -// AddWatchReactor appends a reactor to the end of the chain -func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) { - c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction}) -} - -// PrependWatchReactor adds a reactor to the beginning of the chain -func (c *Fake) PrependWatchReactor(resource string, reaction WatchReactionFunc) { - c.WatchReactionChain = append([]WatchReactor{&SimpleWatchReactor{resource, reaction}}, c.WatchReactionChain...) -} - -// AddProxyReactor appends a reactor to the end of the chain -func (c *Fake) AddProxyReactor(resource string, reaction ProxyReactionFunc) { - c.ProxyReactionChain = append(c.ProxyReactionChain, &SimpleProxyReactor{resource, reaction}) -} - -// PrependProxyReactor adds a reactor to the beginning of the chain -func (c *Fake) PrependProxyReactor(resource string, reaction ProxyReactionFunc) { - c.ProxyReactionChain = append([]ProxyReactor{&SimpleProxyReactor{resource, reaction}}, c.ProxyReactionChain...) -} - -// Invokes records the provided Action and then invokes the ReactFn (if provided). -// defaultReturnObj is expected to be of the same type a normal call would return. -func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) { - c.Lock() - defer c.Unlock() - - c.actions = append(c.actions, action) - for _, reactor := range c.ReactionChain { - if !reactor.Handles(action) { - continue - } - - handled, ret, err := reactor.React(action) - if !handled { - continue - } - - return ret, err - } - - return defaultReturnObj, nil -} - -// InvokesWatch records the provided Action and then invokes the ReactFn (if provided). -func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) { - c.Lock() - defer c.Unlock() - - c.actions = append(c.actions, action) - for _, reactor := range c.WatchReactionChain { - if !reactor.Handles(action) { - continue - } - - handled, ret, err := reactor.React(action) - if !handled { - continue - } - - return ret, err - } - - return nil, fmt.Errorf("unhandled watch: %#v", action) -} - -// InvokesProxy records the provided Action and then invokes the ReactFn (if provided). -func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper { - c.Lock() - defer c.Unlock() - - c.actions = append(c.actions, action) - for _, reactor := range c.ProxyReactionChain { - if !reactor.Handles(action) { - continue - } - - handled, ret, err := reactor.React(action) - if !handled || err != nil { - continue - } - - return ret - } - - return nil -} - -// ClearActions clears the history of actions called on the fake client -func (c *Fake) ClearActions() { - c.Lock() - c.Unlock() - - c.actions = make([]Action, 0) -} - -// Actions returns a chronologically ordered slice fake actions called on the fake client -func (c *Fake) Actions() []Action { - c.RLock() - defer c.RUnlock() - fa := make([]Action, len(c.actions)) - copy(fa, c.actions) - return fa -} - -func (c *Fake) LimitRanges(namespace string) client.LimitRangeInterface { - return &FakeLimitRanges{Fake: c, Namespace: namespace} -} - -func (c *Fake) ResourceQuotas(namespace string) client.ResourceQuotaInterface { - return &FakeResourceQuotas{Fake: c, Namespace: namespace} -} - -func (c *Fake) ReplicationControllers(namespace string) client.ReplicationControllerInterface { - return &FakeReplicationControllers{Fake: c, Namespace: namespace} -} - -func (c *Fake) Nodes() client.NodeInterface { - return &FakeNodes{Fake: c} -} - -func (c *Fake) PodSecurityPolicies() client.PodSecurityPolicyInterface { - return &FakePodSecurityPolicy{Fake: c} -} - -func (c *Fake) Events(namespace string) client.EventInterface { - return &FakeEvents{Fake: c, Namespace: namespace} -} - -func (c *Fake) Endpoints(namespace string) client.EndpointsInterface { - return &FakeEndpoints{Fake: c, Namespace: namespace} -} - -func (c *Fake) PersistentVolumes() client.PersistentVolumeInterface { - return &FakePersistentVolumes{Fake: c} -} - -func (c *Fake) PersistentVolumeClaims(namespace string) client.PersistentVolumeClaimInterface { - return &FakePersistentVolumeClaims{Fake: c, Namespace: namespace} -} - -func (c *Fake) Pods(namespace string) client.PodInterface { - return &FakePods{Fake: c, Namespace: namespace} -} - -func (c *Fake) PodTemplates(namespace string) client.PodTemplateInterface { - return &FakePodTemplates{Fake: c, Namespace: namespace} -} - -func (c *Fake) Services(namespace string) client.ServiceInterface { - return &FakeServices{Fake: c, Namespace: namespace} -} - -func (c *Fake) ServiceAccounts(namespace string) client.ServiceAccountsInterface { - return &FakeServiceAccounts{Fake: c, Namespace: namespace} -} - -func (c *Fake) Secrets(namespace string) client.SecretsInterface { - return &FakeSecrets{Fake: c, Namespace: namespace} -} - -func (c *Fake) Namespaces() client.NamespaceInterface { - return &FakeNamespaces{Fake: c} -} - -func (c *Fake) Autoscaling() client.AutoscalingInterface { - return &FakeAutoscaling{c} -} - -func (c *Fake) Batch() client.BatchInterface { - return &FakeBatch{c} -} - -func (c *Fake) Extensions() client.ExtensionsInterface { - return &FakeExperimental{c} -} - -func (c *Fake) Discovery() discovery.DiscoveryInterface { - return &FakeDiscovery{c} -} - -func (c *Fake) ComponentStatuses() client.ComponentStatusInterface { - return &FakeComponentStatuses{Fake: c} -} - -func (c *Fake) ConfigMaps(namespace string) client.ConfigMapsInterface { - return &FakeConfigMaps{Fake: c, Namespace: namespace} -} - -// SwaggerSchema returns an empty swagger.ApiDeclaration for testing -func (c *Fake) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) { - action := ActionImpl{} - action.Verb = "get" - if version == v1.SchemeGroupVersion { - action.Resource = "/swaggerapi/api/" + version.Version - } else { - action.Resource = "/swaggerapi/apis/" + version.Group + "/" + version.Version - } - - c.Invokes(action, nil) - return &swagger.ApiDeclaration{}, nil -} - -// NewSimpleFakeAutoscaling returns a client that will respond with the provided objects -func NewSimpleFakeAutoscaling(objects ...runtime.Object) *FakeAutoscaling { - return &FakeAutoscaling{Fake: NewSimpleFake(objects...)} -} - -type FakeAutoscaling struct { - *Fake -} - -func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface { - return &FakeHorizontalPodAutoscalersV1{Fake: c, Namespace: namespace} -} - -// NewSimpleFakeBatch returns a client that will respond with the provided objects -func NewSimpleFakeBatch(objects ...runtime.Object) *FakeBatch { - return &FakeBatch{Fake: NewSimpleFake(objects...)} -} - -type FakeBatch struct { - *Fake -} - -func (c *FakeBatch) Jobs(namespace string) client.JobInterface { - return &FakeJobsV1{Fake: c, Namespace: namespace} -} - -// NewSimpleFakeExp returns a client that will respond with the provided objects -func NewSimpleFakeExp(objects ...runtime.Object) *FakeExperimental { - return &FakeExperimental{Fake: NewSimpleFake(objects...)} -} - -type FakeExperimental struct { - *Fake -} - -func (c *FakeExperimental) DaemonSets(namespace string) client.DaemonSetInterface { - return &FakeDaemonSets{Fake: c, Namespace: namespace} -} - -func (c *FakeExperimental) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface { - return &FakeHorizontalPodAutoscalers{Fake: c, Namespace: namespace} -} - -func (c *FakeExperimental) Deployments(namespace string) client.DeploymentInterface { - return &FakeDeployments{Fake: c, Namespace: namespace} -} - -func (c *FakeExperimental) Scales(namespace string) client.ScaleInterface { - return &FakeScales{Fake: c, Namespace: namespace} -} - -func (c *FakeExperimental) Jobs(namespace string) client.JobInterface { - return &FakeJobs{Fake: c, Namespace: namespace} -} - -func (c *FakeExperimental) Ingress(namespace string) client.IngressInterface { - return &FakeIngress{Fake: c, Namespace: namespace} -} - -func (c *FakeExperimental) ThirdPartyResources() client.ThirdPartyResourceInterface { - return &FakeThirdPartyResources{Fake: c} -} - -func (c *FakeExperimental) ReplicaSets(namespace string) client.ReplicaSetInterface { - return &FakeReplicaSets{Fake: c, Namespace: namespace} -} - -type FakeDiscovery struct { - *Fake -} - -func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*unversioned.APIResourceList, error) { - action := ActionImpl{ - Verb: "get", - Resource: "resource", - } - c.Invokes(action, nil) - return c.Resources[groupVersion], nil -} - -func (c *FakeDiscovery) ServerResources() (map[string]*unversioned.APIResourceList, error) { - action := ActionImpl{ - Verb: "get", - Resource: "resource", - } - c.Invokes(action, nil) - return c.Resources, nil -} - -func (c *FakeDiscovery) ServerGroups() (*unversioned.APIGroupList, error) { - return nil, nil -} - -func (c *FakeDiscovery) ServerVersion() (*version.Info, error) { - action := ActionImpl{} - action.Verb = "get" - action.Resource = "version" - - c.Invokes(action, nil) - versionInfo := version.Get() - return &versionInfo, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient_test.go deleted file mode 100644 index b31bdc213..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient_test.go +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testclient - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestNewClient(t *testing.T) { - o := NewObjects(api.Scheme, api.Codecs.UniversalDecoder()) - if err := AddObjectsFromPath("../../../../examples/guestbook/frontend-service.yaml", o, api.Codecs.UniversalDecoder()); err != nil { - t.Fatal(err) - } - client := &Fake{} - client.AddReactor("*", "*", ObjectReaction(o, testapi.Default.RESTMapper())) - list, err := client.Services("test").List(api.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if len(list.Items) != 1 { - t.Fatalf("unexpected list %#v", list) - } - - // When list is invoked a second time, the same results are returned. - list, err = client.Services("test").List(api.ListOptions{}) - if err != nil { - t.Fatal(err) - } - if len(list.Items) != 1 { - t.Fatalf("unexpected list %#v", list) - } - t.Logf("list: %#v", list) -} - -func TestErrors(t *testing.T) { - o := NewObjects(api.Scheme, api.Codecs.UniversalDecoder()) - o.Add(&api.List{ - Items: []runtime.Object{ - // This first call to List will return this error - &(errors.NewNotFound(api.Resource("ServiceList"), "").(*errors.StatusError).ErrStatus), - // The second call to List will return this error - &(errors.NewForbidden(api.Resource("ServiceList"), "", nil).(*errors.StatusError).ErrStatus), - }, - }) - client := &Fake{} - client.AddReactor("*", "*", ObjectReaction(o, testapi.Default.RESTMapper())) - _, err := client.Services("test").List(api.ListOptions{}) - if !errors.IsNotFound(err) { - t.Fatalf("unexpected error: %v", err) - } - t.Logf("error: %#v", err.(*errors.StatusError).Status()) - _, err = client.Services("test").List(api.ListOptions{}) - if !errors.IsForbidden(err) { - t.Fatalf("unexpected error: %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/thirdpartyresources_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/thirdpartyresources_test.go deleted file mode 100644 index 266ff4ae8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/client/unversioned/thirdpartyresources_test.go +++ /dev/null @@ -1,177 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 unversioned_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned/testclient/simple" -) - -func getThirdPartyResourceName() string { - return "thirdpartyresources" -} - -func TestListThirdPartyResources(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{ - Method: "GET", - Path: testapi.Extensions.ResourcePath(getThirdPartyResourceName(), "", ""), - }, - Response: simple.Response{StatusCode: 200, - Body: &extensions.ThirdPartyResourceList{ - Items: []extensions.ThirdPartyResource{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Description: "test third party resource", - }, - }, - }, - }, - } - receivedDSs, err := c.Setup(t).Extensions().ThirdPartyResources().List(api.ListOptions{}) - defer c.Close() - c.Validate(t, receivedDSs, err) - -} - -func TestGetThirdPartyResource(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{Method: "GET", Path: testapi.Extensions.ResourcePath(getThirdPartyResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ThirdPartyResource{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Description: "test third party resource", - }, - }, - } - receivedThirdPartyResource, err := c.Setup(t).Extensions().ThirdPartyResources().Get("foo") - defer c.Close() - c.Validate(t, receivedThirdPartyResource, err) -} - -func TestGetThirdPartyResourceWithNoName(t *testing.T) { - c := &simple.Client{Error: true} - receivedPod, err := c.Setup(t).Extensions().ThirdPartyResources().Get("") - defer c.Close() - if (err != nil) && (err.Error() != simple.NameRequiredError) { - t.Errorf("Expected error: %v, but got %v", simple.NameRequiredError, err) - } - - c.Validate(t, receivedPod, err) -} - -func TestUpdateThirdPartyResource(t *testing.T) { - requestThirdPartyResource := &extensions.ThirdPartyResource{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getThirdPartyResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ThirdPartyResource{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Description: "test third party resource", - }, - }, - } - receivedThirdPartyResource, err := c.Setup(t).Extensions().ThirdPartyResources().Update(requestThirdPartyResource) - defer c.Close() - c.Validate(t, receivedThirdPartyResource, err) -} - -func TestUpdateThirdPartyResourceUpdateStatus(t *testing.T) { - requestThirdPartyResource := &extensions.ThirdPartyResource{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "1"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getThirdPartyResourceName(), "", "foo") + "/status", Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ThirdPartyResource{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Description: "test third party resource", - }, - }, - } - receivedThirdPartyResource, err := c.Setup(t).Extensions().ThirdPartyResources().UpdateStatus(requestThirdPartyResource) - defer c.Close() - c.Validate(t, receivedThirdPartyResource, err) -} - -func TestDeleteThirdPartyResource(t *testing.T) { - c := &simple.Client{ - Request: simple.Request{Method: "DELETE", Path: testapi.Extensions.ResourcePath(getThirdPartyResourceName(), "", "foo"), Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{StatusCode: 200}, - } - err := c.Setup(t).Extensions().ThirdPartyResources().Delete("foo") - defer c.Close() - c.Validate(t, nil, err) -} - -func TestCreateThirdPartyResource(t *testing.T) { - requestThirdPartyResource := &extensions.ThirdPartyResource{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - c := &simple.Client{ - Request: simple.Request{Method: "POST", Path: testapi.Extensions.ResourcePath(getThirdPartyResourceName(), "", ""), Body: requestThirdPartyResource, Query: simple.BuildQueryValues(nil)}, - Response: simple.Response{ - StatusCode: 200, - Body: &extensions.ThirdPartyResource{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{ - "foo": "bar", - "name": "baz", - }, - }, - Description: "test third party resource", - }, - }, - } - receivedThirdPartyResource, err := c.Setup(t).Extensions().ThirdPartyResources().Create(requestThirdPartyResource) - defer c.Close() - c.Validate(t, receivedThirdPartyResource, err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/OWNERS b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/OWNERS deleted file mode 100644 index 3c625f946..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -assignees: - - justinsb diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws.go deleted file mode 100644 index e0cae84b4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws.go +++ /dev/null @@ -1,2725 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws - -import ( - "errors" - "fmt" - "io" - "net" - "net/url" - "os" - "regexp" - "strings" - "sync" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/autoscaling" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/elb" - "gopkg.in/gcfg.v1" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/credentialprovider/aws" - "k8s.io/kubernetes/pkg/types" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api/service" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -const ProviderName = "aws" - -// The tag name we use to differentiate multiple logically independent clusters running in the same AZ -const TagNameKubernetesCluster = "KubernetesCluster" - -// The tag name we use to differentiate multiple services. Used currently for ELBs only. -const TagNameKubernetesService = "kubernetes.io/service-name" - -// The tag name used on a subnet to designate that it should be used for internal ELBs -const TagNameSubnetInternalELB = "kubernetes.io/role/internal-elb" - -// The tag name used on a subnet to designate that it should be used for internet ELBs -const TagNameSubnetPublicELB = "kubernetes.io/role/elb" - -// Annotation used on the service to indicate that we want an internal ELB. -// Currently we accept only the value "0.0.0.0/0" - other values are an error. -// This lets us define more advanced semantics in future. -const ServiceAnnotationLoadBalancerInternal = "service.beta.kubernetes.io/aws-load-balancer-internal" - -// We sometimes read to see if something exists; then try to create it if we didn't find it -// This can fail once in a consistent system if done in parallel -// In an eventually consistent system, it could fail unboundedly -// MaxReadThenCreateRetries sets the maximum number of attempts we will make -const MaxReadThenCreateRetries = 30 - -// Default volume type for newly created Volumes -// TODO: Remove when user/admin can configure volume types and thus we don't -// need hardcoded defaults. -const DefaultVolumeType = "gp2" - -// Amazon recommends having no more that 40 volumes attached to an instance, -// and at least one of those is for the system root volume. -// See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/volume_limits.html#linux-specific-volume-limits -const DefaultMaxEBSVolumes = 39 - -// Used to call aws_credentials.Init() just once -var once sync.Once - -// Abstraction over AWS, to allow mocking/other implementations -type AWSServices interface { - Compute(region string) (EC2, error) - LoadBalancing(region string) (ELB, error) - Autoscaling(region string) (ASG, error) - Metadata() (EC2Metadata, error) -} - -// TODO: Should we rename this to AWS (EBS & ELB are not technically part of EC2) -// Abstraction over EC2, to allow mocking/other implementations -// Note that the DescribeX functions return a list, so callers don't need to deal with paging -type EC2 interface { - // Query EC2 for instances matching the filter - DescribeInstances(request *ec2.DescribeInstancesInput) ([]*ec2.Instance, error) - - // Attach a volume to an instance - AttachVolume(*ec2.AttachVolumeInput) (*ec2.VolumeAttachment, error) - // Detach a volume from an instance it is attached to - DetachVolume(request *ec2.DetachVolumeInput) (resp *ec2.VolumeAttachment, err error) - // Lists volumes - DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.Volume, error) - // Create an EBS volume - CreateVolume(request *ec2.CreateVolumeInput) (resp *ec2.Volume, err error) - // Delete an EBS volume - DeleteVolume(*ec2.DeleteVolumeInput) (*ec2.DeleteVolumeOutput, error) - - DescribeSecurityGroups(request *ec2.DescribeSecurityGroupsInput) ([]*ec2.SecurityGroup, error) - - CreateSecurityGroup(*ec2.CreateSecurityGroupInput) (*ec2.CreateSecurityGroupOutput, error) - DeleteSecurityGroup(request *ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error) - - AuthorizeSecurityGroupIngress(*ec2.AuthorizeSecurityGroupIngressInput) (*ec2.AuthorizeSecurityGroupIngressOutput, error) - RevokeSecurityGroupIngress(*ec2.RevokeSecurityGroupIngressInput) (*ec2.RevokeSecurityGroupIngressOutput, error) - - DescribeSubnets(*ec2.DescribeSubnetsInput) ([]*ec2.Subnet, error) - - CreateTags(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) - - DescribeRouteTables(request *ec2.DescribeRouteTablesInput) ([]*ec2.RouteTable, error) - CreateRoute(request *ec2.CreateRouteInput) (*ec2.CreateRouteOutput, error) - DeleteRoute(request *ec2.DeleteRouteInput) (*ec2.DeleteRouteOutput, error) - - ModifyInstanceAttribute(request *ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error) -} - -// This is a simple pass-through of the ELB client interface, which allows for testing -type ELB interface { - CreateLoadBalancer(*elb.CreateLoadBalancerInput) (*elb.CreateLoadBalancerOutput, error) - DeleteLoadBalancer(*elb.DeleteLoadBalancerInput) (*elb.DeleteLoadBalancerOutput, error) - DescribeLoadBalancers(*elb.DescribeLoadBalancersInput) (*elb.DescribeLoadBalancersOutput, error) - RegisterInstancesWithLoadBalancer(*elb.RegisterInstancesWithLoadBalancerInput) (*elb.RegisterInstancesWithLoadBalancerOutput, error) - DeregisterInstancesFromLoadBalancer(*elb.DeregisterInstancesFromLoadBalancerInput) (*elb.DeregisterInstancesFromLoadBalancerOutput, error) - - DetachLoadBalancerFromSubnets(*elb.DetachLoadBalancerFromSubnetsInput) (*elb.DetachLoadBalancerFromSubnetsOutput, error) - AttachLoadBalancerToSubnets(*elb.AttachLoadBalancerToSubnetsInput) (*elb.AttachLoadBalancerToSubnetsOutput, error) - - CreateLoadBalancerListeners(*elb.CreateLoadBalancerListenersInput) (*elb.CreateLoadBalancerListenersOutput, error) - DeleteLoadBalancerListeners(*elb.DeleteLoadBalancerListenersInput) (*elb.DeleteLoadBalancerListenersOutput, error) - - ApplySecurityGroupsToLoadBalancer(*elb.ApplySecurityGroupsToLoadBalancerInput) (*elb.ApplySecurityGroupsToLoadBalancerOutput, error) - - ConfigureHealthCheck(*elb.ConfigureHealthCheckInput) (*elb.ConfigureHealthCheckOutput, error) -} - -// This is a simple pass-through of the Autoscaling client interface, which allows for testing -type ASG interface { - UpdateAutoScalingGroup(*autoscaling.UpdateAutoScalingGroupInput) (*autoscaling.UpdateAutoScalingGroupOutput, error) - DescribeAutoScalingGroups(*autoscaling.DescribeAutoScalingGroupsInput) (*autoscaling.DescribeAutoScalingGroupsOutput, error) -} - -// Abstraction over the AWS metadata service -type EC2Metadata interface { - // Query the EC2 metadata service (used to discover instance-id etc) - GetMetadata(path string) (string, error) -} - -type VolumeOptions struct { - CapacityGB int - Tags map[string]string -} - -// Volumes is an interface for managing cloud-provisioned volumes -// TODO: Allow other clouds to implement this -type Volumes interface { - // Attach the disk to the specified instance - // instanceName can be empty to mean "the instance on which we are running" - // Returns the device (e.g. /dev/xvdf) where we attached the volume - AttachDisk(diskName string, instanceName string, readOnly bool) (string, error) - // Detach the disk from the specified instance - // instanceName can be empty to mean "the instance on which we are running" - // Returns the device where the volume was attached - DetachDisk(diskName string, instanceName string) (string, error) - - // Create a volume with the specified options - CreateDisk(volumeOptions *VolumeOptions) (volumeName string, err error) - // Delete the specified volume - // Returns true iff the volume was deleted - // If the was not found, returns (false, nil) - DeleteDisk(volumeName string) (bool, error) - - // Get labels to apply to volume on creation - GetVolumeLabels(volumeName string) (map[string]string, error) -} - -// InstanceGroups is an interface for managing cloud-managed instance groups / autoscaling instance groups -// TODO: Allow other clouds to implement this -type InstanceGroups interface { - // Set the size to the fixed size - ResizeInstanceGroup(instanceGroupName string, size int) error - // Queries the cloud provider for information about the specified instance group - DescribeInstanceGroup(instanceGroupName string) (InstanceGroupInfo, error) -} - -// InstanceGroupInfo is returned by InstanceGroups.Describe, and exposes information about the group. -type InstanceGroupInfo interface { - // The number of instances currently running under control of this group - CurrentSize() (int, error) -} - -// AWSCloud is an implementation of Interface, LoadBalancer and Instances for Amazon Web Services. -type AWSCloud struct { - ec2 EC2 - elb ELB - asg ASG - metadata EC2Metadata - cfg *AWSCloudConfig - region string - vpcID string - - filterTags map[string]string - - // The AWS instance that we are running on - // Note that we cache some state in awsInstance (mountpoints), so we must preserve the instance - selfAWSInstance *awsInstance - - mutex sync.Mutex -} - -var _ Volumes = &AWSCloud{} - -type AWSCloudConfig struct { - Global struct { - // TODO: Is there any use for this? We can get it from the instance metadata service - // Maybe if we're not running on AWS, e.g. bootstrap; for now it is not very useful - Zone string - - KubernetesClusterTag string - - //The aws provider creates an inbound rule per load balancer on the node security - //group. However, this can run into the AWS security group rule limit of 50 if - //many LoadBalancers are created. - // - //This flag disables the automatic ingress creation. It requires that the user - //has setup a rule that allows inbound traffic on kubelet ports from the - //local VPC subnet (so load balancers can access it). E.g. 10.82.0.0/16 30000-32000. - DisableSecurityGroupIngress bool - } -} - -// awsSdkEC2 is an implementation of the EC2 interface, backed by aws-sdk-go -type awsSdkEC2 struct { - ec2 *ec2.EC2 -} - -type awsSDKProvider struct { - creds *credentials.Credentials - - mutex sync.Mutex - regionDelayers map[string]*CrossRequestRetryDelay -} - -func newAWSSDKProvider(creds *credentials.Credentials) *awsSDKProvider { - return &awsSDKProvider{ - creds: creds, - regionDelayers: make(map[string]*CrossRequestRetryDelay), - } -} - -func (p *awsSDKProvider) addHandlers(regionName string, h *request.Handlers) { - h.Sign.PushFrontNamed(request.NamedHandler{ - Name: "k8s/logger", - Fn: awsHandlerLogger, - }) - - delayer := p.getCrossRequestRetryDelay(regionName) - if delayer != nil { - h.Sign.PushFrontNamed(request.NamedHandler{ - Name: "k8s/delay-presign", - Fn: delayer.BeforeSign, - }) - - h.AfterRetry.PushFrontNamed(request.NamedHandler{ - Name: "k8s/delay-afterretry", - Fn: delayer.AfterRetry, - }) - } -} - -// Get a CrossRequestRetryDelay, scoped to the region, not to the request. -// This means that when we hit a limit on a call, we will delay _all_ calls to the API. -// We do this to protect the AWS account from becoming overloaded and effectively locked. -// We also log when we hit request limits. -// Note that this delays the current goroutine; this is bad behaviour and will -// likely cause k8s to become slow or unresponsive for cloud operations. -// However, this throttle is intended only as a last resort. When we observe -// this throttling, we need to address the root cause (e.g. add a delay to a -// controller retry loop) -func (p *awsSDKProvider) getCrossRequestRetryDelay(regionName string) *CrossRequestRetryDelay { - p.mutex.Lock() - defer p.mutex.Unlock() - - delayer, found := p.regionDelayers[regionName] - if !found { - delayer = NewCrossRequestRetryDelay() - p.regionDelayers[regionName] = delayer - } - return delayer -} - -func (p *awsSDKProvider) Compute(regionName string) (EC2, error) { - service := ec2.New(session.New(&aws.Config{ - Region: ®ionName, - Credentials: p.creds, - })) - - p.addHandlers(regionName, &service.Handlers) - - ec2 := &awsSdkEC2{ - ec2: service, - } - return ec2, nil -} - -func (p *awsSDKProvider) LoadBalancing(regionName string) (ELB, error) { - elbClient := elb.New(session.New(&aws.Config{ - Region: ®ionName, - Credentials: p.creds, - })) - - p.addHandlers(regionName, &elbClient.Handlers) - - return elbClient, nil -} - -func (p *awsSDKProvider) Autoscaling(regionName string) (ASG, error) { - client := autoscaling.New(session.New(&aws.Config{ - Region: ®ionName, - Credentials: p.creds, - })) - - p.addHandlers(regionName, &client.Handlers) - - return client, nil -} - -func (p *awsSDKProvider) Metadata() (EC2Metadata, error) { - client := ec2metadata.New(session.New(&aws.Config{})) - return client, nil -} - -func stringPointerArray(orig []string) []*string { - if orig == nil { - return nil - } - n := make([]*string, len(orig)) - for i := range orig { - n[i] = &orig[i] - } - return n -} - -func isNilOrEmpty(s *string) bool { - return s == nil || *s == "" -} - -func orEmpty(s *string) string { - if s == nil { - return "" - } - return *s -} - -func newEc2Filter(name string, value string) *ec2.Filter { - filter := &ec2.Filter{ - Name: aws.String(name), - Values: []*string{ - aws.String(value), - }, - } - return filter -} - -func (self *AWSCloud) AddSSHKeyToAllInstances(user string, keyData []byte) error { - return errors.New("unimplemented") -} - -func (c *AWSCloud) CurrentNodeName(hostname string) (string, error) { - return c.selfAWSInstance.nodeName, nil -} - -// Implementation of EC2.Instances -func (self *awsSdkEC2) DescribeInstances(request *ec2.DescribeInstancesInput) ([]*ec2.Instance, error) { - // Instances are paged - results := []*ec2.Instance{} - var nextToken *string - - for { - response, err := self.ec2.DescribeInstances(request) - if err != nil { - return nil, fmt.Errorf("error listing AWS instances: %v", err) - } - - for _, reservation := range response.Reservations { - results = append(results, reservation.Instances...) - } - - nextToken = response.NextToken - if isNilOrEmpty(nextToken) { - break - } - request.NextToken = nextToken - } - - return results, nil -} - -// Implements EC2.DescribeSecurityGroups -func (s *awsSdkEC2) DescribeSecurityGroups(request *ec2.DescribeSecurityGroupsInput) ([]*ec2.SecurityGroup, error) { - // Security groups are not paged - response, err := s.ec2.DescribeSecurityGroups(request) - if err != nil { - return nil, fmt.Errorf("error listing AWS security groups: %v", err) - } - return response.SecurityGroups, nil -} - -func (s *awsSdkEC2) AttachVolume(request *ec2.AttachVolumeInput) (*ec2.VolumeAttachment, error) { - return s.ec2.AttachVolume(request) -} - -func (s *awsSdkEC2) DetachVolume(request *ec2.DetachVolumeInput) (*ec2.VolumeAttachment, error) { - return s.ec2.DetachVolume(request) -} - -func (s *awsSdkEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.Volume, error) { - // Volumes are paged - results := []*ec2.Volume{} - var nextToken *string - - for { - response, err := s.ec2.DescribeVolumes(request) - - if err != nil { - return nil, fmt.Errorf("error listing AWS volumes: %v", err) - } - - results = append(results, response.Volumes...) - - nextToken = response.NextToken - if isNilOrEmpty(nextToken) { - break - } - request.NextToken = nextToken - } - - return results, nil -} - -func (s *awsSdkEC2) CreateVolume(request *ec2.CreateVolumeInput) (resp *ec2.Volume, err error) { - return s.ec2.CreateVolume(request) -} - -func (s *awsSdkEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (*ec2.DeleteVolumeOutput, error) { - return s.ec2.DeleteVolume(request) -} - -func (s *awsSdkEC2) DescribeSubnets(request *ec2.DescribeSubnetsInput) ([]*ec2.Subnet, error) { - // Subnets are not paged - response, err := s.ec2.DescribeSubnets(request) - if err != nil { - return nil, fmt.Errorf("error listing AWS subnets: %v", err) - } - return response.Subnets, nil -} - -func (s *awsSdkEC2) CreateSecurityGroup(request *ec2.CreateSecurityGroupInput) (*ec2.CreateSecurityGroupOutput, error) { - return s.ec2.CreateSecurityGroup(request) -} - -func (s *awsSdkEC2) DeleteSecurityGroup(request *ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error) { - return s.ec2.DeleteSecurityGroup(request) -} - -func (s *awsSdkEC2) AuthorizeSecurityGroupIngress(request *ec2.AuthorizeSecurityGroupIngressInput) (*ec2.AuthorizeSecurityGroupIngressOutput, error) { - return s.ec2.AuthorizeSecurityGroupIngress(request) -} - -func (s *awsSdkEC2) RevokeSecurityGroupIngress(request *ec2.RevokeSecurityGroupIngressInput) (*ec2.RevokeSecurityGroupIngressOutput, error) { - return s.ec2.RevokeSecurityGroupIngress(request) -} - -func (s *awsSdkEC2) CreateTags(request *ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) { - return s.ec2.CreateTags(request) -} - -func (s *awsSdkEC2) DescribeRouteTables(request *ec2.DescribeRouteTablesInput) ([]*ec2.RouteTable, error) { - // Not paged - response, err := s.ec2.DescribeRouteTables(request) - if err != nil { - return nil, fmt.Errorf("error listing AWS route tables: %v", err) - } - return response.RouteTables, nil -} - -func (s *awsSdkEC2) CreateRoute(request *ec2.CreateRouteInput) (*ec2.CreateRouteOutput, error) { - return s.ec2.CreateRoute(request) -} - -func (s *awsSdkEC2) DeleteRoute(request *ec2.DeleteRouteInput) (*ec2.DeleteRouteOutput, error) { - return s.ec2.DeleteRoute(request) -} - -func (s *awsSdkEC2) ModifyInstanceAttribute(request *ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error) { - return s.ec2.ModifyInstanceAttribute(request) -} - -func init() { - cloudprovider.RegisterCloudProvider(ProviderName, func(config io.Reader) (cloudprovider.Interface, error) { - creds := credentials.NewChainCredentials( - []credentials.Provider{ - &credentials.EnvProvider{}, - &ec2rolecreds.EC2RoleProvider{ - Client: ec2metadata.New(session.New(&aws.Config{})), - }, - &credentials.SharedCredentialsProvider{}, - }) - aws := newAWSSDKProvider(creds) - return newAWSCloud(config, aws) - }) -} - -// readAWSCloudConfig reads an instance of AWSCloudConfig from config reader. -func readAWSCloudConfig(config io.Reader, metadata EC2Metadata) (*AWSCloudConfig, error) { - var cfg AWSCloudConfig - var err error - - if config != nil { - err = gcfg.ReadInto(&cfg, config) - if err != nil { - return nil, err - } - } - - if cfg.Global.Zone == "" { - if metadata != nil { - glog.Info("Zone not specified in configuration file; querying AWS metadata service") - cfg.Global.Zone, err = getAvailabilityZone(metadata) - if err != nil { - return nil, err - } - } - if cfg.Global.Zone == "" { - return nil, fmt.Errorf("no zone specified in configuration file") - } - } - - return &cfg, nil -} - -func getInstanceType(metadata EC2Metadata) (string, error) { - return metadata.GetMetadata("instance-type") -} - -func getAvailabilityZone(metadata EC2Metadata) (string, error) { - return metadata.GetMetadata("placement/availability-zone") -} - -func isRegionValid(region string) bool { - regions := [...]string{ - "us-east-1", - "us-west-1", - "us-west-2", - "eu-west-1", - "eu-central-1", - "ap-southeast-1", - "ap-southeast-2", - "ap-northeast-1", - "ap-northeast-2", - "cn-north-1", - "us-gov-west-1", - "sa-east-1", - } - for _, r := range regions { - if r == region { - return true - } - } - return false -} - -// Derives the region from a valid az name. -// Returns an error if the az is known invalid (empty) -func azToRegion(az string) (string, error) { - if len(az) < 1 { - return "", fmt.Errorf("invalid (empty) AZ") - } - region := az[:len(az)-1] - return region, nil -} - -// newAWSCloud creates a new instance of AWSCloud. -// AWSProvider and instanceId are primarily for tests -func newAWSCloud(config io.Reader, awsServices AWSServices) (*AWSCloud, error) { - metadata, err := awsServices.Metadata() - if err != nil { - return nil, fmt.Errorf("error creating AWS metadata client: %v", err) - } - - cfg, err := readAWSCloudConfig(config, metadata) - if err != nil { - return nil, fmt.Errorf("unable to read AWS cloud provider config file: %v", err) - } - - zone := cfg.Global.Zone - if len(zone) <= 1 { - return nil, fmt.Errorf("invalid AWS zone in config file: %s", zone) - } - regionName, err := azToRegion(zone) - if err != nil { - return nil, err - } - - valid := isRegionValid(regionName) - if !valid { - return nil, fmt.Errorf("not a valid AWS zone (unknown region): %s", zone) - } - - ec2, err := awsServices.Compute(regionName) - if err != nil { - return nil, fmt.Errorf("error creating AWS EC2 client: %v", err) - } - - elb, err := awsServices.LoadBalancing(regionName) - if err != nil { - return nil, fmt.Errorf("error creating AWS ELB client: %v", err) - } - - asg, err := awsServices.Autoscaling(regionName) - if err != nil { - return nil, fmt.Errorf("error creating AWS autoscaling client: %v", err) - } - - awsCloud := &AWSCloud{ - ec2: ec2, - elb: elb, - asg: asg, - metadata: metadata, - cfg: cfg, - region: regionName, - } - - selfAWSInstance, err := awsCloud.buildSelfAWSInstance() - if err != nil { - return nil, err - } - - awsCloud.selfAWSInstance = selfAWSInstance - awsCloud.vpcID = selfAWSInstance.vpcID - - filterTags := map[string]string{} - if cfg.Global.KubernetesClusterTag != "" { - filterTags[TagNameKubernetesCluster] = cfg.Global.KubernetesClusterTag - } else { - // TODO: Clean up double-API query - info, err := selfAWSInstance.describeInstance() - if err != nil { - return nil, err - } - for _, tag := range info.Tags { - if orEmpty(tag.Key) == TagNameKubernetesCluster { - filterTags[TagNameKubernetesCluster] = orEmpty(tag.Value) - } - } - } - - if filterTags[TagNameKubernetesCluster] == "" { - glog.Errorf("Tag %q not found; Kuberentes may behave unexpectedly.", TagNameKubernetesCluster) - } - - awsCloud.filterTags = filterTags - if len(filterTags) > 0 { - glog.Infof("AWS cloud filtering on tags: %v", filterTags) - } else { - glog.Infof("AWS cloud - no tag filtering") - } - - // Register handler for ECR credentials - once.Do(func() { - aws_credentials.Init() - }) - - return awsCloud, nil -} - -func (aws *AWSCloud) Clusters() (cloudprovider.Clusters, bool) { - return nil, false -} - -// ProviderName returns the cloud provider ID. -func (aws *AWSCloud) ProviderName() string { - return ProviderName -} - -// ScrubDNS filters DNS settings for pods. -func (aws *AWSCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) { - return nameservers, searches -} - -// LoadBalancer returns an implementation of LoadBalancer for Amazon Web Services. -func (s *AWSCloud) LoadBalancer() (cloudprovider.LoadBalancer, bool) { - return s, true -} - -// Instances returns an implementation of Instances for Amazon Web Services. -func (aws *AWSCloud) Instances() (cloudprovider.Instances, bool) { - return aws, true -} - -// Zones returns an implementation of Zones for Amazon Web Services. -func (aws *AWSCloud) Zones() (cloudprovider.Zones, bool) { - return aws, true -} - -// Routes returns an implementation of Routes for Amazon Web Services. -func (aws *AWSCloud) Routes() (cloudprovider.Routes, bool) { - return aws, true -} - -// NodeAddresses is an implementation of Instances.NodeAddresses. -func (c *AWSCloud) NodeAddresses(name string) ([]api.NodeAddress, error) { - if c.selfAWSInstance.nodeName == name || len(name) == 0 { - addresses := []api.NodeAddress{} - - internalIP, err := c.metadata.GetMetadata("local-ipv4") - if err != nil { - return nil, err - } - addresses = append(addresses, api.NodeAddress{Type: api.NodeInternalIP, Address: internalIP}) - // Legacy compatibility: the private ip was the legacy host ip - addresses = append(addresses, api.NodeAddress{Type: api.NodeLegacyHostIP, Address: internalIP}) - - externalIP, err := c.metadata.GetMetadata("public-ipv4") - if err != nil { - //TODO: It would be nice to be able to determine the reason for the failure, - // but the AWS client masks all failures with the same error description. - glog.V(2).Info("Could not determine public IP from AWS metadata.") - } else { - addresses = append(addresses, api.NodeAddress{Type: api.NodeExternalIP, Address: externalIP}) - } - - return addresses, nil - } - instance, err := c.getInstanceByNodeName(name) - if err != nil { - return nil, err - } - - addresses := []api.NodeAddress{} - - if !isNilOrEmpty(instance.PrivateIpAddress) { - ipAddress := *instance.PrivateIpAddress - ip := net.ParseIP(ipAddress) - if ip == nil { - return nil, fmt.Errorf("EC2 instance had invalid private address: %s (%s)", orEmpty(instance.InstanceId), ipAddress) - } - addresses = append(addresses, api.NodeAddress{Type: api.NodeInternalIP, Address: ip.String()}) - - // Legacy compatibility: the private ip was the legacy host ip - addresses = append(addresses, api.NodeAddress{Type: api.NodeLegacyHostIP, Address: ip.String()}) - } - - // TODO: Other IP addresses (multiple ips)? - if !isNilOrEmpty(instance.PublicIpAddress) { - ipAddress := *instance.PublicIpAddress - ip := net.ParseIP(ipAddress) - if ip == nil { - return nil, fmt.Errorf("EC2 instance had invalid public address: %s (%s)", orEmpty(instance.InstanceId), ipAddress) - } - addresses = append(addresses, api.NodeAddress{Type: api.NodeExternalIP, Address: ip.String()}) - } - - return addresses, nil -} - -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (c *AWSCloud) ExternalID(name string) (string, error) { - if c.selfAWSInstance.nodeName == name { - // We assume that if this is run on the instance itself, the instance exists and is alive - return c.selfAWSInstance.awsID, nil - } else { - // We must verify that the instance still exists - // Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound) - instance, err := c.findInstanceByNodeName(name) - if err != nil { - return "", err - } - if instance == nil { - return "", cloudprovider.InstanceNotFound - } - return orEmpty(instance.InstanceId), nil - } -} - -// InstanceID returns the cloud provider ID of the specified instance. -func (c *AWSCloud) InstanceID(name string) (string, error) { - // In the future it is possible to also return an endpoint as: - // // - if c.selfAWSInstance.nodeName == name { - return "/" + c.selfAWSInstance.availabilityZone + "/" + c.selfAWSInstance.awsID, nil - } else { - inst, err := c.getInstanceByNodeName(name) - if err != nil { - return "", err - } - return "/" + orEmpty(inst.Placement.AvailabilityZone) + "/" + orEmpty(inst.InstanceId), nil - } -} - -// InstanceType returns the type of the specified instance. -func (c *AWSCloud) InstanceType(name string) (string, error) { - if c.selfAWSInstance.nodeName == name { - return c.selfAWSInstance.instanceType, nil - } else { - inst, err := c.getInstanceByNodeName(name) - if err != nil { - return "", err - } - return orEmpty(inst.InstanceType), nil - } -} - -// Return a list of instances matching regex string. -func (s *AWSCloud) getInstancesByRegex(regex string) ([]string, error) { - filters := []*ec2.Filter{newEc2Filter("instance-state-name", "running")} - filters = s.addFilters(filters) - request := &ec2.DescribeInstancesInput{ - Filters: filters, - } - - instances, err := s.ec2.DescribeInstances(request) - if err != nil { - return []string{}, err - } - if len(instances) == 0 { - return []string{}, fmt.Errorf("no instances returned") - } - - if strings.HasPrefix(regex, "'") && strings.HasSuffix(regex, "'") { - glog.Infof("Stripping quotes around regex (%s)", regex) - regex = regex[1 : len(regex)-1] - } - - re, err := regexp.Compile(regex) - if err != nil { - return []string{}, err - } - - matchingInstances := []string{} - for _, instance := range instances { - // Only return fully-ready instances when listing instances - // (vs a query by name, where we will return it if we find it) - if orEmpty(instance.State.Name) == "pending" { - glog.V(2).Infof("Skipping EC2 instance (pending): %s", *instance.InstanceId) - continue - } - - privateDNSName := orEmpty(instance.PrivateDnsName) - if privateDNSName == "" { - glog.V(2).Infof("Skipping EC2 instance (no PrivateDNSName): %s", - orEmpty(instance.InstanceId)) - continue - } - - for _, tag := range instance.Tags { - if orEmpty(tag.Key) == "Name" && re.MatchString(orEmpty(tag.Value)) { - matchingInstances = append(matchingInstances, privateDNSName) - break - } - } - } - glog.V(2).Infof("Matched EC2 instances: %s", matchingInstances) - return matchingInstances, nil -} - -// List is an implementation of Instances.List. -func (aws *AWSCloud) List(filter string) ([]string, error) { - // TODO: Should really use tag query. No need to go regexp. - return aws.getInstancesByRegex(filter) -} - -// GetZone implements Zones.GetZone -func (c *AWSCloud) GetZone() (cloudprovider.Zone, error) { - return cloudprovider.Zone{ - FailureDomain: c.selfAWSInstance.availabilityZone, - Region: c.region, - }, nil -} - -// Abstraction around AWS Instance Types -// There isn't an API to get information for a particular instance type (that I know of) -type awsInstanceType struct { -} - -// Used to represent a mount device for attaching an EBS volume -// This should be stored as a single letter (i.e. c, not sdc or /dev/sdc) -type mountDevice string - -// TODO: Also return number of mounts allowed? -func (self *awsInstanceType) getEBSMountDevices() []mountDevice { - // See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html - // We will generate "ba", "bb", "bc"..."bz", "ca", ..., up to DefaultMaxEBSVolumes - devices := []mountDevice{} - count := 0 - for first := 'b'; count < DefaultMaxEBSVolumes; first++ { - for second := 'a'; count < DefaultMaxEBSVolumes && second <= 'z'; second++ { - device := mountDevice(fmt.Sprintf("%c%c", first, second)) - devices = append(devices, device) - count++ - } - } - - return devices -} - -type awsInstance struct { - ec2 EC2 - - // id in AWS - awsID string - - // node name in k8s - nodeName string - - // availability zone the instance resides in - availabilityZone string - - // ID of VPC the instance resides in - vpcID string - - // ID of subnet the instance resides in - subnetID string - - // instance type - instanceType string - - mutex sync.Mutex - - // We keep an active list of devices we have assigned but not yet - // attached, to avoid a race condition where we assign a device mapping - // and then get a second request before we attach the volume - attaching map[mountDevice]string -} - -// newAWSInstance creates a new awsInstance object -func newAWSInstance(ec2Service EC2, instance *ec2.Instance) *awsInstance { - az := "" - if instance.Placement != nil { - az = aws.StringValue(instance.Placement.AvailabilityZone) - } - self := &awsInstance{ - ec2: ec2Service, - awsID: aws.StringValue(instance.InstanceId), - nodeName: aws.StringValue(instance.PrivateDnsName), - availabilityZone: az, - instanceType: aws.StringValue(instance.InstanceType), - vpcID: aws.StringValue(instance.VpcId), - subnetID: aws.StringValue(instance.SubnetId), - } - - self.attaching = make(map[mountDevice]string) - - return self -} - -// Gets the awsInstanceType that models the instance type of this instance -func (self *awsInstance) getInstanceType() *awsInstanceType { - // TODO: Make this real - awsInstanceType := &awsInstanceType{} - return awsInstanceType -} - -// Gets the full information about this instance from the EC2 API -func (self *awsInstance) describeInstance() (*ec2.Instance, error) { - instanceID := self.awsID - request := &ec2.DescribeInstancesInput{ - InstanceIds: []*string{&instanceID}, - } - - instances, err := self.ec2.DescribeInstances(request) - if err != nil { - return nil, err - } - if len(instances) == 0 { - return nil, fmt.Errorf("no instances found for instance: %s", self.awsID) - } - if len(instances) > 1 { - return nil, fmt.Errorf("multiple instances found for instance: %s", self.awsID) - } - return instances[0], nil -} - -// Gets the mountDevice already assigned to the volume, or assigns an unused mountDevice. -// If the volume is already assigned, this will return the existing mountDevice with alreadyAttached=true. -// Otherwise the mountDevice is assigned by finding the first available mountDevice, and it is returned with alreadyAttached=false. -func (self *awsInstance) getMountDevice(volumeID string, assign bool) (assigned mountDevice, alreadyAttached bool, err error) { - instanceType := self.getInstanceType() - if instanceType == nil { - return "", false, fmt.Errorf("could not get instance type for instance: %s", self.awsID) - } - - // We lock to prevent concurrent mounts from conflicting - // We may still conflict if someone calls the API concurrently, - // but the AWS API will then fail one of the two attach operations - self.mutex.Lock() - defer self.mutex.Unlock() - - info, err := self.describeInstance() - if err != nil { - return "", false, err - } - deviceMappings := map[mountDevice]string{} - for _, blockDevice := range info.BlockDeviceMappings { - name := aws.StringValue(blockDevice.DeviceName) - if strings.HasPrefix(name, "/dev/sd") { - name = name[7:] - } - if strings.HasPrefix(name, "/dev/xvd") { - name = name[8:] - } - if len(name) < 1 || len(name) > 2 { - glog.Warningf("Unexpected EBS DeviceName: %q", aws.StringValue(blockDevice.DeviceName)) - } - deviceMappings[mountDevice(name)] = aws.StringValue(blockDevice.Ebs.VolumeId) - } - - for mountDevice, volume := range self.attaching { - deviceMappings[mountDevice] = volume - } - - // Check to see if this volume is already assigned a device on this machine - for mountDevice, mappingVolumeID := range deviceMappings { - if volumeID == mappingVolumeID { - if assign { - glog.Warningf("Got assignment call for already-assigned volume: %s@%s", mountDevice, mappingVolumeID) - } - return mountDevice, true, nil - } - } - - if !assign { - return mountDevice(""), false, nil - } - - // Check all the valid mountpoints to see if any of them are free - valid := instanceType.getEBSMountDevices() - chosen := mountDevice("") - for _, mountDevice := range valid { - _, found := deviceMappings[mountDevice] - if !found { - chosen = mountDevice - break - } - } - - if chosen == "" { - glog.Warningf("Could not assign a mount device (all in use?). mappings=%v, valid=%v", deviceMappings, valid) - return "", false, fmt.Errorf("Too many EBS volumes attached to node %s.", self.nodeName) - } - - self.attaching[chosen] = volumeID - glog.V(2).Infof("Assigned mount device %s -> volume %s", chosen, volumeID) - - return chosen, false, nil -} - -func (self *awsInstance) endAttaching(volumeID string, mountDevice mountDevice) { - self.mutex.Lock() - defer self.mutex.Unlock() - - existingVolumeID, found := self.attaching[mountDevice] - if !found { - glog.Errorf("endAttaching on non-allocated device") - return - } - if volumeID != existingVolumeID { - glog.Errorf("endAttaching on device assigned to different volume") - return - } - glog.V(2).Infof("Releasing mount device mapping: %s -> volume %s", mountDevice, volumeID) - delete(self.attaching, mountDevice) -} - -type awsDisk struct { - ec2 EC2 - - // Name in k8s - name string - // id in AWS - awsID string -} - -func newAWSDisk(aws *AWSCloud, name string) (*awsDisk, error) { - // name looks like aws://availability-zone/id - - // The original idea of the URL-style name was to put the AZ into the - // host, so we could find the AZ immediately from the name without - // querying the API. But it turns out we don't actually need it for - // Ubernetes-Lite, as we put the AZ into the labels on the PV instead. - // However, if in future we want to support Ubernetes-Lite - // volume-awareness without using PersistentVolumes, we likely will - // want the AZ in the host. - - if !strings.HasPrefix(name, "aws://") { - name = "aws://" + "" + "/" + name - } - url, err := url.Parse(name) - if err != nil { - // TODO: Maybe we should pass a URL into the Volume functions - return nil, fmt.Errorf("Invalid disk name (%s): %v", name, err) - } - if url.Scheme != "aws" { - return nil, fmt.Errorf("Invalid scheme for AWS volume (%s)", name) - } - - awsID := url.Path - if len(awsID) > 1 && awsID[0] == '/' { - awsID = awsID[1:] - } - - // TODO: Regex match? - if strings.Contains(awsID, "/") || !strings.HasPrefix(awsID, "vol-") { - return nil, fmt.Errorf("Invalid format for AWS volume (%s)", name) - } - - disk := &awsDisk{ec2: aws.ec2, name: name, awsID: awsID} - return disk, nil -} - -// Gets the full information about this volume from the EC2 API -func (self *awsDisk) describeVolume() (*ec2.Volume, error) { - volumeID := self.awsID - - request := &ec2.DescribeVolumesInput{ - VolumeIds: []*string{&volumeID}, - } - - volumes, err := self.ec2.DescribeVolumes(request) - if err != nil { - return nil, fmt.Errorf("error querying ec2 for volume info: %v", err) - } - if len(volumes) == 0 { - return nil, fmt.Errorf("no volumes found for volume: %s", self.awsID) - } - if len(volumes) > 1 { - return nil, fmt.Errorf("multiple volumes found for volume: %s", self.awsID) - } - return volumes[0], nil -} - -// waitForAttachmentStatus polls until the attachment status is the expected value -// TODO(justinsb): return (bool, error) -func (self *awsDisk) waitForAttachmentStatus(status string) error { - // TODO: There may be a faster way to get this when we're attaching locally - attempt := 0 - maxAttempts := 60 - - for { - info, err := self.describeVolume() - if err != nil { - return err - } - if len(info.Attachments) > 1 { - glog.Warningf("Found multiple attachments for volume: %v", info) - } - attachmentStatus := "" - for _, attachment := range info.Attachments { - if attachmentStatus != "" { - glog.Warning("Found multiple attachments: ", info) - } - if attachment.State != nil { - attachmentStatus = *attachment.State - } else { - // Shouldn't happen, but don't panic... - glog.Warning("Ignoring nil attachment state: ", attachment) - } - } - if attachmentStatus == "" { - attachmentStatus = "detached" - } - if attachmentStatus == status { - return nil - } - - glog.V(2).Infof("Waiting for volume state: actual=%s, desired=%s", attachmentStatus, status) - - attempt++ - if attempt > maxAttempts { - glog.Warningf("Timeout waiting for volume state: actual=%s, desired=%s", attachmentStatus, status) - return errors.New("Timeout waiting for volume state") - } - - time.Sleep(1 * time.Second) - } -} - -// Deletes the EBS disk -func (self *awsDisk) deleteVolume() (bool, error) { - request := &ec2.DeleteVolumeInput{VolumeId: aws.String(self.awsID)} - _, err := self.ec2.DeleteVolume(request) - if err != nil { - if awsError, ok := err.(awserr.Error); ok { - if awsError.Code() == "InvalidVolume.NotFound" { - return false, nil - } - } - return false, fmt.Errorf("error deleting EBS volumes: %v", err) - } - return true, nil -} - -// Builds the awsInstance for the EC2 instance on which we are running. -// This is called when the AWSCloud is initialized, and should not be called otherwise (because the awsInstance for the local instance is a singleton with drive mapping state) -func (c *AWSCloud) buildSelfAWSInstance() (*awsInstance, error) { - if c.selfAWSInstance != nil { - panic("do not call buildSelfAWSInstance directly") - } - instanceId, err := c.metadata.GetMetadata("instance-id") - if err != nil { - return nil, fmt.Errorf("error fetching instance-id from ec2 metadata service: %v", err) - } - - // We want to fetch the hostname via the EC2 metadata service - // (`GetMetadata("local-hostname")`): But see #11543 - we need to use - // the EC2 API to get the privateDnsName in case of a private DNS zone - // e.g. mydomain.io, because the metadata service returns the wrong - // hostname. Once we're doing that, we might as well get all our - // information from the instance returned by the EC2 API - it is a - // single API call to get all the information, and it means we don't - // have two code paths. - instance, err := c.getInstanceByID(instanceId) - if err != nil { - return nil, fmt.Errorf("error finding instance %s: %v", instanceId, err) - } - return newAWSInstance(c.ec2, instance), nil -} - -// Gets the awsInstance with node-name nodeName, or the 'self' instance if nodeName == "" -func (c *AWSCloud) getAwsInstance(nodeName string) (*awsInstance, error) { - var awsInstance *awsInstance - if nodeName == "" { - awsInstance = c.selfAWSInstance - } else { - instance, err := c.getInstanceByNodeName(nodeName) - if err != nil { - return nil, fmt.Errorf("error finding instance %s: %v", nodeName, err) - } - - awsInstance = newAWSInstance(c.ec2, instance) - } - - return awsInstance, nil -} - -// Implements Volumes.AttachDisk -func (c *AWSCloud) AttachDisk(diskName string, instanceName string, readOnly bool) (string, error) { - disk, err := newAWSDisk(c, diskName) - if err != nil { - return "", err - } - - awsInstance, err := c.getAwsInstance(instanceName) - if err != nil { - return "", err - } - - if readOnly { - // TODO: We could enforce this when we mount the volume (?) - // TODO: We could also snapshot the volume and attach copies of it - return "", errors.New("AWS volumes cannot be mounted read-only") - } - - mountDevice, alreadyAttached, err := awsInstance.getMountDevice(disk.awsID, true) - if err != nil { - return "", err - } - - // Inside the instance, the mountpoint always looks like /dev/xvdX (?) - hostDevice := "/dev/xvd" + string(mountDevice) - // In the EC2 API, it is sometimes is /dev/sdX and sometimes /dev/xvdX - // We are running on the node here, so we check if /dev/xvda exists to determine this - ec2Device := "/dev/xvd" + string(mountDevice) - if _, err := os.Stat("/dev/xvda"); os.IsNotExist(err) { - ec2Device = "/dev/sd" + string(mountDevice) - } - - // attachEnded is set to true if the attach operation completed - // (successfully or not) - attachEnded := false - defer func() { - if attachEnded { - awsInstance.endAttaching(disk.awsID, mountDevice) - } - }() - - if !alreadyAttached { - request := &ec2.AttachVolumeInput{ - Device: aws.String(ec2Device), - InstanceId: aws.String(awsInstance.awsID), - VolumeId: aws.String(disk.awsID), - } - - attachResponse, err := c.ec2.AttachVolume(request) - if err != nil { - attachEnded = true - // TODO: Check if the volume was concurrently attached? - return "", fmt.Errorf("Error attaching EBS volume: %v", err) - } - - glog.V(2).Infof("AttachVolume request returned %v", attachResponse) - } - - err = disk.waitForAttachmentStatus("attached") - if err != nil { - return "", err - } - - attachEnded = true - - return hostDevice, nil -} - -// Implements Volumes.DetachDisk -func (aws *AWSCloud) DetachDisk(diskName string, instanceName string) (string, error) { - disk, err := newAWSDisk(aws, diskName) - if err != nil { - return "", err - } - - awsInstance, err := aws.getAwsInstance(instanceName) - if err != nil { - return "", err - } - - mountDevice, alreadyAttached, err := awsInstance.getMountDevice(disk.awsID, false) - if err != nil { - return "", err - } - - if !alreadyAttached { - glog.Warning("DetachDisk called on non-attached disk: ", diskName) - // TODO: Continue? Tolerate non-attached error in DetachVolume? - } - - request := ec2.DetachVolumeInput{ - InstanceId: &awsInstance.awsID, - VolumeId: &disk.awsID, - } - - response, err := aws.ec2.DetachVolume(&request) - if err != nil { - return "", fmt.Errorf("error detaching EBS volume: %v", err) - } - if response == nil { - return "", errors.New("no response from DetachVolume") - } - - err = disk.waitForAttachmentStatus("detached") - if err != nil { - return "", err - } - - if mountDevice != "" { - awsInstance.endAttaching(disk.awsID, mountDevice) - } - - hostDevicePath := "/dev/xvd" + string(mountDevice) - return hostDevicePath, err -} - -// Implements Volumes.CreateVolume -func (s *AWSCloud) CreateDisk(volumeOptions *VolumeOptions) (string, error) { - // Default to creating in the current zone - // TODO: Spread across zones? - createAZ := s.selfAWSInstance.availabilityZone - - // TODO: Should we tag this with the cluster id (so it gets deleted when the cluster does?) - request := &ec2.CreateVolumeInput{} - request.AvailabilityZone = &createAZ - volSize := int64(volumeOptions.CapacityGB) - request.Size = &volSize - request.VolumeType = aws.String(DefaultVolumeType) - response, err := s.ec2.CreateVolume(request) - if err != nil { - return "", err - } - - az := orEmpty(response.AvailabilityZone) - awsID := orEmpty(response.VolumeId) - - volumeName := "aws://" + az + "/" + awsID - - // apply tags - tags := make(map[string]string) - for k, v := range volumeOptions.Tags { - tags[k] = v - } - - if s.getClusterName() != "" { - tags[TagNameKubernetesCluster] = s.getClusterName() - } - - if len(tags) != 0 { - if err := s.createTags(awsID, tags); err != nil { - // delete the volume and hope it succeeds - _, delerr := s.DeleteDisk(volumeName) - if delerr != nil { - // delete did not succeed, we have a stray volume! - return "", fmt.Errorf("error tagging volume %s, could not delete the volume: %v", volumeName, delerr) - } - return "", fmt.Errorf("error tagging volume %s: %v", volumeName, err) - } - } - return volumeName, nil -} - -// Implements Volumes.DeleteDisk -func (c *AWSCloud) DeleteDisk(volumeName string) (bool, error) { - awsDisk, err := newAWSDisk(c, volumeName) - if err != nil { - return false, err - } - return awsDisk.deleteVolume() -} - -// Implements Volumes.GetVolumeLabels -func (c *AWSCloud) GetVolumeLabels(volumeName string) (map[string]string, error) { - awsDisk, err := newAWSDisk(c, volumeName) - if err != nil { - return nil, err - } - info, err := awsDisk.describeVolume() - if err != nil { - return nil, err - } - labels := make(map[string]string) - az := aws.StringValue(info.AvailabilityZone) - if az == "" { - return nil, fmt.Errorf("volume did not have AZ information: %q", info.VolumeId) - } - - labels[unversioned.LabelZoneFailureDomain] = az - region, err := azToRegion(az) - if err != nil { - return nil, err - } - labels[unversioned.LabelZoneRegion] = region - - return labels, nil -} - -// Gets the current load balancer state -func (s *AWSCloud) describeLoadBalancer(name string) (*elb.LoadBalancerDescription, error) { - request := &elb.DescribeLoadBalancersInput{} - request.LoadBalancerNames = []*string{&name} - - response, err := s.elb.DescribeLoadBalancers(request) - if err != nil { - if awsError, ok := err.(awserr.Error); ok { - if awsError.Code() == "LoadBalancerNotFound" { - return nil, nil - } - } - return nil, err - } - - var ret *elb.LoadBalancerDescription - for _, loadBalancer := range response.LoadBalancerDescriptions { - if ret != nil { - glog.Errorf("Found multiple load balancers with name: %s", name) - } - ret = loadBalancer - } - return ret, nil -} - -// Retrieves instance's vpc id from metadata -func (self *AWSCloud) findVPCID() (string, error) { - macs, err := self.metadata.GetMetadata("network/interfaces/macs/") - if err != nil { - return "", fmt.Errorf("Could not list interfaces of the instance: %v", err) - } - - // loop over interfaces, first vpc id returned wins - for _, macPath := range strings.Split(macs, "\n") { - if len(macPath) == 0 { - continue - } - url := fmt.Sprintf("network/interfaces/macs/%svpc-id", macPath) - vpcID, err := self.metadata.GetMetadata(url) - if err != nil { - continue - } - return vpcID, nil - } - return "", fmt.Errorf("Could not find VPC ID in instance metadata") -} - -// Retrieves the specified security group from the AWS API, or returns nil if not found -func (s *AWSCloud) findSecurityGroup(securityGroupId string) (*ec2.SecurityGroup, error) { - describeSecurityGroupsRequest := &ec2.DescribeSecurityGroupsInput{ - GroupIds: []*string{&securityGroupId}, - } - // We don't apply our tag filters because we are retrieving by ID - - groups, err := s.ec2.DescribeSecurityGroups(describeSecurityGroupsRequest) - if err != nil { - glog.Warningf("Error retrieving security group: %q", err) - return nil, err - } - - if len(groups) == 0 { - return nil, nil - } - if len(groups) != 1 { - // This should not be possible - ids should be unique - return nil, fmt.Errorf("multiple security groups found with same id %q", securityGroupId) - } - group := groups[0] - return group, nil -} - -func isEqualIntPointer(l, r *int64) bool { - if l == nil { - return r == nil - } - if r == nil { - return l == nil - } - return *l == *r -} - -func isEqualStringPointer(l, r *string) bool { - if l == nil { - return r == nil - } - if r == nil { - return l == nil - } - return *l == *r -} - -func ipPermissionExists(newPermission, existing *ec2.IpPermission, compareGroupUserIDs bool) bool { - if !isEqualIntPointer(newPermission.FromPort, existing.FromPort) { - return false - } - if !isEqualIntPointer(newPermission.ToPort, existing.ToPort) { - return false - } - if !isEqualStringPointer(newPermission.IpProtocol, existing.IpProtocol) { - return false - } - // Check only if newPermission is a subset of existing. Usually it has zero or one elements. - // Not doing actual CIDR math yet; not clear it's needed, either. - glog.V(4).Infof("Comparing %v to %v", newPermission, existing) - if len(newPermission.IpRanges) > len(existing.IpRanges) { - return false - } - - for j := range newPermission.IpRanges { - found := false - for k := range existing.IpRanges { - if isEqualStringPointer(newPermission.IpRanges[j].CidrIp, existing.IpRanges[k].CidrIp) { - found = true - break - } - } - if found == false { - return false - } - } - for _, leftPair := range newPermission.UserIdGroupPairs { - for _, rightPair := range existing.UserIdGroupPairs { - if isEqualUserGroupPair(leftPair, rightPair, compareGroupUserIDs) { - return true - } - } - return false - } - - return true -} - -func isEqualUserGroupPair(l, r *ec2.UserIdGroupPair, compareGroupUserIDs bool) bool { - glog.V(2).Infof("Comparing %v to %v", *l.GroupId, *r.GroupId) - if isEqualStringPointer(l.GroupId, r.GroupId) { - if compareGroupUserIDs { - if isEqualStringPointer(l.UserId, r.UserId) { - return true - } - } else { - return true - } - } - - return false -} - -// Makes sure the security group ingress is exactly the specified permissions -// Returns true if and only if changes were made -// The security group must already exist -func (s *AWSCloud) setSecurityGroupIngress(securityGroupId string, permissions IPPermissionSet) (bool, error) { - group, err := s.findSecurityGroup(securityGroupId) - if err != nil { - glog.Warning("Error retrieving security group", err) - return false, err - } - - if group == nil { - return false, fmt.Errorf("security group not found: %s", securityGroupId) - } - - glog.V(2).Infof("Existing security group ingress: %s %v", securityGroupId, group.IpPermissions) - - actual := NewIPPermissionSet(group.IpPermissions...) - - // EC2 groups rules together, for example combining: - // - // { Port=80, Range=[A] } and { Port=80, Range=[B] } - // - // into { Port=80, Range=[A,B] } - // - // We have to ungroup them, because otherwise the logic becomes really - // complicated, and also because if we have Range=[A,B] and we try to - // add Range=[A] then EC2 complains about a duplicate rule. - permissions = permissions.Ungroup() - actual = actual.Ungroup() - - remove := actual.Difference(permissions) - add := permissions.Difference(actual) - - if add.Len() == 0 && remove.Len() == 0 { - return false, nil - } - - // TODO: There is a limit in VPC of 100 rules per security group, so we - // probably should try grouping or combining to fit under this limit. - // But this is only used on the ELB security group currently, so it - // would require (ports * CIDRS) > 100. Also, it isn't obvious exactly - // how removing single permissions from compound rules works, and we - // don't want to accidentally open more than intended while we're - // applying changes. - if add.Len() != 0 { - glog.V(2).Infof("Adding security group ingress: %s %v", securityGroupId, add.List()) - - request := &ec2.AuthorizeSecurityGroupIngressInput{} - request.GroupId = &securityGroupId - request.IpPermissions = add.List() - _, err = s.ec2.AuthorizeSecurityGroupIngress(request) - if err != nil { - return false, fmt.Errorf("error authorizing security group ingress: %v", err) - } - } - if remove.Len() != 0 { - glog.V(2).Infof("Remove security group ingress: %s %v", securityGroupId, remove.List()) - - request := &ec2.RevokeSecurityGroupIngressInput{} - request.GroupId = &securityGroupId - request.IpPermissions = remove.List() - _, err = s.ec2.RevokeSecurityGroupIngress(request) - if err != nil { - return false, fmt.Errorf("error revoking security group ingress: %v", err) - } - } - - return true, nil -} - -// Makes sure the security group includes the specified permissions -// Returns true if and only if changes were made -// The security group must already exist -func (s *AWSCloud) addSecurityGroupIngress(securityGroupId string, addPermissions []*ec2.IpPermission) (bool, error) { - group, err := s.findSecurityGroup(securityGroupId) - if err != nil { - glog.Warningf("Error retrieving security group: %v", err) - return false, err - } - - if group == nil { - return false, fmt.Errorf("security group not found: %s", securityGroupId) - } - - glog.V(2).Infof("Existing security group ingress: %s %v", securityGroupId, group.IpPermissions) - - changes := []*ec2.IpPermission{} - for _, addPermission := range addPermissions { - hasUserID := false - for i := range addPermission.UserIdGroupPairs { - if addPermission.UserIdGroupPairs[i].UserId != nil { - hasUserID = true - } - } - - found := false - for _, groupPermission := range group.IpPermissions { - if ipPermissionExists(addPermission, groupPermission, hasUserID) { - found = true - break - } - } - - if !found { - changes = append(changes, addPermission) - } - } - - if len(changes) == 0 { - return false, nil - } - - glog.V(2).Infof("Adding security group ingress: %s %v", securityGroupId, changes) - - request := &ec2.AuthorizeSecurityGroupIngressInput{} - request.GroupId = &securityGroupId - request.IpPermissions = changes - _, err = s.ec2.AuthorizeSecurityGroupIngress(request) - if err != nil { - glog.Warning("Error authorizing security group ingress", err) - return false, fmt.Errorf("error authorizing security group ingress: %v", err) - } - - return true, nil -} - -// Makes sure the security group no longer includes the specified permissions -// Returns true if and only if changes were made -// If the security group no longer exists, will return (false, nil) -func (s *AWSCloud) removeSecurityGroupIngress(securityGroupId string, removePermissions []*ec2.IpPermission) (bool, error) { - group, err := s.findSecurityGroup(securityGroupId) - if err != nil { - glog.Warningf("Error retrieving security group: %v", err) - return false, err - } - - if group == nil { - glog.Warning("Security group not found: ", securityGroupId) - return false, nil - } - - changes := []*ec2.IpPermission{} - for _, removePermission := range removePermissions { - hasUserID := false - for i := range removePermission.UserIdGroupPairs { - if removePermission.UserIdGroupPairs[i].UserId != nil { - hasUserID = true - } - } - - var found *ec2.IpPermission - for _, groupPermission := range group.IpPermissions { - if ipPermissionExists(removePermission, groupPermission, hasUserID) { - found = removePermission - break - } - } - - if found != nil { - changes = append(changes, found) - } - } - - if len(changes) == 0 { - return false, nil - } - - glog.V(2).Infof("Removing security group ingress: %s %v", securityGroupId, changes) - - request := &ec2.RevokeSecurityGroupIngressInput{} - request.GroupId = &securityGroupId - request.IpPermissions = changes - _, err = s.ec2.RevokeSecurityGroupIngress(request) - if err != nil { - glog.Warningf("Error revoking security group ingress: %v", err) - return false, err - } - - return true, nil -} - -// Ensure that a resource has the correct tags -// If it has no tags, we assume that this was a problem caused by an error in between creation and tagging, -// and we add the tags. If it has a different cluster's tags, that is an error. -func (s *AWSCloud) ensureClusterTags(resourceID string, tags []*ec2.Tag) error { - actualTags := make(map[string]string) - for _, tag := range tags { - actualTags[aws.StringValue(tag.Key)] = aws.StringValue(tag.Value) - } - - addTags := make(map[string]string) - for k, expected := range s.filterTags { - actual := actualTags[k] - if actual == expected { - continue - } - if actual == "" { - glog.Warningf("Resource %q was missing expected cluster tag %q. Will add (with value %q)", resourceID, k, expected) - addTags[k] = expected - } else { - return fmt.Errorf("resource %q has tag belonging to another cluster: %q=%q (expected %q)", resourceID, k, actual, expected) - } - } - - if err := s.createTags(resourceID, addTags); err != nil { - return fmt.Errorf("error adding missing tags to resource %q: %v", resourceID, err) - } - - return nil -} - -// Makes sure the security group exists. -// For multi-cluster isolation, name must be globally unique, for example derived from the service UUID. -// Returns the security group id or error -func (s *AWSCloud) ensureSecurityGroup(name string, description string) (string, error) { - groupID := "" - attempt := 0 - for { - attempt++ - - request := &ec2.DescribeSecurityGroupsInput{} - filters := []*ec2.Filter{ - newEc2Filter("group-name", name), - newEc2Filter("vpc-id", s.vpcID), - } - // Note that we do _not_ add our tag filters; group-name + vpc-id is the EC2 primary key. - // However, we do check that it matches our tags. - // If it doesn't have any tags, we tag it; this is how we recover if we failed to tag before. - // If it has a different cluster's tags, that is an error. - // This shouldn't happen because name is expected to be globally unique (UUID derived) - request.Filters = filters - - securityGroups, err := s.ec2.DescribeSecurityGroups(request) - if err != nil { - return "", err - } - - if len(securityGroups) >= 1 { - if len(securityGroups) > 1 { - glog.Warningf("Found multiple security groups with name: %q", name) - } - err := s.ensureClusterTags(aws.StringValue(securityGroups[0].GroupId), securityGroups[0].Tags) - if err != nil { - return "", err - } - - return aws.StringValue(securityGroups[0].GroupId), nil - } - - createRequest := &ec2.CreateSecurityGroupInput{} - createRequest.VpcId = &s.vpcID - createRequest.GroupName = &name - createRequest.Description = &description - - createResponse, err := s.ec2.CreateSecurityGroup(createRequest) - if err != nil { - ignore := false - switch err := err.(type) { - case awserr.Error: - if err.Code() == "InvalidGroup.Duplicate" && attempt < MaxReadThenCreateRetries { - glog.V(2).Infof("Got InvalidGroup.Duplicate while creating security group (race?); will retry") - ignore = true - } - } - if !ignore { - glog.Error("Error creating security group: ", err) - return "", err - } - time.Sleep(1 * time.Second) - } else { - groupID = orEmpty(createResponse.GroupId) - break - } - } - if groupID == "" { - return "", fmt.Errorf("created security group, but id was not returned: %s", name) - } - - err := s.createTags(groupID, s.filterTags) - if err != nil { - // If we retry, ensureClusterTags will recover from this - it - // will add the missing tags. We could delete the security - // group here, but that doesn't feel like the right thing, as - // the caller is likely to retry the create - return "", fmt.Errorf("error tagging security group: %v", err) - } - return groupID, nil -} - -// createTags calls EC2 CreateTags, but adds retry-on-failure logic -// We retry mainly because if we create an object, we cannot tag it until it is "fully created" (eventual consistency) -// The error code varies though (depending on what we are tagging), so we simply retry on all errors -func (s *AWSCloud) createTags(resourceID string, tags map[string]string) error { - if tags == nil || len(tags) == 0 { - return nil - } - - var awsTags []*ec2.Tag - for k, v := range tags { - tag := &ec2.Tag{ - Key: aws.String(k), - Value: aws.String(v), - } - awsTags = append(awsTags, tag) - } - - request := &ec2.CreateTagsInput{} - request.Resources = []*string{&resourceID} - request.Tags = awsTags - - // TODO: We really should do exponential backoff here - attempt := 0 - maxAttempts := 60 - - for { - _, err := s.ec2.CreateTags(request) - if err == nil { - return nil - } - - // We could check that the error is retryable, but the error code changes based on what we are tagging - // SecurityGroup: InvalidGroup.NotFound - attempt++ - if attempt > maxAttempts { - glog.Warningf("Failed to create tags (too many attempts): %v", err) - return err - } - glog.V(2).Infof("Failed to create tags; will retry. Error was %v", err) - time.Sleep(1 * time.Second) - } -} - -// Finds the value for a given tag. -func findTag(tags []*ec2.Tag, key string) (string, bool) { - for _, tag := range tags { - if aws.StringValue(tag.Key) == key { - return aws.StringValue(tag.Value), true - } - } - return "", false -} - -// Finds the subnets associated with the cluster, by matching tags. -// For maximal backwards compatibility, if no subnets are tagged, it will fall-back to the current subnet. -// However, in future this will likely be treated as an error. -func (c *AWSCloud) findSubnets() ([]*ec2.Subnet, error) { - request := &ec2.DescribeSubnetsInput{} - vpcIDFilter := newEc2Filter("vpc-id", c.vpcID) - filters := []*ec2.Filter{vpcIDFilter} - filters = c.addFilters(filters) - request.Filters = filters - - subnets, err := c.ec2.DescribeSubnets(request) - if err != nil { - return nil, fmt.Errorf("error describing subnets: %v", err) - } - - if len(subnets) != 0 { - return subnets, nil - } - - // Fall back to the current instance subnets, if nothing is tagged - glog.Warningf("No tagged subnets found; will fall-back to the current subnet only. This is likely to be an error in a future version of k8s.") - - request = &ec2.DescribeSubnetsInput{} - filters = []*ec2.Filter{newEc2Filter("subnet-id", c.selfAWSInstance.subnetID)} - request.Filters = filters - - subnets, err = c.ec2.DescribeSubnets(request) - if err != nil { - return nil, fmt.Errorf("error describing subnets: %v", err) - } - - return subnets, nil -} - -// Finds the subnets to use for an ELB we are creating. -// Normal (Internet-facing) ELBs must use public subnets, so we skip private subnets. -// Internal ELBs can use public or private subnets, but if we have a private subnet we should prefer that. -func (s *AWSCloud) findELBSubnets(internalELB bool) ([]string, error) { - vpcIDFilter := newEc2Filter("vpc-id", s.vpcID) - - subnets, err := s.findSubnets() - if err != nil { - return nil, err - } - - rRequest := &ec2.DescribeRouteTablesInput{} - rRequest.Filters = []*ec2.Filter{vpcIDFilter} - rt, err := s.ec2.DescribeRouteTables(rRequest) - if err != nil { - return nil, fmt.Errorf("error describe route table: %v", err) - } - - subnetsByAZ := make(map[string]*ec2.Subnet) - for _, subnet := range subnets { - az := aws.StringValue(subnet.AvailabilityZone) - id := aws.StringValue(subnet.SubnetId) - if az == "" || id == "" { - glog.Warningf("Ignoring subnet with empty az/id: %v", subnet) - continue - } - - isPublic, err := isSubnetPublic(rt, id) - if err != nil { - return nil, err - } - if !internalELB && !isPublic { - glog.V(2).Infof("Ignoring private subnet for public ELB %q", id) - continue - } - - existing := subnetsByAZ[az] - if existing == nil { - subnetsByAZ[az] = subnet - continue - } - - // Try to break the tie using a tag - var tagName string - if internalELB { - tagName = TagNameSubnetInternalELB - } else { - tagName = TagNameSubnetPublicELB - } - - _, existingHasTag := findTag(existing.Tags, tagName) - _, subnetHasTag := findTag(subnet.Tags, tagName) - - if existingHasTag != subnetHasTag { - if subnetHasTag { - subnetsByAZ[az] = subnet - } - continue - } - - // TODO: Should this be an error? - glog.Warningf("Found multiple subnets in AZ %q; making arbitrary choice between subnets %q and %q", az, *existing.SubnetId, *subnet.SubnetId) - continue - } - - var subnetIDs []string - for _, subnet := range subnetsByAZ { - subnetIDs = append(subnetIDs, aws.StringValue(subnet.SubnetId)) - } - - return subnetIDs, nil -} - -func isSubnetPublic(rt []*ec2.RouteTable, subnetID string) (bool, error) { - var subnetTable *ec2.RouteTable - for _, table := range rt { - for _, assoc := range table.Associations { - if aws.StringValue(assoc.SubnetId) == subnetID { - subnetTable = table - break - } - } - } - - if subnetTable == nil { - // If there is no explicit association, the subnet will be implicitly - // associated with the VPC's main routing table. - for _, table := range rt { - for _, assoc := range table.Associations { - if aws.BoolValue(assoc.Main) == true { - glog.V(4).Infof("Assuming implicit use of main routing table %s for %s", - aws.StringValue(table.RouteTableId), subnetID) - subnetTable = table - break - } - } - } - } - - if subnetTable == nil { - return false, fmt.Errorf("Could not locate routing table for subnet %s", subnetID) - } - - for _, route := range subnetTable.Routes { - // There is no direct way in the AWS API to determine if a subnet is public or private. - // A public subnet is one which has an internet gateway route - // we look for the gatewayId and make sure it has the prefix of igw to differentiate - // from the default in-subnet route which is called "local" - // or other virtual gateway (starting with vgv) - // or vpc peering connections (starting with pcx). - if strings.HasPrefix(aws.StringValue(route.GatewayId), "igw") { - return true, nil - } - } - - return false, nil -} - -// EnsureLoadBalancer implements LoadBalancer.EnsureLoadBalancer -func (s *AWSCloud) EnsureLoadBalancer(apiService *api.Service, hosts []string, annotations map[string]string) (*api.LoadBalancerStatus, error) { - glog.V(2).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v, %v)", - apiService.Namespace, apiService.Name, s.region, apiService.Spec.LoadBalancerIP, apiService.Spec.Ports, hosts, annotations) - - if apiService.Spec.SessionAffinity != api.ServiceAffinityNone { - // ELB supports sticky sessions, but only when configured for HTTP/HTTPS - return nil, fmt.Errorf("unsupported load balancer affinity: %v", apiService.Spec.SessionAffinity) - } - - if len(apiService.Spec.Ports) == 0 { - return nil, fmt.Errorf("requested load balancer with no ports") - } - - for _, port := range apiService.Spec.Ports { - if port.Protocol != api.ProtocolTCP { - return nil, fmt.Errorf("Only TCP LoadBalancer is supported for AWS ELB") - } - } - - if apiService.Spec.LoadBalancerIP != "" { - return nil, fmt.Errorf("LoadBalancerIP cannot be specified for AWS ELB") - } - - instances, err := s.getInstancesByNodeNames(hosts) - if err != nil { - return nil, err - } - - sourceRanges, err := service.GetLoadBalancerSourceRanges(annotations) - if err != nil { - return nil, err - } - - // Determine if this is tagged as an Internal ELB - internalELB := false - internalAnnotation := annotations[ServiceAnnotationLoadBalancerInternal] - if internalAnnotation != "" { - if internalAnnotation != "0.0.0.0/0" { - return nil, fmt.Errorf("annotation %q=%q detected, but the only value supported currently is 0.0.0.0/0", ServiceAnnotationLoadBalancerInternal, internalAnnotation) - } - if !service.IsAllowAll(sourceRanges) { - // TODO: Unify the two annotations - return nil, fmt.Errorf("source-range annotation cannot be combined with the internal-elb annotation") - } - internalELB = true - } - - // Find the subnets that the ELB will live in - subnetIDs, err := s.findELBSubnets(internalELB) - if err != nil { - glog.Error("Error listing subnets in VPC: ", err) - return nil, err - } - - // Bail out early if there are no subnets - if len(subnetIDs) == 0 { - return nil, fmt.Errorf("could not find any suitable subnets for creating the ELB") - } - - loadBalancerName := cloudprovider.GetLoadBalancerName(apiService) - serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name} - - // Create a security group for the load balancer - var securityGroupID string - { - sgName := "k8s-elb-" + loadBalancerName - sgDescription := fmt.Sprintf("Security group for Kubernetes ELB %s (%v)", loadBalancerName, serviceName) - securityGroupID, err = s.ensureSecurityGroup(sgName, sgDescription) - if err != nil { - glog.Error("Error creating load balancer security group: ", err) - return nil, err - } - - ec2SourceRanges := []*ec2.IpRange{} - for _, sourceRange := range sourceRanges.StringSlice() { - ec2SourceRanges = append(ec2SourceRanges, &ec2.IpRange{CidrIp: aws.String(sourceRange)}) - } - - permissions := NewIPPermissionSet() - for _, port := range apiService.Spec.Ports { - portInt64 := int64(port.Port) - protocol := strings.ToLower(string(port.Protocol)) - - permission := &ec2.IpPermission{} - permission.FromPort = &portInt64 - permission.ToPort = &portInt64 - permission.IpRanges = ec2SourceRanges - permission.IpProtocol = &protocol - - permissions.Insert(permission) - } - _, err = s.setSecurityGroupIngress(securityGroupID, permissions) - if err != nil { - return nil, err - } - } - securityGroupIDs := []string{securityGroupID} - - // Figure out what mappings we want on the load balancer - listeners := []*elb.Listener{} - for _, port := range apiService.Spec.Ports { - if port.NodePort == 0 { - glog.Errorf("Ignoring port without NodePort defined: %v", port) - continue - } - instancePort := int64(port.NodePort) - loadBalancerPort := int64(port.Port) - protocol := strings.ToLower(string(port.Protocol)) - - listener := &elb.Listener{} - listener.InstancePort = &instancePort - listener.LoadBalancerPort = &loadBalancerPort - listener.Protocol = &protocol - listener.InstanceProtocol = &protocol - - listeners = append(listeners, listener) - } - - // Build the load balancer itself - loadBalancer, err := s.ensureLoadBalancer(serviceName, loadBalancerName, listeners, subnetIDs, securityGroupIDs, internalELB) - if err != nil { - return nil, err - } - - err = s.ensureLoadBalancerHealthCheck(loadBalancer, listeners) - if err != nil { - return nil, err - } - - err = s.updateInstanceSecurityGroupsForLoadBalancer(loadBalancer, instances) - if err != nil { - glog.Warningf("Error opening ingress rules for the load balancer to the instances: %v", err) - return nil, err - } - - err = s.ensureLoadBalancerInstances(orEmpty(loadBalancer.LoadBalancerName), loadBalancer.Instances, instances) - if err != nil { - glog.Warningf("Error registering instances with the load balancer: %v", err) - return nil, err - } - - glog.V(1).Infof("Loadbalancer %s (%v) has DNS name %s", loadBalancerName, serviceName, orEmpty(loadBalancer.DNSName)) - - // TODO: Wait for creation? - - status := toStatus(loadBalancer) - return status, nil -} - -// GetLoadBalancer is an implementation of LoadBalancer.GetLoadBalancer -func (s *AWSCloud) GetLoadBalancer(service *api.Service) (*api.LoadBalancerStatus, bool, error) { - loadBalancerName := cloudprovider.GetLoadBalancerName(service) - lb, err := s.describeLoadBalancer(loadBalancerName) - if err != nil { - return nil, false, err - } - - if lb == nil { - return nil, false, nil - } - - status := toStatus(lb) - return status, true, nil -} - -func toStatus(lb *elb.LoadBalancerDescription) *api.LoadBalancerStatus { - status := &api.LoadBalancerStatus{} - - if !isNilOrEmpty(lb.DNSName) { - var ingress api.LoadBalancerIngress - ingress.Hostname = orEmpty(lb.DNSName) - status.Ingress = []api.LoadBalancerIngress{ingress} - } - - return status -} - -// Returns the first security group for an instance, or nil -// We only create instances with one security group, so we don't expect multiple security groups. -// However, if there are multiple security groups, we will choose the one tagged with our cluster filter. -// Otherwise we will return an error. -func findSecurityGroupForInstance(instance *ec2.Instance, taggedSecurityGroups map[string]*ec2.SecurityGroup) (*ec2.GroupIdentifier, error) { - instanceID := aws.StringValue(instance.InstanceId) - - var tagged []*ec2.GroupIdentifier - var untagged []*ec2.GroupIdentifier - for _, group := range instance.SecurityGroups { - groupID := aws.StringValue(group.GroupId) - if groupID == "" { - glog.Warningf("Ignoring security group without id for instance %q: %v", instanceID, group) - continue - } - _, isTagged := taggedSecurityGroups[groupID] - if isTagged { - tagged = append(tagged, group) - } else { - untagged = append(untagged, group) - } - } - - if len(tagged) > 0 { - // We create instances with one SG - // If users create multiple SGs, they must tag one of them as being k8s owned - if len(tagged) != 1 { - return nil, fmt.Errorf("Multiple tagged security groups found for instance %s; ensure only the k8s security group is tagged", instanceID) - } - return tagged[0], nil - } - - if len(untagged) > 0 { - // For back-compat, we will allow a single untagged SG - if len(untagged) != 1 { - return nil, fmt.Errorf("Multiple untagged security groups found for instance %s; ensure the k8s security group is tagged", instanceID) - } - return untagged[0], nil - } - - glog.Warningf("No security group found for instance %q", instanceID) - return nil, nil -} - -// Return all the security groups that are tagged as being part of our cluster -func (s *AWSCloud) getTaggedSecurityGroups() (map[string]*ec2.SecurityGroup, error) { - request := &ec2.DescribeSecurityGroupsInput{} - request.Filters = s.addFilters(nil) - groups, err := s.ec2.DescribeSecurityGroups(request) - if err != nil { - return nil, fmt.Errorf("error querying security groups: %v", err) - } - - m := make(map[string]*ec2.SecurityGroup) - for _, group := range groups { - id := aws.StringValue(group.GroupId) - if id == "" { - glog.Warningf("Ignoring group without id: %v", group) - continue - } - m[id] = group - } - return m, nil -} - -// Open security group ingress rules on the instances so that the load balancer can talk to them -// Will also remove any security groups ingress rules for the load balancer that are _not_ needed for allInstances -func (s *AWSCloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancerDescription, allInstances []*ec2.Instance) error { - if s.cfg.Global.DisableSecurityGroupIngress { - return nil - } - - // Determine the load balancer security group id - loadBalancerSecurityGroupId := "" - for _, securityGroup := range lb.SecurityGroups { - if isNilOrEmpty(securityGroup) { - continue - } - if loadBalancerSecurityGroupId != "" { - // We create LBs with one SG - glog.Warningf("Multiple security groups for load balancer: %q", orEmpty(lb.LoadBalancerName)) - } - loadBalancerSecurityGroupId = *securityGroup - } - if loadBalancerSecurityGroupId == "" { - return fmt.Errorf("Could not determine security group for load balancer: %s", orEmpty(lb.LoadBalancerName)) - } - - // Get the actual list of groups that allow ingress from the load-balancer - describeRequest := &ec2.DescribeSecurityGroupsInput{} - filters := []*ec2.Filter{} - filters = append(filters, newEc2Filter("ip-permission.group-id", loadBalancerSecurityGroupId)) - describeRequest.Filters = s.addFilters(filters) - actualGroups, err := s.ec2.DescribeSecurityGroups(describeRequest) - if err != nil { - return fmt.Errorf("error querying security groups for ELB: %v", err) - } - - taggedSecurityGroups, err := s.getTaggedSecurityGroups() - if err != nil { - return fmt.Errorf("error querying for tagged security groups: %v", err) - } - - // Open the firewall from the load balancer to the instance - // We don't actually have a trivial way to know in advance which security group the instance is in - // (it is probably the minion security group, but we don't easily have that). - // However, we _do_ have the list of security groups on the instance records. - - // Map containing the changes we want to make; true to add, false to remove - instanceSecurityGroupIds := map[string]bool{} - - // Scan instances for groups we want open - for _, instance := range allInstances { - securityGroup, err := findSecurityGroupForInstance(instance, taggedSecurityGroups) - if err != nil { - return err - } - - if securityGroup == nil { - glog.Warning("Ignoring instance without security group: ", orEmpty(instance.InstanceId)) - continue - } - id := aws.StringValue(securityGroup.GroupId) - if id == "" { - glog.Warningf("found security group without id: %v", securityGroup) - continue - } - - instanceSecurityGroupIds[id] = true - } - - // Compare to actual groups - for _, actualGroup := range actualGroups { - actualGroupID := aws.StringValue(actualGroup.GroupId) - if actualGroupID == "" { - glog.Warning("Ignoring group without ID: ", actualGroup) - continue - } - - adding, found := instanceSecurityGroupIds[actualGroupID] - if found && adding { - // We don't need to make a change; the permission is already in place - delete(instanceSecurityGroupIds, actualGroupID) - } else { - // This group is not needed by allInstances; delete it - instanceSecurityGroupIds[actualGroupID] = false - } - } - - for instanceSecurityGroupId, add := range instanceSecurityGroupIds { - if add { - glog.V(2).Infof("Adding rule for traffic from the load balancer (%s) to instances (%s)", loadBalancerSecurityGroupId, instanceSecurityGroupId) - } else { - glog.V(2).Infof("Removing rule for traffic from the load balancer (%s) to instance (%s)", loadBalancerSecurityGroupId, instanceSecurityGroupId) - } - sourceGroupId := &ec2.UserIdGroupPair{} - sourceGroupId.GroupId = &loadBalancerSecurityGroupId - - allProtocols := "-1" - - permission := &ec2.IpPermission{} - permission.IpProtocol = &allProtocols - permission.UserIdGroupPairs = []*ec2.UserIdGroupPair{sourceGroupId} - - permissions := []*ec2.IpPermission{permission} - - if add { - changed, err := s.addSecurityGroupIngress(instanceSecurityGroupId, permissions) - if err != nil { - return err - } - if !changed { - glog.Warning("Allowing ingress was not needed; concurrent change? groupId=", instanceSecurityGroupId) - } - } else { - changed, err := s.removeSecurityGroupIngress(instanceSecurityGroupId, permissions) - if err != nil { - return err - } - if !changed { - glog.Warning("Revoking ingress was not needed; concurrent change? groupId=", instanceSecurityGroupId) - } - } - } - - return nil -} - -// EnsureLoadBalancerDeleted implements LoadBalancer.EnsureLoadBalancerDeleted. -func (s *AWSCloud) EnsureLoadBalancerDeleted(service *api.Service) error { - loadBalancerName := cloudprovider.GetLoadBalancerName(service) - lb, err := s.describeLoadBalancer(loadBalancerName) - if err != nil { - return err - } - - if lb == nil { - glog.Info("Load balancer already deleted: ", loadBalancerName) - return nil - } - - { - // De-authorize the load balancer security group from the instances security group - err = s.updateInstanceSecurityGroupsForLoadBalancer(lb, nil) - if err != nil { - glog.Error("Error deregistering load balancer from instance security groups: ", err) - return err - } - } - - { - // Delete the load balancer itself - request := &elb.DeleteLoadBalancerInput{} - request.LoadBalancerName = lb.LoadBalancerName - - _, err = s.elb.DeleteLoadBalancer(request) - if err != nil { - // TODO: Check if error was because load balancer was concurrently deleted - glog.Error("Error deleting load balancer: ", err) - return err - } - } - - { - // Delete the security group(s) for the load balancer - // Note that this is annoying: the load balancer disappears from the API immediately, but it is still - // deleting in the background. We get a DependencyViolation until the load balancer has deleted itself - - // Collect the security groups to delete - securityGroupIDs := map[string]struct{}{} - for _, securityGroupID := range lb.SecurityGroups { - if isNilOrEmpty(securityGroupID) { - glog.Warning("Ignoring empty security group in ", service.Name) - continue - } - securityGroupIDs[*securityGroupID] = struct{}{} - } - - // Loop through and try to delete them - timeoutAt := time.Now().Add(time.Second * 600) - for { - for securityGroupID := range securityGroupIDs { - request := &ec2.DeleteSecurityGroupInput{} - request.GroupId = &securityGroupID - _, err := s.ec2.DeleteSecurityGroup(request) - if err == nil { - delete(securityGroupIDs, securityGroupID) - } else { - ignore := false - if awsError, ok := err.(awserr.Error); ok { - if awsError.Code() == "DependencyViolation" { - glog.V(2).Infof("Ignoring DependencyViolation while deleting load-balancer security group (%s), assuming because LB is in process of deleting", securityGroupID) - ignore = true - } - } - if !ignore { - return fmt.Errorf("error while deleting load balancer security group (%s): %v", securityGroupID, err) - } - } - } - - if len(securityGroupIDs) == 0 { - glog.V(2).Info("Deleted all security groups for load balancer: ", service.Name) - break - } - - if time.Now().After(timeoutAt) { - ids := []string{} - for id := range securityGroupIDs { - ids = append(ids, id) - } - - return fmt.Errorf("timed out deleting ELB: %s. Could not delete security groups %v", service.Name, strings.Join(ids, ",")) - } - - glog.V(2).Info("Waiting for load-balancer to delete so we can delete security groups: ", service.Name) - - time.Sleep(10 * time.Second) - } - } - - return nil -} - -// UpdateLoadBalancer implements LoadBalancer.UpdateLoadBalancer -func (s *AWSCloud) UpdateLoadBalancer(service *api.Service, hosts []string) error { - instances, err := s.getInstancesByNodeNames(hosts) - if err != nil { - return err - } - - loadBalancerName := cloudprovider.GetLoadBalancerName(service) - lb, err := s.describeLoadBalancer(loadBalancerName) - if err != nil { - return err - } - - if lb == nil { - return fmt.Errorf("Load balancer not found") - } - - err = s.ensureLoadBalancerInstances(orEmpty(lb.LoadBalancerName), lb.Instances, instances) - if err != nil { - return nil - } - - err = s.updateInstanceSecurityGroupsForLoadBalancer(lb, instances) - if err != nil { - return err - } - - return nil -} - -// Returns the instance with the specified ID -func (a *AWSCloud) getInstanceByID(instanceID string) (*ec2.Instance, error) { - instances, err := a.getInstancesByIDs([]*string{&instanceID}) - if err != nil { - return nil, err - } - - if len(instances) == 0 { - return nil, fmt.Errorf("no instances found for instance: %s", instanceID) - } - if len(instances) > 1 { - return nil, fmt.Errorf("multiple instances found for instance: %s", instanceID) - } - - return instances[instanceID], nil -} - -func (a *AWSCloud) getInstancesByIDs(instanceIDs []*string) (map[string]*ec2.Instance, error) { - instancesByID := make(map[string]*ec2.Instance) - if len(instanceIDs) == 0 { - return instancesByID, nil - } - - request := &ec2.DescribeInstancesInput{ - InstanceIds: instanceIDs, - } - - instances, err := a.ec2.DescribeInstances(request) - if err != nil { - return nil, err - } - - for _, instance := range instances { - instanceID := orEmpty(instance.InstanceId) - if instanceID == "" { - continue - } - - instancesByID[instanceID] = instance - } - - return instancesByID, nil -} - -// Fetches instances by node names; returns an error if any cannot be found. -// This is implemented with a multi value filter on the node names, fetching the desired instances with a single query. -func (a *AWSCloud) getInstancesByNodeNames(nodeNames []string) ([]*ec2.Instance, error) { - names := aws.StringSlice(nodeNames) - - nodeNameFilter := &ec2.Filter{ - Name: aws.String("private-dns-name"), - Values: names, - } - - filters := []*ec2.Filter{ - nodeNameFilter, - newEc2Filter("instance-state-name", "running"), - } - - filters = a.addFilters(filters) - request := &ec2.DescribeInstancesInput{ - Filters: filters, - } - - instances, err := a.ec2.DescribeInstances(request) - if err != nil { - glog.V(2).Infof("Failed to describe instances %v", nodeNames) - return nil, err - } - - if len(instances) == 0 { - glog.V(3).Infof("Failed to find any instances %v", nodeNames) - return nil, nil - } - - return instances, nil -} - -// Returns the instance with the specified node name -// Returns nil if it does not exist -func (a *AWSCloud) findInstanceByNodeName(nodeName string) (*ec2.Instance, error) { - filters := []*ec2.Filter{ - newEc2Filter("private-dns-name", nodeName), - newEc2Filter("instance-state-name", "running"), - } - filters = a.addFilters(filters) - request := &ec2.DescribeInstancesInput{ - Filters: filters, - } - - instances, err := a.ec2.DescribeInstances(request) - if err != nil { - return nil, err - } - if len(instances) == 0 { - return nil, nil - } - if len(instances) > 1 { - return nil, fmt.Errorf("multiple instances found for name: %s", nodeName) - } - return instances[0], nil -} - -// Returns the instance with the specified node name -// Like findInstanceByNodeName, but returns error if node not found -func (a *AWSCloud) getInstanceByNodeName(nodeName string) (*ec2.Instance, error) { - instance, err := a.findInstanceByNodeName(nodeName) - if err == nil && instance == nil { - return nil, fmt.Errorf("no instances found for name: %s", nodeName) - } - return instance, err -} - -// Add additional filters, to match on our tags -// This lets us run multiple k8s clusters in a single EC2 AZ -func (s *AWSCloud) addFilters(filters []*ec2.Filter) []*ec2.Filter { - for k, v := range s.filterTags { - filters = append(filters, newEc2Filter("tag:"+k, v)) - } - if len(filters) == 0 { - // We can't pass a zero-length Filters to AWS (it's an error) - // So if we end up with no filters; just return nil - return nil - } - - return filters -} - -// Returns the cluster name or an empty string -func (s *AWSCloud) getClusterName() string { - return s.filterTags[TagNameKubernetesCluster] -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_instancegroups.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_instancegroups.go deleted file mode 100644 index 563c90de1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_instancegroups.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws - -import ( - "fmt" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/autoscaling" - "github.com/golang/glog" -) - -// AWSCloud implements InstanceGroups -var _ InstanceGroups = &AWSCloud{} - -// ResizeInstanceGroup sets the size of the specificed instancegroup Exported -// so it can be used by the e2e tests, which don't want to instantiate a full -// cloudprovider. -func ResizeInstanceGroup(asg ASG, instanceGroupName string, size int) error { - request := &autoscaling.UpdateAutoScalingGroupInput{ - AutoScalingGroupName: aws.String(instanceGroupName), - MinSize: aws.Int64(int64(size)), - MaxSize: aws.Int64(int64(size)), - } - if _, err := asg.UpdateAutoScalingGroup(request); err != nil { - return fmt.Errorf("error resizing AWS autoscaling group: %v", err) - } - return nil -} - -// Implement InstanceGroups.ResizeInstanceGroup -// Set the size to the fixed size -func (a *AWSCloud) ResizeInstanceGroup(instanceGroupName string, size int) error { - return ResizeInstanceGroup(a.asg, instanceGroupName, size) -} - -// DescribeInstanceGroup gets info about the specified instancegroup -// Exported so it can be used by the e2e tests, -// which don't want to instantiate a full cloudprovider. -func DescribeInstanceGroup(asg ASG, instanceGroupName string) (InstanceGroupInfo, error) { - request := &autoscaling.DescribeAutoScalingGroupsInput{ - AutoScalingGroupNames: []*string{aws.String(instanceGroupName)}, - } - response, err := asg.DescribeAutoScalingGroups(request) - if err != nil { - return nil, fmt.Errorf("error listing AWS autoscaling group (%s): %v", instanceGroupName, err) - } - - if len(response.AutoScalingGroups) == 0 { - return nil, nil - } - if len(response.AutoScalingGroups) > 1 { - glog.Warning("AWS returned multiple autoscaling groups with name ", instanceGroupName) - } - group := response.AutoScalingGroups[0] - return &awsInstanceGroup{group: group}, nil -} - -// Implement InstanceGroups.DescribeInstanceGroup -// Queries the cloud provider for information about the specified instance group -func (a *AWSCloud) DescribeInstanceGroup(instanceGroupName string) (InstanceGroupInfo, error) { - return DescribeInstanceGroup(a.asg, instanceGroupName) -} - -// awsInstanceGroup implements InstanceGroupInfo -var _ InstanceGroupInfo = &awsInstanceGroup{} - -type awsInstanceGroup struct { - group *autoscaling.Group -} - -// Implement InstanceGroupInfo.CurrentSize -// The number of instances currently running under control of this group -func (g *awsInstanceGroup) CurrentSize() (int, error) { - return len(g.group.Instances), nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_loadbalancer.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_loadbalancer.go deleted file mode 100644 index fe48045cf..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_loadbalancer.go +++ /dev/null @@ -1,310 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws - -import ( - "fmt" - "strconv" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/elb" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/sets" -) - -func (s *AWSCloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBalancerName string, listeners []*elb.Listener, subnetIDs []string, securityGroupIDs []string, internalELB bool) (*elb.LoadBalancerDescription, error) { - loadBalancer, err := s.describeLoadBalancer(loadBalancerName) - if err != nil { - return nil, err - } - - dirty := false - - if loadBalancer == nil { - createRequest := &elb.CreateLoadBalancerInput{} - createRequest.LoadBalancerName = aws.String(loadBalancerName) - - createRequest.Listeners = listeners - - if internalELB { - createRequest.Scheme = aws.String("internal") - } - - // We are supposed to specify one subnet per AZ. - // TODO: What happens if we have more than one subnet per AZ? - createRequest.Subnets = stringPointerArray(subnetIDs) - - createRequest.SecurityGroups = stringPointerArray(securityGroupIDs) - - createRequest.Tags = []*elb.Tag{ - {Key: aws.String(TagNameKubernetesCluster), Value: aws.String(s.getClusterName())}, - {Key: aws.String(TagNameKubernetesService), Value: aws.String(namespacedName.String())}, - } - - glog.Infof("Creating load balancer for %v with name: ", namespacedName, loadBalancerName) - _, err := s.elb.CreateLoadBalancer(createRequest) - if err != nil { - return nil, err - } - dirty = true - } else { - // TODO: Sync internal vs non-internal - - { - // Sync subnets - expected := sets.NewString(subnetIDs...) - actual := stringSetFromPointers(loadBalancer.Subnets) - - additions := expected.Difference(actual) - removals := actual.Difference(expected) - - if removals.Len() != 0 { - request := &elb.DetachLoadBalancerFromSubnetsInput{} - request.LoadBalancerName = aws.String(loadBalancerName) - request.Subnets = stringSetToPointers(removals) - glog.V(2).Info("Detaching load balancer from removed subnets") - _, err := s.elb.DetachLoadBalancerFromSubnets(request) - if err != nil { - return nil, fmt.Errorf("error detaching AWS loadbalancer from subnets: %v", err) - } - dirty = true - } - - if additions.Len() != 0 { - request := &elb.AttachLoadBalancerToSubnetsInput{} - request.LoadBalancerName = aws.String(loadBalancerName) - request.Subnets = stringSetToPointers(additions) - glog.V(2).Info("Attaching load balancer to added subnets") - _, err := s.elb.AttachLoadBalancerToSubnets(request) - if err != nil { - return nil, fmt.Errorf("error attaching AWS loadbalancer to subnets: %v", err) - } - dirty = true - } - } - - { - // Sync security groups - expected := sets.NewString(securityGroupIDs...) - actual := stringSetFromPointers(loadBalancer.SecurityGroups) - - if !expected.Equal(actual) { - // This call just replaces the security groups, unlike e.g. subnets (!) - request := &elb.ApplySecurityGroupsToLoadBalancerInput{} - request.LoadBalancerName = aws.String(loadBalancerName) - request.SecurityGroups = stringPointerArray(securityGroupIDs) - glog.V(2).Info("Applying updated security groups to load balancer") - _, err := s.elb.ApplySecurityGroupsToLoadBalancer(request) - if err != nil { - return nil, fmt.Errorf("error applying AWS loadbalancer security groups: %v", err) - } - dirty = true - } - } - - { - // Sync listeners - listenerDescriptions := loadBalancer.ListenerDescriptions - - foundSet := make(map[int]bool) - removals := []*int64{} - for _, listenerDescription := range listenerDescriptions { - actual := listenerDescription.Listener - if actual == nil { - glog.Warning("Ignoring empty listener in AWS loadbalancer: ", loadBalancerName) - continue - } - - found := -1 - for i, expected := range listeners { - if orEmpty(actual.Protocol) != orEmpty(expected.Protocol) { - continue - } - if orEmpty(actual.InstanceProtocol) != orEmpty(expected.InstanceProtocol) { - continue - } - if orZero(actual.InstancePort) != orZero(expected.InstancePort) { - continue - } - if orZero(actual.LoadBalancerPort) != orZero(expected.LoadBalancerPort) { - continue - } - if orEmpty(actual.SSLCertificateId) != orEmpty(expected.SSLCertificateId) { - continue - } - found = i - } - if found != -1 { - foundSet[found] = true - } else { - removals = append(removals, actual.LoadBalancerPort) - } - } - - additions := []*elb.Listener{} - for i := range listeners { - if foundSet[i] { - continue - } - additions = append(additions, listeners[i]) - } - - if len(removals) != 0 { - request := &elb.DeleteLoadBalancerListenersInput{} - request.LoadBalancerName = aws.String(loadBalancerName) - request.LoadBalancerPorts = removals - glog.V(2).Info("Deleting removed load balancer listeners") - _, err := s.elb.DeleteLoadBalancerListeners(request) - if err != nil { - return nil, fmt.Errorf("error deleting AWS loadbalancer listeners: %v", err) - } - dirty = true - } - - if len(additions) != 0 { - request := &elb.CreateLoadBalancerListenersInput{} - request.LoadBalancerName = aws.String(loadBalancerName) - request.Listeners = additions - glog.V(2).Info("Creating added load balancer listeners") - _, err := s.elb.CreateLoadBalancerListeners(request) - if err != nil { - return nil, fmt.Errorf("error creating AWS loadbalancer listeners: %v", err) - } - dirty = true - } - } - } - - if dirty { - loadBalancer, err = s.describeLoadBalancer(loadBalancerName) - if err != nil { - glog.Warning("Unable to retrieve load balancer after creation/update") - return nil, err - } - } - - return loadBalancer, nil -} - -// Makes sure that the health check for an ELB matches the configured listeners -func (s *AWSCloud) ensureLoadBalancerHealthCheck(loadBalancer *elb.LoadBalancerDescription, listeners []*elb.Listener) error { - actual := loadBalancer.HealthCheck - - // Default AWS settings - expectedHealthyThreshold := int64(2) - expectedUnhealthyThreshold := int64(6) - expectedTimeout := int64(5) - expectedInterval := int64(10) - - // We only configure a TCP health-check on the first port - expectedTarget := "" - for _, listener := range listeners { - if listener.InstancePort == nil { - continue - } - expectedTarget = "TCP:" + strconv.FormatInt(*listener.InstancePort, 10) - break - } - - if expectedTarget == "" { - return fmt.Errorf("unable to determine health check port (no valid listeners)") - } - - if expectedTarget == orEmpty(actual.Target) && - expectedHealthyThreshold == orZero(actual.HealthyThreshold) && - expectedUnhealthyThreshold == orZero(actual.UnhealthyThreshold) && - expectedTimeout == orZero(actual.Timeout) && - expectedInterval == orZero(actual.Interval) { - return nil - } - - glog.V(2).Info("Updating load-balancer health-check") - - healthCheck := &elb.HealthCheck{} - healthCheck.HealthyThreshold = &expectedHealthyThreshold - healthCheck.UnhealthyThreshold = &expectedUnhealthyThreshold - healthCheck.Timeout = &expectedTimeout - healthCheck.Interval = &expectedInterval - healthCheck.Target = &expectedTarget - - request := &elb.ConfigureHealthCheckInput{} - request.HealthCheck = healthCheck - request.LoadBalancerName = loadBalancer.LoadBalancerName - - _, err := s.elb.ConfigureHealthCheck(request) - if err != nil { - return fmt.Errorf("error configuring load-balancer health-check: %v", err) - } - - return nil -} - -// Makes sure that exactly the specified hosts are registered as instances with the load balancer -func (s *AWSCloud) ensureLoadBalancerInstances(loadBalancerName string, lbInstances []*elb.Instance, instances []*ec2.Instance) error { - expected := sets.NewString() - for _, instance := range instances { - expected.Insert(orEmpty(instance.InstanceId)) - } - - actual := sets.NewString() - for _, lbInstance := range lbInstances { - actual.Insert(orEmpty(lbInstance.InstanceId)) - } - - additions := expected.Difference(actual) - removals := actual.Difference(expected) - - addInstances := []*elb.Instance{} - for _, instanceId := range additions.List() { - addInstance := &elb.Instance{} - addInstance.InstanceId = aws.String(instanceId) - addInstances = append(addInstances, addInstance) - } - - removeInstances := []*elb.Instance{} - for _, instanceId := range removals.List() { - removeInstance := &elb.Instance{} - removeInstance.InstanceId = aws.String(instanceId) - removeInstances = append(removeInstances, removeInstance) - } - - if len(addInstances) > 0 { - registerRequest := &elb.RegisterInstancesWithLoadBalancerInput{} - registerRequest.Instances = addInstances - registerRequest.LoadBalancerName = aws.String(loadBalancerName) - _, err := s.elb.RegisterInstancesWithLoadBalancer(registerRequest) - if err != nil { - return err - } - glog.V(1).Infof("Instances added to load-balancer %s", loadBalancerName) - } - - if len(removeInstances) > 0 { - deregisterRequest := &elb.DeregisterInstancesFromLoadBalancerInput{} - deregisterRequest.Instances = removeInstances - deregisterRequest.LoadBalancerName = aws.String(loadBalancerName) - _, err := s.elb.DeregisterInstancesFromLoadBalancer(deregisterRequest) - if err != nil { - return err - } - glog.V(1).Infof("Instances removed from load-balancer %s", loadBalancerName) - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_routes.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_routes.go deleted file mode 100644 index a469e5f70..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_routes.go +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws - -import ( - "fmt" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/cloudprovider" -) - -func (s *AWSCloud) findRouteTable(clusterName string) (*ec2.RouteTable, error) { - // This should be unnecessary (we already filter on TagNameKubernetesCluster, - // and something is broken if cluster name doesn't match, but anyway... - // TODO: All clouds should be cluster-aware by default - filters := []*ec2.Filter{newEc2Filter("tag:"+TagNameKubernetesCluster, clusterName)} - request := &ec2.DescribeRouteTablesInput{Filters: s.addFilters(filters)} - - tables, err := s.ec2.DescribeRouteTables(request) - if err != nil { - return nil, err - } - - if len(tables) == 0 { - return nil, fmt.Errorf("unable to find route table for AWS cluster: %s", clusterName) - } - - if len(tables) != 1 { - return nil, fmt.Errorf("found multiple matching AWS route tables for AWS cluster: %s", clusterName) - } - return tables[0], nil -} - -// ListRoutes implements Routes.ListRoutes -// List all routes that match the filter -func (s *AWSCloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) { - table, err := s.findRouteTable(clusterName) - if err != nil { - return nil, err - } - - var routes []*cloudprovider.Route - var instanceIDs []*string - - for _, r := range table.Routes { - instanceID := orEmpty(r.InstanceId) - - if instanceID == "" { - continue - } - - instanceIDs = append(instanceIDs, &instanceID) - } - - instances, err := s.getInstancesByIDs(instanceIDs) - if err != nil { - return nil, err - } - - for _, r := range table.Routes { - instanceID := orEmpty(r.InstanceId) - destinationCIDR := orEmpty(r.DestinationCidrBlock) - - if instanceID == "" || destinationCIDR == "" { - continue - } - - instance, found := instances[instanceID] - if !found { - glog.Warningf("unable to find instance ID %s in the list of instances being routed to", instanceID) - continue - } - instanceName := orEmpty(instance.PrivateDnsName) - routeName := clusterName + "-" + destinationCIDR - routes = append(routes, &cloudprovider.Route{Name: routeName, TargetInstance: instanceName, DestinationCIDR: destinationCIDR}) - } - - return routes, nil -} - -// Sets the instance attribute "source-dest-check" to the specified value -func (s *AWSCloud) configureInstanceSourceDestCheck(instanceID string, sourceDestCheck bool) error { - request := &ec2.ModifyInstanceAttributeInput{} - request.InstanceId = aws.String(instanceID) - request.SourceDestCheck = &ec2.AttributeBooleanValue{Value: aws.Bool(sourceDestCheck)} - - _, err := s.ec2.ModifyInstanceAttribute(request) - if err != nil { - return fmt.Errorf("error configuring source-dest-check on instance %s: %v", instanceID, err) - } - return nil -} - -// CreateRoute implements Routes.CreateRoute -// Create the described route -func (s *AWSCloud) CreateRoute(clusterName string, nameHint string, route *cloudprovider.Route) error { - instance, err := s.getInstanceByNodeName(route.TargetInstance) - if err != nil { - return err - } - - // In addition to configuring the route itself, we also need to configure the instance to accept that traffic - // On AWS, this requires turning source-dest checks off - err = s.configureInstanceSourceDestCheck(orEmpty(instance.InstanceId), false) - if err != nil { - return err - } - - table, err := s.findRouteTable(clusterName) - if err != nil { - return err - } - - var deleteRoute *ec2.Route - for _, r := range table.Routes { - destinationCIDR := aws.StringValue(r.DestinationCidrBlock) - - if destinationCIDR != route.DestinationCIDR { - continue - } - - if aws.StringValue(r.State) == ec2.RouteStateBlackhole { - deleteRoute = r - } - } - - if deleteRoute != nil { - glog.Infof("deleting blackholed route: %s", aws.StringValue(deleteRoute.DestinationCidrBlock)) - - request := &ec2.DeleteRouteInput{} - request.DestinationCidrBlock = deleteRoute.DestinationCidrBlock - request.RouteTableId = table.RouteTableId - - _, err = s.ec2.DeleteRoute(request) - if err != nil { - return fmt.Errorf("error deleting blackholed AWS route (%s): %v", aws.StringValue(deleteRoute.DestinationCidrBlock), err) - } - } - - request := &ec2.CreateRouteInput{} - // TODO: use ClientToken for idempotency? - request.DestinationCidrBlock = aws.String(route.DestinationCIDR) - request.InstanceId = instance.InstanceId - request.RouteTableId = table.RouteTableId - - _, err = s.ec2.CreateRoute(request) - if err != nil { - return fmt.Errorf("error creating AWS route (%s): %v", route.DestinationCIDR, err) - } - - return nil -} - -// DeleteRoute implements Routes.DeleteRoute -// Delete the specified route -func (s *AWSCloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error { - table, err := s.findRouteTable(clusterName) - if err != nil { - return err - } - - request := &ec2.DeleteRouteInput{} - request.DestinationCidrBlock = aws.String(route.DestinationCIDR) - request.RouteTableId = table.RouteTableId - - _, err = s.ec2.DeleteRoute(request) - if err != nil { - return fmt.Errorf("error deleting AWS route (%s): %v", route.DestinationCIDR, err) - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_test.go deleted file mode 100644 index 338886530..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_test.go +++ /dev/null @@ -1,1201 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws - -import ( - "io" - "reflect" - "strings" - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/elb" - - "github.com/aws/aws-sdk-go/service/autoscaling" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -const TestClusterId = "clusterid.test" - -func TestReadAWSCloudConfig(t *testing.T) { - tests := []struct { - name string - - reader io.Reader - aws AWSServices - - expectError bool - zone string - }{ - { - "No config reader", - nil, nil, - true, "", - }, - { - "Empty config, no metadata", - strings.NewReader(""), nil, - true, "", - }, - { - "No zone in config, no metadata", - strings.NewReader("[global]\n"), nil, - true, "", - }, - { - "Zone in config, no metadata", - strings.NewReader("[global]\nzone = eu-west-1a"), nil, - false, "eu-west-1a", - }, - { - "No zone in config, metadata does not have zone", - strings.NewReader("[global]\n"), NewFakeAWSServices().withAz(""), - true, "", - }, - { - "No zone in config, metadata has zone", - strings.NewReader("[global]\n"), NewFakeAWSServices(), - false, "us-east-1a", - }, - { - "Zone in config should take precedence over metadata", - strings.NewReader("[global]\nzone = eu-west-1a"), NewFakeAWSServices(), - false, "eu-west-1a", - }, - } - - for _, test := range tests { - t.Logf("Running test case %s", test.name) - var metadata EC2Metadata - if test.aws != nil { - metadata, _ = test.aws.Metadata() - } - cfg, err := readAWSCloudConfig(test.reader, metadata) - if test.expectError { - if err == nil { - t.Errorf("Should error for case %s (cfg=%v)", test.name, cfg) - } - } else { - if err != nil { - t.Errorf("Should succeed for case: %s", test.name) - } - if cfg.Global.Zone != test.zone { - t.Errorf("Incorrect zone value (%s vs %s) for case: %s", - cfg.Global.Zone, test.zone, test.name) - } - } - } -} - -type FakeAWSServices struct { - region string - instances []*ec2.Instance - selfInstance *ec2.Instance - networkInterfacesMacs []string - networkInterfacesVpcIDs []string - - ec2 *FakeEC2 - elb *FakeELB - asg *FakeASG - metadata *FakeMetadata -} - -func NewFakeAWSServices() *FakeAWSServices { - s := &FakeAWSServices{} - s.region = "us-east-1" - s.ec2 = &FakeEC2{aws: s} - s.elb = &FakeELB{aws: s} - s.asg = &FakeASG{aws: s} - s.metadata = &FakeMetadata{aws: s} - - s.networkInterfacesMacs = []string{"aa:bb:cc:dd:ee:00", "aa:bb:cc:dd:ee:01"} - s.networkInterfacesVpcIDs = []string{"vpc-mac0", "vpc-mac1"} - - selfInstance := &ec2.Instance{} - selfInstance.InstanceId = aws.String("i-self") - selfInstance.Placement = &ec2.Placement{ - AvailabilityZone: aws.String("us-east-1a"), - } - selfInstance.PrivateDnsName = aws.String("ip-172-20-0-100.ec2.internal") - selfInstance.PrivateIpAddress = aws.String("192.168.0.1") - selfInstance.PublicIpAddress = aws.String("1.2.3.4") - s.selfInstance = selfInstance - s.instances = []*ec2.Instance{selfInstance} - - var tag ec2.Tag - tag.Key = aws.String(TagNameKubernetesCluster) - tag.Value = aws.String(TestClusterId) - selfInstance.Tags = []*ec2.Tag{&tag} - - return s -} - -func (s *FakeAWSServices) withAz(az string) *FakeAWSServices { - if s.selfInstance.Placement == nil { - s.selfInstance.Placement = &ec2.Placement{} - } - s.selfInstance.Placement.AvailabilityZone = aws.String(az) - return s -} - -func (s *FakeAWSServices) Compute(region string) (EC2, error) { - return s.ec2, nil -} - -func (s *FakeAWSServices) LoadBalancing(region string) (ELB, error) { - return s.elb, nil -} - -func (s *FakeAWSServices) Autoscaling(region string) (ASG, error) { - return s.asg, nil -} - -func (s *FakeAWSServices) Metadata() (EC2Metadata, error) { - return s.metadata, nil -} - -func TestFilterTags(t *testing.T) { - awsServices := NewFakeAWSServices() - c, err := newAWSCloud(strings.NewReader("[global]"), awsServices) - if err != nil { - t.Errorf("Error building aws cloud: %v", err) - return - } - - if len(c.filterTags) != 1 { - t.Errorf("unexpected filter tags: %v", c.filterTags) - return - } - - if c.filterTags[TagNameKubernetesCluster] != TestClusterId { - t.Errorf("unexpected filter tags: %v", c.filterTags) - } -} - -func TestNewAWSCloud(t *testing.T) { - tests := []struct { - name string - - reader io.Reader - awsServices AWSServices - - expectError bool - region string - }{ - { - "No config reader", - nil, NewFakeAWSServices().withAz(""), - true, "", - }, - { - "Config specified invalid zone", - strings.NewReader("[global]\nzone = blahonga"), NewFakeAWSServices(), - true, "", - }, - { - "Config specifies valid zone", - strings.NewReader("[global]\nzone = eu-west-1a"), NewFakeAWSServices(), - false, "eu-west-1", - }, - { - "Gets zone from metadata when not in config", - strings.NewReader("[global]\n"), - NewFakeAWSServices(), - false, "us-east-1", - }, - { - "No zone in config or metadata", - strings.NewReader("[global]\n"), - NewFakeAWSServices().withAz(""), - true, "", - }, - } - - for _, test := range tests { - t.Logf("Running test case %s", test.name) - c, err := newAWSCloud(test.reader, test.awsServices) - if test.expectError { - if err == nil { - t.Errorf("Should error for case %s", test.name) - } - } else { - if err != nil { - t.Errorf("Should succeed for case: %s, got %v", test.name, err) - } else if c.region != test.region { - t.Errorf("Incorrect region value (%s vs %s) for case: %s", - c.region, test.region, test.name) - } - } - } -} - -type FakeEC2 struct { - aws *FakeAWSServices - Subnets []*ec2.Subnet - DescribeSubnetsInput *ec2.DescribeSubnetsInput - RouteTables []*ec2.RouteTable - DescribeRouteTablesInput *ec2.DescribeRouteTablesInput - mock.Mock -} - -func contains(haystack []*string, needle string) bool { - for _, s := range haystack { - // (deliberately panic if s == nil) - if needle == *s { - return true - } - } - return false -} - -func instanceMatchesFilter(instance *ec2.Instance, filter *ec2.Filter) bool { - name := *filter.Name - if name == "private-dns-name" { - if instance.PrivateDnsName == nil { - return false - } - return contains(filter.Values, *instance.PrivateDnsName) - } - - if name == "instance-state-name" { - return contains(filter.Values, *instance.State.Name) - } - - if strings.HasPrefix(name, "tag:") { - tagName := name[4:] - for _, instanceTag := range instance.Tags { - if aws.StringValue(instanceTag.Key) == tagName && contains(filter.Values, aws.StringValue(instanceTag.Value)) { - return true - } - } - } - panic("Unknown filter name: " + name) -} - -func (self *FakeEC2) DescribeInstances(request *ec2.DescribeInstancesInput) ([]*ec2.Instance, error) { - matches := []*ec2.Instance{} - for _, instance := range self.aws.instances { - if request.InstanceIds != nil { - if instance.InstanceId == nil { - glog.Warning("Instance with no instance id: ", instance) - continue - } - - found := false - for _, instanceID := range request.InstanceIds { - if *instanceID == *instance.InstanceId { - found = true - break - } - } - if !found { - continue - } - } - if request.Filters != nil { - allMatch := true - for _, filter := range request.Filters { - if !instanceMatchesFilter(instance, filter) { - allMatch = false - break - } - } - if !allMatch { - continue - } - } - matches = append(matches, instance) - } - - return matches, nil -} - -type FakeMetadata struct { - aws *FakeAWSServices -} - -func (self *FakeMetadata) GetMetadata(key string) (string, error) { - networkInterfacesPrefix := "network/interfaces/macs/" - i := self.aws.selfInstance - if key == "placement/availability-zone" { - az := "" - if i.Placement != nil { - az = aws.StringValue(i.Placement.AvailabilityZone) - } - return az, nil - } else if key == "instance-id" { - return aws.StringValue(i.InstanceId), nil - } else if key == "local-hostname" { - return aws.StringValue(i.PrivateDnsName), nil - } else if key == "local-ipv4" { - return aws.StringValue(i.PrivateIpAddress), nil - } else if key == "public-ipv4" { - return aws.StringValue(i.PublicIpAddress), nil - } else if strings.HasPrefix(key, networkInterfacesPrefix) { - if key == networkInterfacesPrefix { - return strings.Join(self.aws.networkInterfacesMacs, "/\n") + "/\n", nil - } else { - keySplit := strings.Split(key, "/") - macParam := keySplit[3] - if len(keySplit) == 5 && keySplit[4] == "vpc-id" { - for i, macElem := range self.aws.networkInterfacesMacs { - if macParam == macElem { - return self.aws.networkInterfacesVpcIDs[i], nil - } - } - } - return "", nil - } - } else { - return "", nil - } -} - -func (ec2 *FakeEC2) AttachVolume(request *ec2.AttachVolumeInput) (resp *ec2.VolumeAttachment, err error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) DetachVolume(request *ec2.DetachVolumeInput) (resp *ec2.VolumeAttachment, err error) { - panic("Not implemented") -} - -func (e *FakeEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.Volume, error) { - args := e.Called(request) - return args.Get(0).([]*ec2.Volume), nil -} - -func (ec2 *FakeEC2) CreateVolume(request *ec2.CreateVolumeInput) (resp *ec2.Volume, err error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) DeleteVolume(request *ec2.DeleteVolumeInput) (resp *ec2.DeleteVolumeOutput, err error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) DescribeSecurityGroups(request *ec2.DescribeSecurityGroupsInput) ([]*ec2.SecurityGroup, error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) CreateSecurityGroup(*ec2.CreateSecurityGroupInput) (*ec2.CreateSecurityGroupOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) DeleteSecurityGroup(*ec2.DeleteSecurityGroupInput) (*ec2.DeleteSecurityGroupOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) AuthorizeSecurityGroupIngress(*ec2.AuthorizeSecurityGroupIngressInput) (*ec2.AuthorizeSecurityGroupIngressOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) RevokeSecurityGroupIngress(*ec2.RevokeSecurityGroupIngressInput) (*ec2.RevokeSecurityGroupIngressOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) DescribeSubnets(request *ec2.DescribeSubnetsInput) ([]*ec2.Subnet, error) { - ec2.DescribeSubnetsInput = request - return ec2.Subnets, nil -} - -func (ec2 *FakeEC2) CreateTags(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeEC2) DescribeRouteTables(request *ec2.DescribeRouteTablesInput) ([]*ec2.RouteTable, error) { - ec2.DescribeRouteTablesInput = request - return ec2.RouteTables, nil -} - -func (s *FakeEC2) CreateRoute(request *ec2.CreateRouteInput) (*ec2.CreateRouteOutput, error) { - panic("Not implemented") -} - -func (s *FakeEC2) DeleteRoute(request *ec2.DeleteRouteInput) (*ec2.DeleteRouteOutput, error) { - panic("Not implemented") -} - -func (s *FakeEC2) ModifyInstanceAttribute(request *ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error) { - panic("Not implemented") -} - -type FakeELB struct { - aws *FakeAWSServices - mock.Mock -} - -func (ec2 *FakeELB) CreateLoadBalancer(*elb.CreateLoadBalancerInput) (*elb.CreateLoadBalancerOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) DeleteLoadBalancer(input *elb.DeleteLoadBalancerInput) (*elb.DeleteLoadBalancerOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) DescribeLoadBalancers(input *elb.DescribeLoadBalancersInput) (*elb.DescribeLoadBalancersOutput, error) { - args := ec2.Called(input) - return args.Get(0).(*elb.DescribeLoadBalancersOutput), nil -} -func (ec2 *FakeELB) RegisterInstancesWithLoadBalancer(*elb.RegisterInstancesWithLoadBalancerInput) (*elb.RegisterInstancesWithLoadBalancerOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) DeregisterInstancesFromLoadBalancer(*elb.DeregisterInstancesFromLoadBalancerInput) (*elb.DeregisterInstancesFromLoadBalancerOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) DetachLoadBalancerFromSubnets(*elb.DetachLoadBalancerFromSubnetsInput) (*elb.DetachLoadBalancerFromSubnetsOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) AttachLoadBalancerToSubnets(*elb.AttachLoadBalancerToSubnetsInput) (*elb.AttachLoadBalancerToSubnetsOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) CreateLoadBalancerListeners(*elb.CreateLoadBalancerListenersInput) (*elb.CreateLoadBalancerListenersOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) DeleteLoadBalancerListeners(*elb.DeleteLoadBalancerListenersInput) (*elb.DeleteLoadBalancerListenersOutput, error) { - panic("Not implemented") -} - -func (ec2 *FakeELB) ApplySecurityGroupsToLoadBalancer(*elb.ApplySecurityGroupsToLoadBalancerInput) (*elb.ApplySecurityGroupsToLoadBalancerOutput, error) { - panic("Not implemented") -} - -func (elb *FakeELB) ConfigureHealthCheck(*elb.ConfigureHealthCheckInput) (*elb.ConfigureHealthCheckOutput, error) { - panic("Not implemented") -} - -type FakeASG struct { - aws *FakeAWSServices -} - -func (a *FakeASG) UpdateAutoScalingGroup(*autoscaling.UpdateAutoScalingGroupInput) (*autoscaling.UpdateAutoScalingGroupOutput, error) { - panic("Not implemented") -} - -func (a *FakeASG) DescribeAutoScalingGroups(*autoscaling.DescribeAutoScalingGroupsInput) (*autoscaling.DescribeAutoScalingGroupsOutput, error) { - panic("Not implemented") -} - -func mockInstancesResp(selfInstance *ec2.Instance, instances []*ec2.Instance) (*AWSCloud, *FakeAWSServices) { - awsServices := NewFakeAWSServices() - awsServices.instances = instances - awsServices.selfInstance = selfInstance - awsCloud, err := newAWSCloud(nil, awsServices) - if err != nil { - panic(err) - } - return awsCloud, awsServices -} - -func mockAvailabilityZone(availabilityZone string) *AWSCloud { - awsServices := NewFakeAWSServices().withAz(availabilityZone) - awsCloud, err := newAWSCloud(nil, awsServices) - if err != nil { - panic(err) - } - return awsCloud -} - -func TestList(t *testing.T) { - // TODO this setup is not very clean and could probably be improved - var instance0 ec2.Instance - var instance1 ec2.Instance - var instance2 ec2.Instance - var instance3 ec2.Instance - - //0 - tag0 := ec2.Tag{ - Key: aws.String("Name"), - Value: aws.String("foo"), - } - instance0.Tags = []*ec2.Tag{&tag0} - instance0.InstanceId = aws.String("instance0") - instance0.PrivateDnsName = aws.String("instance0.ec2.internal") - instance0.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")} - state0 := ec2.InstanceState{ - Name: aws.String("running"), - } - instance0.State = &state0 - - //1 - tag1 := ec2.Tag{ - Key: aws.String("Name"), - Value: aws.String("bar"), - } - instance1.Tags = []*ec2.Tag{&tag1} - instance1.InstanceId = aws.String("instance1") - instance1.PrivateDnsName = aws.String("instance1.ec2.internal") - instance1.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")} - state1 := ec2.InstanceState{ - Name: aws.String("running"), - } - instance1.State = &state1 - - //2 - tag2 := ec2.Tag{ - Key: aws.String("Name"), - Value: aws.String("baz"), - } - instance2.Tags = []*ec2.Tag{&tag2} - instance2.InstanceId = aws.String("instance2") - instance2.PrivateDnsName = aws.String("instance2.ec2.internal") - instance2.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")} - state2 := ec2.InstanceState{ - Name: aws.String("running"), - } - instance2.State = &state2 - - //3 - tag3 := ec2.Tag{ - Key: aws.String("Name"), - Value: aws.String("quux"), - } - instance3.Tags = []*ec2.Tag{&tag3} - instance3.InstanceId = aws.String("instance3") - instance3.PrivateDnsName = aws.String("instance3.ec2.internal") - instance3.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")} - state3 := ec2.InstanceState{ - Name: aws.String("running"), - } - instance3.State = &state3 - - instances := []*ec2.Instance{&instance0, &instance1, &instance2, &instance3} - aws, _ := mockInstancesResp(&instance0, instances) - - table := []struct { - input string - expect []string - }{ - {"blahonga", []string{}}, - {"quux", []string{"instance3.ec2.internal"}}, - {"a", []string{"instance1.ec2.internal", "instance2.ec2.internal"}}, - } - - for _, item := range table { - result, err := aws.List(item.input) - if err != nil { - t.Errorf("Expected call with %v to succeed, failed with %s", item.input, err) - } - if e, a := item.expect, result; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %v, got %v", e, a) - } - } -} - -func testHasNodeAddress(t *testing.T, addrs []api.NodeAddress, addressType api.NodeAddressType, address string) { - for _, addr := range addrs { - if addr.Type == addressType && addr.Address == address { - return - } - } - t.Errorf("Did not find expected address: %s:%s in %v", addressType, address, addrs) -} - -func TestNodeAddresses(t *testing.T) { - // Note these instances have the same name - // (we test that this produces an error) - var instance0 ec2.Instance - var instance1 ec2.Instance - var instance2 ec2.Instance - - //0 - instance0.InstanceId = aws.String("i-0") - instance0.PrivateDnsName = aws.String("instance-same.ec2.internal") - instance0.PrivateIpAddress = aws.String("192.168.0.1") - instance0.PublicIpAddress = aws.String("1.2.3.4") - instance0.InstanceType = aws.String("c3.large") - instance0.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")} - state0 := ec2.InstanceState{ - Name: aws.String("running"), - } - instance0.State = &state0 - - //1 - instance1.InstanceId = aws.String("i-1") - instance1.PrivateDnsName = aws.String("instance-same.ec2.internal") - instance1.PrivateIpAddress = aws.String("192.168.0.2") - instance1.InstanceType = aws.String("c3.large") - instance1.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")} - state1 := ec2.InstanceState{ - Name: aws.String("running"), - } - instance1.State = &state1 - - //2 - instance2.InstanceId = aws.String("i-2") - instance2.PrivateDnsName = aws.String("instance-other.ec2.internal") - instance2.PrivateIpAddress = aws.String("192.168.0.1") - instance2.PublicIpAddress = aws.String("1.2.3.4") - instance2.InstanceType = aws.String("c3.large") - instance2.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")} - state2 := ec2.InstanceState{ - Name: aws.String("running"), - } - instance2.State = &state2 - - instances := []*ec2.Instance{&instance0, &instance1, &instance2} - - aws1, _ := mockInstancesResp(&instance0, []*ec2.Instance{&instance0}) - _, err1 := aws1.NodeAddresses("instance-mismatch.ec2.internal") - if err1 == nil { - t.Errorf("Should error when no instance found") - } - - aws2, _ := mockInstancesResp(&instance2, instances) - _, err2 := aws2.NodeAddresses("instance-same.ec2.internal") - if err2 == nil { - t.Errorf("Should error when multiple instances found") - } - - aws3, _ := mockInstancesResp(&instance0, instances[0:1]) - addrs3, err3 := aws3.NodeAddresses("instance-same.ec2.internal") - if err3 != nil { - t.Errorf("Should not error when instance found") - } - if len(addrs3) != 3 { - t.Errorf("Should return exactly 3 NodeAddresses") - } - testHasNodeAddress(t, addrs3, api.NodeInternalIP, "192.168.0.1") - testHasNodeAddress(t, addrs3, api.NodeLegacyHostIP, "192.168.0.1") - testHasNodeAddress(t, addrs3, api.NodeExternalIP, "1.2.3.4") - - // Fetch from metadata - aws4, fakeServices := mockInstancesResp(&instance0, []*ec2.Instance{&instance0}) - fakeServices.selfInstance.PublicIpAddress = aws.String("2.3.4.5") - fakeServices.selfInstance.PrivateIpAddress = aws.String("192.168.0.2") - - addrs4, err4 := aws4.NodeAddresses(*instance0.PrivateDnsName) - if err4 != nil { - t.Errorf("unexpected error: %v", err4) - } - testHasNodeAddress(t, addrs4, api.NodeInternalIP, "192.168.0.2") - testHasNodeAddress(t, addrs4, api.NodeExternalIP, "2.3.4.5") -} - -func TestGetRegion(t *testing.T) { - aws := mockAvailabilityZone("us-west-2e") - zones, ok := aws.Zones() - if !ok { - t.Fatalf("Unexpected missing zones impl") - } - zone, err := zones.GetZone() - if err != nil { - t.Fatalf("unexpected error %v", err) - } - if zone.Region != "us-west-2" { - t.Errorf("Unexpected region: %s", zone.Region) - } - if zone.FailureDomain != "us-west-2e" { - t.Errorf("Unexpected FailureDomain: %s", zone.FailureDomain) - } -} - -func TestFindVPCID(t *testing.T) { - awsServices := NewFakeAWSServices() - c, err := newAWSCloud(strings.NewReader("[global]"), awsServices) - if err != nil { - t.Errorf("Error building aws cloud: %v", err) - return - } - vpcID, err := c.findVPCID() - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if vpcID != "vpc-mac0" { - t.Errorf("Unexpected vpcID: %s", vpcID) - } -} - -func constructSubnets(subnetsIn map[int]map[string]string) (subnetsOut []*ec2.Subnet) { - for i := range subnetsIn { - subnetsOut = append( - subnetsOut, - constructSubnet( - subnetsIn[i]["id"], - subnetsIn[i]["az"], - ), - ) - } - return -} - -func constructSubnet(id string, az string) *ec2.Subnet { - return &ec2.Subnet{ - SubnetId: &id, - AvailabilityZone: &az, - } -} - -func constructRouteTables(routeTablesIn map[string]bool) (routeTablesOut []*ec2.RouteTable) { - routeTablesOut = append(routeTablesOut, - &ec2.RouteTable{ - Associations: []*ec2.RouteTableAssociation{{Main: aws.Bool(true)}}, - Routes: []*ec2.Route{{ - DestinationCidrBlock: aws.String("0.0.0.0/0"), - GatewayId: aws.String("igw-main"), - }}, - }) - - for subnetID := range routeTablesIn { - routeTablesOut = append( - routeTablesOut, - constructRouteTable( - subnetID, - routeTablesIn[subnetID], - ), - ) - } - return -} - -func constructRouteTable(subnetID string, public bool) *ec2.RouteTable { - var gatewayID string - if public { - gatewayID = "igw-" + subnetID[len(subnetID)-8:8] - } else { - gatewayID = "vgw-" + subnetID[len(subnetID)-8:8] - } - return &ec2.RouteTable{ - Associations: []*ec2.RouteTableAssociation{{SubnetId: aws.String(subnetID)}}, - Routes: []*ec2.Route{{ - DestinationCidrBlock: aws.String("0.0.0.0/0"), - GatewayId: aws.String(gatewayID), - }}, - } -} - -func TestSubnetIDsinVPC(t *testing.T) { - awsServices := NewFakeAWSServices() - c, err := newAWSCloud(strings.NewReader("[global]"), awsServices) - if err != nil { - t.Errorf("Error building aws cloud: %v", err) - return - } - - // test with 3 subnets from 3 different AZs - subnets := make(map[int]map[string]string) - subnets[0] = make(map[string]string) - subnets[0]["id"] = "subnet-a0000001" - subnets[0]["az"] = "af-south-1a" - subnets[1] = make(map[string]string) - subnets[1]["id"] = "subnet-b0000001" - subnets[1]["az"] = "af-south-1b" - subnets[2] = make(map[string]string) - subnets[2]["id"] = "subnet-c0000001" - subnets[2]["az"] = "af-south-1c" - awsServices.ec2.Subnets = constructSubnets(subnets) - - routeTables := map[string]bool{ - "subnet-a0000001": true, - "subnet-b0000001": true, - "subnet-c0000001": true, - } - awsServices.ec2.RouteTables = constructRouteTables(routeTables) - - result, err := c.findELBSubnets(false) - if err != nil { - t.Errorf("Error listing subnets: %v", err) - return - } - - if len(result) != 3 { - t.Errorf("Expected 3 subnets but got %d", len(result)) - return - } - - result_set := make(map[string]bool) - for _, v := range result { - result_set[v] = true - } - - for i := range subnets { - if !result_set[subnets[i]["id"]] { - t.Errorf("Expected subnet%d '%s' in result: %v", i, subnets[i]["id"], result) - return - } - } - - // test implicit routing table - when subnets are not explicitly linked to a table they should use main - awsServices.ec2.RouteTables = constructRouteTables(map[string]bool{}) - - result, err = c.findELBSubnets(false) - if err != nil { - t.Errorf("Error listing subnets: %v", err) - return - } - - if len(result) != 3 { - t.Errorf("Expected 3 subnets but got %d", len(result)) - return - } - - result_set = make(map[string]bool) - for _, v := range result { - result_set[v] = true - } - - for i := range subnets { - if !result_set[subnets[i]["id"]] { - t.Errorf("Expected subnet%d '%s' in result: %v", i, subnets[i]["id"], result) - return - } - } - - // test with 4 subnets from 3 different AZs - // add duplicate az subnet - subnets[3] = make(map[string]string) - subnets[3]["id"] = "subnet-c0000002" - subnets[3]["az"] = "af-south-1c" - awsServices.ec2.Subnets = constructSubnets(subnets) - routeTables["subnet-c0000002"] = true - awsServices.ec2.RouteTables = constructRouteTables(routeTables) - - result, err = c.findELBSubnets(false) - if err != nil { - t.Errorf("Error listing subnets: %v", err) - return - } - - if len(result) != 3 { - t.Errorf("Expected 3 subnets but got %d", len(result)) - return - } - - // test with 6 subnets from 3 different AZs - // with 3 private subnets - subnets[4] = make(map[string]string) - subnets[4]["id"] = "subnet-d0000001" - subnets[4]["az"] = "af-south-1a" - subnets[5] = make(map[string]string) - subnets[5]["id"] = "subnet-d0000002" - subnets[5]["az"] = "af-south-1b" - - awsServices.ec2.Subnets = constructSubnets(subnets) - routeTables["subnet-a0000001"] = false - routeTables["subnet-b0000001"] = false - routeTables["subnet-c0000001"] = false - routeTables["subnet-c0000002"] = true - routeTables["subnet-d0000001"] = true - routeTables["subnet-d0000002"] = true - awsServices.ec2.RouteTables = constructRouteTables(routeTables) - result, err = c.findELBSubnets(false) - if err != nil { - t.Errorf("Error listing subnets: %v", err) - return - } - - if len(result) != 3 { - t.Errorf("Expected 3 subnets but got %d", len(result)) - return - } - - expected := []*string{aws.String("subnet-c0000002"), aws.String("subnet-d0000001"), aws.String("subnet-d0000002")} - for _, s := range result { - if !contains(expected, s) { - t.Errorf("Unexpected subnet '%s' found", s) - return - } - } -} - -func TestIpPermissionExistsHandlesMultipleGroupIds(t *testing.T) { - oldIpPermission := ec2.IpPermission{ - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - {GroupId: aws.String("firstGroupId")}, - {GroupId: aws.String("secondGroupId")}, - {GroupId: aws.String("thirdGroupId")}, - }, - } - - existingIpPermission := ec2.IpPermission{ - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - {GroupId: aws.String("secondGroupId")}, - }, - } - - newIpPermission := ec2.IpPermission{ - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - {GroupId: aws.String("fourthGroupId")}, - }, - } - - equals := ipPermissionExists(&existingIpPermission, &oldIpPermission, false) - if !equals { - t.Errorf("Should have been considered equal since first is in the second array of groups") - } - - equals = ipPermissionExists(&newIpPermission, &oldIpPermission, false) - if equals { - t.Errorf("Should have not been considered equal since first is not in the second array of groups") - } -} - -func TestIpPermissionExistsHandlesRangeSubsets(t *testing.T) { - // Two existing scenarios we'll test against - emptyIpPermission := ec2.IpPermission{} - - oldIpPermission := ec2.IpPermission{ - IpRanges: []*ec2.IpRange{ - {CidrIp: aws.String("10.0.0.0/8")}, - {CidrIp: aws.String("192.168.1.0/24")}, - }, - } - - // Two already existing ranges and a new one - existingIpPermission := ec2.IpPermission{ - IpRanges: []*ec2.IpRange{ - {CidrIp: aws.String("10.0.0.0/8")}, - }, - } - existingIpPermission2 := ec2.IpPermission{ - IpRanges: []*ec2.IpRange{ - {CidrIp: aws.String("192.168.1.0/24")}, - }, - } - - newIpPermission := ec2.IpPermission{ - IpRanges: []*ec2.IpRange{ - {CidrIp: aws.String("172.16.0.0/16")}, - }, - } - - exists := ipPermissionExists(&emptyIpPermission, &emptyIpPermission, false) - if !exists { - t.Errorf("Should have been considered existing since we're comparing a range array against itself") - } - exists = ipPermissionExists(&oldIpPermission, &oldIpPermission, false) - if !exists { - t.Errorf("Should have been considered existing since we're comparing a range array against itself") - } - - exists = ipPermissionExists(&existingIpPermission, &oldIpPermission, false) - if !exists { - t.Errorf("Should have been considered existing since 10.* is in oldIpPermission's array of ranges") - } - exists = ipPermissionExists(&existingIpPermission2, &oldIpPermission, false) - if !exists { - t.Errorf("Should have been considered existing since 192.* is in oldIpPermission2's array of ranges") - } - - exists = ipPermissionExists(&newIpPermission, &emptyIpPermission, false) - if exists { - t.Errorf("Should have not been considered existing since we compared against a missing array of ranges") - } - exists = ipPermissionExists(&newIpPermission, &oldIpPermission, false) - if exists { - t.Errorf("Should have not been considered existing since 172.* is not in oldIpPermission's array of ranges") - } -} - -func TestIpPermissionExistsHandlesMultipleGroupIdsWithUserIds(t *testing.T) { - oldIpPermission := ec2.IpPermission{ - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - {GroupId: aws.String("firstGroupId"), UserId: aws.String("firstUserId")}, - {GroupId: aws.String("secondGroupId"), UserId: aws.String("secondUserId")}, - {GroupId: aws.String("thirdGroupId"), UserId: aws.String("thirdUserId")}, - }, - } - - existingIpPermission := ec2.IpPermission{ - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - {GroupId: aws.String("secondGroupId"), UserId: aws.String("secondUserId")}, - }, - } - - newIpPermission := ec2.IpPermission{ - UserIdGroupPairs: []*ec2.UserIdGroupPair{ - {GroupId: aws.String("secondGroupId"), UserId: aws.String("anotherUserId")}, - }, - } - - equals := ipPermissionExists(&existingIpPermission, &oldIpPermission, true) - if !equals { - t.Errorf("Should have been considered equal since first is in the second array of groups") - } - - equals = ipPermissionExists(&newIpPermission, &oldIpPermission, true) - if equals { - t.Errorf("Should have not been considered equal since first is not in the second array of groups") - } -} -func TestFindInstanceByNodeNameExcludesTerminatedInstances(t *testing.T) { - awsServices := NewFakeAWSServices() - - nodeName := "my-dns.internal" - - var tag ec2.Tag - tag.Key = aws.String(TagNameKubernetesCluster) - tag.Value = aws.String(TestClusterId) - tags := []*ec2.Tag{&tag} - - var runningInstance ec2.Instance - runningInstance.InstanceId = aws.String("i-running") - runningInstance.PrivateDnsName = aws.String(nodeName) - runningInstance.State = &ec2.InstanceState{Code: aws.Int64(16), Name: aws.String("running")} - runningInstance.Tags = tags - - var terminatedInstance ec2.Instance - terminatedInstance.InstanceId = aws.String("i-terminated") - terminatedInstance.PrivateDnsName = aws.String(nodeName) - terminatedInstance.State = &ec2.InstanceState{Code: aws.Int64(48), Name: aws.String("terminated")} - terminatedInstance.Tags = tags - - instances := []*ec2.Instance{&terminatedInstance, &runningInstance} - awsServices.instances = append(awsServices.instances, instances...) - - c, err := newAWSCloud(strings.NewReader("[global]"), awsServices) - if err != nil { - t.Errorf("Error building aws cloud: %v", err) - return - } - - instance, err := c.findInstanceByNodeName(nodeName) - - if err != nil { - t.Errorf("Failed to find instance: %v", err) - return - } - - if *instance.InstanceId != "i-running" { - t.Errorf("Expected running instance but got %v", *instance.InstanceId) - } -} - -func TestFindInstancesByNodeName(t *testing.T) { - awsServices := NewFakeAWSServices() - - nodeNameOne := "my-dns.internal" - nodeNameTwo := "my-dns-two.internal" - - var tag ec2.Tag - tag.Key = aws.String(TagNameKubernetesCluster) - tag.Value = aws.String(TestClusterId) - tags := []*ec2.Tag{&tag} - - var runningInstance ec2.Instance - runningInstance.InstanceId = aws.String("i-running") - runningInstance.PrivateDnsName = aws.String(nodeNameOne) - runningInstance.State = &ec2.InstanceState{Code: aws.Int64(16), Name: aws.String("running")} - runningInstance.Tags = tags - - var secondInstance ec2.Instance - - secondInstance.InstanceId = aws.String("i-running") - secondInstance.PrivateDnsName = aws.String(nodeNameTwo) - secondInstance.State = &ec2.InstanceState{Code: aws.Int64(48), Name: aws.String("running")} - secondInstance.Tags = tags - - var terminatedInstance ec2.Instance - terminatedInstance.InstanceId = aws.String("i-terminated") - terminatedInstance.PrivateDnsName = aws.String(nodeNameOne) - terminatedInstance.State = &ec2.InstanceState{Code: aws.Int64(48), Name: aws.String("terminated")} - terminatedInstance.Tags = tags - - instances := []*ec2.Instance{&secondInstance, &runningInstance, &terminatedInstance} - awsServices.instances = append(awsServices.instances, instances...) - - c, err := newAWSCloud(strings.NewReader("[global]"), awsServices) - if err != nil { - t.Errorf("Error building aws cloud: %v", err) - return - } - - nodeNames := []string{nodeNameOne} - returnedInstances, errr := c.getInstancesByNodeNames(nodeNames) - - if errr != nil { - t.Errorf("Failed to find instance: %v", err) - return - } - - if len(returnedInstances) != 1 { - t.Errorf("Expected a single isntance but found: %v", returnedInstances) - } - - if *returnedInstances[0].PrivateDnsName != nodeNameOne { - t.Errorf("Expected node name %v but got %v", nodeNameOne, returnedInstances[0].PrivateDnsName) - } -} - -func TestGetVolumeLabels(t *testing.T) { - awsServices := NewFakeAWSServices() - c, err := newAWSCloud(strings.NewReader("[global]"), awsServices) - assert.Nil(t, err, "Error building aws cloud: %v", err) - volumeId := aws.String("vol-VolumeId") - expectedVolumeRequest := &ec2.DescribeVolumesInput{VolumeIds: []*string{volumeId}} - awsServices.ec2.On("DescribeVolumes", expectedVolumeRequest).Return([]*ec2.Volume{ - { - VolumeId: volumeId, - AvailabilityZone: aws.String("us-east-1a"), - }, - }) - - labels, err := c.GetVolumeLabels(*volumeId) - - assert.Nil(t, err, "Error creating Volume %v", err) - assert.Equal(t, map[string]string{ - unversioned.LabelZoneFailureDomain: "us-east-1a", - unversioned.LabelZoneRegion: "us-east-1"}, labels) - awsServices.ec2.AssertExpectations(t) -} - -func (self *FakeELB) expectDescribeLoadBalancers(loadBalancerName string) { - self.On("DescribeLoadBalancers", &elb.DescribeLoadBalancersInput{LoadBalancerNames: []*string{aws.String(loadBalancerName)}}).Return(&elb.DescribeLoadBalancersOutput{ - LoadBalancerDescriptions: []*elb.LoadBalancerDescription{{}}, - }) -} - -func TestDescribeLoadBalancerOnDelete(t *testing.T) { - awsServices := NewFakeAWSServices() - c, _ := newAWSCloud(strings.NewReader("[global]"), awsServices) - awsServices.elb.expectDescribeLoadBalancers("aid") - - c.EnsureLoadBalancerDeleted(&api.Service{ObjectMeta: api.ObjectMeta{Name: "myservice", UID: "id"}}) -} - -func TestDescribeLoadBalancerOnUpdate(t *testing.T) { - awsServices := NewFakeAWSServices() - c, _ := newAWSCloud(strings.NewReader("[global]"), awsServices) - awsServices.elb.expectDescribeLoadBalancers("aid") - - c.UpdateLoadBalancer(&api.Service{ObjectMeta: api.ObjectMeta{Name: "myservice", UID: "id"}}, []string{}) -} - -func TestDescribeLoadBalancerOnGet(t *testing.T) { - awsServices := NewFakeAWSServices() - c, _ := newAWSCloud(strings.NewReader("[global]"), awsServices) - awsServices.elb.expectDescribeLoadBalancers("aid") - - c.GetLoadBalancer(&api.Service{ObjectMeta: api.ObjectMeta{Name: "myservice", UID: "id"}}) -} - -func TestDescribeLoadBalancerOnEnsure(t *testing.T) { - awsServices := NewFakeAWSServices() - c, _ := newAWSCloud(strings.NewReader("[global]"), awsServices) - awsServices.elb.expectDescribeLoadBalancers("aid") - - c.EnsureLoadBalancer(&api.Service{ObjectMeta: api.ObjectMeta{Name: "myservice", UID: "id"}}, []string{}, map[string]string{}) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_utils.go deleted file mode 100644 index 310b4898e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/aws_utils.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws - -import ( - "github.com/aws/aws-sdk-go/aws" - "k8s.io/kubernetes/pkg/util/sets" -) - -func stringSetToPointers(in sets.String) []*string { - if in == nil { - return nil - } - out := make([]*string, len(in)) - for k := range in { - out = append(out, aws.String(k)) - } - return out -} - -func stringSetFromPointers(in []*string) sets.String { - if in == nil { - return nil - } - out := sets.NewString() - for i := range in { - out.Insert(orEmpty(in[i])) - } - return out -} - -func orZero(v *int64) int64 { - if v == nil { - return 0 - } - return *v -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/log_handler.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/log_handler.go deleted file mode 100644 index 177c7074a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/log_handler.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 aws - -import ( - "github.com/aws/aws-sdk-go/aws/request" - "github.com/golang/glog" -) - -// Handler for aws-sdk-go that logs all requests -func awsHandlerLogger(req *request.Request) { - service := req.ClientInfo.ServiceName - - name := "?" - if req.Operation != nil { - name = req.Operation.Name - } - - glog.V(4).Infof("AWS request: %s %s", service, name) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler.go deleted file mode 100644 index 6e6657bf0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler.go +++ /dev/null @@ -1,161 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 aws - -import ( - "math" - "sync" - "time" - - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/golang/glog" -) - -const ( - decayIntervalSeconds = 20 - decayFraction = 0.8 - maxDelay = 60 * time.Second -) - -// CrossRequestRetryDelay inserts delays before AWS calls, when we are observing RequestLimitExceeded errors -// Note that we share a CrossRequestRetryDelay across multiple AWS requests; this is a process-wide back-off, -// whereas the aws-sdk-go implements a per-request exponential backoff/retry -type CrossRequestRetryDelay struct { - backoff Backoff -} - -// Create a new CrossRequestRetryDelay -func NewCrossRequestRetryDelay() *CrossRequestRetryDelay { - c := &CrossRequestRetryDelay{} - c.backoff.init(decayIntervalSeconds, decayFraction, maxDelay) - return c -} - -// Added to the Sign chain; called before each request -func (c *CrossRequestRetryDelay) BeforeSign(r *request.Request) { - now := time.Now() - delay := c.backoff.ComputeDelayForRequest(now) - if delay > 0 { - glog.Warningf("Inserting delay before AWS request (%s) to avoid RequestLimitExceeded: %s", - describeRequest(r), delay.String()) - r.Config.SleepDelay(delay) - - // Avoid clock skew problems - r.Time = now - } -} - -// Return a user-friendly string describing the request, for use in log messages -func describeRequest(r *request.Request) string { - service := r.ClientInfo.ServiceName - - name := "?" - if r.Operation != nil { - name = r.Operation.Name - } - - return service + "::" + name -} - -// Added to the AfterRetry chain; called after any error -func (c *CrossRequestRetryDelay) AfterRetry(r *request.Request) { - if r.Error == nil { - return - } - awsError, ok := r.Error.(awserr.Error) - if !ok { - return - } - if awsError.Code() == "RequestLimitExceeded" { - c.backoff.ReportError() - glog.Warningf("Got RequestLimitExceeded error on AWS request (%s)", - describeRequest(r)) - } -} - -// Backoff manages a backoff that varies based on the recently observed failures -type Backoff struct { - decayIntervalSeconds int64 - decayFraction float64 - maxDelay time.Duration - - mutex sync.Mutex - - // We count all requests & the number of requests which hit a - // RequestLimit. We only really care about 'recent' requests, so we - // decay the counts exponentially to bias towards recent values. - countErrorsRequestLimit float32 - countRequests float32 - lastDecay int64 -} - -func (b *Backoff) init(decayIntervalSeconds int, decayFraction float64, maxDelay time.Duration) { - b.lastDecay = time.Now().Unix() - // Bias so that if the first request hits the limit we don't immediately apply the full delay - b.countRequests = 4 - b.decayIntervalSeconds = int64(decayIntervalSeconds) - b.decayFraction = decayFraction - b.maxDelay = maxDelay -} - -// Computes the delay required for a request, also updating internal state to count this request -func (b *Backoff) ComputeDelayForRequest(now time.Time) time.Duration { - b.mutex.Lock() - defer b.mutex.Unlock() - - // Apply exponential decay to the counters - timeDeltaSeconds := now.Unix() - b.lastDecay - if timeDeltaSeconds > b.decayIntervalSeconds { - intervals := float64(timeDeltaSeconds) / float64(b.decayIntervalSeconds) - decay := float32(math.Pow(b.decayFraction, intervals)) - b.countErrorsRequestLimit *= decay - b.countRequests *= decay - b.lastDecay = now.Unix() - } - - // Count this request - b.countRequests += 1.0 - - // Compute the failure rate - errorFraction := float32(0.0) - if b.countRequests > 0.5 { - // Avoid tiny residuals & rounding errors - errorFraction = b.countErrorsRequestLimit / b.countRequests - } - - // Ignore a low fraction of errors - // This also allows them to time-out - if errorFraction < 0.1 { - return time.Duration(0) - } - - // Delay by the max delay multiplied by the recent error rate - // (i.e. we apply a linear delay function) - // TODO: This is pretty arbitrary - delay := time.Nanosecond * time.Duration(float32(b.maxDelay.Nanoseconds())*errorFraction) - // Round down to the nearest second for sanity - return time.Second * time.Duration(int(delay.Seconds())) -} - -// Called when we observe a throttling error -func (b *Backoff) ReportError() { - b.mutex.Lock() - defer b.mutex.Unlock() - - b.countErrorsRequestLimit += 1.0 -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler_test.go deleted file mode 100644 index e02b52d6d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/retry_handler_test.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 aws - -import ( - "testing" - "time" -) - -// There follows a group of tests for the backoff logic. There's nothing -// particularly special about the values chosen: if we tweak the values in the -// backoff logic then we might well have to update the tests. However the key -// behavioural elements should remain (e.g. no errors => no backoff), and these -// are each tested by one of the tests below. - -// Test that we don't apply any delays when there are no errors -func TestBackoffNoErrors(t *testing.T) { - b := &Backoff{} - b.init(decayIntervalSeconds, decayFraction, maxDelay) - - now := time.Now() - for i := 0; i < 100; i++ { - d := b.ComputeDelayForRequest(now) - if d.Nanoseconds() != 0 { - t.Fatalf("unexpected delay during no-error case") - } - now = now.Add(time.Second) - } -} - -// Test that we always apply a delay when there are errors, and also that we -// don't "flap" - that our own delay doesn't cause us to oscillate between -// delay and no-delay. -func TestBackoffAllErrors(t *testing.T) { - b := &Backoff{} - b.init(decayIntervalSeconds, decayFraction, maxDelay) - - now := time.Now() - // Warm up - for i := 0; i < 10; i++ { - _ = b.ComputeDelayForRequest(now) - b.ReportError() - now = now.Add(time.Second) - } - - for i := 0; i < 100; i++ { - d := b.ComputeDelayForRequest(now) - b.ReportError() - if d.Seconds() < 5 { - t.Fatalf("unexpected short-delay during all-error case: %v", d) - } - t.Logf("delay @%d %v", i, d) - now = now.Add(d) - } -} - -// Test that we do come close to our max delay, when we see all errors at 1 -// second intervals (this simulates multiple concurrent requests, because we -// don't wait for delay in between requests) -func TestBackoffHitsMax(t *testing.T) { - b := &Backoff{} - b.init(decayIntervalSeconds, decayFraction, maxDelay) - - now := time.Now() - for i := 0; i < 100; i++ { - _ = b.ComputeDelayForRequest(now) - b.ReportError() - now = now.Add(time.Second) - } - - for i := 0; i < 10; i++ { - d := b.ComputeDelayForRequest(now) - b.ReportError() - if float32(d.Nanoseconds()) < (float32(maxDelay.Nanoseconds()) * 0.95) { - t.Fatalf("expected delay to be >= 95 percent of max delay, was %v", d) - } - t.Logf("delay @%d %v", i, d) - now = now.Add(time.Second) - } -} - -// Test that after a phase of errors, we eventually stop applying a delay once there are -// no more errors. -func TestBackoffRecovers(t *testing.T) { - b := &Backoff{} - b.init(decayIntervalSeconds, decayFraction, maxDelay) - - now := time.Now() - - // Phase of all-errors - for i := 0; i < 100; i++ { - _ = b.ComputeDelayForRequest(now) - b.ReportError() - now = now.Add(time.Second) - } - - for i := 0; i < 10; i++ { - d := b.ComputeDelayForRequest(now) - b.ReportError() - if d.Seconds() < 5 { - t.Fatalf("unexpected short-delay during all-error phase: %v", d) - } - t.Logf("error phase delay @%d %v", i, d) - now = now.Add(time.Second) - } - - // Phase of no errors - for i := 0; i < 100; i++ { - _ = b.ComputeDelayForRequest(now) - now = now.Add(3 * time.Second) - } - - for i := 0; i < 10; i++ { - d := b.ComputeDelayForRequest(now) - if d.Seconds() != 0 { - t.Fatalf("unexpected delay during error recovery phase: %v", d) - } - t.Logf("no-error phase delay @%d %v", i, d) - now = now.Add(time.Second) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/sets_ippermissions.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/sets_ippermissions.go deleted file mode 100644 index 2e1343ff8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/aws/sets_ippermissions.go +++ /dev/null @@ -1,146 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 aws - -import ( - "encoding/json" - "fmt" - - "github.com/aws/aws-sdk-go/service/ec2" -) - -type IPPermissionSet map[string]*ec2.IpPermission - -func NewIPPermissionSet(items ...*ec2.IpPermission) IPPermissionSet { - s := make(IPPermissionSet) - s.Insert(items...) - return s -} - -// Ungroup splits permissions out into individual permissions -// EC2 will combine permissions with the same port but different SourceRanges together, for example -// We ungroup them so we can process them -func (s IPPermissionSet) Ungroup() IPPermissionSet { - l := []*ec2.IpPermission{} - for _, p := range s.List() { - if len(p.IpRanges) <= 1 { - l = append(l, p) - continue - } - for _, ipRange := range p.IpRanges { - c := &ec2.IpPermission{} - *c = *p - c.IpRanges = []*ec2.IpRange{ipRange} - l = append(l, c) - } - } - - l2 := []*ec2.IpPermission{} - for _, p := range l { - if len(p.UserIdGroupPairs) <= 1 { - l2 = append(l2, p) - continue - } - for _, u := range p.UserIdGroupPairs { - c := &ec2.IpPermission{} - *c = *p - c.UserIdGroupPairs = []*ec2.UserIdGroupPair{u} - l2 = append(l, c) - } - } - - l3 := []*ec2.IpPermission{} - for _, p := range l2 { - if len(p.PrefixListIds) <= 1 { - l3 = append(l3, p) - continue - } - for _, v := range p.PrefixListIds { - c := &ec2.IpPermission{} - *c = *p - c.PrefixListIds = []*ec2.PrefixListId{v} - l3 = append(l3, c) - } - } - - return NewIPPermissionSet(l3...) -} - -// Insert adds items to the set. -func (s IPPermissionSet) Insert(items ...*ec2.IpPermission) { - for _, p := range items { - k := keyForIPPermission(p) - s[k] = p - } -} - -// List returns the contents as a slice. Order is not defined. -func (s IPPermissionSet) List() []*ec2.IpPermission { - res := make([]*ec2.IpPermission, 0, len(s)) - for _, v := range s { - res = append(res, v) - } - return res -} - -// IsSuperset returns true if and only if s1 is a superset of s2. -func (s1 IPPermissionSet) IsSuperset(s2 IPPermissionSet) bool { - for k := range s2 { - _, found := s1[k] - if !found { - return false - } - } - return true -} - -// Equal returns true if and only if s1 is equal (as a set) to s2. -// Two sets are equal if their membership is identical. -// (In practice, this means same elements, order doesn't matter) -func (s1 IPPermissionSet) Equal(s2 IPPermissionSet) bool { - return len(s1) == len(s2) && s1.IsSuperset(s2) -} - -// Difference returns a set of objects that are not in s2 -// For example: -// s1 = {a1, a2, a3} -// s2 = {a1, a2, a4, a5} -// s1.Difference(s2) = {a3} -// s2.Difference(s1) = {a4, a5} -func (s IPPermissionSet) Difference(s2 IPPermissionSet) IPPermissionSet { - result := NewIPPermissionSet() - for k, v := range s { - _, found := s2[k] - if !found { - result[k] = v - } - } - return result -} - -// Len returns the size of the set. -func (s IPPermissionSet) Len() int { - return len(s) -} - -func keyForIPPermission(p *ec2.IpPermission) string { - v, err := json.Marshal(p) - if err != nil { - panic(fmt.Sprintf("error building JSON representation of ec2.IpPermission: %v", err)) - } - return string(v) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/doc.go deleted file mode 100644 index ff22d568f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 fake is a test-double implementation of cloudprovider -// Interface, LoadBalancer and Instances. It is useful for testing. -package fake diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/fake.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/fake.go deleted file mode 100644 index 6bc0a0e76..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/fake/fake.go +++ /dev/null @@ -1,267 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 fake - -import ( - "errors" - "fmt" - "net" - "regexp" - "sync" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/cloudprovider" -) - -const ProviderName = "fake" - -// FakeBalancer is a fake storage of balancer information -type FakeBalancer struct { - Name string - Region string - LoadBalancerIP string - Ports []api.ServicePort - Hosts []string -} - -type FakeUpdateBalancerCall struct { - Service *api.Service - Hosts []string -} - -// FakeCloud is a test-double implementation of Interface, LoadBalancer, Instances, and Routes. It is useful for testing. -type FakeCloud struct { - Exists bool - Err error - Calls []string - Addresses []api.NodeAddress - ExtID map[string]string - InstanceTypes map[string]string - Machines []string - NodeResources *api.NodeResources - ClusterList []string - MasterName string - ExternalIP net.IP - Balancers map[string]FakeBalancer - UpdateCalls []FakeUpdateBalancerCall - RouteMap map[string]*FakeRoute - Lock sync.Mutex - cloudprovider.Zone -} - -type FakeRoute struct { - ClusterName string - Route cloudprovider.Route -} - -func (f *FakeCloud) addCall(desc string) { - f.Calls = append(f.Calls, desc) -} - -// ClearCalls clears internal record of method calls to this FakeCloud. -func (f *FakeCloud) ClearCalls() { - f.Calls = []string{} -} - -func (f *FakeCloud) ListClusters() ([]string, error) { - return f.ClusterList, f.Err -} - -func (f *FakeCloud) Master(name string) (string, error) { - return f.MasterName, f.Err -} - -func (f *FakeCloud) Clusters() (cloudprovider.Clusters, bool) { - return f, true -} - -// ProviderName returns the cloud provider ID. -func (f *FakeCloud) ProviderName() string { - return ProviderName -} - -// ScrubDNS filters DNS settings for pods. -func (f *FakeCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) { - return nameservers, searches -} - -// LoadBalancer returns a fake implementation of LoadBalancer. -// Actually it just returns f itself. -func (f *FakeCloud) LoadBalancer() (cloudprovider.LoadBalancer, bool) { - return f, true -} - -// Instances returns a fake implementation of Instances. -// -// Actually it just returns f itself. -func (f *FakeCloud) Instances() (cloudprovider.Instances, bool) { - return f, true -} - -func (f *FakeCloud) Zones() (cloudprovider.Zones, bool) { - return f, true -} - -func (f *FakeCloud) Routes() (cloudprovider.Routes, bool) { - return f, true -} - -// GetLoadBalancer is a stub implementation of LoadBalancer.GetLoadBalancer. -func (f *FakeCloud) GetLoadBalancer(service *api.Service) (*api.LoadBalancerStatus, bool, error) { - status := &api.LoadBalancerStatus{} - status.Ingress = []api.LoadBalancerIngress{{IP: f.ExternalIP.String()}} - - return status, f.Exists, f.Err -} - -// EnsureLoadBalancer is a test-spy implementation of LoadBalancer.EnsureLoadBalancer. -// It adds an entry "create" into the internal method call record. -func (f *FakeCloud) EnsureLoadBalancer(service *api.Service, hosts []string, annotations map[string]string) (*api.LoadBalancerStatus, error) { - f.addCall("create") - if f.Balancers == nil { - f.Balancers = make(map[string]FakeBalancer) - } - - name := cloudprovider.GetLoadBalancerName(service) - spec := service.Spec - - zone, err := f.GetZone() - if err != nil { - return nil, err - } - region := zone.Region - - f.Balancers[name] = FakeBalancer{name, region, spec.LoadBalancerIP, spec.Ports, hosts} - - status := &api.LoadBalancerStatus{} - status.Ingress = []api.LoadBalancerIngress{{IP: f.ExternalIP.String()}} - - return status, f.Err -} - -// UpdateLoadBalancer is a test-spy implementation of LoadBalancer.UpdateLoadBalancer. -// It adds an entry "update" into the internal method call record. -func (f *FakeCloud) UpdateLoadBalancer(service *api.Service, hosts []string) error { - f.addCall("update") - f.UpdateCalls = append(f.UpdateCalls, FakeUpdateBalancerCall{service, hosts}) - return f.Err -} - -// EnsureLoadBalancerDeleted is a test-spy implementation of LoadBalancer.EnsureLoadBalancerDeleted. -// It adds an entry "delete" into the internal method call record. -func (f *FakeCloud) EnsureLoadBalancerDeleted(service *api.Service) error { - f.addCall("delete") - return f.Err -} - -func (f *FakeCloud) AddSSHKeyToAllInstances(user string, keyData []byte) error { - return errors.New("unimplemented") -} - -// Implementation of Instances.CurrentNodeName -func (f *FakeCloud) CurrentNodeName(hostname string) (string, error) { - return hostname, nil -} - -// NodeAddresses is a test-spy implementation of Instances.NodeAddresses. -// It adds an entry "node-addresses" into the internal method call record. -func (f *FakeCloud) NodeAddresses(instance string) ([]api.NodeAddress, error) { - f.addCall("node-addresses") - return f.Addresses, f.Err -} - -// ExternalID is a test-spy implementation of Instances.ExternalID. -// It adds an entry "external-id" into the internal method call record. -// It returns an external id to the mapped instance name, if not found, it will return "ext-{instance}" -func (f *FakeCloud) ExternalID(instance string) (string, error) { - f.addCall("external-id") - return f.ExtID[instance], f.Err -} - -// InstanceID returns the cloud provider ID of the specified instance. -func (f *FakeCloud) InstanceID(instance string) (string, error) { - f.addCall("instance-id") - return f.ExtID[instance], nil -} - -// InstanceType returns the type of the specified instance. -func (f *FakeCloud) InstanceType(instance string) (string, error) { - f.addCall("instance-type") - return f.InstanceTypes[instance], nil -} - -// List is a test-spy implementation of Instances.List. -// It adds an entry "list" into the internal method call record. -func (f *FakeCloud) List(filter string) ([]string, error) { - f.addCall("list") - result := []string{} - for _, machine := range f.Machines { - if match, _ := regexp.MatchString(filter, machine); match { - result = append(result, machine) - } - } - return result, f.Err -} - -func (f *FakeCloud) GetZone() (cloudprovider.Zone, error) { - f.addCall("get-zone") - return f.Zone, f.Err -} - -func (f *FakeCloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) { - f.Lock.Lock() - defer f.Lock.Unlock() - f.addCall("list-routes") - var routes []*cloudprovider.Route - for _, fakeRoute := range f.RouteMap { - if clusterName == fakeRoute.ClusterName { - routeCopy := fakeRoute.Route - routes = append(routes, &routeCopy) - } - } - return routes, f.Err -} - -func (f *FakeCloud) CreateRoute(clusterName string, nameHint string, route *cloudprovider.Route) error { - f.Lock.Lock() - defer f.Lock.Unlock() - f.addCall("create-route") - name := clusterName + "-" + nameHint - if _, exists := f.RouteMap[name]; exists { - f.Err = fmt.Errorf("route %q already exists", name) - return f.Err - } - fakeRoute := FakeRoute{} - fakeRoute.Route = *route - fakeRoute.Route.Name = name - fakeRoute.ClusterName = clusterName - f.RouteMap[name] = &fakeRoute - return nil -} - -func (f *FakeCloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error { - f.Lock.Lock() - defer f.Lock.Unlock() - f.addCall("delete-route") - name := route.Name - if _, exists := f.RouteMap[name]; !exists { - f.Err = fmt.Errorf("no route found with name %q", name) - return f.Err - } - delete(f.RouteMap, name) - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go deleted file mode 100644 index f1633d889..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go +++ /dev/null @@ -1,150 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 gce - -import ( - "reflect" - "testing" -) - -func TestGetRegion(t *testing.T) { - zoneName := "us-central1-b" - regionName, err := GetGCERegion(zoneName) - if err != nil { - t.Fatalf("unexpected error from GetGCERegion: %v", err) - } - if regionName != "us-central1" { - t.Errorf("Unexpected region from GetGCERegion: %s", regionName) - } - gce := &GCECloud{ - localZone: zoneName, - region: regionName, - } - zones, ok := gce.Zones() - if !ok { - t.Fatalf("Unexpected missing zones impl") - } - zone, err := zones.GetZone() - if err != nil { - t.Fatalf("unexpected error %v", err) - } - if zone.Region != "us-central1" { - t.Errorf("Unexpected region: %s", zone.Region) - } -} - -func TestComparingHostURLs(t *testing.T) { - tests := []struct { - host1 string - zone string - name string - expectEqual bool - }{ - { - host1: "https://www.googleapis.com/compute/v1/projects/1234567/zones/us-central1-f/instances/kubernetes-node-fhx1", - zone: "us-central1-f", - name: "kubernetes-node-fhx1", - expectEqual: true, - }, - { - host1: "https://www.googleapis.com/compute/v1/projects/cool-project/zones/us-central1-f/instances/kubernetes-node-fhx1", - zone: "us-central1-f", - name: "kubernetes-node-fhx1", - expectEqual: true, - }, - { - host1: "https://www.googleapis.com/compute/v23/projects/1234567/zones/us-central1-f/instances/kubernetes-node-fhx1", - zone: "us-central1-f", - name: "kubernetes-node-fhx1", - expectEqual: true, - }, - { - host1: "https://www.googleapis.com/compute/v24/projects/1234567/regions/us-central1/zones/us-central1-f/instances/kubernetes-node-fhx1", - zone: "us-central1-f", - name: "kubernetes-node-fhx1", - expectEqual: true, - }, - { - host1: "https://www.googleapis.com/compute/v1/projects/1234567/zones/us-central1-f/instances/kubernetes-node-fhx1", - zone: "us-central1-c", - name: "kubernetes-node-fhx1", - expectEqual: false, - }, - { - host1: "https://www.googleapis.com/compute/v1/projects/1234567/zones/us-central1-f/instances/kubernetes-node-fhx", - zone: "us-central1-f", - name: "kubernetes-node-fhx1", - expectEqual: false, - }, - { - host1: "https://www.googleapis.com/compute/v1/projects/1234567/zones/us-central1-f/instances/kubernetes-node-fhx1", - zone: "us-central1-f", - name: "kubernetes-node-fhx", - expectEqual: false, - }, - } - - for _, test := range tests { - link1 := hostURLToComparablePath(test.host1) - testInstance := &gceInstance{ - Name: canonicalizeInstanceName(test.name), - Zone: test.zone, - } - link2 := testInstance.makeComparableHostPath() - if test.expectEqual && link1 != link2 { - t.Errorf("expected link1 and link2 to be equal, got %s and %s", link1, link2) - } else if !test.expectEqual && link1 == link2 { - t.Errorf("expected link1 and link2 not to be equal, got %s and %s", link1, link2) - } - } -} - -func TestScrubDNS(t *testing.T) { - tcs := []struct { - nameserversIn []string - searchesIn []string - nameserversOut []string - searchesOut []string - }{ - { - nameserversIn: []string{"1.2.3.4", "5.6.7.8"}, - nameserversOut: []string{"1.2.3.4", "5.6.7.8"}, - }, - { - searchesIn: []string{"c.prj.internal.", "12345678910.google.internal.", "google.internal."}, - searchesOut: []string{"c.prj.internal.", "google.internal."}, - }, - { - searchesIn: []string{"c.prj.internal.", "12345678910.google.internal.", "zone.c.prj.internal.", "google.internal."}, - searchesOut: []string{"c.prj.internal.", "zone.c.prj.internal.", "google.internal."}, - }, - { - searchesIn: []string{"c.prj.internal.", "12345678910.google.internal.", "zone.c.prj.internal.", "google.internal.", "unexpected"}, - searchesOut: []string{"c.prj.internal.", "zone.c.prj.internal.", "google.internal.", "unexpected"}, - }, - } - gce := &GCECloud{} - for i := range tcs { - n, s := gce.ScrubDNS(tcs[i].nameserversIn, tcs[i].searchesIn) - if !reflect.DeepEqual(n, tcs[i].nameserversOut) { - t.Errorf("Expected %v, got %v", tcs[i].nameserversOut, n) - } - if !reflect.DeepEqual(s, tcs[i].searchesOut) { - t.Errorf("Expected %v, got %v", tcs[i].searchesOut, s) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/client.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/client.go deleted file mode 100644 index 1b488bc62..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/client.go +++ /dev/null @@ -1,376 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mesos - -import ( - "encoding/binary" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "net" - "net/http" - "sync" - "time" - - log "github.com/golang/glog" - "github.com/mesos/mesos-go/detector" - mesos "github.com/mesos/mesos-go/mesosproto" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - utilnet "k8s.io/kubernetes/pkg/util/net" -) - -const defaultClusterName = "mesos" - -var noLeadingMasterError = errors.New("there is no current leading master available to query") - -type mesosClient struct { - masterLock sync.RWMutex - master string // host:port formatted address - httpClient *http.Client - tr *http.Transport - initialMaster <-chan struct{} // signal chan, closes once an initial, non-nil master is found - state *stateCache -} - -type slaveNode struct { - hostname string - kubeletRunning bool - resources *api.NodeResources -} - -type mesosState struct { - clusterName string - nodes map[string]*slaveNode // by hostname -} - -type stateCache struct { - sync.Mutex - expiresAt time.Time - cached *mesosState - err error - ttl time.Duration - refill func(context.Context) (*mesosState, error) -} - -// reloadCache reloads the state cache if it has expired. -func (c *stateCache) reloadCache(ctx context.Context) { - now := time.Now() - c.Lock() - defer c.Unlock() - if c.expiresAt.Before(now) { - log.V(4).Infof("Reloading cached Mesos state") - c.cached, c.err = c.refill(ctx) - c.expiresAt = now.Add(c.ttl) - } else { - log.V(4).Infof("Using cached Mesos state") - } -} - -// cachedState returns the cached Mesos state. -func (c *stateCache) cachedState(ctx context.Context) (*mesosState, error) { - c.reloadCache(ctx) - return c.cached, c.err -} - -// clusterName returns the cached Mesos cluster name. -func (c *stateCache) clusterName(ctx context.Context) (string, error) { - cached, err := c.cachedState(ctx) - if err != nil { - return "", err - } - return cached.clusterName, nil -} - -// nodes returns the cached list of slave nodes. -func (c *stateCache) nodes(ctx context.Context) (map[string]*slaveNode, error) { - cached, err := c.cachedState(ctx) - if err != nil { - return nil, err - } - return cached.nodes, nil -} - -func newMesosClient( - md detector.Master, - mesosHttpClientTimeout, stateCacheTTL time.Duration) (*mesosClient, error) { - - tr := utilnet.SetTransportDefaults(&http.Transport{}) - httpClient := &http.Client{ - Transport: tr, - Timeout: mesosHttpClientTimeout, - } - return createMesosClient(md, httpClient, tr, stateCacheTTL) -} - -func createMesosClient( - md detector.Master, - httpClient *http.Client, - tr *http.Transport, - stateCacheTTL time.Duration) (*mesosClient, error) { - - initialMaster := make(chan struct{}) - client := &mesosClient{ - httpClient: httpClient, - tr: tr, - initialMaster: initialMaster, - state: &stateCache{ - ttl: stateCacheTTL, - }, - } - client.state.refill = client.pollMasterForState - first := true - if err := md.Detect(detector.OnMasterChanged(func(info *mesos.MasterInfo) { - host, port := extractMasterAddress(info) - if len(host) > 0 { - client.masterLock.Lock() - defer client.masterLock.Unlock() - client.master = fmt.Sprintf("%s:%d", host, port) - if first { - first = false - close(initialMaster) - } - } - log.Infof("cloud master changed to '%v'", client.master) - })); err != nil { - log.V(1).Infof("detector initialization failed: %v", err) - return nil, err - } - return client, nil -} - -func extractMasterAddress(info *mesos.MasterInfo) (host string, port int) { - if info != nil { - host = info.GetAddress().GetHostname() - if host == "" { - host = info.GetAddress().GetIp() - } - - if host != "" { - // use port from Address - port = int(info.GetAddress().GetPort()) - } else { - // deprecated: get host and port directly from MasterInfo (and not Address) - host = info.GetHostname() - if host == "" { - host = unpackIPv4(info.GetIp()) - } - port = int(info.GetPort()) - } - } - return -} - -func unpackIPv4(ip uint32) string { - octets := make([]byte, 4, 4) - binary.BigEndian.PutUint32(octets, ip) - ipv4 := net.IP(octets) - return ipv4.String() -} - -// listSlaves returns a (possibly cached) map of slave nodes by hostname. -// Callers must not mutate the contents of the returned slice. -func (c *mesosClient) listSlaves(ctx context.Context) (map[string]*slaveNode, error) { - return c.state.nodes(ctx) -} - -// clusterName returns a (possibly cached) cluster name. -func (c *mesosClient) clusterName(ctx context.Context) (string, error) { - return c.state.clusterName(ctx) -} - -// pollMasterForState returns an array of slave nodes -func (c *mesosClient) pollMasterForState(ctx context.Context) (*mesosState, error) { - // wait for initial master detection - select { - case <-c.initialMaster: // noop - case <-ctx.Done(): - return nil, ctx.Err() - } - - master := func() string { - c.masterLock.RLock() - defer c.masterLock.RUnlock() - return c.master - }() - if master == "" { - return nil, noLeadingMasterError - } - - //TODO(jdef) should not assume master uses http (what about https?) - - var state *mesosState - successHandler := func(res *http.Response) error { - blob, err1 := ioutil.ReadAll(res.Body) - if err1 != nil { - return err1 - } - log.V(3).Infof("Got mesos state, content length %v", len(blob)) - state, err1 = parseMesosState(blob) - return err1 - } - // thinking here is that we may get some other status codes from mesos at some point: - // - authentication - // - redirection (possibly from http to https) - // ... - for _, tt := range []struct { - uri string - handlers map[int]func(*http.Response) error - }{ - { - uri: fmt.Sprintf("http://%s/state", master), - handlers: map[int]func(*http.Response) error{ - 200: successHandler, - }, - }, - { - uri: fmt.Sprintf("http://%s/state.json", master), - handlers: map[int]func(*http.Response) error{ - 200: successHandler, - }, - }, - } { - req, err := http.NewRequest("GET", tt.uri, nil) - if err != nil { - return nil, err - } - err = c.httpDo(ctx, req, func(res *http.Response, err error) error { - if err != nil { - return err - } - defer res.Body.Close() - if handler, ok := tt.handlers[res.StatusCode]; ok { - err1 := handler(res) - if err1 != nil { - return err1 - } - } - // no handler for this error code, proceed to the next connection type - return nil - }) - if state != nil || err != nil { - return state, err - } - } - return nil, errors.New("failed to sync with Mesos master") -} - -func parseMesosState(blob []byte) (*mesosState, error) { - type State struct { - ClusterName string `json:"cluster"` - Slaves []*struct { - Id string `json:"id"` // ex: 20150106-162714-3815890698-5050-2453-S2 - Pid string `json:"pid"` // ex: slave(1)@10.22.211.18:5051 - Hostname string `json:"hostname"` // ex: 10.22.211.18, or slave-123.nowhere.com - Resources map[string]interface{} `json:"resources"` // ex: {"mem": 123, "ports": "[31000-3200]"} - } `json:"slaves"` - Frameworks []*struct { - Id string `json:"id"` // ex: 20151105-093752-3745622208-5050-1-0000 - Pid string `json:"pid"` // ex: scheduler(1)@192.168.65.228:57124 - Executors []*struct { - SlaveId string `json:"slave_id"` // ex: 20151105-093752-3745622208-5050-1-S1 - ExecutorId string `json:"executor_id"` // ex: 6704d375c68fee1e_k8sm-executor - Name string `json:"name"` // ex: Kubelet-Executor - } `json:"executors"` - } `json:"frameworks"` - } - - state := &State{ClusterName: defaultClusterName} - if err := json.Unmarshal(blob, state); err != nil { - return nil, err - } - - executorSlaveIds := map[string]struct{}{} - for _, f := range state.Frameworks { - for _, e := range f.Executors { - // Note that this simple comparison breaks when we support more than one - // k8s instance in a cluster. At the moment this is not possible for - // a number of reasons. - // TODO(sttts): find way to detect executors of this k8s instance - if e.Name == KubernetesExecutorName { - executorSlaveIds[e.SlaveId] = struct{}{} - } - } - } - - nodes := map[string]*slaveNode{} // by hostname - for _, slave := range state.Slaves { - if slave.Hostname == "" { - continue - } - node := &slaveNode{hostname: slave.Hostname} - cap := api.ResourceList{} - if slave.Resources != nil && len(slave.Resources) > 0 { - // attempt to translate CPU (cores) and memory (MB) resources - if cpu, found := slave.Resources["cpus"]; found { - if cpuNum, ok := cpu.(float64); ok { - cap[api.ResourceCPU] = *resource.NewQuantity(int64(cpuNum), resource.DecimalSI) - } else { - log.Warningf("unexpected slave cpu resource type %T: %v", cpu, cpu) - } - } else { - log.Warningf("slave failed to report cpu resource") - } - if mem, found := slave.Resources["mem"]; found { - if memNum, ok := mem.(float64); ok { - cap[api.ResourceMemory] = *resource.NewQuantity(int64(memNum), resource.BinarySI) - } else { - log.Warningf("unexpected slave mem resource type %T: %v", mem, mem) - } - } else { - log.Warningf("slave failed to report mem resource") - } - } - if len(cap) > 0 { - node.resources = &api.NodeResources{ - Capacity: cap, - } - log.V(4).Infof("node %q reporting capacity %v", node.hostname, cap) - } - if _, ok := executorSlaveIds[slave.Id]; ok { - node.kubeletRunning = true - } - nodes[node.hostname] = node - } - - result := &mesosState{ - clusterName: state.ClusterName, - nodes: nodes, - } - - return result, nil -} - -type responseHandler func(*http.Response, error) error - -// httpDo executes an HTTP request in the given context, canceling an ongoing request if the context -// is canceled prior to completion of the request. hacked from https://blog.golang.org/context -func (c *mesosClient) httpDo(ctx context.Context, req *http.Request, f responseHandler) error { - // Run the HTTP request in a goroutine and pass the response to f. - ch := make(chan error, 1) - go func() { ch <- f(c.httpClient.Do(req)) }() - select { - case <-ctx.Done(): - c.tr.CancelRequest(req) - <-ch // Wait for f to return. - return ctx.Err() - case err := <-ch: - return err - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/client_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/client_test.go deleted file mode 100644 index 849a039ca..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/client_test.go +++ /dev/null @@ -1,269 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mesos - -import ( - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "reflect" - "testing" - "time" - - log "github.com/golang/glog" - "github.com/mesos/mesos-go/detector" - "github.com/mesos/mesos-go/mesosutil" - "golang.org/x/net/context" - - utilnet "k8s.io/kubernetes/pkg/util/net" -) - -// Test data - -const ( - TEST_MASTER_ID = "master-12345" - TEST_MASTER_IP = 177048842 // 10.141.141.10 - TEST_MASTER_PORT = 5050 - - TEST_STATE_JSON = ` - { - "version": "0.22.0", - "unregistered_frameworks": [], - "started_tasks": 0, - "start_time": 1429456501.61141, - "staged_tasks": 0, - "slaves": [ - { - "resources": { - "ports": "[31000-32000]", - "mem": 15360, - "disk": 470842, - "cpus": 8 - }, - "registered_time": 1429456502.46999, - "pid": "slave(1)@mesos1.internal.company.com:5050", - "id": "20150419-081501-16777343-5050-16383-S2", - "hostname": "mesos1.internal.company.com", - "attributes": {}, - "active": true - }, - { - "resources": { - "ports": "[31000-32000]", - "mem": 15360, - "disk": 470842, - "cpus": 8 - }, - "registered_time": 1429456502.4144, - "pid": "slave(1)@mesos2.internal.company.com:5050", - "id": "20150419-081501-16777343-5050-16383-S1", - "hostname": "mesos2.internal.company.com", - "attributes": {}, - "active": true - }, - { - "resources": { - "ports": "[31000-32000]", - "mem": 15360, - "disk": 470842, - "cpus": 8 - }, - "registered_time": 1429456502.02879, - "pid": "slave(1)@mesos3.internal.company.com:5050", - "id": "20150419-081501-16777343-5050-16383-S0", - "hostname": "mesos3.internal.company.com", - "attributes": {}, - "active": true - } - ], - "pid": "master@mesos-master0.internal.company.com:5050", - "orphan_tasks": [], - "lost_tasks": 0, - "leader": "master@mesos-master0.internal.company.com:5050", - "killed_tasks": 0, - "failed_tasks": 0, - "elected_time": 1429456501.61638, - "deactivated_slaves": 0, - "completed_frameworks": [], - "build_user": "buildbot", - "build_time": 1425085311, - "build_date": "2015-02-27 17:01:51", - "activated_slaves": 3, - "finished_tasks": 0, - "flags": { - "zk_session_timeout": "10secs", - "work_dir": "/somepath/mesos/local/Lc9arz", - "webui_dir": "/usr/local/share/mesos/webui", - "version": "false", - "user_sorter": "drf", - "slave_reregister_timeout": "10mins", - "logbufsecs": "0", - "log_auto_initialize": "true", - "initialize_driver_logging": "true", - "framework_sorter": "drf", - "authenticators": "crammd5", - "authenticate_slaves": "false", - "authenticate": "false", - "allocation_interval": "1secs", - "logging_level": "INFO", - "quiet": "false", - "recovery_slave_removal_limit": "100%", - "registry": "replicated_log", - "registry_fetch_timeout": "1mins", - "registry_store_timeout": "5secs", - "registry_strict": "false", - "root_submissions": "true" - }, - "frameworks": [], - "git_branch": "refs/heads/0.22.0-rc1", - "git_sha": "46834faca67f877631e1beb7d61be5c080ec3dc2", - "git_tag": "0.22.0-rc1", - "hostname": "localhost", - "id": "20150419-081501-16777343-5050-16383" - }` -) - -// Mocks - -type FakeMasterDetector struct { - callback detector.MasterChanged - done chan struct{} -} - -func newFakeMasterDetector() *FakeMasterDetector { - return &FakeMasterDetector{ - done: make(chan struct{}), - } -} - -func (md FakeMasterDetector) Cancel() { - close(md.done) -} - -func (md FakeMasterDetector) Detect(cb detector.MasterChanged) error { - md.callback = cb - leadingMaster := mesosutil.NewMasterInfo(TEST_MASTER_ID, TEST_MASTER_IP, TEST_MASTER_PORT) - cb.OnMasterChanged(leadingMaster) - return nil -} - -func (md FakeMasterDetector) Done() <-chan struct{} { - return md.done -} - -// Auxiliary functions - -func makeHttpMocks() (*httptest.Server, *http.Client, *http.Transport) { - httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - log.V(4).Infof("Mocking response for HTTP request: %#v", r) - if r.URL.Path == "/state.json" { - w.WriteHeader(200) // OK - w.Header().Set("Content-Type", "application/json") - fmt.Fprintln(w, TEST_STATE_JSON) - } else { - w.WriteHeader(400) - fmt.Fprintln(w, "Bad Request") - } - })) - - // Intercept all client requests and feed them to the test server - transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(httpServer.URL) - }, - }) - - httpClient := &http.Client{Transport: transport} - - return httpServer, httpClient, transport -} - -// Tests - -// test mesos.parseMesosState -func Test_parseMesosState(t *testing.T) { - state, err := parseMesosState([]byte(TEST_STATE_JSON)) - - if err != nil { - t.Fatalf("parseMesosState does not yield an error") - } - if state == nil { - t.Fatalf("parseMesosState yields a non-nil state") - } - if len(state.nodes) != 3 { - t.Fatalf("parseMesosState yields a state with 3 nodes") - } -} - -// test mesos.listSlaves -func Test_listSlaves(t *testing.T) { - defer log.Flush() - md := FakeMasterDetector{} - httpServer, httpClient, httpTransport := makeHttpMocks() - defer httpServer.Close() - - cacheTTL := 500 * time.Millisecond - mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) - - if err != nil { - t.Fatalf("createMesosClient does not yield an error") - } - - slaveNodes, err := mesosClient.listSlaves(context.TODO()) - - if err != nil { - t.Fatalf("listSlaves does not yield an error") - } - if len(slaveNodes) != 3 { - t.Fatalf("listSlaves yields a collection of size 3") - } - - expectedHostnames := map[string]struct{}{ - "mesos1.internal.company.com": {}, - "mesos2.internal.company.com": {}, - "mesos3.internal.company.com": {}, - } - - actualHostnames := make(map[string]struct{}) - for _, node := range slaveNodes { - actualHostnames[node.hostname] = struct{}{} - } - - if !reflect.DeepEqual(expectedHostnames, actualHostnames) { - t.Fatalf("listSlaves yields a collection with the expected hostnames") - } -} - -// test mesos.clusterName -func Test_clusterName(t *testing.T) { - defer log.Flush() - md := FakeMasterDetector{} - httpServer, httpClient, httpTransport := makeHttpMocks() - defer httpServer.Close() - cacheTTL := 500 * time.Millisecond - mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) - - name, err := mesosClient.clusterName(context.TODO()) - - if err != nil { - t.Fatalf("clusterName does not yield an error") - } - if name != defaultClusterName { - t.Fatalf("clusterName yields the expected (default) value") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/config.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/config.go deleted file mode 100644 index 9edbc8f5f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/config.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mesos - -import ( - "io" - "time" - - "gopkg.in/gcfg.v1" -) - -const ( - DefaultMesosMaster = "localhost:5050" - DefaultHttpClientTimeout = time.Duration(10) * time.Second - DefaultStateCacheTTL = time.Duration(5) * time.Second -) - -// Example Mesos cloud provider configuration file: -// -// [mesos-cloud] -// mesos-master = leader.mesos:5050 -// http-client-timeout = 500ms -// state-cache-ttl = 1h - -type ConfigWrapper struct { - Mesos_Cloud Config -} - -type Config struct { - MesosMaster string `gcfg:"mesos-master"` - MesosHttpClientTimeout Duration `gcfg:"http-client-timeout"` - StateCacheTTL Duration `gcfg:"state-cache-ttl"` -} - -type Duration struct { - Duration time.Duration `gcfg:"duration"` -} - -func (d *Duration) UnmarshalText(data []byte) error { - underlying, err := time.ParseDuration(string(data)) - if err == nil { - d.Duration = underlying - } - return err -} - -func createDefaultConfig() *Config { - return &Config{ - MesosMaster: DefaultMesosMaster, - MesosHttpClientTimeout: Duration{Duration: DefaultHttpClientTimeout}, - StateCacheTTL: Duration{Duration: DefaultStateCacheTTL}, - } -} - -func readConfig(configReader io.Reader) (*Config, error) { - config := createDefaultConfig() - wrapper := &ConfigWrapper{Mesos_Cloud: *config} - if configReader != nil { - if err := gcfg.ReadInto(wrapper, configReader); err != nil { - return nil, err - } - config = &(wrapper.Mesos_Cloud) - } - return config, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/config_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/config_test.go deleted file mode 100644 index d1013471c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/config_test.go +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mesos - -import ( - "bytes" - "testing" - "time" - - log "github.com/golang/glog" -) - -// test mesos.createDefaultConfig -func Test_createDefaultConfig(t *testing.T) { - defer log.Flush() - - config := createDefaultConfig() - - if config.MesosMaster != DefaultMesosMaster { - t.Fatalf("Default config has the expected MesosMaster value") - } - - if config.MesosHttpClientTimeout.Duration != DefaultHttpClientTimeout { - t.Fatalf("Default config has the expected MesosHttpClientTimeout value") - } - - if config.StateCacheTTL.Duration != DefaultStateCacheTTL { - t.Fatalf("Default config has the expected StateCacheTTL value") - } -} - -// test mesos.readConfig -func Test_readConfig(t *testing.T) { - defer log.Flush() - - configString := ` -[mesos-cloud] - mesos-master = leader.mesos:5050 - http-client-timeout = 500ms - state-cache-ttl = 1h` - - reader := bytes.NewBufferString(configString) - - config, err := readConfig(reader) - - if err != nil { - t.Fatalf("Reading configuration does not yield an error: %#v", err) - } - - if config.MesosMaster != "leader.mesos:5050" { - t.Fatalf("Parsed config has the expected MesosMaster value") - } - - if config.MesosHttpClientTimeout.Duration != time.Duration(500)*time.Millisecond { - t.Fatalf("Parsed config has the expected MesosHttpClientTimeout value") - } - - if config.StateCacheTTL.Duration != time.Duration(1)*time.Hour { - t.Fatalf("Parsed config has the expected StateCacheTTL value") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/mesos.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/mesos.go deleted file mode 100644 index 20285843b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/mesos.go +++ /dev/null @@ -1,283 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mesos - -import ( - "errors" - "fmt" - "io" - "net" - "regexp" - - log "github.com/golang/glog" - "github.com/mesos/mesos-go/detector" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/cloudprovider" -) - -const ( - ProviderName = "mesos" - - // KubernetesExecutorName is shared between contrib/mesos and Mesos cloud provider. - // Because cloud provider -> contrib dependencies are forbidden, this constant - // is defined here, not in contrib. - KubernetesExecutorName = "Kubelet-Executor" -) - -var ( - CloudProvider *MesosCloud - - noHostNameSpecified = errors.New("No hostname specified") -) - -func init() { - cloudprovider.RegisterCloudProvider( - ProviderName, - func(configReader io.Reader) (cloudprovider.Interface, error) { - provider, err := newMesosCloud(configReader) - if err == nil { - CloudProvider = provider - } - return provider, err - }) -} - -type MesosCloud struct { - client *mesosClient - config *Config -} - -func (c *MesosCloud) MasterURI() string { - return c.config.MesosMaster -} - -func newMesosCloud(configReader io.Reader) (*MesosCloud, error) { - config, err := readConfig(configReader) - if err != nil { - return nil, err - } - - log.V(1).Infof("new mesos cloud, master='%v'", config.MesosMaster) - if d, err := detector.New(config.MesosMaster); err != nil { - log.V(1).Infof("failed to create master detector: %v", err) - return nil, err - } else if cl, err := newMesosClient(d, - config.MesosHttpClientTimeout.Duration, - config.StateCacheTTL.Duration); err != nil { - log.V(1).Infof("failed to create mesos cloud client: %v", err) - return nil, err - } else { - return &MesosCloud{client: cl, config: config}, nil - } -} - -// Implementation of Instances.CurrentNodeName -func (c *MesosCloud) CurrentNodeName(hostname string) (string, error) { - return hostname, nil -} - -func (c *MesosCloud) AddSSHKeyToAllInstances(user string, keyData []byte) error { - return errors.New("unimplemented") -} - -// Instances returns a copy of the Mesos cloud Instances implementation. -// Mesos natively provides minimal cloud-type resources. More robust cloud -// support requires a combination of Mesos and cloud-specific knowledge. -func (c *MesosCloud) Instances() (cloudprovider.Instances, bool) { - return c, true -} - -// LoadBalancer always returns nil, false in this implementation. -// Mesos does not provide any type of native load balancing by default, -// so this implementation always returns (nil, false). -func (c *MesosCloud) LoadBalancer() (cloudprovider.LoadBalancer, bool) { - return nil, false -} - -// Zones always returns nil, false in this implementation. -// Mesos does not provide any type of native region or zone awareness, -// so this implementation always returns (nil, false). -func (c *MesosCloud) Zones() (cloudprovider.Zones, bool) { - return nil, false -} - -// Clusters returns a copy of the Mesos cloud Clusters implementation. -// Mesos does not provide support for multiple clusters. -func (c *MesosCloud) Clusters() (cloudprovider.Clusters, bool) { - return c, true -} - -// Routes always returns nil, false in this implementation. -func (c *MesosCloud) Routes() (cloudprovider.Routes, bool) { - return nil, false -} - -// ProviderName returns the cloud provider ID. -func (c *MesosCloud) ProviderName() string { - return ProviderName -} - -// ScrubDNS filters DNS settings for pods. -func (c *MesosCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) { - return nameservers, searches -} - -// ListClusters lists the names of the available Mesos clusters. -func (c *MesosCloud) ListClusters() ([]string, error) { - // Always returns a single cluster (this one!) - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() - name, err := c.client.clusterName(ctx) - return []string{name}, err -} - -// Master gets back the address (either DNS name or IP address) of the leading Mesos master node for the cluster. -func (c *MesosCloud) Master(clusterName string) (string, error) { - clusters, err := c.ListClusters() - if err != nil { - return "", err - } - for _, name := range clusters { - if name == clusterName { - if c.client.master == "" { - return "", errors.New("The currently leading master is unknown.") - } - - host, _, err := net.SplitHostPort(c.client.master) - if err != nil { - return "", err - } - - return host, nil - } - } - return "", errors.New(fmt.Sprintf("The supplied cluster '%v' does not exist", clusterName)) -} - -// ipAddress returns an IP address of the specified instance. -func ipAddress(name string) (net.IP, error) { - if name == "" { - return nil, noHostNameSpecified - } - ipaddr := net.ParseIP(name) - if ipaddr != nil { - return ipaddr, nil - } - iplist, err := net.LookupIP(name) - if err != nil { - log.V(2).Infof("failed to resolve IP from host name '%v': %v", name, err) - return nil, err - } - ipaddr = iplist[0] - log.V(2).Infof("resolved host '%v' to '%v'", name, ipaddr) - return ipaddr, nil -} - -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (c *MesosCloud) ExternalID(instance string) (string, error) { - //TODO(jdef) use a timeout here? 15s? - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() - - nodes, err := c.client.listSlaves(ctx) - if err != nil { - return "", err - } - - node := nodes[instance] - if node == nil { - return "", cloudprovider.InstanceNotFound - } - - ip, err := ipAddress(node.hostname) - if err != nil { - return "", err - } - return ip.String(), nil -} - -// InstanceID returns the cloud provider ID of the specified instance. -func (c *MesosCloud) InstanceID(name string) (string, error) { - return "", nil -} - -// InstanceType returns the type of the specified instance. -func (c *MesosCloud) InstanceType(name string) (string, error) { - return "", nil -} - -func (c *MesosCloud) listNodes() (map[string]*slaveNode, error) { - //TODO(jdef) use a timeout here? 15s? - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() - - nodes, err := c.client.listSlaves(ctx) - if err != nil { - return nil, err - } - if len(nodes) == 0 { - log.V(2).Info("no slaves found, are any running?") - return nil, nil - } - return nodes, nil -} - -// List lists instances that match 'filter' which is a regular expression -// which must match the entire instance name (fqdn). -func (c *MesosCloud) List(filter string) ([]string, error) { - nodes, err := c.listNodes() - if err != nil { - return nil, err - } - filterRegex, err := regexp.Compile(filter) - if err != nil { - return nil, err - } - addr := []string{} - for _, node := range nodes { - if filterRegex.MatchString(node.hostname) { - addr = append(addr, node.hostname) - } - } - return addr, nil -} - -// ListWithKubelet list those instance which have no running kubelet, i.e. the -// Kubernetes executor. -func (c *MesosCloud) ListWithoutKubelet() ([]string, error) { - nodes, err := c.listNodes() - if err != nil { - return nil, err - } - addr := make([]string, 0, len(nodes)) - for _, n := range nodes { - if !n.kubeletRunning { - addr = append(addr, n.hostname) - } - } - return addr, nil -} - -// NodeAddresses returns the addresses of the specified instance. -func (c *MesosCloud) NodeAddresses(name string) ([]api.NodeAddress, error) { - ip, err := ipAddress(name) - if err != nil { - return nil, err - } - return []api.NodeAddress{{Type: api.NodeLegacyHostIP, Address: ip.String()}}, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/mesos_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/mesos_test.go deleted file mode 100644 index b504f4ef0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/mesos_test.go +++ /dev/null @@ -1,279 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mesos - -import ( - "bytes" - "net" - "reflect" - "testing" - "time" - - log "github.com/golang/glog" - "k8s.io/kubernetes/pkg/cloudprovider" -) - -func TestIPAddress(t *testing.T) { - expected4 := net.IPv4(127, 0, 0, 1) - ip, err := ipAddress("127.0.0.1") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !reflect.DeepEqual(ip, expected4) { - t.Fatalf("expected %#v instead of %#v", expected4, ip) - } - - expected6 := net.ParseIP("::1") - if expected6 == nil { - t.Fatalf("failed to parse ipv6 ::1") - } - ip, err = ipAddress("::1") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !reflect.DeepEqual(ip, expected6) { - t.Fatalf("expected %#v instead of %#v", expected6, ip) - } - - ip, err = ipAddress("localhost") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !reflect.DeepEqual(ip, expected4) && !reflect.DeepEqual(ip, expected6) { - t.Fatalf("expected %#v or %#v instead of %#v", expected4, expected6, ip) - } - - _, err = ipAddress("") - if err != noHostNameSpecified { - t.Fatalf("expected error noHostNameSpecified but got none") - } -} - -// test mesos.newMesosCloud with no config -func Test_newMesosCloud_NoConfig(t *testing.T) { - defer log.Flush() - mesosCloud, err := newMesosCloud(nil) - - if err != nil { - t.Fatalf("Creating a new Mesos cloud provider without config does not yield an error: %#v", err) - } - - if mesosCloud.client.httpClient.Timeout != DefaultHttpClientTimeout { - t.Fatalf("Creating a new Mesos cloud provider without config does not yield an error: %#v", err) - } - - if mesosCloud.client.state.ttl != DefaultStateCacheTTL { - t.Fatalf("Mesos client with default config has the expected state cache TTL value") - } -} - -// test mesos.newMesosCloud with custom config -func Test_newMesosCloud_WithConfig(t *testing.T) { - defer log.Flush() - - configString := ` -[mesos-cloud] - http-client-timeout = 500ms - state-cache-ttl = 1h` - - reader := bytes.NewBufferString(configString) - - mesosCloud, err := newMesosCloud(reader) - - if err != nil { - t.Fatalf("Creating a new Mesos cloud provider with a custom config does not yield an error: %#v", err) - } - - if mesosCloud.client.httpClient.Timeout != time.Duration(500)*time.Millisecond { - t.Fatalf("Mesos client with a custom config has the expected HTTP client timeout value") - } - - if mesosCloud.client.state.ttl != time.Duration(1)*time.Hour { - t.Fatalf("Mesos client with a custom config has the expected state cache TTL value") - } -} - -// tests for capability reporting functions - -// test mesos.Instances -func Test_Instances(t *testing.T) { - defer log.Flush() - mesosCloud, _ := newMesosCloud(nil) - - instances, supports_instances := mesosCloud.Instances() - - if !supports_instances || instances == nil { - t.Fatalf("MesosCloud provides an implementation of Instances") - } -} - -// test mesos.LoadBalancer -func Test_TcpLoadBalancer(t *testing.T) { - defer log.Flush() - mesosCloud, _ := newMesosCloud(nil) - - lb, supports_lb := mesosCloud.LoadBalancer() - - if supports_lb || lb != nil { - t.Fatalf("MesosCloud does not provide an implementation of LoadBalancer") - } -} - -// test mesos.Zones -func Test_Zones(t *testing.T) { - defer log.Flush() - mesosCloud, _ := newMesosCloud(nil) - - zones, supports_zones := mesosCloud.Zones() - - if supports_zones || zones != nil { - t.Fatalf("MesosCloud does not provide an implementation of Zones") - } -} - -// test mesos.Clusters -func Test_Clusters(t *testing.T) { - defer log.Flush() - mesosCloud, _ := newMesosCloud(nil) - - clusters, supports_clusters := mesosCloud.Clusters() - - if !supports_clusters || clusters == nil { - t.Fatalf("MesosCloud does not provide an implementation of Clusters") - } -} - -// test mesos.MasterURI -func Test_MasterURI(t *testing.T) { - defer log.Flush() - mesosCloud, _ := newMesosCloud(nil) - - uri := mesosCloud.MasterURI() - - if uri != DefaultMesosMaster { - t.Fatalf("MasterURI returns the expected master URI (expected \"localhost\", actual \"%s\"", uri) - } -} - -// test mesos.ListClusters -func Test_ListClusters(t *testing.T) { - defer log.Flush() - md := FakeMasterDetector{} - httpServer, httpClient, httpTransport := makeHttpMocks() - defer httpServer.Close() - cacheTTL := 500 * time.Millisecond - mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) - mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} - - clusters, err := mesosCloud.ListClusters() - - if err != nil { - t.Fatalf("ListClusters does not yield an error: %#v", err) - } - - if len(clusters) != 1 { - t.Fatalf("ListClusters should return a list of size 1: (actual: %#v)", clusters) - } - - expectedClusterNames := []string{"mesos"} - - if !reflect.DeepEqual(clusters, expectedClusterNames) { - t.Fatalf("ListClusters should return the expected list of names: (expected: %#v, actual: %#v)", - expectedClusterNames, - clusters) - } -} - -// test mesos.Master -func Test_Master(t *testing.T) { - defer log.Flush() - md := FakeMasterDetector{} - httpServer, httpClient, httpTransport := makeHttpMocks() - defer httpServer.Close() - cacheTTL := 500 * time.Millisecond - mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) - mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} - - clusters, err := mesosCloud.ListClusters() - clusterName := clusters[0] - master, err := mesosCloud.Master(clusterName) - - if err != nil { - t.Fatalf("Master does not yield an error: %#v", err) - } - - expectedMaster := unpackIPv4(TEST_MASTER_IP) - - if master != expectedMaster { - t.Fatalf("Master returns the expected value: (expected: %#v, actual: %#v", expectedMaster, master) - } -} - -// test mesos.List -func Test_List(t *testing.T) { - defer log.Flush() - md := FakeMasterDetector{} - httpServer, httpClient, httpTransport := makeHttpMocks() - defer httpServer.Close() - cacheTTL := 500 * time.Millisecond - mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) - mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} - - clusters, err := mesosCloud.List(".*") // recognizes the language of all strings - - if err != nil { - t.Fatalf("List does not yield an error: %#v", err) - } - - if len(clusters) != 3 { - t.Fatalf("List with a catch-all filter should return a list of size 3: (actual: %#v)", clusters) - } - - clusters, err = mesosCloud.List("$^") // end-of-string followed by start-of-string: recognizes the empty language - - if err != nil { - t.Fatalf("List does not yield an error: %#v", err) - } - - if len(clusters) != 0 { - t.Fatalf("List with a reject-all filter should return a list of size 0: (actual: %#v)", clusters) - } -} - -func Test_ExternalID(t *testing.T) { - defer log.Flush() - md := FakeMasterDetector{} - httpServer, httpClient, httpTransport := makeHttpMocks() - defer httpServer.Close() - cacheTTL := 500 * time.Millisecond - mesosClient, err := createMesosClient(md, httpClient, httpTransport, cacheTTL) - mesosCloud := &MesosCloud{client: mesosClient, config: createDefaultConfig()} - - _, err = mesosCloud.ExternalID("unknown") - if err != cloudprovider.InstanceNotFound { - t.Fatalf("ExternalID did not return InstanceNotFound on an unknown instance") - } - - slaveName := "mesos3.internal.company.com" - id, err := mesosCloud.ExternalID(slaveName) - if id != "" { - t.Fatalf("ExternalID should not be able to resolve %q", slaveName) - } - if err == cloudprovider.InstanceNotFound { - t.Fatalf("ExternalID should find %q", slaveName) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/plugins.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/plugins.go deleted file mode 100644 index 2baf7b47f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/mesos/plugins.go +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mesos - -import ( - _ "github.com/mesos/mesos-go/detector/zoo" -) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/MAINTAINERS.md b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/MAINTAINERS.md deleted file mode 100644 index f71afec99..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/MAINTAINERS.md +++ /dev/null @@ -1,6 +0,0 @@ -# Maintainers - -* [Angus Lees](https://github.com/anguslees) - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/pkg/cloudprovider/providers/openstack/MAINTAINERS.md?pixel)]() diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack.go deleted file mode 100644 index 8c5b8ac4c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack.go +++ /dev/null @@ -1,1125 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 openstack - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "path" - "regexp" - "strings" - "time" - - "github.com/rackspace/gophercloud" - "github.com/rackspace/gophercloud/openstack" - "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes" - "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach" - "github.com/rackspace/gophercloud/openstack/compute/v2/flavors" - "github.com/rackspace/gophercloud/openstack/compute/v2/servers" - "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" - "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members" - "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors" - "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools" - "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips" - "github.com/rackspace/gophercloud/pagination" - "gopkg.in/gcfg.v1" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/service" - "k8s.io/kubernetes/pkg/cloudprovider" -) - -const ProviderName = "openstack" - -// metadataUrl is URL to OpenStack metadata server. It's hadrcoded IPv4 -// link-local address as documented in "OpenStack Cloud Administrator Guide", -// chapter Compute - Networking with nova-network. -// http://docs.openstack.org/admin-guide-cloud/compute-networking-nova.html#metadata-service -const metadataUrl = "http://169.254.169.254/openstack/2012-08-10/meta_data.json" - -var ErrNotFound = errors.New("Failed to find object") -var ErrMultipleResults = errors.New("Multiple results where only one expected") -var ErrNoAddressFound = errors.New("No address found for host") -var ErrAttrNotFound = errors.New("Expected attribute not found") - -const ( - MiB = 1024 * 1024 - GB = 1000 * 1000 * 1000 -) - -// encoding.TextUnmarshaler interface for time.Duration -type MyDuration struct { - time.Duration -} - -func (d *MyDuration) UnmarshalText(text []byte) error { - res, err := time.ParseDuration(string(text)) - if err != nil { - return err - } - d.Duration = res - return nil -} - -type LoadBalancerOpts struct { - SubnetId string `gcfg:"subnet-id"` // required - FloatingNetworkId string `gcfg:"floating-network-id"` - LBMethod string `gcfg:"lb-method"` - CreateMonitor bool `gcfg:"create-monitor"` - MonitorDelay MyDuration `gcfg:"monitor-delay"` - MonitorTimeout MyDuration `gcfg:"monitor-timeout"` - MonitorMaxRetries uint `gcfg:"monitor-max-retries"` -} - -// OpenStack is an implementation of cloud provider Interface for OpenStack. -type OpenStack struct { - provider *gophercloud.ProviderClient - region string - lbOpts LoadBalancerOpts - // InstanceID of the server where this OpenStack object is instantiated. - localInstanceID string -} - -type Config struct { - Global struct { - AuthUrl string `gcfg:"auth-url"` - Username string - UserId string `gcfg:"user-id"` - Password string - ApiKey string `gcfg:"api-key"` - TenantId string `gcfg:"tenant-id"` - TenantName string `gcfg:"tenant-name"` - DomainId string `gcfg:"domain-id"` - DomainName string `gcfg:"domain-name"` - Region string - } - LoadBalancer LoadBalancerOpts -} - -func init() { - cloudprovider.RegisterCloudProvider(ProviderName, func(config io.Reader) (cloudprovider.Interface, error) { - cfg, err := readConfig(config) - if err != nil { - return nil, err - } - return newOpenStack(cfg) - }) -} - -func (cfg Config) toAuthOptions() gophercloud.AuthOptions { - return gophercloud.AuthOptions{ - IdentityEndpoint: cfg.Global.AuthUrl, - Username: cfg.Global.Username, - UserID: cfg.Global.UserId, - Password: cfg.Global.Password, - APIKey: cfg.Global.ApiKey, - TenantID: cfg.Global.TenantId, - TenantName: cfg.Global.TenantName, - DomainID: cfg.Global.DomainId, - DomainName: cfg.Global.DomainName, - - // Persistent service, so we need to be able to renew tokens. - AllowReauth: true, - } -} - -func readConfig(config io.Reader) (Config, error) { - if config == nil { - err := fmt.Errorf("no OpenStack cloud provider config file given") - return Config{}, err - } - - var cfg Config - err := gcfg.ReadInto(&cfg, config) - return cfg, err -} - -// parseMetadataUUID reads JSON from OpenStack metadata server and parses -// instance ID out of it. -func parseMetadataUUID(jsonData []byte) (string, error) { - // We should receive an object with { 'uuid': '' } and couple of other - // properties (which we ignore). - - obj := struct{ UUID string }{} - err := json.Unmarshal(jsonData, &obj) - if err != nil { - return "", err - } - - uuid := obj.UUID - if uuid == "" { - err = fmt.Errorf("cannot parse OpenStack metadata, got empty uuid") - return "", err - } - - return uuid, nil -} - -func readInstanceID() (string, error) { - // Try to find instance ID on the local filesystem (created by cloud-init) - const instanceIDFile = "/var/lib/cloud/data/instance-id" - idBytes, err := ioutil.ReadFile(instanceIDFile) - if err == nil { - instanceID := string(idBytes) - instanceID = strings.TrimSpace(instanceID) - glog.V(3).Infof("Got instance id from %s: %s", instanceIDFile, instanceID) - if instanceID != "" { - return instanceID, nil - } - // Fall through with empty instanceID and try metadata server. - } - glog.V(5).Infof("Cannot read %s: '%v', trying metadata server", instanceIDFile, err) - - // Try to get JSON from metdata server. - resp, err := http.Get(metadataUrl) - if err != nil { - glog.V(3).Infof("Cannot read %s: %v", metadataUrl, err) - return "", err - } - - if resp.StatusCode != 200 { - err = fmt.Errorf("got unexpected status code when reading metadata from %s: %s", metadataUrl, resp.Status) - glog.V(3).Infof("%v", err) - return "", err - } - - defer resp.Body.Close() - bodyBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - glog.V(3).Infof("Cannot get HTTP response body from %s: %v", metadataUrl, err) - return "", err - } - instanceID, err := parseMetadataUUID(bodyBytes) - if err != nil { - glog.V(3).Infof("Cannot parse instance ID from metadata from %s: %v", metadataUrl, err) - return "", err - } - - glog.V(3).Infof("Got instance id from %s: %s", metadataUrl, instanceID) - return instanceID, nil -} - -func newOpenStack(cfg Config) (*OpenStack, error) { - provider, err := openstack.AuthenticatedClient(cfg.toAuthOptions()) - if err != nil { - return nil, err - } - - id, err := readInstanceID() - if err != nil { - return nil, err - } - - os := OpenStack{ - provider: provider, - region: cfg.Global.Region, - lbOpts: cfg.LoadBalancer, - localInstanceID: id, - } - - return &os, nil -} - -type Instances struct { - compute *gophercloud.ServiceClient - flavor_to_resource map[string]*api.NodeResources // keyed by flavor id -} - -// Instances returns an implementation of Instances for OpenStack. -func (os *OpenStack) Instances() (cloudprovider.Instances, bool) { - glog.V(4).Info("openstack.Instances() called") - - compute, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - if err != nil { - glog.Warningf("Failed to find compute endpoint: %v", err) - return nil, false - } - - pager := flavors.ListDetail(compute, nil) - - flavor_to_resource := make(map[string]*api.NodeResources) - err = pager.EachPage(func(page pagination.Page) (bool, error) { - flavorList, err := flavors.ExtractFlavors(page) - if err != nil { - return false, err - } - for _, flavor := range flavorList { - rsrc := api.NodeResources{ - Capacity: api.ResourceList{ - api.ResourceCPU: *resource.NewQuantity(int64(flavor.VCPUs), resource.DecimalSI), - api.ResourceMemory: *resource.NewQuantity(int64(flavor.RAM)*MiB, resource.BinarySI), - "openstack.org/disk": *resource.NewQuantity(int64(flavor.Disk)*GB, resource.DecimalSI), - "openstack.org/rxTxFactor": *resource.NewMilliQuantity(int64(flavor.RxTxFactor)*1000, resource.DecimalSI), - "openstack.org/swap": *resource.NewQuantity(int64(flavor.Swap)*MiB, resource.BinarySI), - }, - } - flavor_to_resource[flavor.ID] = &rsrc - } - return true, nil - }) - if err != nil { - glog.Warningf("Failed to find compute flavors: %v", err) - return nil, false - } - - glog.V(3).Infof("Found %v compute flavors", len(flavor_to_resource)) - glog.V(1).Info("Claiming to support Instances") - - return &Instances{compute, flavor_to_resource}, true -} - -func (i *Instances) List(name_filter string) ([]string, error) { - glog.V(4).Infof("openstack List(%v) called", name_filter) - - opts := servers.ListOpts{ - Name: name_filter, - Status: "ACTIVE", - } - pager := servers.List(i.compute, opts) - - ret := make([]string, 0) - err := pager.EachPage(func(page pagination.Page) (bool, error) { - sList, err := servers.ExtractServers(page) - if err != nil { - return false, err - } - for _, server := range sList { - ret = append(ret, server.Name) - } - return true, nil - }) - if err != nil { - return nil, err - } - - glog.V(3).Infof("Found %v instances matching %v: %v", - len(ret), name_filter, ret) - - return ret, nil -} - -func getServerByName(client *gophercloud.ServiceClient, name string) (*servers.Server, error) { - opts := servers.ListOpts{ - Name: fmt.Sprintf("^%s$", regexp.QuoteMeta(name)), - Status: "ACTIVE", - } - pager := servers.List(client, opts) - - serverList := make([]servers.Server, 0, 1) - - err := pager.EachPage(func(page pagination.Page) (bool, error) { - s, err := servers.ExtractServers(page) - if err != nil { - return false, err - } - serverList = append(serverList, s...) - if len(serverList) > 1 { - return false, ErrMultipleResults - } - return true, nil - }) - if err != nil { - return nil, err - } - - if len(serverList) == 0 { - return nil, ErrNotFound - } else if len(serverList) > 1 { - return nil, ErrMultipleResults - } - - return &serverList[0], nil -} - -func getAddressesByName(client *gophercloud.ServiceClient, name string) ([]api.NodeAddress, error) { - srv, err := getServerByName(client, name) - if err != nil { - return nil, err - } - - addrs := []api.NodeAddress{} - - for network, netblob := range srv.Addresses { - list, ok := netblob.([]interface{}) - if !ok { - continue - } - - for _, item := range list { - var addressType api.NodeAddressType - - props, ok := item.(map[string]interface{}) - if !ok { - continue - } - - extIPType, ok := props["OS-EXT-IPS:type"] - if (ok && extIPType == "floating") || (!ok && network == "public") { - addressType = api.NodeExternalIP - } else { - addressType = api.NodeInternalIP - } - - tmp, ok := props["addr"] - if !ok { - continue - } - addr, ok := tmp.(string) - if !ok { - continue - } - - api.AddToNodeAddresses(&addrs, - api.NodeAddress{ - Type: addressType, - Address: addr, - }, - ) - } - } - - // AccessIPs are usually duplicates of "public" addresses. - if srv.AccessIPv4 != "" { - api.AddToNodeAddresses(&addrs, - api.NodeAddress{ - Type: api.NodeExternalIP, - Address: srv.AccessIPv4, - }, - ) - } - - if srv.AccessIPv6 != "" { - api.AddToNodeAddresses(&addrs, - api.NodeAddress{ - Type: api.NodeExternalIP, - Address: srv.AccessIPv6, - }, - ) - } - - return addrs, nil -} - -func getAddressByName(client *gophercloud.ServiceClient, name string) (string, error) { - addrs, err := getAddressesByName(client, name) - if err != nil { - return "", err - } else if len(addrs) == 0 { - return "", ErrNoAddressFound - } - - for _, addr := range addrs { - if addr.Type == api.NodeInternalIP { - return addr.Address, nil - } - } - - return addrs[0].Address, nil -} - -// Implementation of Instances.CurrentNodeName -func (i *Instances) CurrentNodeName(hostname string) (string, error) { - return hostname, nil -} - -func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error { - return errors.New("unimplemented") -} - -func (i *Instances) NodeAddresses(name string) ([]api.NodeAddress, error) { - glog.V(4).Infof("NodeAddresses(%v) called", name) - - addrs, err := getAddressesByName(i.compute, name) - if err != nil { - return nil, err - } - - glog.V(4).Infof("NodeAddresses(%v) => %v", name, addrs) - return addrs, nil -} - -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (i *Instances) ExternalID(name string) (string, error) { - srv, err := getServerByName(i.compute, name) - if err != nil { - return "", err - } - return srv.ID, nil -} - -// InstanceID returns the kubelet's cloud provider ID. -func (os *OpenStack) InstanceID() (string, error) { - return os.localInstanceID, nil -} - -// InstanceID returns the cloud provider ID of the specified instance. -func (i *Instances) InstanceID(name string) (string, error) { - srv, err := getServerByName(i.compute, name) - if err != nil { - return "", err - } - // In the future it is possible to also return an endpoint as: - // / - return "/" + srv.ID, nil -} - -// InstanceType returns the type of the specified instance. -func (i *Instances) InstanceType(name string) (string, error) { - return "", nil -} - -func (os *OpenStack) Clusters() (cloudprovider.Clusters, bool) { - return nil, false -} - -// ProviderName returns the cloud provider ID. -func (os *OpenStack) ProviderName() string { - return ProviderName -} - -// ScrubDNS filters DNS settings for pods. -func (os *OpenStack) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) { - return nameservers, searches -} - -type LoadBalancer struct { - network *gophercloud.ServiceClient - compute *gophercloud.ServiceClient - opts LoadBalancerOpts -} - -func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) { - glog.V(4).Info("openstack.LoadBalancer() called") - - // TODO: Search for and support Rackspace loadbalancer API, and others. - network, err := openstack.NewNetworkV2(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - if err != nil { - glog.Warningf("Failed to find neutron endpoint: %v", err) - return nil, false - } - - compute, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - if err != nil { - glog.Warningf("Failed to find compute endpoint: %v", err) - return nil, false - } - - glog.V(1).Info("Claiming to support LoadBalancer") - - return &LoadBalancer{network, compute, os.lbOpts}, true -} - -func isNotFound(err error) bool { - e, ok := err.(*gophercloud.UnexpectedResponseCodeError) - return ok && e.Actual == http.StatusNotFound -} - -func getPoolByName(client *gophercloud.ServiceClient, name string) (*pools.Pool, error) { - opts := pools.ListOpts{ - Name: name, - } - pager := pools.List(client, opts) - - poolList := make([]pools.Pool, 0, 1) - - err := pager.EachPage(func(page pagination.Page) (bool, error) { - p, err := pools.ExtractPools(page) - if err != nil { - return false, err - } - poolList = append(poolList, p...) - if len(poolList) > 1 { - return false, ErrMultipleResults - } - return true, nil - }) - if err != nil { - if isNotFound(err) { - return nil, ErrNotFound - } - return nil, err - } - - if len(poolList) == 0 { - return nil, ErrNotFound - } else if len(poolList) > 1 { - return nil, ErrMultipleResults - } - - return &poolList[0], nil -} - -func getVipByName(client *gophercloud.ServiceClient, name string) (*vips.VirtualIP, error) { - opts := vips.ListOpts{ - Name: name, - } - pager := vips.List(client, opts) - - vipList := make([]vips.VirtualIP, 0, 1) - - err := pager.EachPage(func(page pagination.Page) (bool, error) { - v, err := vips.ExtractVIPs(page) - if err != nil { - return false, err - } - vipList = append(vipList, v...) - if len(vipList) > 1 { - return false, ErrMultipleResults - } - return true, nil - }) - if err != nil { - if isNotFound(err) { - return nil, ErrNotFound - } - return nil, err - } - - if len(vipList) == 0 { - return nil, ErrNotFound - } else if len(vipList) > 1 { - return nil, ErrMultipleResults - } - - return &vipList[0], nil -} - -func getFloatingIPByPortID(client *gophercloud.ServiceClient, portID string) (*floatingips.FloatingIP, error) { - opts := floatingips.ListOpts{ - PortID: portID, - } - pager := floatingips.List(client, opts) - - floatingIPList := make([]floatingips.FloatingIP, 0, 1) - - err := pager.EachPage(func(page pagination.Page) (bool, error) { - f, err := floatingips.ExtractFloatingIPs(page) - if err != nil { - return false, err - } - floatingIPList = append(floatingIPList, f...) - if len(floatingIPList) > 1 { - return false, ErrMultipleResults - } - return true, nil - }) - if err != nil { - if isNotFound(err) { - return nil, ErrNotFound - } - return nil, err - } - - if len(floatingIPList) == 0 { - return nil, ErrNotFound - } else if len(floatingIPList) > 1 { - return nil, ErrMultipleResults - } - - return &floatingIPList[0], nil -} - -func (lb *LoadBalancer) GetLoadBalancer(service *api.Service) (*api.LoadBalancerStatus, bool, error) { - loadBalancerName := cloudprovider.GetLoadBalancerName(service) - vip, err := getVipByName(lb.network, loadBalancerName) - if err == ErrNotFound { - return nil, false, nil - } - if vip == nil { - return nil, false, err - } - - status := &api.LoadBalancerStatus{} - status.Ingress = []api.LoadBalancerIngress{{IP: vip.Address}} - - return status, true, err -} - -// TODO: This code currently ignores 'region' and always creates a -// loadbalancer in only the current OpenStack region. We should take -// a list of regions (from config) and query/create loadbalancers in -// each region. - -func (lb *LoadBalancer) EnsureLoadBalancer(apiService *api.Service, hosts []string, annotations map[string]string) (*api.LoadBalancerStatus, error) { - glog.V(4).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v, %v)", apiService.Namespace, apiService.Name, apiService.Spec.LoadBalancerIP, apiService.Spec.Ports, hosts, annotations) - - ports := apiService.Spec.Ports - if len(ports) > 1 { - return nil, fmt.Errorf("multiple ports are not yet supported in openstack load balancers") - } else if len(ports) == 0 { - return nil, fmt.Errorf("no ports provided to openstack load balancer") - } - - // The service controller verified all the protocols match on the ports, just check and use the first one - // TODO: Convert all error messages to use an event recorder - if ports[0].Protocol != api.ProtocolTCP { - return nil, fmt.Errorf("Only TCP LoadBalancer is supported for openstack load balancers") - } - - affinity := apiService.Spec.SessionAffinity - var persistence *vips.SessionPersistence - switch affinity { - case api.ServiceAffinityNone: - persistence = nil - case api.ServiceAffinityClientIP: - persistence = &vips.SessionPersistence{Type: "SOURCE_IP"} - default: - return nil, fmt.Errorf("unsupported load balancer affinity: %v", affinity) - } - - sourceRanges, err := service.GetLoadBalancerSourceRanges(annotations) - if err != nil { - return nil, err - } - - if !service.IsAllowAll(sourceRanges) { - return nil, fmt.Errorf("Source range restrictions are not supported for openstack load balancers") - } - - glog.V(2).Infof("Checking if openstack load balancer already exists: %s", cloudprovider.GetLoadBalancerName(apiService)) - _, exists, err := lb.GetLoadBalancer(apiService) - if err != nil { - return nil, fmt.Errorf("error checking if openstack load balancer already exists: %v", err) - } - - // TODO: Implement a more efficient update strategy for common changes than delete & create - // In particular, if we implement hosts update, we can get rid of UpdateHosts - if exists { - err := lb.EnsureLoadBalancerDeleted(apiService) - if err != nil { - return nil, fmt.Errorf("error deleting existing openstack load balancer: %v", err) - } - } - - lbmethod := lb.opts.LBMethod - if lbmethod == "" { - lbmethod = pools.LBMethodRoundRobin - } - name := cloudprovider.GetLoadBalancerName(apiService) - pool, err := pools.Create(lb.network, pools.CreateOpts{ - Name: name, - Protocol: pools.ProtocolTCP, - SubnetID: lb.opts.SubnetId, - LBMethod: lbmethod, - }).Extract() - if err != nil { - return nil, err - } - - for _, host := range hosts { - addr, err := getAddressByName(lb.compute, host) - if err != nil { - return nil, err - } - - _, err = members.Create(lb.network, members.CreateOpts{ - PoolID: pool.ID, - ProtocolPort: int(ports[0].NodePort), //TODO: need to handle multi-port - Address: addr, - }).Extract() - if err != nil { - pools.Delete(lb.network, pool.ID) - return nil, err - } - } - - var mon *monitors.Monitor - if lb.opts.CreateMonitor { - mon, err = monitors.Create(lb.network, monitors.CreateOpts{ - Type: monitors.TypeTCP, - Delay: int(lb.opts.MonitorDelay.Duration.Seconds()), - Timeout: int(lb.opts.MonitorTimeout.Duration.Seconds()), - MaxRetries: int(lb.opts.MonitorMaxRetries), - }).Extract() - if err != nil { - pools.Delete(lb.network, pool.ID) - return nil, err - } - - _, err = pools.AssociateMonitor(lb.network, pool.ID, mon.ID).Extract() - if err != nil { - monitors.Delete(lb.network, mon.ID) - pools.Delete(lb.network, pool.ID) - return nil, err - } - } - - createOpts := vips.CreateOpts{ - Name: name, - Description: fmt.Sprintf("Kubernetes external service %s", name), - Protocol: "TCP", - ProtocolPort: int(ports[0].Port), //TODO: need to handle multi-port - PoolID: pool.ID, - SubnetID: lb.opts.SubnetId, - Persistence: persistence, - } - - loadBalancerIP := apiService.Spec.LoadBalancerIP - if loadBalancerIP != "" { - createOpts.Address = loadBalancerIP - } - - vip, err := vips.Create(lb.network, createOpts).Extract() - if err != nil { - if mon != nil { - monitors.Delete(lb.network, mon.ID) - } - pools.Delete(lb.network, pool.ID) - return nil, err - } - - status := &api.LoadBalancerStatus{} - - status.Ingress = []api.LoadBalancerIngress{{IP: vip.Address}} - - if lb.opts.FloatingNetworkId != "" { - floatIPOpts := floatingips.CreateOpts{ - FloatingNetworkID: lb.opts.FloatingNetworkId, - PortID: vip.PortID, - } - floatIP, err := floatingips.Create(lb.network, floatIPOpts).Extract() - if err != nil { - return nil, err - } - - status.Ingress = append(status.Ingress, api.LoadBalancerIngress{IP: floatIP.FloatingIP}) - } - - return status, nil - -} - -func (lb *LoadBalancer) UpdateLoadBalancer(service *api.Service, hosts []string) error { - loadBalancerName := cloudprovider.GetLoadBalancerName(service) - glog.V(4).Infof("UpdateLoadBalancer(%v, %v)", loadBalancerName, hosts) - - vip, err := getVipByName(lb.network, loadBalancerName) - if err != nil { - return err - } - - // Set of member (addresses) that _should_ exist - addrs := map[string]bool{} - for _, host := range hosts { - addr, err := getAddressByName(lb.compute, host) - if err != nil { - return err - } - - addrs[addr] = true - } - - // Iterate over members that _do_ exist - pager := members.List(lb.network, members.ListOpts{PoolID: vip.PoolID}) - err = pager.EachPage(func(page pagination.Page) (bool, error) { - memList, err := members.ExtractMembers(page) - if err != nil { - return false, err - } - - for _, member := range memList { - if _, found := addrs[member.Address]; found { - // Member already exists - delete(addrs, member.Address) - } else { - // Member needs to be deleted - err = members.Delete(lb.network, member.ID).ExtractErr() - if err != nil { - return false, err - } - } - } - - return true, nil - }) - if err != nil { - return err - } - - // Anything left in addrs is a new member that needs to be added - for addr := range addrs { - _, err := members.Create(lb.network, members.CreateOpts{ - PoolID: vip.PoolID, - Address: addr, - ProtocolPort: vip.ProtocolPort, - }).Extract() - if err != nil { - return err - } - } - - return nil -} - -func (lb *LoadBalancer) EnsureLoadBalancerDeleted(service *api.Service) error { - loadBalancerName := cloudprovider.GetLoadBalancerName(service) - glog.V(4).Infof("EnsureLoadBalancerDeleted(%v)", loadBalancerName) - - vip, err := getVipByName(lb.network, loadBalancerName) - if err != nil && err != ErrNotFound { - return err - } - - if lb.opts.FloatingNetworkId != "" && vip != nil { - floatingIP, err := getFloatingIPByPortID(lb.network, vip.PortID) - if err != nil && !isNotFound(err) { - return err - } - if floatingIP != nil { - err = floatingips.Delete(lb.network, floatingIP.ID).ExtractErr() - if err != nil && !isNotFound(err) { - return err - } - } - } - - // We have to delete the VIP before the pool can be deleted, - // so no point continuing if this fails. - if vip != nil { - err := vips.Delete(lb.network, vip.ID).ExtractErr() - if err != nil && !isNotFound(err) { - return err - } - } - - var pool *pools.Pool - if vip != nil { - pool, err = pools.Get(lb.network, vip.PoolID).Extract() - if err != nil && !isNotFound(err) { - return err - } - } else { - // The VIP is gone, but it is conceivable that a Pool - // still exists that we failed to delete on some - // previous occasion. Make a best effort attempt to - // cleanup any pools with the same name as the VIP. - pool, err = getPoolByName(lb.network, service.Name) - if err != nil && err != ErrNotFound { - return err - } - } - - if pool != nil { - for _, monId := range pool.MonitorIDs { - _, err = pools.DisassociateMonitor(lb.network, pool.ID, monId).Extract() - if err != nil { - return err - } - - err = monitors.Delete(lb.network, monId).ExtractErr() - if err != nil && !isNotFound(err) { - return err - } - } - err = pools.Delete(lb.network, pool.ID).ExtractErr() - if err != nil && !isNotFound(err) { - return err - } - } - - return nil -} - -func (os *OpenStack) Zones() (cloudprovider.Zones, bool) { - glog.V(1).Info("Claiming to support Zones") - - return os, true -} -func (os *OpenStack) GetZone() (cloudprovider.Zone, error) { - glog.V(1).Infof("Current zone is %v", os.region) - - return cloudprovider.Zone{Region: os.region}, nil -} - -func (os *OpenStack) Routes() (cloudprovider.Routes, bool) { - return nil, false -} - -// Attaches given cinder volume to the compute running kubelet -func (os *OpenStack) AttachDisk(instanceID string, diskName string) (string, error) { - disk, err := os.getVolume(diskName) - if err != nil { - return "", err - } - cClient, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - if err != nil || cClient == nil { - glog.Errorf("Unable to initialize nova client for region: %s", os.region) - return "", err - } - - if len(disk.Attachments) > 0 && disk.Attachments[0]["server_id"] != nil { - if instanceID == disk.Attachments[0]["server_id"] { - glog.V(4).Infof("Disk: %q is already attached to compute: %q", diskName, instanceID) - return disk.ID, nil - } else { - errMsg := fmt.Sprintf("Disk %q is attached to a different compute: %q, should be detached before proceeding", diskName, disk.Attachments[0]["server_id"]) - glog.Errorf(errMsg) - return "", errors.New(errMsg) - } - } - // add read only flag here if possible spothanis - _, err = volumeattach.Create(cClient, instanceID, &volumeattach.CreateOpts{ - VolumeID: disk.ID, - }).Extract() - if err != nil { - glog.Errorf("Failed to attach %s volume to %s compute", diskName, instanceID) - return "", err - } - glog.V(2).Infof("Successfully attached %s volume to %s compute", diskName, instanceID) - return disk.ID, nil -} - -// Detaches given cinder volume from the compute running kubelet -func (os *OpenStack) DetachDisk(instanceID string, partialDiskId string) error { - disk, err := os.getVolume(partialDiskId) - if err != nil { - return err - } - cClient, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - if err != nil || cClient == nil { - glog.Errorf("Unable to initialize nova client for region: %s", os.region) - return err - } - if len(disk.Attachments) > 0 && disk.Attachments[0]["server_id"] != nil && instanceID == disk.Attachments[0]["server_id"] { - // This is a blocking call and effects kubelet's performance directly. - // We should consider kicking it out into a separate routine, if it is bad. - err = volumeattach.Delete(cClient, instanceID, disk.ID).ExtractErr() - if err != nil { - glog.Errorf("Failed to delete volume %s from compute %s attached %v", disk.ID, instanceID, err) - return err - } - glog.V(2).Infof("Successfully detached volume: %s from compute: %s", disk.ID, instanceID) - } else { - errMsg := fmt.Sprintf("Disk: %s has no attachments or is not attached to compute: %s", disk.Name, instanceID) - glog.Errorf(errMsg) - return errors.New(errMsg) - } - return nil -} - -// Takes a partial/full disk id or diskname -func (os *OpenStack) getVolume(diskName string) (volumes.Volume, error) { - sClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - - var volume volumes.Volume - if err != nil || sClient == nil { - glog.Errorf("Unable to initialize cinder client for region: %s", os.region) - return volume, err - } - - err = volumes.List(sClient, nil).EachPage(func(page pagination.Page) (bool, error) { - vols, err := volumes.ExtractVolumes(page) - if err != nil { - glog.Errorf("Failed to extract volumes: %v", err) - return false, err - } else { - for _, v := range vols { - glog.V(4).Infof("%s %s %v", v.ID, v.Name, v.Attachments) - if v.Name == diskName || strings.Contains(v.ID, diskName) { - volume = v - return true, nil - } - } - } - // if it reached here then no disk with the given name was found. - errmsg := fmt.Sprintf("Unable to find disk: %s in region %s", diskName, os.region) - return false, errors.New(errmsg) - }) - if err != nil { - glog.Errorf("Error occured getting volume: %s", diskName) - return volume, err - } - return volume, err -} - -// Create a volume of given size (in GiB) -func (os *OpenStack) CreateVolume(name string, size int, tags *map[string]string) (volumeName string, err error) { - - sClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - - if err != nil || sClient == nil { - glog.Errorf("Unable to initialize cinder client for region: %s", os.region) - return "", err - } - - opts := volumes.CreateOpts{ - Name: name, - Size: size, - } - if tags != nil { - opts.Metadata = *tags - } - vol, err := volumes.Create(sClient, opts).Extract() - if err != nil { - glog.Errorf("Failed to create a %d GB volume: %v", size, err) - return "", err - } - glog.Infof("Created volume %v", vol.ID) - return vol.ID, err -} - -// GetDevicePath returns the path of an attached block storage volume, specified by its id. -func (os *OpenStack) GetDevicePath(diskId string) string { - files, _ := ioutil.ReadDir("/dev/disk/by-id/") - for _, f := range files { - if strings.Contains(f.Name(), "virtio-") { - devid_prefix := f.Name()[len("virtio-"):len(f.Name())] - if strings.Contains(diskId, devid_prefix) { - glog.V(4).Infof("Found disk attached as %q; full devicepath: %s\n", f.Name(), path.Join("/dev/disk/by-id/", f.Name())) - return path.Join("/dev/disk/by-id/", f.Name()) - } - } - } - glog.Warningf("Failed to find device for the diskid: %q\n", diskId) - return "" -} - -func (os *OpenStack) DeleteVolume(volumeName string) error { - sClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{ - Region: os.region, - }) - - if err != nil || sClient == nil { - glog.Errorf("Unable to initialize cinder client for region: %s", os.region) - return err - } - err = volumes.Delete(sClient, volumeName).ExtractErr() - if err != nil { - glog.Errorf("Cannot delete volume %s: %v", volumeName, err) - } - return err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_test.go deleted file mode 100644 index 06f618e45..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/openstack/openstack_test.go +++ /dev/null @@ -1,293 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 openstack - -import ( - "os" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/util/rand" - - "github.com/rackspace/gophercloud" - "k8s.io/kubernetes/pkg/api" -) - -const volumeAvailableStatus = "available" -const volumeInUseStatus = "in-use" -const volumeCreateTimeoutSeconds = 30 - -func WaitForVolumeStatus(t *testing.T, os *OpenStack, volumeName string, status string, timeoutSeconds int) { - timeout := timeoutSeconds - start := time.Now().Second() - for { - time.Sleep(1 * time.Second) - - if timeout >= 0 && time.Now().Second()-start >= timeout { - t.Logf("Volume (%s) status did not change to %s after %v seconds\n", - volumeName, - status, - timeout) - return - } - - getVol, err := os.getVolume(volumeName) - if err != nil { - t.Fatalf("Cannot get existing Cinder volume (%s): %v", volumeName, err) - } - if getVol.Status == status { - t.Logf("Volume (%s) status changed to %s after %v seconds\n", - volumeName, - status, - timeout) - return - } - } -} - -func TestReadConfig(t *testing.T) { - _, err := readConfig(nil) - if err == nil { - t.Errorf("Should fail when no config is provided: %s", err) - } - - cfg, err := readConfig(strings.NewReader(` -[Global] -auth-url = http://auth.url -username = user -[LoadBalancer] -create-monitor = yes -monitor-delay = 1m -monitor-timeout = 30s -monitor-max-retries = 3 -`)) - if err != nil { - t.Fatalf("Should succeed when a valid config is provided: %s", err) - } - if cfg.Global.AuthUrl != "http://auth.url" { - t.Errorf("incorrect authurl: %s", cfg.Global.AuthUrl) - } - - if !cfg.LoadBalancer.CreateMonitor { - t.Errorf("incorrect lb.createmonitor: %t", cfg.LoadBalancer.CreateMonitor) - } - if cfg.LoadBalancer.MonitorDelay.Duration != 1*time.Minute { - t.Errorf("incorrect lb.monitordelay: %s", cfg.LoadBalancer.MonitorDelay) - } - if cfg.LoadBalancer.MonitorTimeout.Duration != 30*time.Second { - t.Errorf("incorrect lb.monitortimeout: %s", cfg.LoadBalancer.MonitorTimeout) - } - if cfg.LoadBalancer.MonitorMaxRetries != 3 { - t.Errorf("incorrect lb.monitormaxretries: %d", cfg.LoadBalancer.MonitorMaxRetries) - } -} - -func TestToAuthOptions(t *testing.T) { - cfg := Config{} - cfg.Global.Username = "user" - // etc. - - ao := cfg.toAuthOptions() - - if !ao.AllowReauth { - t.Errorf("Will need to be able to reauthenticate") - } - if ao.Username != cfg.Global.Username { - t.Errorf("Username %s != %s", ao.Username, cfg.Global.Username) - } -} - -// This allows acceptance testing against an existing OpenStack -// install, using the standard OS_* OpenStack client environment -// variables. -// FIXME: it would be better to hermetically test against canned JSON -// requests/responses. -func configFromEnv() (cfg Config, ok bool) { - cfg.Global.AuthUrl = os.Getenv("OS_AUTH_URL") - - cfg.Global.TenantId = os.Getenv("OS_TENANT_ID") - // Rax/nova _insists_ that we don't specify both tenant ID and name - if cfg.Global.TenantId == "" { - cfg.Global.TenantName = os.Getenv("OS_TENANT_NAME") - } - - cfg.Global.Username = os.Getenv("OS_USERNAME") - cfg.Global.Password = os.Getenv("OS_PASSWORD") - cfg.Global.ApiKey = os.Getenv("OS_API_KEY") - cfg.Global.Region = os.Getenv("OS_REGION_NAME") - cfg.Global.DomainId = os.Getenv("OS_DOMAIN_ID") - cfg.Global.DomainName = os.Getenv("OS_DOMAIN_NAME") - - ok = (cfg.Global.AuthUrl != "" && - cfg.Global.Username != "" && - (cfg.Global.Password != "" || cfg.Global.ApiKey != "") && - (cfg.Global.TenantId != "" || cfg.Global.TenantName != "" || - cfg.Global.DomainId != "" || cfg.Global.DomainName != "")) - - return -} - -func TestNewOpenStack(t *testing.T) { - cfg, ok := configFromEnv() - if !ok { - t.Skipf("No config found in environment") - } - - _, err := newOpenStack(cfg) - if err != nil { - t.Fatalf("Failed to construct/authenticate OpenStack: %s", err) - } -} - -func TestInstances(t *testing.T) { - cfg, ok := configFromEnv() - if !ok { - t.Skipf("No config found in environment") - } - - os, err := newOpenStack(cfg) - if err != nil { - t.Fatalf("Failed to construct/authenticate OpenStack: %s", err) - } - - i, ok := os.Instances() - if !ok { - t.Fatalf("Instances() returned false") - } - - srvs, err := i.List(".") - if err != nil { - t.Fatalf("Instances.List() failed: %s", err) - } - if len(srvs) == 0 { - t.Fatalf("Instances.List() returned zero servers") - } - t.Logf("Found servers (%d): %s\n", len(srvs), srvs) - - srvExternalId, err := i.ExternalID(srvs[0]) - if err != nil { - t.Fatalf("Instances.ExternalId(%s) failed: %s", srvs[0], err) - } - t.Logf("Found server (%s), with external id: %s\n", srvs[0], srvExternalId) - - srvInstanceId, err := i.InstanceID(srvs[0]) - if err != nil { - t.Fatalf("Instance.InstanceId(%s) failed: %s", srvs[0], err) - } - t.Logf("Found server (%s), with instance id: %s\n", srvs[0], srvInstanceId) - - addrs, err := i.NodeAddresses(srvs[0]) - if err != nil { - t.Fatalf("Instances.NodeAddresses(%s) failed: %s", srvs[0], err) - } - t.Logf("Found NodeAddresses(%s) = %s\n", srvs[0], addrs) -} - -func TestLoadBalancer(t *testing.T) { - cfg, ok := configFromEnv() - if !ok { - t.Skipf("No config found in environment") - } - - os, err := newOpenStack(cfg) - if err != nil { - t.Fatalf("Failed to construct/authenticate OpenStack: %s", err) - } - - lb, ok := os.LoadBalancer() - if !ok { - t.Fatalf("LoadBalancer() returned false - perhaps your stack doesn't support Neutron?") - } - - _, exists, err := lb.GetLoadBalancer(&api.Service{ObjectMeta: api.ObjectMeta{Name: "noexist"}}) - if err != nil { - t.Fatalf("GetLoadBalancer(\"noexist\") returned error: %s", err) - } - if exists { - t.Fatalf("GetLoadBalancer(\"noexist\") returned exists") - } -} - -func TestZones(t *testing.T) { - os := OpenStack{ - provider: &gophercloud.ProviderClient{ - IdentityBase: "http://auth.url/", - }, - region: "myRegion", - } - - z, ok := os.Zones() - if !ok { - t.Fatalf("Zones() returned false") - } - - zone, err := z.GetZone() - if err != nil { - t.Fatalf("GetZone() returned error: %s", err) - } - - if zone.Region != "myRegion" { - t.Fatalf("GetZone() returned wrong region (%s)", zone.Region) - } -} - -func TestVolumes(t *testing.T) { - cfg, ok := configFromEnv() - if !ok { - t.Skipf("No config found in environment") - } - - os, err := newOpenStack(cfg) - if err != nil { - t.Fatalf("Failed to construct/authenticate OpenStack: %s", err) - } - - tags := map[string]string{ - "test": "value", - } - vol, err := os.CreateVolume("kubernetes-test-volume-"+rand.String(10), 1, &tags) - if err != nil { - t.Fatalf("Cannot create a new Cinder volume: %v", err) - } - t.Logf("Volume (%s) created\n", vol) - - WaitForVolumeStatus(t, os, vol, volumeAvailableStatus, volumeCreateTimeoutSeconds) - - diskId, err := os.AttachDisk(os.localInstanceID, vol) - if err != nil { - t.Fatalf("Cannot AttachDisk Cinder volume %s: %v", vol, err) - } - t.Logf("Volume (%s) attached, disk ID: %s\n", vol, diskId) - - WaitForVolumeStatus(t, os, vol, volumeInUseStatus, volumeCreateTimeoutSeconds) - - err = os.DetachDisk(os.localInstanceID, vol) - if err != nil { - t.Fatalf("Cannot DetachDisk Cinder volume %s: %v", vol, err) - } - t.Logf("Volume (%s) detached\n", vol) - - WaitForVolumeStatus(t, os, vol, volumeAvailableStatus, volumeCreateTimeoutSeconds) - - err = os.DeleteVolume(vol) - if err != nil { - t.Fatalf("Cannot delete Cinder volume %s: %v", vol, err) - } - t.Logf("Volume (%s) deleted\n", vol) - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt.go deleted file mode 100644 index d2ba03c10..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt.go +++ /dev/null @@ -1,291 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 ovirt - -import ( - "encoding/xml" - "errors" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/url" - "path" - "sort" - "strings" - - "gopkg.in/gcfg.v1" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/cloudprovider" -) - -const ProviderName = "ovirt" - -type OVirtInstance struct { - UUID string - Name string - IPAddress string -} - -type OVirtInstanceMap map[string]OVirtInstance - -type OVirtCloud struct { - VmsRequest *url.URL - HostsRequest *url.URL -} - -type OVirtApiConfig struct { - Connection struct { - ApiEntry string `gcfg:"uri"` - Username string `gcfg:"username"` - Password string `gcfg:"password"` - } - Filters struct { - VmsQuery string `gcfg:"vms"` - } -} - -type XmlVmAddress struct { - Address string `xml:"address,attr"` -} - -type XmlVmInfo struct { - UUID string `xml:"id,attr"` - Name string `xml:"name"` - Hostname string `xml:"guest_info>fqdn"` - Addresses []XmlVmAddress `xml:"guest_info>ips>ip"` - State string `xml:"status>state"` -} - -type XmlVmsList struct { - XMLName xml.Name `xml:"vms"` - Vm []XmlVmInfo `xml:"vm"` -} - -func init() { - cloudprovider.RegisterCloudProvider(ProviderName, - func(config io.Reader) (cloudprovider.Interface, error) { - return newOVirtCloud(config) - }) -} - -func newOVirtCloud(config io.Reader) (*OVirtCloud, error) { - if config == nil { - return nil, fmt.Errorf("missing configuration file for ovirt cloud provider") - } - - oVirtConfig := OVirtApiConfig{} - - /* defaults */ - oVirtConfig.Connection.Username = "admin@internal" - - if err := gcfg.ReadInto(&oVirtConfig, config); err != nil { - return nil, err - } - - if oVirtConfig.Connection.ApiEntry == "" { - return nil, fmt.Errorf("missing ovirt uri in cloud provider configuration") - } - - request, err := url.Parse(oVirtConfig.Connection.ApiEntry) - if err != nil { - return nil, err - } - - request.Path = path.Join(request.Path, "vms") - request.User = url.UserPassword(oVirtConfig.Connection.Username, oVirtConfig.Connection.Password) - request.RawQuery = url.Values{"search": {oVirtConfig.Filters.VmsQuery}}.Encode() - - return &OVirtCloud{VmsRequest: request}, nil -} - -func (aws *OVirtCloud) Clusters() (cloudprovider.Clusters, bool) { - return nil, false -} - -// ProviderName returns the cloud provider ID. -func (v *OVirtCloud) ProviderName() string { - return ProviderName -} - -// ScrubDNS filters DNS settings for pods. -func (v *OVirtCloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) { - return nameservers, searches -} - -// LoadBalancer returns an implementation of LoadBalancer for oVirt cloud -func (v *OVirtCloud) LoadBalancer() (cloudprovider.LoadBalancer, bool) { - return nil, false -} - -// Instances returns an implementation of Instances for oVirt cloud -func (v *OVirtCloud) Instances() (cloudprovider.Instances, bool) { - return v, true -} - -// Zones returns an implementation of Zones for oVirt cloud -func (v *OVirtCloud) Zones() (cloudprovider.Zones, bool) { - return nil, false -} - -// Routes returns an implementation of Routes for oVirt cloud -func (v *OVirtCloud) Routes() (cloudprovider.Routes, bool) { - return nil, false -} - -// NodeAddresses returns the NodeAddresses of a particular machine instance -func (v *OVirtCloud) NodeAddresses(name string) ([]api.NodeAddress, error) { - instance, err := v.fetchInstance(name) - if err != nil { - return nil, err - } - - var address net.IP - - if instance.IPAddress != "" { - address = net.ParseIP(instance.IPAddress) - if address == nil { - return nil, fmt.Errorf("couldn't parse address: %s", instance.IPAddress) - } - } else { - resolved, err := net.LookupIP(name) - if err != nil || len(resolved) < 1 { - return nil, fmt.Errorf("couldn't lookup address: %s", name) - } - address = resolved[0] - } - - return []api.NodeAddress{{Type: api.NodeLegacyHostIP, Address: address.String()}}, nil -} - -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (v *OVirtCloud) ExternalID(name string) (string, error) { - instance, err := v.fetchInstance(name) - if err != nil { - return "", err - } - return instance.UUID, nil -} - -// InstanceID returns the cloud provider ID of the specified instance. -func (v *OVirtCloud) InstanceID(name string) (string, error) { - instance, err := v.fetchInstance(name) - if err != nil { - return "", err - } - // TODO: define a way to identify the provider instance to complete - // the format /. - return "/" + instance.UUID, err -} - -// InstanceType returns the type of the specified instance. -func (v *OVirtCloud) InstanceType(name string) (string, error) { - return "", nil -} - -func getInstancesFromXml(body io.Reader) (OVirtInstanceMap, error) { - if body == nil { - return nil, fmt.Errorf("ovirt rest-api response body is missing") - } - - content, err := ioutil.ReadAll(body) - if err != nil { - return nil, err - } - - vmlist := XmlVmsList{} - - if err := xml.Unmarshal(content, &vmlist); err != nil { - return nil, err - } - - instances := make(OVirtInstanceMap) - - for _, vm := range vmlist.Vm { - // Always return only vms that are up and running - if vm.Hostname != "" && strings.ToLower(vm.State) == "up" { - address := "" - if len(vm.Addresses) > 0 { - address = vm.Addresses[0].Address - } - - instances[vm.Hostname] = OVirtInstance{ - UUID: vm.UUID, - Name: vm.Name, - IPAddress: address, - } - } - } - - return instances, nil -} - -func (v *OVirtCloud) fetchAllInstances() (OVirtInstanceMap, error) { - response, err := http.Get(v.VmsRequest.String()) - if err != nil { - return nil, err - } - - defer response.Body.Close() - - return getInstancesFromXml(response.Body) -} - -func (v *OVirtCloud) fetchInstance(name string) (*OVirtInstance, error) { - allInstances, err := v.fetchAllInstances() - if err != nil { - return nil, err - } - - instance, found := allInstances[name] - if !found { - return nil, fmt.Errorf("cannot find instance: %s", name) - } - - return &instance, nil -} - -func (m *OVirtInstanceMap) ListSortedNames() []string { - var names []string - - for k := range *m { - names = append(names, k) - } - - sort.Strings(names) - - return names -} - -// List enumerates the set of minions instances known by the cloud provider -func (v *OVirtCloud) List(filter string) ([]string, error) { - instances, err := v.fetchAllInstances() - if err != nil { - return nil, err - } - return instances.ListSortedNames(), nil -} - -// Implementation of Instances.CurrentNodeName -func (v *OVirtCloud) CurrentNodeName(hostname string) (string, error) { - return hostname, nil -} - -func (v *OVirtCloud) AddSSHKeyToAllInstances(user string, keyData []byte) error { - return errors.New("unimplemented") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt_test.go deleted file mode 100644 index c76bde726..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt/ovirt_test.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 ovirt - -import ( - "io" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/cloudprovider" -) - -func TestOVirtCloudConfiguration(t *testing.T) { - config1 := (io.Reader)(nil) - - _, err1 := cloudprovider.GetCloudProvider("ovirt", config1) - if err1 == nil { - t.Fatalf("An error is expected when the configuration is missing") - } - - config2 := strings.NewReader("") - - _, err2 := cloudprovider.GetCloudProvider("ovirt", config2) - if err2 == nil { - t.Fatalf("An error is expected when the configuration is empty") - } - - config3 := strings.NewReader(` -[connection] - `) - - _, err3 := cloudprovider.GetCloudProvider("ovirt", config3) - if err3 == nil { - t.Fatalf("An error is expected when the uri is missing") - } - - config4 := strings.NewReader(` -[connection] -uri = https://localhost:8443/ovirt-engine/api -`) - - _, err4 := cloudprovider.GetCloudProvider("ovirt", config4) - if err4 != nil { - t.Fatalf("Unexpected error creating the provider: %s", err4) - } -} - -func TestOVirtCloudXmlParsing(t *testing.T) { - body1 := (io.Reader)(nil) - - _, err1 := getInstancesFromXml(body1) - if err1 == nil { - t.Fatalf("An error is expected when body is missing") - } - - body2 := strings.NewReader("") - - _, err2 := getInstancesFromXml(body2) - if err2 == nil { - t.Fatalf("An error is expected when body is empty") - } - - body3 := strings.NewReader(` - - - -`) - - instances3, err3 := getInstancesFromXml(body3) - if err3 != nil { - t.Fatalf("Unexpected error listing instances: %s", err3) - } - if len(instances3) > 0 { - t.Fatalf("Unexpected number of instance(s): %d", len(instances3)) - } - - body4 := strings.NewReader(` - - - Up - host1 - - - - - - Up - - - Down - host2 - - - Up - host3 - - -`) - - instances4, err4 := getInstancesFromXml(body4) - if err4 != nil { - t.Fatalf("Unexpected error listing instances: %s", err4) - } - if len(instances4) != 2 { - t.Fatalf("Unexpected number of instance(s): %d", len(instances4)) - } - - names := instances4.ListSortedNames() - if names[0] != "host1" || names[1] != "host3" { - t.Fatalf("Unexpected instance(s): %s", instances4) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/providers.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/providers.go deleted file mode 100644 index 6664e8903..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/providers.go +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cloudprovider - -import ( - // Cloud providers - _ "k8s.io/kubernetes/pkg/cloudprovider/providers/aws" - _ "k8s.io/kubernetes/pkg/cloudprovider/providers/gce" - _ "k8s.io/kubernetes/pkg/cloudprovider/providers/mesos" - _ "k8s.io/kubernetes/pkg/cloudprovider/providers/openstack" - _ "k8s.io/kubernetes/pkg/cloudprovider/providers/ovirt" - _ "k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace" -) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/MAINTAINERS.md b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/MAINTAINERS.md deleted file mode 100644 index 4c72c1a0a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/MAINTAINERS.md +++ /dev/null @@ -1,6 +0,0 @@ -# Maintainers - -* [Thom May](https://github.com/thommay) - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/pkg/cloudprovider/providers/rackspace/MAINTAINERS.md?pixel)]() diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/rackspace.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/rackspace.go deleted file mode 100644 index 35d4e1e3b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/rackspace.go +++ /dev/null @@ -1,614 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rackspace - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net" - "os" - "regexp" - "strings" - "time" - - "github.com/rackspace/gophercloud" - osvolumeattach "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach" - osservers "github.com/rackspace/gophercloud/openstack/compute/v2/servers" - "github.com/rackspace/gophercloud/pagination" - "github.com/rackspace/gophercloud/rackspace" - "github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes" - "github.com/rackspace/gophercloud/rackspace/compute/v2/servers" - "github.com/rackspace/gophercloud/rackspace/compute/v2/volumeattach" - "gopkg.in/gcfg.v1" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/cloudprovider" -) - -const ProviderName = "rackspace" -const metaDataPath = "/media/configdrive/openstack/latest/meta_data.json" - -var ErrNotFound = errors.New("Failed to find object") -var ErrMultipleResults = errors.New("Multiple results where only one expected") -var ErrNoAddressFound = errors.New("No address found for host") -var ErrAttrNotFound = errors.New("Expected attribute not found") - -// encoding.TextUnmarshaler interface for time.Duration -type MyDuration struct { - time.Duration -} - -func (d *MyDuration) UnmarshalText(text []byte) error { - res, err := time.ParseDuration(string(text)) - if err != nil { - return err - } - d.Duration = res - return nil -} - -type MetaData struct { - UUID string `json:"uuid"` - Name string `json:"name"` -} - -type LoadBalancerOpts struct { - SubnetId string `gcfg:"subnet-id"` // required - CreateMonitor bool `gcfg:"create-monitor"` - MonitorDelay MyDuration `gcfg:"monitor-delay"` - MonitorTimeout MyDuration `gcfg:"monitor-timeout"` - MonitorMaxRetries uint `gcfg:"monitor-max-retries"` -} - -// Rackspace is an implementation of cloud provider Interface for Rackspace. -type Rackspace struct { - provider *gophercloud.ProviderClient - region string - lbOpts LoadBalancerOpts -} - -type Config struct { - Global struct { - AuthUrl string `gcfg:"auth-url"` - Username string - UserId string `gcfg:"user-id"` - Password string - ApiKey string `gcfg:"api-key"` - TenantId string `gcfg:"tenant-id"` - TenantName string `gcfg:"tenant-name"` - DomainId string `gcfg:"domain-id"` - DomainName string `gcfg:"domain-name"` - Region string - } - LoadBalancer LoadBalancerOpts -} - -func probeNodeAddress(compute *gophercloud.ServiceClient, name string) (string, error) { - id, err := readInstanceID() - if err == nil { - srv, err := servers.Get(compute, id).Extract() - if err != nil { - return "", err - } - return getAddressByServer(srv) - } - - ip, err := getAddressByName(compute, name) - if err != nil { - return "", err - } - - return ip, nil -} - -func probeInstanceID(client *gophercloud.ServiceClient, name string) (string, error) { - // Attempt to read id from config drive. - id, err := readInstanceID() - if err == nil { - return id, nil - } - - // Attempt to get the server by the name from the API - server, err := getServerByName(client, name) - if err != nil { - return "", err - } - - return server.ID, nil -} - -func parseMetaData(file io.Reader) (string, error) { - metaDataBytes, err := ioutil.ReadAll(file) - if err != nil { - return "", fmt.Errorf("Cannot read %s: %v", file, err) - } - - metaData := MetaData{} - err = json.Unmarshal(metaDataBytes, &metaData) - if err != nil { - return "", fmt.Errorf("Cannot parse %s: %v", metaDataPath, err) - } - - return metaData.UUID, nil -} - -func readInstanceID() (string, error) { - file, err := os.Open(metaDataPath) - if err != nil { - return "", fmt.Errorf("Cannot open %s: %v", metaDataPath, err) - } - - return parseMetaData(file) -} - -func init() { - cloudprovider.RegisterCloudProvider(ProviderName, func(config io.Reader) (cloudprovider.Interface, error) { - cfg, err := readConfig(config) - if err != nil { - return nil, err - } - return newRackspace(cfg) - }) -} - -func (cfg Config) toAuthOptions() gophercloud.AuthOptions { - return gophercloud.AuthOptions{ - IdentityEndpoint: cfg.Global.AuthUrl, - Username: cfg.Global.Username, - UserID: cfg.Global.UserId, - Password: cfg.Global.Password, - APIKey: cfg.Global.ApiKey, - TenantID: cfg.Global.TenantId, - TenantName: cfg.Global.TenantName, - - // Persistent service, so we need to be able to renew tokens - AllowReauth: true, - } -} - -func readConfig(config io.Reader) (Config, error) { - if config == nil { - err := fmt.Errorf("no Rackspace cloud provider config file given") - return Config{}, err - } - - var cfg Config - err := gcfg.ReadInto(&cfg, config) - return cfg, err -} - -func newRackspace(cfg Config) (*Rackspace, error) { - provider, err := rackspace.AuthenticatedClient(cfg.toAuthOptions()) - if err != nil { - return nil, err - } - - os := Rackspace{ - provider: provider, - region: cfg.Global.Region, - lbOpts: cfg.LoadBalancer, - } - - return &os, nil -} - -type Instances struct { - compute *gophercloud.ServiceClient -} - -// Instances returns an implementation of Instances for Rackspace. -func (os *Rackspace) Instances() (cloudprovider.Instances, bool) { - glog.V(2).Info("rackspace.Instances() called") - - compute, err := os.getComputeClient() - if err != nil { - glog.Warningf("Failed to find compute endpoint: %v", err) - return nil, false - } - glog.V(1).Info("Claiming to support Instances") - - return &Instances{compute}, true -} - -func (i *Instances) List(name_filter string) ([]string, error) { - glog.V(2).Infof("rackspace List(%v) called", name_filter) - - opts := osservers.ListOpts{ - Name: name_filter, - Status: "ACTIVE", - } - pager := servers.List(i.compute, opts) - - ret := make([]string, 0) - err := pager.EachPage(func(page pagination.Page) (bool, error) { - sList, err := servers.ExtractServers(page) - if err != nil { - return false, err - } - for _, server := range sList { - ret = append(ret, server.Name) - } - return true, nil - }) - if err != nil { - return nil, err - } - - glog.V(2).Infof("Found %v entries: %v", len(ret), ret) - - return ret, nil -} - -func serverHasAddress(srv osservers.Server, ip string) bool { - if ip == firstAddr(srv.Addresses["private"]) { - return true - } - if ip == firstAddr(srv.Addresses["public"]) { - return true - } - if ip == srv.AccessIPv4 { - return true - } - if ip == srv.AccessIPv6 { - return true - } - return false -} - -func getServerByAddress(client *gophercloud.ServiceClient, name string) (*osservers.Server, error) { - pager := servers.List(client, nil) - - serverList := make([]osservers.Server, 0, 1) - - err := pager.EachPage(func(page pagination.Page) (bool, error) { - s, err := servers.ExtractServers(page) - if err != nil { - return false, err - } - for _, v := range s { - if serverHasAddress(v, name) { - serverList = append(serverList, v) - } - } - if len(serverList) > 1 { - return false, ErrMultipleResults - } - return true, nil - }) - if err != nil { - return nil, err - } - - if len(serverList) == 0 { - return nil, ErrNotFound - } else if len(serverList) > 1 { - return nil, ErrMultipleResults - } - - return &serverList[0], nil -} - -func getServerByName(client *gophercloud.ServiceClient, name string) (*osservers.Server, error) { - if net.ParseIP(name) != nil { - // we're an IP, so we'll have to walk the full list of servers to - // figure out which one we are. - return getServerByAddress(client, name) - } - opts := osservers.ListOpts{ - Name: fmt.Sprintf("^%s$", regexp.QuoteMeta(name)), - Status: "ACTIVE", - } - pager := servers.List(client, opts) - - serverList := make([]osservers.Server, 0, 1) - - err := pager.EachPage(func(page pagination.Page) (bool, error) { - s, err := servers.ExtractServers(page) - if err != nil { - return false, err - } - serverList = append(serverList, s...) - if len(serverList) > 1 { - return false, ErrMultipleResults - } - return true, nil - }) - if err != nil { - return nil, err - } - - if len(serverList) == 0 { - return nil, ErrNotFound - } else if len(serverList) > 1 { - return nil, ErrMultipleResults - } - - return &serverList[0], nil -} - -func firstAddr(netblob interface{}) string { - // Run-time types for the win :( - list, ok := netblob.([]interface{}) - if !ok || len(list) < 1 { - return "" - } - props, ok := list[0].(map[string]interface{}) - if !ok { - return "" - } - tmp, ok := props["addr"] - if !ok { - return "" - } - addr, ok := tmp.(string) - if !ok { - return "" - } - return addr -} - -func getAddressByServer(srv *osservers.Server) (string, error) { - var s string - if s == "" { - s = firstAddr(srv.Addresses["private"]) - } - if s == "" { - s = firstAddr(srv.Addresses["public"]) - } - if s == "" { - s = srv.AccessIPv4 - } - if s == "" { - s = srv.AccessIPv6 - } - if s == "" { - return "", ErrNoAddressFound - } - return s, nil -} - -func getAddressByName(api *gophercloud.ServiceClient, name string) (string, error) { - srv, err := getServerByName(api, name) - if err != nil { - return "", err - } - - return getAddressByServer(srv) -} - -func (i *Instances) NodeAddresses(name string) ([]api.NodeAddress, error) { - glog.V(2).Infof("NodeAddresses(%v) called", name) - - ip, err := probeNodeAddress(i.compute, name) - if err != nil { - return nil, err - } - - glog.V(2).Infof("NodeAddresses(%v) => %v", name, ip) - - // net.ParseIP().String() is to maintain compatibility with the old code - return []api.NodeAddress{{Type: api.NodeLegacyHostIP, Address: net.ParseIP(ip).String()}}, nil -} - -// ExternalID returns the cloud provider ID of the specified instance (deprecated). -func (i *Instances) ExternalID(name string) (string, error) { - return probeInstanceID(i.compute, name) -} - -// InstanceID returns the cloud provider ID of the kubelet's instance. -func (rs *Rackspace) InstanceID() (string, error) { - return readInstanceID() -} - -// InstanceID returns the cloud provider ID of the specified instance. -func (i *Instances) InstanceID(name string) (string, error) { - return probeInstanceID(i.compute, name) -} - -// InstanceType returns the type of the specified instance. -func (i *Instances) InstanceType(name string) (string, error) { - return "", nil -} - -func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error { - return errors.New("unimplemented") -} - -// Implementation of Instances.CurrentNodeName -func (i *Instances) CurrentNodeName(hostname string) (string, error) { - // Beware when changing this, nodename == hostname assumption is crucial to - // apiserver => kubelet communication. - return hostname, nil -} - -func (os *Rackspace) Clusters() (cloudprovider.Clusters, bool) { - return nil, false -} - -// ProviderName returns the cloud provider ID. -func (os *Rackspace) ProviderName() string { - return ProviderName -} - -// ScrubDNS filters DNS settings for pods. -func (os *Rackspace) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) { - return nameservers, searches -} - -func (os *Rackspace) LoadBalancer() (cloudprovider.LoadBalancer, bool) { - return nil, false -} - -func (os *Rackspace) Zones() (cloudprovider.Zones, bool) { - glog.V(1).Info("Claiming to support Zones") - - return os, true -} - -func (os *Rackspace) Routes() (cloudprovider.Routes, bool) { - return nil, false -} - -func (os *Rackspace) GetZone() (cloudprovider.Zone, error) { - glog.V(1).Infof("Current zone is %v", os.region) - - return cloudprovider.Zone{Region: os.region}, nil -} - -// Create a volume of given size (in GiB) -func (rs *Rackspace) CreateVolume(name string, size int, tags *map[string]string) (volumeName string, err error) { - return "", errors.New("unimplemented") -} - -func (rs *Rackspace) DeleteVolume(volumeName string) error { - return errors.New("unimplemented") -} - -// Attaches given cinder volume to the compute running kubelet -func (rs *Rackspace) AttachDisk(instanceID string, diskName string) (string, error) { - disk, err := rs.getVolume(diskName) - if err != nil { - return "", err - } - - compute, err := rs.getComputeClient() - if err != nil { - return "", err - } - - if len(disk.Attachments) > 0 { - if instanceID == disk.Attachments[0]["server_id"] { - glog.V(4).Infof("Disk: %q is already attached to compute: %q", diskName, instanceID) - return disk.ID, nil - } - - errMsg := fmt.Sprintf("Disk %q is attached to a different compute: %q, should be detached before proceeding", diskName, disk.Attachments[0]["server_id"]) - glog.Errorf(errMsg) - return "", errors.New(errMsg) - } - - _, err = volumeattach.Create(compute, instanceID, &osvolumeattach.CreateOpts{ - VolumeID: disk.ID, - }).Extract() - if err != nil { - glog.Errorf("Failed to attach %s volume to %s compute", diskName, instanceID) - return "", err - } - glog.V(2).Infof("Successfully attached %s volume to %s compute", diskName, instanceID) - return disk.ID, nil -} - -// GetDevicePath returns the path of an attached block storage volume, specified by its id. -func (rs *Rackspace) GetDevicePath(diskId string) string { - volume, err := rs.getVolume(diskId) - if err != nil { - return "" - } - attachments := volume.Attachments - if len(attachments) != 1 { - glog.Warningf("Unexpected number of volume attachments on %s: %d", diskId, len(attachments)) - return "" - } - return attachments[0]["device"].(string) -} - -// Takes a partial/full disk id or diskname -func (rs *Rackspace) getVolume(diskName string) (volumes.Volume, error) { - sClient, err := rackspace.NewBlockStorageV1(rs.provider, gophercloud.EndpointOpts{ - Region: rs.region, - }) - - var volume volumes.Volume - if err != nil || sClient == nil { - glog.Errorf("Unable to initialize cinder client for region: %s", rs.region) - return volume, err - } - - err = volumes.List(sClient).EachPage(func(page pagination.Page) (bool, error) { - vols, err := volumes.ExtractVolumes(page) - if err != nil { - glog.Errorf("Failed to extract volumes: %v", err) - return false, err - } - - for _, v := range vols { - glog.V(4).Infof("%s %s %v", v.ID, v.Name, v.Attachments) - if v.Name == diskName || strings.Contains(v.ID, diskName) { - volume = v - return true, nil - } - } - - // if it reached here then no disk with the given name was found. - errmsg := fmt.Sprintf("Unable to find disk: %s in region %s", diskName, rs.region) - return false, errors.New(errmsg) - }) - if err != nil { - glog.Errorf("Error occured getting volume: %s", diskName) - } - return volume, err -} - -func (rs *Rackspace) getComputeClient() (*gophercloud.ServiceClient, error) { - client, err := rackspace.NewComputeV2(rs.provider, gophercloud.EndpointOpts{ - Region: rs.region, - }) - if err != nil || client == nil { - glog.Errorf("Unable to initialize nova client for region: %s", rs.region) - } - return client, nil -} - -// Detaches given cinder volume from the compute running kubelet -func (rs *Rackspace) DetachDisk(instanceID string, partialDiskId string) error { - disk, err := rs.getVolume(partialDiskId) - if err != nil { - return err - } - - compute, err := rs.getComputeClient() - if err != nil { - return err - } - - if len(disk.Attachments) > 1 { - // Rackspace does not support "multiattach", this is a sanity check. - errmsg := fmt.Sprintf("Volume %s is attached to multiple instances, which is not supported by this provider.", disk.ID) - return errors.New(errmsg) - } - - if len(disk.Attachments) > 0 && instanceID == disk.Attachments[0]["server_id"] { - // This is a blocking call and effects kubelet's performance directly. - // We should consider kicking it out into a separate routine, if it is bad. - err = volumeattach.Delete(compute, instanceID, disk.ID).ExtractErr() - if err != nil { - glog.Errorf("Failed to delete volume %s from compute %s attached %v", disk.ID, instanceID, err) - return err - } - glog.V(2).Infof("Successfully detached volume: %s from compute: %s", disk.ID, instanceID) - } else { - errMsg := fmt.Sprintf("Disk: %s has no attachments or is not attached to compute: %s", disk.Name, instanceID) - glog.Errorf(errMsg) - return errors.New(errMsg) - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/rackspace_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/rackspace_test.go deleted file mode 100644 index 1b00b1330..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/cloudprovider/providers/rackspace/rackspace_test.go +++ /dev/null @@ -1,196 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rackspace - -import ( - "os" - "strings" - "testing" - "time" - - "github.com/rackspace/gophercloud" -) - -func TestReadConfig(t *testing.T) { - _, err := readConfig(nil) - if err == nil { - t.Errorf("Should fail when no config is provided: %s", err) - } - - cfg, err := readConfig(strings.NewReader(` -[Global] -auth-url = http://auth.url -username = user -[LoadBalancer] -create-monitor = yes -monitor-delay = 1m -monitor-timeout = 30s -monitor-max-retries = 3 -`)) - if err != nil { - t.Fatalf("Should succeed when a valid config is provided: %s", err) - } - if cfg.Global.AuthUrl != "http://auth.url" { - t.Errorf("incorrect authurl: %s", cfg.Global.AuthUrl) - } - - if !cfg.LoadBalancer.CreateMonitor { - t.Errorf("incorrect lb.createmonitor: %t", cfg.LoadBalancer.CreateMonitor) - } - if cfg.LoadBalancer.MonitorDelay.Duration != 1*time.Minute { - t.Errorf("incorrect lb.monitordelay: %s", cfg.LoadBalancer.MonitorDelay) - } - if cfg.LoadBalancer.MonitorTimeout.Duration != 30*time.Second { - t.Errorf("incorrect lb.monitortimeout: %s", cfg.LoadBalancer.MonitorTimeout) - } - if cfg.LoadBalancer.MonitorMaxRetries != 3 { - t.Errorf("incorrect lb.monitormaxretries: %d", cfg.LoadBalancer.MonitorMaxRetries) - } -} - -func TestToAuthOptions(t *testing.T) { - cfg := Config{} - cfg.Global.Username = "user" - // etc. - - ao := cfg.toAuthOptions() - - if !ao.AllowReauth { - t.Errorf("Will need to be able to reauthenticate") - } - if ao.Username != cfg.Global.Username { - t.Errorf("Username %s != %s", ao.Username, cfg.Global.Username) - } -} - -// This allows acceptance testing against an existing Rackspace -// install, using the standard OS_* Rackspace client environment -// variables. -// FIXME: it would be better to hermetically test against canned JSON -// requests/responses. -func configFromEnv() (cfg Config, ok bool) { - cfg.Global.AuthUrl = os.Getenv("OS_AUTH_URL") - - cfg.Global.TenantId = os.Getenv("OS_TENANT_ID") - // Rax/nova _insists_ that we don't specify both tenant ID and name - if cfg.Global.TenantId == "" { - cfg.Global.TenantName = os.Getenv("OS_TENANT_NAME") - } - - cfg.Global.Username = os.Getenv("OS_USERNAME") - cfg.Global.Password = os.Getenv("OS_PASSWORD") - cfg.Global.ApiKey = os.Getenv("OS_API_KEY") - cfg.Global.Region = os.Getenv("OS_REGION_NAME") - cfg.Global.DomainId = os.Getenv("OS_DOMAIN_ID") - cfg.Global.DomainName = os.Getenv("OS_DOMAIN_NAME") - - ok = (cfg.Global.AuthUrl != "" && - cfg.Global.Username != "" && - (cfg.Global.Password != "" || cfg.Global.ApiKey != "") && - (cfg.Global.TenantId != "" || cfg.Global.TenantName != "" || - cfg.Global.DomainId != "" || cfg.Global.DomainName != "")) - - return -} - -func TestParseMetaData(t *testing.T) { - _, err := parseMetaData(strings.NewReader("")) - if err == nil { - t.Errorf("Should fail when invalid meta data is provided: %s", err) - } - - id, err := parseMetaData(strings.NewReader(` - { - "UUID":"someuuid", - "name":"somename", - "project_id":"someprojectid" - } - `)) - if err != nil { - t.Fatalf("Should succeed when valid meta data is provided: %s", err) - } - if id != "someuuid" { - t.Errorf("incorrect uuid: %s", id) - } -} - -func TestNewRackspace(t *testing.T) { - cfg, ok := configFromEnv() - if !ok { - t.Skipf("No config found in environment") - } - - _, err := newRackspace(cfg) - if err != nil { - t.Fatalf("Failed to construct/authenticate Rackspace: %s", err) - } -} - -func TestInstances(t *testing.T) { - cfg, ok := configFromEnv() - if !ok { - t.Skipf("No config found in environment") - } - - os, err := newRackspace(cfg) - if err != nil { - t.Fatalf("Failed to construct/authenticate Rackspace: %s", err) - } - - i, ok := os.Instances() - if !ok { - t.Fatalf("Instances() returned false") - } - - srvs, err := i.List(".") - if err != nil { - t.Fatalf("Instances.List() failed: %s", err) - } - if len(srvs) == 0 { - t.Fatalf("Instances.List() returned zero servers") - } - t.Logf("Found servers (%d): %s\n", len(srvs), srvs) - - addrs, err := i.NodeAddresses(srvs[0]) - if err != nil { - t.Fatalf("Instances.NodeAddresses(%s) failed: %s", srvs[0], err) - } - t.Logf("Found NodeAddresses(%s) = %s\n", srvs[0], addrs) -} - -func TestZones(t *testing.T) { - os := Rackspace{ - provider: &gophercloud.ProviderClient{ - IdentityBase: "http://auth.url/", - }, - region: "myRegion", - } - - z, ok := os.Zones() - if !ok { - t.Fatalf("Zones() returned false") - } - - zone, err := z.GetZone() - if err != nil { - t.Fatalf("GetZone() returned error: %s", err) - } - - if zone.Region != "myRegion" { - t.Fatalf("GetZone() returned wrong region (%s)", zone.Region) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/controller_utils_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/controller_utils_test.go deleted file mode 100644 index 423e42703..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/controller_utils_test.go +++ /dev/null @@ -1,372 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 controller - -import ( - "fmt" - "math/rand" - "net/http/httptest" - "reflect" - "sort" - "sync" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/securitycontext" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/sets" - utiltesting "k8s.io/kubernetes/pkg/util/testing" -) - -// NewFakeControllerExpectationsLookup creates a fake store for PodExpectations. -func NewFakeControllerExpectationsLookup(ttl time.Duration) (*ControllerExpectations, *util.FakeClock) { - fakeTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) - fakeClock := util.NewFakeClock(fakeTime) - ttlPolicy := &cache.TTLPolicy{Ttl: ttl, Clock: fakeClock} - ttlStore := cache.NewFakeExpirationStore( - ExpKeyFunc, nil, ttlPolicy, fakeClock) - return &ControllerExpectations{ttlStore}, fakeClock -} - -func newReplicationController(replicas int) *api.ReplicationController { - rc := &api.ReplicationController{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Default.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - UID: util.NewUUID(), - Name: "foobar", - Namespace: api.NamespaceDefault, - ResourceVersion: "18", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: int32(replicas), - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "name": "foo", - "type": "production", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo/bar", - TerminationMessagePath: api.TerminationMessagePathDefault, - ImagePullPolicy: api.PullIfNotPresent, - SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), - }, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSDefault, - NodeSelector: map[string]string{ - "baz": "blah", - }, - }, - }, - }, - } - return rc -} - -// create count pods with the given phase for the given rc (same selectors and namespace), and add them to the store. -func newPodList(store cache.Store, count int, status api.PodPhase, rc *api.ReplicationController) *api.PodList { - pods := []api.Pod{} - for i := 0; i < count; i++ { - newPod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("pod%d", i), - Labels: rc.Spec.Selector, - Namespace: rc.Namespace, - }, - Status: api.PodStatus{Phase: status}, - } - if store != nil { - store.Add(&newPod) - } - pods = append(pods, newPod) - } - return &api.PodList{ - Items: pods, - } -} - -func TestControllerExpectations(t *testing.T) { - ttl := 30 * time.Second - e, fakeClock := NewFakeControllerExpectationsLookup(ttl) - // In practice we can't really have add and delete expectations since we only either create or - // delete replicas in one rc pass, and the rc goes to sleep soon after until the expectations are - // either fulfilled or timeout. - adds, dels := 10, 30 - rc := newReplicationController(1) - - // RC fires off adds and deletes at apiserver, then sets expectations - rcKey, err := KeyFunc(rc) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", rc, err) - } - e.SetExpectations(rcKey, adds, dels) - var wg sync.WaitGroup - for i := 0; i < adds+1; i++ { - wg.Add(1) - go func() { - // In prod this can happen either because of a failed create by the rc - // or after having observed a create via informer - e.CreationObserved(rcKey) - wg.Done() - }() - } - wg.Wait() - - // There are still delete expectations - if e.SatisfiedExpectations(rcKey) { - t.Errorf("Rc will sync before expectations are met") - } - for i := 0; i < dels+1; i++ { - wg.Add(1) - go func() { - e.DeletionObserved(rcKey) - wg.Done() - }() - } - wg.Wait() - - // Expectations have been surpassed - if podExp, exists, err := e.GetExpectations(rcKey); err == nil && exists { - add, del := podExp.GetExpectations() - if add != -1 || del != -1 { - t.Errorf("Unexpected pod expectations %#v", podExp) - } - } else { - t.Errorf("Could not get expectations for rc, exists %v and err %v", exists, err) - } - if !e.SatisfiedExpectations(rcKey) { - t.Errorf("Expectations are met but the rc will not sync") - } - - // Next round of rc sync, old expectations are cleared - e.SetExpectations(rcKey, 1, 2) - if podExp, exists, err := e.GetExpectations(rcKey); err == nil && exists { - add, del := podExp.GetExpectations() - if add != 1 || del != 2 { - t.Errorf("Unexpected pod expectations %#v", podExp) - } - } else { - t.Errorf("Could not get expectations for rc, exists %v and err %v", exists, err) - } - - // Expectations have expired because of ttl - fakeClock.Step(ttl + 1) - if !e.SatisfiedExpectations(rcKey) { - t.Errorf("Expectations should have expired but didn't") - } -} - -func TestUIDExpectations(t *testing.T) { - uidExp := NewUIDTrackingControllerExpectations(NewControllerExpectations()) - rcList := []*api.ReplicationController{ - newReplicationController(2), - newReplicationController(1), - newReplicationController(0), - newReplicationController(5), - } - rcToPods := map[string][]string{} - rcKeys := []string{} - for i := range rcList { - rc := rcList[i] - rcName := fmt.Sprintf("rc-%v", i) - rc.Name = rcName - rc.Spec.Selector[rcName] = rcName - podList := newPodList(nil, 5, api.PodRunning, rc) - rcKey, err := KeyFunc(rc) - if err != nil { - t.Fatalf("Couldn't get key for object %+v: %v", rc, err) - } - rcKeys = append(rcKeys, rcKey) - rcPodNames := []string{} - for i := range podList.Items { - p := &podList.Items[i] - p.Name = fmt.Sprintf("%v-%v", p.Name, rc.Name) - rcPodNames = append(rcPodNames, PodKey(p)) - } - rcToPods[rcKey] = rcPodNames - uidExp.ExpectDeletions(rcKey, rcPodNames) - } - for i := range rcKeys { - j := rand.Intn(i + 1) - rcKeys[i], rcKeys[j] = rcKeys[j], rcKeys[i] - } - for _, rcKey := range rcKeys { - if uidExp.SatisfiedExpectations(rcKey) { - t.Errorf("Controller %v satisfied expectations before deletion", rcKey) - } - for _, p := range rcToPods[rcKey] { - uidExp.DeletionObserved(rcKey, p) - } - if !uidExp.SatisfiedExpectations(rcKey) { - t.Errorf("Controller %v didn't satisfy expectations after deletion", rcKey) - } - uidExp.DeleteExpectations(rcKey) - if uidExp.GetUIDs(rcKey) != nil { - t.Errorf("Failed to delete uid expectations for %v", rcKey) - } - } -} - -func TestCreatePods(t *testing.T) { - ns := api.NamespaceDefault - body := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Name: "empty_pod"}}) - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: string(body), - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - - podControl := RealPodControl{ - KubeClient: clientset, - Recorder: &record.FakeRecorder{}, - } - - controllerSpec := newReplicationController(1) - - // Make sure createReplica sends a POST to the apiserver with a pod from the controllers pod template - podControl.CreatePods(ns, controllerSpec.Spec.Template, controllerSpec) - - expectedPod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: controllerSpec.Spec.Template.Labels, - GenerateName: fmt.Sprintf("%s-", controllerSpec.Name), - }, - Spec: controllerSpec.Spec.Template.Spec, - } - fakeHandler.ValidateRequest(t, testapi.Default.ResourcePath("pods", api.NamespaceDefault, ""), "POST", nil) - actualPod, err := runtime.Decode(testapi.Default.Codec(), []byte(fakeHandler.RequestBody)) - if err != nil { - t.Errorf("Unexpected error: %#v", err) - } - if !api.Semantic.DeepDerivative(&expectedPod, actualPod) { - t.Logf("Body: %s", fakeHandler.RequestBody) - t.Errorf("Unexpected mismatch. Expected\n %#v,\n Got:\n %#v", &expectedPod, actualPod) - } -} - -func TestActivePodFiltering(t *testing.T) { - // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. - rc := newReplicationController(0) - podList := newPodList(nil, 5, api.PodRunning, rc) - podList.Items[0].Status.Phase = api.PodSucceeded - podList.Items[1].Status.Phase = api.PodFailed - expectedNames := sets.NewString() - for _, pod := range podList.Items[2:] { - expectedNames.Insert(pod.Name) - } - - got := FilterActivePods(podList.Items) - gotNames := sets.NewString() - for _, pod := range got { - gotNames.Insert(pod.Name) - } - if expectedNames.Difference(gotNames).Len() != 0 || gotNames.Difference(expectedNames).Len() != 0 { - t.Errorf("expected %v, got %v", expectedNames.List(), gotNames.List()) - } -} - -func TestSortingActivePods(t *testing.T) { - numPods := 9 - // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. - rc := newReplicationController(0) - podList := newPodList(nil, numPods, api.PodRunning, rc) - - pods := make([]*api.Pod, len(podList.Items)) - for i := range podList.Items { - pods[i] = &podList.Items[i] - } - // pods[0] is not scheduled yet. - pods[0].Spec.NodeName = "" - pods[0].Status.Phase = api.PodPending - // pods[1] is scheduled but pending. - pods[1].Spec.NodeName = "bar" - pods[1].Status.Phase = api.PodPending - // pods[2] is unknown. - pods[2].Spec.NodeName = "foo" - pods[2].Status.Phase = api.PodUnknown - // pods[3] is running but not ready. - pods[3].Spec.NodeName = "foo" - pods[3].Status.Phase = api.PodRunning - // pods[4] is running and ready but without LastTransitionTime. - now := unversioned.Now() - pods[4].Spec.NodeName = "foo" - pods[4].Status.Phase = api.PodRunning - pods[4].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue}} - pods[4].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} - // pods[5] is running and ready and with LastTransitionTime. - pods[5].Spec.NodeName = "foo" - pods[5].Status.Phase = api.PodRunning - pods[5].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: now}} - pods[5].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} - // pods[6] is running ready for a longer time than pods[5]. - then := unversioned.Time{Time: now.AddDate(0, -1, 0)} - pods[6].Spec.NodeName = "foo" - pods[6].Status.Phase = api.PodRunning - pods[6].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: then}} - pods[6].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 3}, {RestartCount: 0}} - // pods[7] has lower container restart count than pods[6]. - pods[7].Spec.NodeName = "foo" - pods[7].Status.Phase = api.PodRunning - pods[7].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: then}} - pods[7].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}} - pods[7].CreationTimestamp = now - // pods[8] is older than pods[7]. - pods[8].Spec.NodeName = "foo" - pods[8].Status.Phase = api.PodRunning - pods[8].Status.Conditions = []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue, LastTransitionTime: then}} - pods[8].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 2}, {RestartCount: 1}} - pods[8].CreationTimestamp = then - - getOrder := func(pods []*api.Pod) []string { - names := make([]string, len(pods)) - for i := range pods { - names[i] = pods[i].Name - } - return names - } - - expected := getOrder(pods) - - for i := 0; i < 20; i++ { - idx := rand.Perm(numPods) - randomizedPods := make([]*api.Pod, numPods) - for j := 0; j < numPods; j++ { - randomizedPods[j] = pods[idx[j]] - } - sort.Sort(ActivePods(randomizedPods)) - actual := getOrder(randomizedPods) - - if !reflect.DeepEqual(actual, expected) { - t.Errorf("expected %v, got %v", expected, actual) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/controller.go deleted file mode 100644 index 0066fd086..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/controller.go +++ /dev/null @@ -1,742 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 daemon - -import ( - "reflect" - "sort" - "sync" - "time" - - "fmt" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - unversionedextensions "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/controller/framework/informers" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/validation/field" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" - "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/predicates" -) - -const ( - // Daemon sets will periodically check that their daemon pods are running as expected. - FullDaemonSetResyncPeriod = 30 * time.Second // TODO: Figure out if this time seems reasonable. - - // Realistic value of the burstReplica field for the replication manager based off - // performance requirements for kubernetes 1.0. - BurstReplicas = 500 - - // We must avoid counting pods until the pod store has synced. If it hasn't synced, to - // avoid a hot loop, we'll wait this long between checks. - PodStoreSyncedPollPeriod = 100 * time.Millisecond - - // If sending a status upate to API server fails, we retry a finite number of times. - StatusUpdateRetries = 1 -) - -// DaemonSetsController is responsible for synchronizing DaemonSet objects stored -// in the system with actual running pods. -type DaemonSetsController struct { - kubeClient clientset.Interface - eventRecorder record.EventRecorder - podControl controller.PodControlInterface - - // internalPodInformer is used to hold a personal informer. If we're using - // a normal shared informer, then the informer will be started for us. If - // we have a personal informer, we must start it ourselves. If you start - // the controller using NewDaemonSetsController(passing SharedInformer), this - // will be null - internalPodInformer framework.SharedInformer - - // An dsc is temporarily suspended after creating/deleting these many replicas. - // It resumes normal action after observing the watch events for them. - burstReplicas int - - // To allow injection of syncDaemonSet for testing. - syncHandler func(dsKey string) error - // A TTLCache of pod creates/deletes each ds expects to see - expectations controller.ControllerExpectationsInterface - // A store of daemon sets - dsStore cache.StoreToDaemonSetLister - // A store of pods - podStore cache.StoreToPodLister - // A store of nodes - nodeStore cache.StoreToNodeLister - // Watches changes to all daemon sets. - dsController *framework.Controller - // Watches changes to all pods - podController framework.ControllerInterface - // Watches changes to all nodes. - nodeController *framework.Controller - // podStoreSynced returns true if the pod store has been synced at least once. - // Added as a member to the struct to allow injection for testing. - podStoreSynced func() bool - - lookupCache *controller.MatchingCache - - // Daemon sets that need to be synced. - queue *workqueue.Type -} - -func NewDaemonSetsController(podInformer framework.SharedIndexInformer, kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, lookupCacheSize int) *DaemonSetsController { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. - eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) - - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("daemon_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - dsc := &DaemonSetsController{ - kubeClient: kubeClient, - eventRecorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "daemonset-controller"}), - podControl: controller.RealPodControl{ - KubeClient: kubeClient, - Recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "daemon-set"}), - }, - burstReplicas: BurstReplicas, - expectations: controller.NewControllerExpectations(), - queue: workqueue.New(), - } - // Manage addition/update of daemon sets. - dsc.dsStore.Store, dsc.dsController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return dsc.kubeClient.Extensions().DaemonSets(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return dsc.kubeClient.Extensions().DaemonSets(api.NamespaceAll).Watch(options) - }, - }, - &extensions.DaemonSet{}, - // TODO: Can we have much longer period here? - FullDaemonSetResyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - ds := obj.(*extensions.DaemonSet) - glog.V(4).Infof("Adding daemon set %s", ds.Name) - dsc.enqueueDaemonSet(ds) - }, - UpdateFunc: func(old, cur interface{}) { - oldDS := old.(*extensions.DaemonSet) - curDS := cur.(*extensions.DaemonSet) - // We should invalidate the whole lookup cache if a DS's selector has been updated. - // - // Imagine that you have two RSs: - // * old DS1 - // * new DS2 - // You also have a pod that is attached to DS2 (because it doesn't match DS1 selector). - // Now imagine that you are changing DS1 selector so that it is now matching that pod, - // in such case we must invalidate the whole cache so that pod could be adopted by DS1 - // - // This makes the lookup cache less helpful, but selector update does not happen often, - // so it's not a big problem - if !reflect.DeepEqual(oldDS.Spec.Selector, curDS.Spec.Selector) { - dsc.lookupCache.InvalidateAll() - } - - glog.V(4).Infof("Updating daemon set %s", oldDS.Name) - dsc.enqueueDaemonSet(curDS) - }, - DeleteFunc: func(obj interface{}) { - ds := obj.(*extensions.DaemonSet) - glog.V(4).Infof("Deleting daemon set %s", ds.Name) - dsc.enqueueDaemonSet(ds) - }, - }, - ) - - // Watch for creation/deletion of pods. The reason we watch is that we don't want a daemon set to create/delete - // more pods until all the effects (expectations) of a daemon set's create/delete have been observed. - podInformer.AddEventHandler(framework.ResourceEventHandlerFuncs{ - AddFunc: dsc.addPod, - UpdateFunc: dsc.updatePod, - DeleteFunc: dsc.deletePod, - }) - dsc.podStore.Indexer = podInformer.GetIndexer() - dsc.podController = podInformer.GetController() - dsc.podStoreSynced = podInformer.HasSynced - - // Watch for new nodes or updates to nodes - daemon pods are launched on new nodes, and possibly when labels on nodes change, - dsc.nodeStore.Store, dsc.nodeController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return dsc.kubeClient.Core().Nodes().List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return dsc.kubeClient.Core().Nodes().Watch(options) - }, - }, - &api.Node{}, - resyncPeriod(), - framework.ResourceEventHandlerFuncs{ - AddFunc: dsc.addNode, - UpdateFunc: dsc.updateNode, - }, - ) - dsc.syncHandler = dsc.syncDaemonSet - dsc.lookupCache = controller.NewMatchingCache(lookupCacheSize) - return dsc -} - -func NewDaemonSetsControllerFromClient(kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, lookupCacheSize int) *DaemonSetsController { - podInformer := informers.CreateSharedPodIndexInformer(kubeClient, resyncPeriod()) - dsc := NewDaemonSetsController(podInformer, kubeClient, resyncPeriod, lookupCacheSize) - dsc.internalPodInformer = podInformer - - return dsc -} - -// Run begins watching and syncing daemon sets. -func (dsc *DaemonSetsController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - glog.Infof("Starting Daemon Sets controller manager") - go dsc.dsController.Run(stopCh) - go dsc.podController.Run(stopCh) - go dsc.nodeController.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(dsc.worker, time.Second, stopCh) - } - - if dsc.internalPodInformer != nil { - go dsc.internalPodInformer.Run(stopCh) - } - - <-stopCh - glog.Infof("Shutting down Daemon Set Controller") - dsc.queue.ShutDown() -} - -func (dsc *DaemonSetsController) worker() { - for { - func() { - dsKey, quit := dsc.queue.Get() - if quit { - return - } - defer dsc.queue.Done(dsKey) - err := dsc.syncHandler(dsKey.(string)) - if err != nil { - glog.Errorf("Error syncing daemon set with key %s: %v", dsKey.(string), err) - } - }() - } -} - -func (dsc *DaemonSetsController) enqueueAllDaemonSets() { - glog.V(4).Infof("Enqueueing all daemon sets") - ds, err := dsc.dsStore.List() - if err != nil { - glog.Errorf("Error enqueueing daemon sets: %v", err) - return - } - for i := range ds.Items { - dsc.enqueueDaemonSet(&ds.Items[i]) - } -} - -func (dsc *DaemonSetsController) enqueueDaemonSet(ds *extensions.DaemonSet) { - key, err := controller.KeyFunc(ds) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", ds, err) - return - } - - // TODO: Handle overlapping controllers better. See comment in ReplicationManager. - dsc.queue.Add(key) -} - -func (dsc *DaemonSetsController) getPodDaemonSet(pod *api.Pod) *extensions.DaemonSet { - // look up in the cache, if cached and the cache is valid, just return cached value - if obj, cached := dsc.lookupCache.GetMatchingObject(pod); cached { - ds, ok := obj.(*extensions.DaemonSet) - if !ok { - // This should not happen - glog.Errorf("lookup cache does not retuen a ReplicationController object") - return nil - } - if cached && dsc.isCacheValid(pod, ds) { - return ds - } - } - sets, err := dsc.dsStore.GetPodDaemonSets(pod) - if err != nil { - glog.V(4).Infof("No daemon sets found for pod %v, daemon set controller will avoid syncing", pod.Name) - return nil - } - if len(sets) > 1 { - // More than two items in this list indicates user error. If two daemon - // sets overlap, sort by creation timestamp, subsort by name, then pick - // the first. - glog.Errorf("user error! more than one daemon is selecting pods with labels: %+v", pod.Labels) - sort.Sort(byCreationTimestamp(sets)) - } - - // update lookup cache - dsc.lookupCache.Update(pod, &sets[0]) - - return &sets[0] -} - -// isCacheValid check if the cache is valid -func (dsc *DaemonSetsController) isCacheValid(pod *api.Pod, cachedDS *extensions.DaemonSet) bool { - _, exists, err := dsc.dsStore.Get(cachedDS) - // ds has been deleted or updated, cache is invalid - if err != nil || !exists || !isDaemonSetMatch(pod, cachedDS) { - return false - } - return true -} - -// isDaemonSetMatch take a Pod and DaemonSet, return whether the Pod and DaemonSet are matching -// TODO(mqliang): This logic is a copy from GetPodDaemonSets(), remove the duplication -func isDaemonSetMatch(pod *api.Pod, ds *extensions.DaemonSet) bool { - if ds.Namespace != pod.Namespace { - return false - } - selector, err := unversioned.LabelSelectorAsSelector(ds.Spec.Selector) - if err != nil { - err = fmt.Errorf("invalid selector: %v", err) - return false - } - - // If a ReplicaSet with a nil or empty selector creeps in, it should match nothing, not everything. - if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { - return false - } - return true -} - -func (dsc *DaemonSetsController) addPod(obj interface{}) { - pod := obj.(*api.Pod) - glog.V(4).Infof("Pod %s added.", pod.Name) - if ds := dsc.getPodDaemonSet(pod); ds != nil { - dsKey, err := controller.KeyFunc(ds) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", ds, err) - return - } - dsc.expectations.CreationObserved(dsKey) - dsc.enqueueDaemonSet(ds) - } -} - -// When a pod is updated, figure out what sets manage it and wake them -// up. If the labels of the pod have changed we need to awaken both the old -// and new set. old and cur must be *api.Pod types. -func (dsc *DaemonSetsController) updatePod(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - // A periodic relist will send update events for all known pods. - return - } - curPod := cur.(*api.Pod) - glog.V(4).Infof("Pod %s updated.", curPod.Name) - if curDS := dsc.getPodDaemonSet(curPod); curDS != nil { - dsc.enqueueDaemonSet(curDS) - } - oldPod := old.(*api.Pod) - // If the labels have not changed, then the daemon set responsible for - // the pod is the same as it was before. In that case we have enqueued the daemon - // set above, and do not have to enqueue the set again. - if !reflect.DeepEqual(curPod.Labels, oldPod.Labels) { - // It's ok if both oldDS and curDS are the same, because curDS will set - // the expectations on its run so oldDS will have no effect. - if oldDS := dsc.getPodDaemonSet(oldPod); oldDS != nil { - dsc.enqueueDaemonSet(oldDS) - } - } -} - -func (dsc *DaemonSetsController) deletePod(obj interface{}) { - pod, ok := obj.(*api.Pod) - // When a delete is dropped, the relist will notice a pod in the store not - // in the list, leading to the insertion of a tombstone object which contains - // the deleted key/value. Note that this value might be stale. If the pod - // changed labels the new daemonset will not be woken up till the periodic - // resync. - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("Couldn't get object from tombstone %+v", obj) - return - } - pod, ok = tombstone.Obj.(*api.Pod) - if !ok { - glog.Errorf("Tombstone contained object that is not a pod %+v", obj) - return - } - } - glog.V(4).Infof("Pod %s deleted.", pod.Name) - if ds := dsc.getPodDaemonSet(pod); ds != nil { - dsKey, err := controller.KeyFunc(ds) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", ds, err) - return - } - dsc.expectations.DeletionObserved(dsKey) - dsc.enqueueDaemonSet(ds) - } -} - -func (dsc *DaemonSetsController) addNode(obj interface{}) { - // TODO: it'd be nice to pass a hint with these enqueues, so that each ds would only examine the added node (unless it has other work to do, too). - dsList, err := dsc.dsStore.List() - if err != nil { - glog.V(4).Infof("Error enqueueing daemon sets: %v", err) - return - } - node := obj.(*api.Node) - for i := range dsList.Items { - ds := &dsList.Items[i] - shouldEnqueue := dsc.nodeShouldRunDaemonPod(node, ds) - if shouldEnqueue { - dsc.enqueueDaemonSet(ds) - } - } -} - -func (dsc *DaemonSetsController) updateNode(old, cur interface{}) { - oldNode := old.(*api.Node) - curNode := cur.(*api.Node) - if api.Semantic.DeepEqual(oldNode.Name, curNode.Name) && api.Semantic.DeepEqual(oldNode.Namespace, curNode.Namespace) && api.Semantic.DeepEqual(oldNode.Labels, curNode.Labels) { - // A periodic relist will send update events for all known pods. - return - } - dsList, err := dsc.dsStore.List() - if err != nil { - glog.V(4).Infof("Error enqueueing daemon sets: %v", err) - return - } - for i := range dsList.Items { - ds := &dsList.Items[i] - shouldEnqueue := (dsc.nodeShouldRunDaemonPod(oldNode, ds) != dsc.nodeShouldRunDaemonPod(curNode, ds)) - if shouldEnqueue { - dsc.enqueueDaemonSet(ds) - } - } - // TODO: it'd be nice to pass a hint with these enqueues, so that each ds would only examine the added node (unless it has other work to do, too). -} - -// getNodesToDaemonSetPods returns a map from nodes to daemon pods (corresponding to ds) running on the nodes. -func (dsc *DaemonSetsController) getNodesToDaemonPods(ds *extensions.DaemonSet) (map[string][]*api.Pod, error) { - nodeToDaemonPods := make(map[string][]*api.Pod) - selector, err := unversioned.LabelSelectorAsSelector(ds.Spec.Selector) - if err != nil { - return nil, err - } - daemonPods, err := dsc.podStore.Pods(ds.Namespace).List(selector) - if err != nil { - return nodeToDaemonPods, err - } - for i := range daemonPods.Items { - nodeName := daemonPods.Items[i].Spec.NodeName - nodeToDaemonPods[nodeName] = append(nodeToDaemonPods[nodeName], &daemonPods.Items[i]) - } - return nodeToDaemonPods, nil -} - -func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) { - // Find out which nodes are running the daemon pods selected by ds. - nodeToDaemonPods, err := dsc.getNodesToDaemonPods(ds) - if err != nil { - glog.Errorf("Error getting node to daemon pod mapping for daemon set %+v: %v", ds, err) - } - - // For each node, if the node is running the daemon pod but isn't supposed to, kill the daemon - // pod. If the node is supposed to run the daemon pod, but isn't, create the daemon pod on the node. - nodeList, err := dsc.nodeStore.List() - if err != nil { - glog.Errorf("Couldn't get list of nodes when syncing daemon set %+v: %v", ds, err) - } - var nodesNeedingDaemonPods, podsToDelete []string - for _, node := range nodeList.Items { - shouldRun := dsc.nodeShouldRunDaemonPod(&node, ds) - - daemonPods, isRunning := nodeToDaemonPods[node.Name] - - if shouldRun && !isRunning { - // If daemon pod is supposed to be running on node, but isn't, create daemon pod. - nodesNeedingDaemonPods = append(nodesNeedingDaemonPods, node.Name) - } else if shouldRun && len(daemonPods) > 1 { - // If daemon pod is supposed to be running on node, but more than 1 daemon pod is running, delete the excess daemon pods. - // Sort the daemon pods by creation time, so the the oldest is preserved. - sort.Sort(podByCreationTimestamp(daemonPods)) - for i := 1; i < len(daemonPods); i++ { - podsToDelete = append(podsToDelete, daemonPods[i].Name) - } - } else if !shouldRun && isRunning { - // If daemon pod isn't supposed to run on node, but it is, delete all daemon pods on node. - for i := range daemonPods { - podsToDelete = append(podsToDelete, daemonPods[i].Name) - } - } - } - - // We need to set expectations before creating/deleting pods to avoid race conditions. - dsKey, err := controller.KeyFunc(ds) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", ds, err) - return - } - - createDiff := len(nodesNeedingDaemonPods) - deleteDiff := len(podsToDelete) - - if createDiff > dsc.burstReplicas { - createDiff = dsc.burstReplicas - } - if deleteDiff > dsc.burstReplicas { - deleteDiff = dsc.burstReplicas - } - - dsc.expectations.SetExpectations(dsKey, createDiff, deleteDiff) - - glog.V(4).Infof("Nodes needing daemon pods for daemon set %s: %+v, creating %d", ds.Name, nodesNeedingDaemonPods, createDiff) - createWait := sync.WaitGroup{} - createWait.Add(createDiff) - for i := 0; i < createDiff; i++ { - go func(ix int) { - defer createWait.Done() - if err := dsc.podControl.CreatePodsOnNode(nodesNeedingDaemonPods[ix], ds.Namespace, &ds.Spec.Template, ds); err != nil { - glog.V(2).Infof("Failed creation, decrementing expectations for set %q/%q", ds.Namespace, ds.Name) - dsc.expectations.CreationObserved(dsKey) - utilruntime.HandleError(err) - } - }(i) - } - createWait.Wait() - - glog.V(4).Infof("Pods to delete for daemon set %s: %+v, deleting %d", ds.Name, podsToDelete, deleteDiff) - deleteWait := sync.WaitGroup{} - deleteWait.Add(deleteDiff) - for i := 0; i < deleteDiff; i++ { - go func(ix int) { - defer deleteWait.Done() - if err := dsc.podControl.DeletePod(ds.Namespace, podsToDelete[ix], ds); err != nil { - glog.V(2).Infof("Failed deletion, decrementing expectations for set %q/%q", ds.Namespace, ds.Name) - dsc.expectations.DeletionObserved(dsKey) - utilruntime.HandleError(err) - } - }(i) - } - deleteWait.Wait() -} - -func storeDaemonSetStatus(dsClient unversionedextensions.DaemonSetInterface, ds *extensions.DaemonSet, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled int) error { - if int(ds.Status.DesiredNumberScheduled) == desiredNumberScheduled && int(ds.Status.CurrentNumberScheduled) == currentNumberScheduled && int(ds.Status.NumberMisscheduled) == numberMisscheduled { - return nil - } - - var updateErr, getErr error - for i := 0; i <= StatusUpdateRetries; i++ { - ds.Status.DesiredNumberScheduled = int32(desiredNumberScheduled) - ds.Status.CurrentNumberScheduled = int32(currentNumberScheduled) - ds.Status.NumberMisscheduled = int32(numberMisscheduled) - - _, updateErr = dsClient.UpdateStatus(ds) - if updateErr == nil { - // successful update - return nil - } - // Update the set with the latest resource version for the next poll - if ds, getErr = dsClient.Get(ds.Name); getErr != nil { - // If the GET fails we can't trust status.Replicas anymore. This error - // is bound to be more interesting than the update failure. - return getErr - } - } - return updateErr -} - -func (dsc *DaemonSetsController) updateDaemonSetStatus(ds *extensions.DaemonSet) { - glog.V(4).Infof("Updating daemon set status") - nodeToDaemonPods, err := dsc.getNodesToDaemonPods(ds) - if err != nil { - glog.Errorf("Error getting node to daemon pod mapping for daemon set %+v: %v", ds, err) - } - - nodeList, err := dsc.nodeStore.List() - if err != nil { - glog.Errorf("Couldn't get list of nodes when updating daemon set %+v: %v", ds, err) - } - - var desiredNumberScheduled, currentNumberScheduled, numberMisscheduled int - for _, node := range nodeList.Items { - shouldRun := dsc.nodeShouldRunDaemonPod(&node, ds) - - numDaemonPods := len(nodeToDaemonPods[node.Name]) - - if shouldRun && numDaemonPods > 0 { - currentNumberScheduled++ - } - - if shouldRun { - desiredNumberScheduled++ - } - - if !shouldRun && numDaemonPods > 0 { - numberMisscheduled++ - } - } - - err = storeDaemonSetStatus(dsc.kubeClient.Extensions().DaemonSets(ds.Namespace), ds, desiredNumberScheduled, currentNumberScheduled, numberMisscheduled) - if err != nil { - glog.Errorf("Error storing status for daemon set %+v: %v", ds, err) - } -} - -func (dsc *DaemonSetsController) syncDaemonSet(key string) error { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing daemon set %q (%v)", key, time.Now().Sub(startTime)) - }() - - if !dsc.podStoreSynced() { - // Sleep so we give the pod reflector goroutine a chance to run. - time.Sleep(PodStoreSyncedPollPeriod) - glog.Infof("Waiting for pods controller to sync, requeuing ds %v", key) - dsc.queue.Add(key) - return nil - } - - obj, exists, err := dsc.dsStore.Store.GetByKey(key) - if err != nil { - glog.Infof("Unable to retrieve ds %v from store: %v", key, err) - dsc.queue.Add(key) - return err - } - if !exists { - glog.V(3).Infof("daemon set has been deleted %v", key) - dsc.expectations.DeleteExpectations(key) - return nil - } - ds := obj.(*extensions.DaemonSet) - - everything := unversioned.LabelSelector{} - if reflect.DeepEqual(ds.Spec.Selector, &everything) { - dsc.eventRecorder.Eventf(ds, api.EventTypeWarning, "SelectingAll", "This daemon set is selecting all pods. A non-empty selector is required.") - return nil - } - - // Don't process a daemon set until all its creations and deletions have been processed. - // For example if daemon set foo asked for 3 new daemon pods in the previous call to manage, - // then we do not want to call manage on foo until the daemon pods have been created. - dsKey, err := controller.KeyFunc(ds) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", ds, err) - return err - } - dsNeedsSync := dsc.expectations.SatisfiedExpectations(dsKey) - if dsNeedsSync { - dsc.manage(ds) - } - - dsc.updateDaemonSetStatus(ds) - return nil -} - -func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *api.Node, ds *extensions.DaemonSet) bool { - // Check if the node satisfies the daemon set's node selector. - nodeSelector := labels.Set(ds.Spec.Template.Spec.NodeSelector).AsSelector() - if !nodeSelector.Matches(labels.Set(node.Labels)) { - return false - } - // If the daemon set specifies a node name, check that it matches with node.Name. - if !(ds.Spec.Template.Spec.NodeName == "" || ds.Spec.Template.Spec.NodeName == node.Name) { - return false - } - - for _, c := range node.Status.Conditions { - if c.Type == api.NodeOutOfDisk && c.Status == api.ConditionTrue { - return false - } - } - - newPod := &api.Pod{Spec: ds.Spec.Template.Spec} - newPod.Spec.NodeName = node.Name - pods := []*api.Pod{newPod} - - for _, m := range dsc.podStore.Indexer.List() { - pod := m.(*api.Pod) - if pod.Spec.NodeName != node.Name { - continue - } - if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed { - continue - } - // ignore pods that belong to the daemonset when taking into account wheter - // a daemonset should bind to a node. - if pds := dsc.getPodDaemonSet(pod); pds != nil && ds.Name == pds.Name { - continue - } - pods = append(pods, pod) - } - _, notFittingCPU, notFittingMemory := predicates.CheckPodsExceedingFreeResources(pods, node.Status.Allocatable) - if len(notFittingCPU)+len(notFittingMemory) != 0 { - dsc.eventRecorder.Eventf(ds, api.EventTypeNormal, "FailedPlacement", "failed to place pod on %q: insufficent free resources", node.ObjectMeta.Name) - return false - } - ports := sets.String{} - for _, pod := range pods { - if errs := validation.AccumulateUniqueHostPorts(pod.Spec.Containers, &ports, field.NewPath("spec", "containers")); len(errs) > 0 { - dsc.eventRecorder.Eventf(ds, api.EventTypeNormal, "FailedPlacement", "failed to place pod on %q: host port conflict", node.ObjectMeta.Name) - return false - } - } - return true -} - -// byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker. -type byCreationTimestamp []extensions.DaemonSet - -func (o byCreationTimestamp) Len() int { return len(o) } -func (o byCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o byCreationTimestamp) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} - -type podByCreationTimestamp []*api.Pod - -func (o podByCreationTimestamp) Len() int { return len(o) } -func (o podByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o podByCreationTimestamp) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/controller_test.go deleted file mode 100644 index d47545dff..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/controller_test.go +++ /dev/null @@ -1,551 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 daemon - -import ( - "fmt" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/securitycontext" -) - -var ( - simpleDaemonSetLabel = map[string]string{"name": "simple-daemon", "type": "production"} - simpleDaemonSetLabel2 = map[string]string{"name": "simple-daemon", "type": "test"} - simpleNodeLabel = map[string]string{"color": "blue", "speed": "fast"} - simpleNodeLabel2 = map[string]string{"color": "red", "speed": "fast"} - alwaysReady = func() bool { return true } -) - -func getKey(ds *extensions.DaemonSet, t *testing.T) string { - if key, err := controller.KeyFunc(ds); err != nil { - t.Errorf("Unexpected error getting key for ds %v: %v", ds.Name, err) - return "" - } else { - return key - } -} - -func newDaemonSet(name string) *extensions.DaemonSet { - return &extensions.DaemonSet{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Extensions.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: api.NamespaceDefault, - }, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: simpleDaemonSetLabel}, - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: simpleDaemonSetLabel, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo/bar", - TerminationMessagePath: api.TerminationMessagePathDefault, - ImagePullPolicy: api.PullIfNotPresent, - SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), - }, - }, - DNSPolicy: api.DNSDefault, - }, - }, - }, - } -} - -func newNode(name string, label map[string]string) *api.Node { - return &api.Node{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Default.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - Name: name, - Labels: label, - Namespace: api.NamespaceDefault, - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - {Type: api.NodeReady, Status: api.ConditionTrue}, - }, - }, - } -} - -func addNodes(nodeStore cache.Store, startIndex, numNodes int, label map[string]string) { - for i := startIndex; i < startIndex+numNodes; i++ { - nodeStore.Add(newNode(fmt.Sprintf("node-%d", i), label)) - } -} - -func newPod(podName string, nodeName string, label map[string]string) *api.Pod { - pod := &api.Pod{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Default.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - GenerateName: podName, - Labels: label, - Namespace: api.NamespaceDefault, - }, - Spec: api.PodSpec{ - NodeName: nodeName, - Containers: []api.Container{ - { - Image: "foo/bar", - TerminationMessagePath: api.TerminationMessagePathDefault, - ImagePullPolicy: api.PullIfNotPresent, - SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), - }, - }, - DNSPolicy: api.DNSDefault, - }, - } - api.GenerateName(api.SimpleNameGenerator, &pod.ObjectMeta) - return pod -} - -func addPods(podStore cache.Store, nodeName string, label map[string]string, number int) { - for i := 0; i < number; i++ { - podStore.Add(newPod(fmt.Sprintf("%s-", nodeName), nodeName, label)) - } -} - -func newTestController() (*DaemonSetsController, *controller.FakePodControl) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewDaemonSetsControllerFromClient(clientset, controller.NoResyncPeriodFunc, 0) - manager.podStoreSynced = alwaysReady - podControl := &controller.FakePodControl{} - manager.podControl = podControl - return manager, podControl -} - -func validateSyncDaemonSets(t *testing.T, fakePodControl *controller.FakePodControl, expectedCreates, expectedDeletes int) { - if len(fakePodControl.Templates) != expectedCreates { - t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", expectedCreates, len(fakePodControl.Templates)) - } - if len(fakePodControl.DeletePodName) != expectedDeletes { - t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", expectedDeletes, len(fakePodControl.DeletePodName)) - } -} - -func syncAndValidateDaemonSets(t *testing.T, manager *DaemonSetsController, ds *extensions.DaemonSet, podControl *controller.FakePodControl, expectedCreates, expectedDeletes int) { - key, err := controller.KeyFunc(ds) - if err != nil { - t.Errorf("Could not get key for daemon.") - } - manager.syncHandler(key) - validateSyncDaemonSets(t, podControl, expectedCreates, expectedDeletes) -} - -// DaemonSets without node selectors should launch pods on every node. -func TestSimpleDaemonSetLaunchesPods(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 5, nil) - ds := newDaemonSet("foo") - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 5, 0) -} - -// DaemonSets should do nothing if there aren't any nodes -func TestNoNodesDoesNothing(t *testing.T) { - manager, podControl := newTestController() - ds := newDaemonSet("foo") - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -// DaemonSets without node selectors should launch on a single node in a -// single node cluster. -func TestOneNodeDaemonLaunchesPod(t *testing.T) { - manager, podControl := newTestController() - manager.nodeStore.Add(newNode("only-node", nil)) - ds := newDaemonSet("foo") - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} - -// DaemonSets should place onto NotReady nodes -func TestNotReadNodeDaemonDoesNotLaunchPod(t *testing.T) { - manager, podControl := newTestController() - node := newNode("not-ready", nil) - node.Status = api.NodeStatus{ - Conditions: []api.NodeCondition{ - {Type: api.NodeReady, Status: api.ConditionFalse}, - }, - } - manager.nodeStore.Add(node) - ds := newDaemonSet("foo") - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} - -// DaemonSets should not place onto OutOfDisk nodes -func TestOutOfDiskNodeDaemonDoesNotLaunchPod(t *testing.T) { - manager, podControl := newTestController() - node := newNode("not-enough-disk", nil) - node.Status.Conditions = []api.NodeCondition{{Type: api.NodeOutOfDisk, Status: api.ConditionTrue}} - manager.nodeStore.Add(node) - ds := newDaemonSet("foo") - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -// DaemonSets should not place onto nodes with insufficient free resource -func TestInsufficentCapacityNodeDaemonDoesNotLaunchPod(t *testing.T) { - podSpec := api.PodSpec{ - NodeName: "too-much-mem", - Containers: []api.Container{{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceMemory: resource.MustParse("75M"), - api.ResourceCPU: resource.MustParse("75m"), - }, - }, - }}, - } - manager, podControl := newTestController() - node := newNode("too-much-mem", nil) - node.Status.Allocatable = api.ResourceList{ - api.ResourceMemory: resource.MustParse("100M"), - api.ResourceCPU: resource.MustParse("200m"), - } - manager.nodeStore.Add(node) - manager.podStore.Add(&api.Pod{ - Spec: podSpec, - }) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec = podSpec - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -func TestSufficentCapacityWithTerminatedPodsDaemonLaunchesPod(t *testing.T) { - podSpec := api.PodSpec{ - NodeName: "too-much-mem", - Containers: []api.Container{{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceMemory: resource.MustParse("75M"), - api.ResourceCPU: resource.MustParse("75m"), - }, - }, - }}, - } - manager, podControl := newTestController() - node := newNode("too-much-mem", nil) - node.Status.Allocatable = api.ResourceList{ - api.ResourceMemory: resource.MustParse("100M"), - api.ResourceCPU: resource.MustParse("200m"), - } - manager.nodeStore.Add(node) - manager.podStore.Add(&api.Pod{ - Spec: podSpec, - Status: api.PodStatus{Phase: api.PodSucceeded}, - }) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec = podSpec - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} - -// DaemonSets should place onto nodes with sufficient free resource -func TestSufficentCapacityNodeDaemonLaunchesPod(t *testing.T) { - podSpec := api.PodSpec{ - NodeName: "not-too-much-mem", - Containers: []api.Container{{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceMemory: resource.MustParse("75M"), - api.ResourceCPU: resource.MustParse("75m"), - }, - }, - }}, - } - manager, podControl := newTestController() - node := newNode("not-too-much-mem", nil) - node.Status.Allocatable = api.ResourceList{ - api.ResourceMemory: resource.MustParse("200M"), - api.ResourceCPU: resource.MustParse("200m"), - } - manager.nodeStore.Add(node) - manager.podStore.Add(&api.Pod{ - Spec: podSpec, - }) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec = podSpec - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} - -// DaemonSets should not place onto nodes that would cause port conflicts -func TestPortConflictNodeDaemonDoesNotLaunchPod(t *testing.T) { - podSpec := api.PodSpec{ - NodeName: "port-conflict", - Containers: []api.Container{{ - Ports: []api.ContainerPort{{ - HostPort: 666, - }}, - }}, - } - manager, podControl := newTestController() - node := newNode("port-conflict", nil) - manager.nodeStore.Add(node) - manager.podStore.Add(&api.Pod{ - Spec: podSpec, - }) - - ds := newDaemonSet("foo") - ds.Spec.Template.Spec = podSpec - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -// Test that if the node is already scheduled with a pod using a host port -// but belonging to the same daemonset, we don't delete that pod -// -// Issue: https://github.com/kubernetes/kubernetes/issues/22309 -func TestPortConflictWithSameDaemonPodDoesNotDeletePod(t *testing.T) { - podSpec := api.PodSpec{ - NodeName: "port-conflict", - Containers: []api.Container{{ - Ports: []api.ContainerPort{{ - HostPort: 666, - }}, - }}, - } - manager, podControl := newTestController() - node := newNode("port-conflict", nil) - manager.nodeStore.Add(node) - manager.podStore.Add(&api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: simpleDaemonSetLabel, - Namespace: api.NamespaceDefault, - }, - Spec: podSpec, - }) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec = podSpec - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -// DaemonSets should place onto nodes that would not cause port conflicts -func TestNoPortConflictNodeDaemonLaunchesPod(t *testing.T) { - podSpec1 := api.PodSpec{ - NodeName: "no-port-conflict", - Containers: []api.Container{{ - Ports: []api.ContainerPort{{ - HostPort: 6661, - }}, - }}, - } - podSpec2 := api.PodSpec{ - NodeName: "no-port-conflict", - Containers: []api.Container{{ - Ports: []api.ContainerPort{{ - HostPort: 6662, - }}, - }}, - } - manager, podControl := newTestController() - node := newNode("no-port-conflict", nil) - manager.nodeStore.Add(node) - manager.podStore.Add(&api.Pod{ - Spec: podSpec1, - }) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec = podSpec2 - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} - -// DaemonSetController should not sync DaemonSets with empty pod selectors. -// -// issue https://github.com/kubernetes/kubernetes/pull/23223 -func TestPodIsNotDeletedByDaemonsetWithEmptyLabelSelector(t *testing.T) { - manager, podControl := newTestController() - manager.nodeStore.Store.Add(newNode("node1", nil)) - // Create pod not controlled by a daemonset. - manager.podStore.Add(&api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"bang": "boom"}, - Namespace: api.NamespaceDefault, - }, - Spec: api.PodSpec{ - NodeName: "node1", - }, - }) - - // Create a misconfigured DaemonSet. An empty pod selector is invalid but could happen - // if we upgrade and make a backwards incompatible change. - // - // The node selector matches no nodes which mimics the behavior of kubectl delete. - // - // The DaemonSet should not schedule pods and should not delete scheduled pods in - // this case even though it's empty pod selector matches all pods. The DaemonSetController - // should detect this misconfiguration and choose not to sync the DaemonSet. We should - // not observe a deletion of the pod on node1. - ds := newDaemonSet("foo") - ls := unversioned.LabelSelector{} - ds.Spec.Selector = &ls - ds.Spec.Template.Spec.NodeSelector = map[string]string{"foo": "bar"} - manager.dsStore.Add(ds) - - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -// Controller should not create pods on nodes which have daemon pods, and should remove excess pods from nodes that have extra pods. -func TestDealsWithExistingPods(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 5, nil) - addPods(manager.podStore.Indexer, "node-1", simpleDaemonSetLabel, 1) - addPods(manager.podStore.Indexer, "node-2", simpleDaemonSetLabel, 2) - addPods(manager.podStore.Indexer, "node-3", simpleDaemonSetLabel, 5) - addPods(manager.podStore.Indexer, "node-4", simpleDaemonSetLabel2, 2) - ds := newDaemonSet("foo") - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 2, 5) -} - -// Daemon with node selector should launch pods on nodes matching selector. -func TestSelectorDaemonLaunchesPods(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 4, nil) - addNodes(manager.nodeStore.Store, 4, 3, simpleNodeLabel) - daemon := newDaemonSet("foo") - daemon.Spec.Template.Spec.NodeSelector = simpleNodeLabel - manager.dsStore.Add(daemon) - syncAndValidateDaemonSets(t, manager, daemon, podControl, 3, 0) -} - -// Daemon with node selector should delete pods from nodes that do not satisfy selector. -func TestSelectorDaemonDeletesUnselectedPods(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 5, nil) - addNodes(manager.nodeStore.Store, 5, 5, simpleNodeLabel) - addPods(manager.podStore.Indexer, "node-0", simpleDaemonSetLabel2, 2) - addPods(manager.podStore.Indexer, "node-1", simpleDaemonSetLabel, 3) - addPods(manager.podStore.Indexer, "node-1", simpleDaemonSetLabel2, 1) - addPods(manager.podStore.Indexer, "node-4", simpleDaemonSetLabel, 1) - daemon := newDaemonSet("foo") - daemon.Spec.Template.Spec.NodeSelector = simpleNodeLabel - manager.dsStore.Add(daemon) - syncAndValidateDaemonSets(t, manager, daemon, podControl, 5, 4) -} - -// DaemonSet with node selector should launch pods on nodes matching selector, but also deal with existing pods on nodes. -func TestSelectorDaemonDealsWithExistingPods(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 5, nil) - addNodes(manager.nodeStore.Store, 5, 5, simpleNodeLabel) - addPods(manager.podStore.Indexer, "node-0", simpleDaemonSetLabel, 1) - addPods(manager.podStore.Indexer, "node-1", simpleDaemonSetLabel, 3) - addPods(manager.podStore.Indexer, "node-1", simpleDaemonSetLabel2, 2) - addPods(manager.podStore.Indexer, "node-2", simpleDaemonSetLabel, 4) - addPods(manager.podStore.Indexer, "node-6", simpleDaemonSetLabel, 13) - addPods(manager.podStore.Indexer, "node-7", simpleDaemonSetLabel2, 4) - addPods(manager.podStore.Indexer, "node-9", simpleDaemonSetLabel, 1) - addPods(manager.podStore.Indexer, "node-9", simpleDaemonSetLabel2, 1) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 3, 20) -} - -// DaemonSet with node selector which does not match any node labels should not launch pods. -func TestBadSelectorDaemonDoesNothing(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 4, nil) - addNodes(manager.nodeStore.Store, 4, 3, simpleNodeLabel) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel2 - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -// DaemonSet with node name should launch pod on node with corresponding name. -func TestNameDaemonSetLaunchesPods(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 5, nil) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec.NodeName = "node-0" - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} - -// DaemonSet with node name that does not exist should not launch pods. -func TestBadNameDaemonSetDoesNothing(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 5, nil) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec.NodeName = "node-10" - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -// DaemonSet with node selector, and node name, matching a node, should launch a pod on the node. -func TestNameAndSelectorDaemonSetLaunchesPods(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 4, nil) - addNodes(manager.nodeStore.Store, 4, 3, simpleNodeLabel) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel - ds.Spec.Template.Spec.NodeName = "node-6" - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} - -// DaemonSet with node selector that matches some nodes, and node name that matches a different node, should do nothing. -func TestInconsistentNameSelectorDaemonSetDoesNothing(t *testing.T) { - manager, podControl := newTestController() - addNodes(manager.nodeStore.Store, 0, 4, nil) - addNodes(manager.nodeStore.Store, 4, 3, simpleNodeLabel) - ds := newDaemonSet("foo") - ds.Spec.Template.Spec.NodeSelector = simpleNodeLabel - ds.Spec.Template.Spec.NodeName = "node-0" - manager.dsStore.Add(ds) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) -} - -func TestDSManagerNotReady(t *testing.T) { - manager, podControl := newTestController() - manager.podStoreSynced = func() bool { return false } - addNodes(manager.nodeStore.Store, 0, 1, nil) - - // Simulates the ds reflector running before the pod reflector. We don't - // want to end up creating daemon pods in this case until the pod reflector - // has synced, so the ds manager should just requeue the ds. - ds := newDaemonSet("foo") - manager.dsStore.Add(ds) - - dsKey := getKey(ds, t) - syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) - queueDS, _ := manager.queue.Get() - if queueDS != dsKey { - t.Fatalf("Expected to find key %v in queue, found %v", dsKey, queueDS) - } - - manager.podStoreSynced = alwaysReady - syncAndValidateDaemonSets(t, manager, ds, podControl, 1, 0) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/doc.go deleted file mode 100644 index db689ac1b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/daemon/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 daemon contains logic for watching and synchronizing -// daemons. -package daemon diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller.go deleted file mode 100644 index 2897583fd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller.go +++ /dev/null @@ -1,1296 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 deployment - -import ( - "fmt" - "reflect" - "sort" - "strconv" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/runtime" - deploymentutil "k8s.io/kubernetes/pkg/util/deployment" - utilerrors "k8s.io/kubernetes/pkg/util/errors" - "k8s.io/kubernetes/pkg/util/integer" - labelsutil "k8s.io/kubernetes/pkg/util/labels" - "k8s.io/kubernetes/pkg/util/metrics" - podutil "k8s.io/kubernetes/pkg/util/pod" - rsutil "k8s.io/kubernetes/pkg/util/replicaset" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" -) - -const ( - // FullDeploymentResyncPeriod means we'll attempt to recompute the required replicas - // of all deployments. - // This recomputation happens based on contents in the local caches. - FullDeploymentResyncPeriod = 30 * time.Second - // We must avoid creating new replica set / counting pods until the replica set / pods store has synced. - // If it hasn't synced, to avoid a hot loop, we'll wait this long between checks. - StoreSyncedPollPeriod = 100 * time.Millisecond -) - -// DeploymentController is responsible for synchronizing Deployment objects stored -// in the system with actual running replica sets and pods. -type DeploymentController struct { - client clientset.Interface - eventRecorder record.EventRecorder - - // To allow injection of syncDeployment for testing. - syncHandler func(dKey string) error - - // A store of deployments, populated by the dController - dStore cache.StoreToDeploymentLister - // Watches changes to all deployments - dController *framework.Controller - // A store of ReplicaSets, populated by the rsController - rsStore cache.StoreToReplicaSetLister - // Watches changes to all ReplicaSets - rsController *framework.Controller - // rsStoreSynced returns true if the ReplicaSet store has been synced at least once. - // Added as a member to the struct to allow injection for testing. - rsStoreSynced func() bool - // A store of pods, populated by the podController - podStore cache.StoreToPodLister - // Watches changes to all pods - podController *framework.Controller - // podStoreSynced returns true if the pod store has been synced at least once. - // Added as a member to the struct to allow injection for testing. - podStoreSynced func() bool - - // Deployments that need to be synced - queue *workqueue.Type -} - -// NewDeploymentController creates a new DeploymentController. -func NewDeploymentController(client clientset.Interface, resyncPeriod controller.ResyncPeriodFunc) *DeploymentController { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. - eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: client.Core().Events("")}) - - if client != nil && client.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("deployment_controller", client.Core().GetRESTClient().GetRateLimiter()) - } - dc := &DeploymentController{ - client: client, - eventRecorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "deployment-controller"}), - queue: workqueue.New(), - } - - dc.dStore.Store, dc.dController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return dc.client.Extensions().Deployments(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return dc.client.Extensions().Deployments(api.NamespaceAll).Watch(options) - }, - }, - &extensions.Deployment{}, - FullDeploymentResyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: dc.addDeploymentNotification, - UpdateFunc: dc.updateDeploymentNotification, - // This will enter the sync loop and no-op, because the deployment has been deleted from the store. - DeleteFunc: dc.deleteDeploymentNotification, - }, - ) - - dc.rsStore.Store, dc.rsController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return dc.client.Extensions().ReplicaSets(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return dc.client.Extensions().ReplicaSets(api.NamespaceAll).Watch(options) - }, - }, - &extensions.ReplicaSet{}, - resyncPeriod(), - framework.ResourceEventHandlerFuncs{ - AddFunc: dc.addReplicaSet, - UpdateFunc: dc.updateReplicaSet, - DeleteFunc: dc.deleteReplicaSet, - }, - ) - - dc.podStore.Indexer, dc.podController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return dc.client.Core().Pods(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return dc.client.Core().Pods(api.NamespaceAll).Watch(options) - }, - }, - &api.Pod{}, - resyncPeriod(), - framework.ResourceEventHandlerFuncs{ - AddFunc: dc.addPod, - UpdateFunc: dc.updatePod, - DeleteFunc: dc.deletePod, - }, - cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, - ) - - dc.syncHandler = dc.syncDeployment - dc.rsStoreSynced = dc.rsController.HasSynced - dc.podStoreSynced = dc.podController.HasSynced - return dc -} - -// Run begins watching and syncing. -func (dc *DeploymentController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - go dc.dController.Run(stopCh) - go dc.rsController.Run(stopCh) - go dc.podController.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(dc.worker, time.Second, stopCh) - } - <-stopCh - glog.Infof("Shutting down deployment controller") - dc.queue.ShutDown() -} - -func (dc *DeploymentController) addDeploymentNotification(obj interface{}) { - d := obj.(*extensions.Deployment) - glog.V(4).Infof("Adding deployment %s", d.Name) - dc.enqueueDeployment(d) -} - -func (dc *DeploymentController) updateDeploymentNotification(old, cur interface{}) { - oldD := old.(*extensions.Deployment) - glog.V(4).Infof("Updating deployment %s", oldD.Name) - // Resync on deployment object relist. - dc.enqueueDeployment(cur.(*extensions.Deployment)) -} - -func (dc *DeploymentController) deleteDeploymentNotification(obj interface{}) { - d, ok := obj.(*extensions.Deployment) - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("Couldn't get object from tombstone %+v", obj) - return - } - d, ok = tombstone.Obj.(*extensions.Deployment) - if !ok { - glog.Errorf("Tombstone contained object that is not a Deployment %+v", obj) - return - } - } - glog.V(4).Infof("Deleting deployment %s", d.Name) - dc.enqueueDeployment(d) -} - -// addReplicaSet enqueues the deployment that manages a ReplicaSet when the ReplicaSet is created. -func (dc *DeploymentController) addReplicaSet(obj interface{}) { - rs := obj.(*extensions.ReplicaSet) - glog.V(4).Infof("ReplicaSet %s added.", rs.Name) - if d := dc.getDeploymentForReplicaSet(rs); d != nil { - dc.enqueueDeployment(d) - } -} - -// getDeploymentForReplicaSet returns the deployment managing the given ReplicaSet. -// TODO: Surface that we are ignoring multiple deployments for a given ReplicaSet. -func (dc *DeploymentController) getDeploymentForReplicaSet(rs *extensions.ReplicaSet) *extensions.Deployment { - deployments, err := dc.dStore.GetDeploymentsForReplicaSet(rs) - if err != nil || len(deployments) == 0 { - glog.V(4).Infof("Error: %v. No deployment found for ReplicaSet %v, deployment controller will avoid syncing.", err, rs.Name) - return nil - } - // Because all ReplicaSet's belonging to a deployment should have a unique label key, - // there should never be more than one deployment returned by the above method. - // If that happens we should probably dynamically repair the situation by ultimately - // trying to clean up one of the controllers, for now we just return one of the two, - // likely randomly. - return &deployments[0] -} - -// updateReplicaSet figures out what deployment(s) manage a ReplicaSet when the ReplicaSet -// is updated and wake them up. If the anything of the ReplicaSets have changed, we need to -// awaken both the old and new deployments. old and cur must be *extensions.ReplicaSet -// types. -func (dc *DeploymentController) updateReplicaSet(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - // A periodic relist will send update events for all known controllers. - return - } - // TODO: Write a unittest for this case - curRS := cur.(*extensions.ReplicaSet) - glog.V(4).Infof("ReplicaSet %s updated.", curRS.Name) - if d := dc.getDeploymentForReplicaSet(curRS); d != nil { - dc.enqueueDeployment(d) - } - // A number of things could affect the old deployment: labels changing, - // pod template changing, etc. - oldRS := old.(*extensions.ReplicaSet) - if !api.Semantic.DeepEqual(oldRS, curRS) { - if oldD := dc.getDeploymentForReplicaSet(oldRS); oldD != nil { - dc.enqueueDeployment(oldD) - } - } -} - -// deleteReplicaSet enqueues the deployment that manages a ReplicaSet when -// the ReplicaSet is deleted. obj could be an *extensions.ReplicaSet, or -// a DeletionFinalStateUnknown marker item. -func (dc *DeploymentController) deleteReplicaSet(obj interface{}) { - rs, ok := obj.(*extensions.ReplicaSet) - - // When a delete is dropped, the relist will notice a pod in the store not - // in the list, leading to the insertion of a tombstone object which contains - // the deleted key/value. Note that this value might be stale. If the ReplicaSet - // changed labels the new deployment will not be woken up till the periodic resync. - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("Couldn't get object from tombstone %+v, could take up to %v before a deployment recreates/updates replicasets", obj, FullDeploymentResyncPeriod) - return - } - rs, ok = tombstone.Obj.(*extensions.ReplicaSet) - if !ok { - glog.Errorf("Tombstone contained object that is not a ReplicaSet %+v, could take up to %v before a deployment recreates/updates replicasets", obj, FullDeploymentResyncPeriod) - return - } - } - glog.V(4).Infof("ReplicaSet %s deleted.", rs.Name) - if d := dc.getDeploymentForReplicaSet(rs); d != nil { - dc.enqueueDeployment(d) - } -} - -// getDeploymentForPod returns the deployment managing the ReplicaSet that manages the given Pod. -// TODO: Surface that we are ignoring multiple deployments for a given Pod. -func (dc *DeploymentController) getDeploymentForPod(pod *api.Pod) *extensions.Deployment { - rss, err := dc.rsStore.GetPodReplicaSets(pod) - if err != nil { - glog.V(4).Infof("Error: %v. No ReplicaSets found for pod %v, deployment controller will avoid syncing.", err, pod.Name) - return nil - } - for _, rs := range rss { - deployments, err := dc.dStore.GetDeploymentsForReplicaSet(&rs) - if err == nil && len(deployments) > 0 { - return &deployments[0] - } - } - glog.V(4).Infof("No deployments found for pod %v, deployment controller will avoid syncing.", pod.Name) - return nil -} - -// When a pod is created, ensure its controller syncs -func (dc *DeploymentController) addPod(obj interface{}) { - pod, ok := obj.(*api.Pod) - if !ok { - return - } - glog.V(4).Infof("Pod %s created: %+v.", pod.Name, pod) - if d := dc.getDeploymentForPod(pod); d != nil { - dc.enqueueDeployment(d) - } -} - -// updatePod figures out what deployment(s) manage the ReplicaSet that manages the Pod when the Pod -// is updated and wake them up. If anything of the Pods have changed, we need to awaken both -// the old and new deployments. old and cur must be *api.Pod types. -func (dc *DeploymentController) updatePod(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - return - } - curPod := cur.(*api.Pod) - oldPod := old.(*api.Pod) - glog.V(4).Infof("Pod %s updated %+v -> %+v.", curPod.Name, oldPod, curPod) - if d := dc.getDeploymentForPod(curPod); d != nil { - dc.enqueueDeployment(d) - } - if !api.Semantic.DeepEqual(oldPod, curPod) { - if oldD := dc.getDeploymentForPod(oldPod); oldD != nil { - dc.enqueueDeployment(oldD) - } - } -} - -// When a pod is deleted, ensure its controller syncs. -// obj could be an *api.Pod, or a DeletionFinalStateUnknown marker item. -func (dc *DeploymentController) deletePod(obj interface{}) { - pod, ok := obj.(*api.Pod) - // When a delete is dropped, the relist will notice a pod in the store not - // in the list, leading to the insertion of a tombstone object which contains - // the deleted key/value. Note that this value might be stale. If the pod - // changed labels the new ReplicaSet will not be woken up till the periodic - // resync. - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("Couldn't get object from tombstone %+v", obj) - return - } - pod, ok = tombstone.Obj.(*api.Pod) - if !ok { - glog.Errorf("Tombstone contained object that is not a pod %+v", obj) - return - } - } - glog.V(4).Infof("Pod %s deleted: %+v.", pod.Name, pod) - if d := dc.getDeploymentForPod(pod); d != nil { - dc.enqueueDeployment(d) - } -} - -func (dc *DeploymentController) enqueueDeployment(deployment *extensions.Deployment) { - key, err := controller.KeyFunc(deployment) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", deployment, err) - return - } - - // TODO: Handle overlapping deployments better. Either disallow them at admission time or - // deterministically avoid syncing deployments that fight over ReplicaSet's. Currently, we - // only ensure that the same deployment is synced for a given ReplicaSet. When we - // periodically relist all deployments there will still be some ReplicaSet instability. One - // way to handle this is by querying the store for all deployments that this deployment - // overlaps, as well as all deployments that overlap this deployments, and sorting them. - dc.queue.Add(key) -} - -// worker runs a worker thread that just dequeues items, processes them, and marks them done. -// It enforces that the syncHandler is never invoked concurrently with the same key. -func (dc *DeploymentController) worker() { - for { - func() { - key, quit := dc.queue.Get() - if quit { - return - } - defer dc.queue.Done(key) - err := dc.syncHandler(key.(string)) - if err != nil { - glog.Errorf("Error syncing deployment %v: %v", key, err) - } - }() - } -} - -// syncDeployment will sync the deployment with the given key. -// This function is not meant to be invoked concurrently with the same key. -func (dc *DeploymentController) syncDeployment(key string) error { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing deployment %q (%v)", key, time.Now().Sub(startTime)) - }() - - if !dc.rsStoreSynced() || !dc.podStoreSynced() { - // Sleep so we give the replica set / pod reflector goroutine a chance to run. - time.Sleep(StoreSyncedPollPeriod) - glog.Infof("Waiting for replica set / pod controller to sync, requeuing deployment %s", key) - dc.queue.Add(key) - return nil - } - - obj, exists, err := dc.dStore.Store.GetByKey(key) - if err != nil { - glog.Infof("Unable to retrieve deployment %v from store: %v", key, err) - dc.queue.Add(key) - return err - } - if !exists { - glog.Infof("Deployment has been deleted %v", key) - return nil - } - - d := obj.(*extensions.Deployment) - everything := unversioned.LabelSelector{} - if reflect.DeepEqual(d.Spec.Selector, &everything) { - dc.eventRecorder.Eventf(d, api.EventTypeWarning, "SelectingAll", "This deployment is selecting all pods. A non-empty selector is required.") - return nil - } - - if d.Spec.Paused { - // TODO: Implement scaling for paused deployments. - // Don't take any action for paused deployment. - // But keep the status up-to-date. - // Ignore paused deployments - glog.V(4).Infof("Updating status only for paused deployment %s/%s", d.Namespace, d.Name) - return dc.syncPausedDeploymentStatus(d) - } - if d.Spec.RollbackTo != nil { - revision := d.Spec.RollbackTo.Revision - if _, err = dc.rollback(d, &revision); err != nil { - return err - } - } - - switch d.Spec.Strategy.Type { - case extensions.RecreateDeploymentStrategyType: - return dc.syncRecreateDeployment(d) - case extensions.RollingUpdateDeploymentStrategyType: - return dc.syncRollingUpdateDeployment(d) - } - return fmt.Errorf("unexpected deployment strategy type: %s", d.Spec.Strategy.Type) -} - -// Updates the status of a paused deployment -func (dc *DeploymentController) syncPausedDeploymentStatus(deployment *extensions.Deployment) error { - newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(deployment, false) - if err != nil { - return err - } - allRSs := append(controller.FilterActiveReplicaSets(oldRSs), newRS) - - // Sync deployment status - return dc.syncDeploymentStatus(allRSs, newRS, deployment) -} - -// Rolling back to a revision; no-op if the toRevision is deployment's current revision -func (dc *DeploymentController) rollback(deployment *extensions.Deployment, toRevision *int64) (*extensions.Deployment, error) { - newRS, allOldRSs, err := dc.getAllReplicaSetsAndSyncRevision(deployment, true) - if err != nil { - return nil, err - } - allRSs := append(allOldRSs, newRS) - // If rollback revision is 0, rollback to the last revision - if *toRevision == 0 { - if *toRevision = lastRevision(allRSs); *toRevision == 0 { - // If we still can't find the last revision, gives up rollback - dc.emitRollbackWarningEvent(deployment, deploymentutil.RollbackRevisionNotFound, "Unable to find last revision.") - // Gives up rollback - return dc.updateDeploymentAndClearRollbackTo(deployment) - } - } - for _, rs := range allRSs { - v, err := deploymentutil.Revision(rs) - if err != nil { - glog.V(4).Infof("Unable to extract revision from deployment's replica set %q: %v", rs.Name, err) - continue - } - if v == *toRevision { - glog.V(4).Infof("Found replica set %q with desired revision %d", rs.Name, v) - // rollback by copying podTemplate.Spec from the replica set, and increment revision number by 1 - // no-op if the the spec matches current deployment's podTemplate.Spec - deployment, performedRollback, err := dc.rollbackToTemplate(deployment, rs) - if performedRollback && err == nil { - dc.emitRollbackNormalEvent(deployment, fmt.Sprintf("Rolled back deployment %q to revision %d", deployment.Name, *toRevision)) - } - return deployment, err - } - } - dc.emitRollbackWarningEvent(deployment, deploymentutil.RollbackRevisionNotFound, "Unable to find the revision to rollback to.") - // Gives up rollback - return dc.updateDeploymentAndClearRollbackTo(deployment) -} - -func (dc *DeploymentController) emitRollbackWarningEvent(deployment *extensions.Deployment, reason, message string) { - dc.eventRecorder.Eventf(deployment, api.EventTypeWarning, reason, message) -} - -func (dc *DeploymentController) emitRollbackNormalEvent(deployment *extensions.Deployment, message string) { - dc.eventRecorder.Eventf(deployment, api.EventTypeNormal, deploymentutil.RollbackDone, message) -} - -// updateDeploymentAndClearRollbackTo sets .spec.rollbackTo to nil and update the input deployment -func (dc *DeploymentController) updateDeploymentAndClearRollbackTo(deployment *extensions.Deployment) (*extensions.Deployment, error) { - glog.V(4).Infof("Cleans up rollbackTo of deployment %s", deployment.Name) - deployment.Spec.RollbackTo = nil - return dc.updateDeployment(deployment) -} - -func (dc *DeploymentController) syncRecreateDeployment(deployment *extensions.Deployment) error { - // Don't create a new RS if not already existed, so that we avoid scaling up before scaling down - newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(deployment, false) - if err != nil { - return err - } - allRSs := append(controller.FilterActiveReplicaSets(oldRSs), newRS) - - // scale down old replica sets - scaledDown, err := dc.scaleDownOldReplicaSetsForRecreate(controller.FilterActiveReplicaSets(oldRSs), deployment) - if err != nil { - return err - } - if scaledDown { - // Update DeploymentStatus - return dc.updateDeploymentStatus(allRSs, newRS, deployment) - } - - // If we need to create a new RS, create it now - // TODO: Create a new RS without re-listing all RSs. - if newRS == nil { - newRS, oldRSs, err = dc.getAllReplicaSetsAndSyncRevision(deployment, true) - if err != nil { - return err - } - allRSs = append(oldRSs, newRS) - } - - // scale up new replica set - scaledUp, err := dc.scaleUpNewReplicaSetForRecreate(newRS, deployment) - if err != nil { - return err - } - if scaledUp { - // Update DeploymentStatus - return dc.updateDeploymentStatus(allRSs, newRS, deployment) - } - - if deployment.Spec.RevisionHistoryLimit != nil { - // Cleanup old replica sets - dc.cleanupOldReplicaSets(oldRSs, deployment) - } - - // Sync deployment status - return dc.syncDeploymentStatus(allRSs, newRS, deployment) -} - -func (dc *DeploymentController) syncRollingUpdateDeployment(deployment *extensions.Deployment) error { - newRS, oldRSs, err := dc.getAllReplicaSetsAndSyncRevision(deployment, true) - if err != nil { - return err - } - allRSs := append(controller.FilterActiveReplicaSets(oldRSs), newRS) - - // Scale up, if we can. - scaledUp, err := dc.reconcileNewReplicaSet(allRSs, newRS, deployment) - if err != nil { - return err - } - if scaledUp { - // Update DeploymentStatus - return dc.updateDeploymentStatus(allRSs, newRS, deployment) - } - - // Scale down, if we can. - scaledDown, err := dc.reconcileOldReplicaSets(allRSs, controller.FilterActiveReplicaSets(oldRSs), newRS, deployment) - if err != nil { - return err - } - if scaledDown { - // Update DeploymentStatus - return dc.updateDeploymentStatus(allRSs, newRS, deployment) - } - - if deployment.Spec.RevisionHistoryLimit != nil { - // Cleanup old replicas sets - dc.cleanupOldReplicaSets(oldRSs, deployment) - } - - // Sync deployment status - return dc.syncDeploymentStatus(allRSs, newRS, deployment) -} - -// syncDeploymentStatus checks if the status is up-to-date and sync it if necessary -func (dc *DeploymentController) syncDeploymentStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, d *extensions.Deployment) error { - totalActualReplicas, updatedReplicas, availableReplicas, _, err := dc.calculateStatus(allRSs, newRS, d) - if err != nil { - return err - } - if d.Generation > d.Status.ObservedGeneration || d.Status.Replicas != totalActualReplicas || d.Status.UpdatedReplicas != updatedReplicas || d.Status.AvailableReplicas != availableReplicas { - return dc.updateDeploymentStatus(allRSs, newRS, d) - } - return nil -} - -// getAllReplicaSetsAndSyncRevision returns all the replica sets for the provided deployment (new and all old), with new RS's and deployment's revision updated. -// 1. Get all old RSes this deployment targets, and calculate the max revision number among them (maxOldV). -// 2. Get new RS this deployment targets (whose pod template matches deployment's), and update new RS's revision number to (maxOldV + 1), -// only if its revision number is smaller than (maxOldV + 1). If this step failed, we'll update it in the next deployment sync loop. -// 3. Copy new RS's revision number to deployment (update deployment's revision). If this step failed, we'll update it in the next deployment sync loop. -func (dc *DeploymentController) getAllReplicaSetsAndSyncRevision(deployment *extensions.Deployment, createIfNotExisted bool) (*extensions.ReplicaSet, []*extensions.ReplicaSet, error) { - _, allOldRSs, err := dc.getOldReplicaSets(deployment) - if err != nil { - return nil, nil, err - } - - // Calculate the max revision number among all old RSes - maxOldV := maxRevision(allOldRSs) - - // Get new replica set with the updated revision number - newRS, err := dc.getNewReplicaSet(deployment, maxOldV, allOldRSs, createIfNotExisted) - if err != nil { - return nil, nil, err - } - - // Sync deployment's revision number with new replica set - if newRS != nil && newRS.Annotations != nil && len(newRS.Annotations[deploymentutil.RevisionAnnotation]) > 0 && - (deployment.Annotations == nil || deployment.Annotations[deploymentutil.RevisionAnnotation] != newRS.Annotations[deploymentutil.RevisionAnnotation]) { - if err = dc.updateDeploymentRevision(deployment, newRS.Annotations[deploymentutil.RevisionAnnotation]); err != nil { - glog.V(4).Infof("Error: %v. Unable to update deployment revision, will retry later.", err) - } - } - - return newRS, allOldRSs, nil -} - -func maxRevision(allRSs []*extensions.ReplicaSet) int64 { - max := int64(0) - for _, rs := range allRSs { - if v, err := deploymentutil.Revision(rs); err != nil { - // Skip the replica sets when it failed to parse their revision information - glog.V(4).Infof("Error: %v. Couldn't parse revision for replica set %#v, deployment controller will skip it when reconciling revisions.", err, rs) - } else if v > max { - max = v - } - } - return max -} - -// lastRevision finds the second max revision number in all replica sets (the last revision) -func lastRevision(allRSs []*extensions.ReplicaSet) int64 { - max, secMax := int64(0), int64(0) - for _, rs := range allRSs { - if v, err := deploymentutil.Revision(rs); err != nil { - // Skip the replica sets when it failed to parse their revision information - glog.V(4).Infof("Error: %v. Couldn't parse revision for replica set %#v, deployment controller will skip it when reconciling revisions.", err, rs) - } else if v >= max { - secMax = max - max = v - } else if v > secMax { - secMax = v - } - } - return secMax -} - -// getOldReplicaSets returns two sets of old replica sets of the deployment. The first set of old replica sets doesn't include -// the ones with no pods, and the second set of old replica sets include all old replica sets. -// Note that the pod-template-hash will be added to adopted RSes and pods. -func (dc *DeploymentController) getOldReplicaSets(deployment *extensions.Deployment) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, error) { - // List the deployment's RSes & Pods and apply pod-template-hash info to deployment's adopted RSes/Pods - rsList, podList, err := dc.rsAndPodsWithHashKeySynced(deployment) - if err != nil { - return nil, nil, fmt.Errorf("error labeling replica sets and pods with pod-template-hash: %v", err) - } - return deploymentutil.FindOldReplicaSets(deployment, rsList, podList) -} - -// Returns a replica set that matches the intent of the given deployment. Returns nil if the new replica set doesn't exist yet. -// 1. Get existing new RS (the RS that the given deployment targets, whose pod template is the same as deployment's). -// 2. If there's existing new RS, update its revision number if it's smaller than (maxOldRevision + 1), where maxOldRevision is the max revision number among all old RSes. -// 3. If there's no existing new RS and createIfNotExisted is true, create one with appropriate revision number (maxOldRevision + 1) and replicas. -// Note that the pod-template-hash will be added to adopted RSes and pods. -func (dc *DeploymentController) getNewReplicaSet(deployment *extensions.Deployment, maxOldRevision int64, oldRSs []*extensions.ReplicaSet, createIfNotExisted bool) (*extensions.ReplicaSet, error) { - // Calculate revision number for this new replica set - newRevision := strconv.FormatInt(maxOldRevision+1, 10) - - // List the deployment's RSes and apply pod-template-hash info to deployment's adopted RSes/Pods - rsList, _, err := dc.rsAndPodsWithHashKeySynced(deployment) - if err != nil { - return nil, fmt.Errorf("error labeling replica sets and pods with pod-template-hash: %v", err) - } - existingNewRS, err := deploymentutil.FindNewReplicaSet(deployment, rsList) - if err != nil { - return nil, err - } else if existingNewRS != nil { - // Set existing new replica set's annotation - if setNewReplicaSetAnnotations(deployment, existingNewRS, newRevision) { - return dc.client.Extensions().ReplicaSets(deployment.ObjectMeta.Namespace).Update(existingNewRS) - } - return existingNewRS, nil - } - - if !createIfNotExisted { - return nil, nil - } - - // new ReplicaSet does not exist, create one. - namespace := deployment.ObjectMeta.Namespace - podTemplateSpecHash := podutil.GetPodTemplateSpecHash(deployment.Spec.Template) - newRSTemplate := deploymentutil.GetNewReplicaSetTemplate(deployment) - // Add podTemplateHash label to selector. - newRSSelector := labelsutil.CloneSelectorAndAddLabel(deployment.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, podTemplateSpecHash) - - // Create new ReplicaSet - newRS := extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - // Make the name deterministic, to ensure idempotence - Name: deployment.Name + "-" + fmt.Sprintf("%d", podTemplateSpecHash), - Namespace: namespace, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: newRSSelector, - Template: newRSTemplate, - }, - } - // Set new replica set's annotation - setNewReplicaSetAnnotations(deployment, &newRS, newRevision) - allRSs := append(oldRSs, &newRS) - newReplicasCount, err := deploymentutil.NewRSNewReplicas(deployment, allRSs, &newRS) - if err != nil { - return nil, err - } - - newRS.Spec.Replicas = newReplicasCount - createdRS, err := dc.client.Extensions().ReplicaSets(namespace).Create(&newRS) - if err != nil { - dc.enqueueDeployment(deployment) - return nil, fmt.Errorf("error creating replica set %v: %v", deployment.Name, err) - } - if newReplicasCount > 0 { - dc.eventRecorder.Eventf(deployment, api.EventTypeNormal, "ScalingReplicaSet", "Scaled %s replica set %s to %d", "up", createdRS.Name, newReplicasCount) - } - - return createdRS, dc.updateDeploymentRevision(deployment, newRevision) -} - -// rsAndPodsWithHashKeySynced returns the RSes and pods the given deployment targets, with pod-template-hash information synced. -func (dc *DeploymentController) rsAndPodsWithHashKeySynced(deployment *extensions.Deployment) ([]extensions.ReplicaSet, *api.PodList, error) { - rsList, err := deploymentutil.ListReplicaSets(deployment, - func(namespace string, options api.ListOptions) ([]extensions.ReplicaSet, error) { - return dc.rsStore.ReplicaSets(namespace).List(options.LabelSelector) - }) - if err != nil { - return nil, nil, fmt.Errorf("error listing ReplicaSets: %v", err) - } - syncedRSList := []extensions.ReplicaSet{} - for _, rs := range rsList { - // Add pod-template-hash information if it's not in the RS. - // Otherwise, new RS produced by Deployment will overlap with pre-existing ones - // that aren't constrained by the pod-template-hash. - syncedRS, err := dc.addHashKeyToRSAndPods(rs) - if err != nil { - return nil, nil, err - } - syncedRSList = append(syncedRSList, *syncedRS) - } - syncedPodList, err := deploymentutil.ListPods(deployment, - func(namespace string, options api.ListOptions) (*api.PodList, error) { - podList, err := dc.podStore.Pods(namespace).List(options.LabelSelector) - return &podList, err - }) - - if err != nil { - return nil, nil, err - } - return syncedRSList, syncedPodList, nil -} - -// addHashKeyToRSAndPods adds pod-template-hash information to the given rs, if it's not already there, with the following steps: -// 1. Add hash label to the rs's pod template, and make sure the controller sees this update so that no orphaned pods will be created -// 2. Add hash label to all pods this rs owns, wait until replicaset controller reports rs.Status.FullyLabeledReplicas equal to the desired number of replicas -// 3. Add hash label to the rs's label and selector -func (dc *DeploymentController) addHashKeyToRSAndPods(rs extensions.ReplicaSet) (updatedRS *extensions.ReplicaSet, err error) { - updatedRS = &rs - // If the rs already has the new hash label in its selector, it's done syncing - if labelsutil.SelectorHasLabel(rs.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey) { - return - } - namespace := rs.Namespace - hash := rsutil.GetPodTemplateSpecHash(rs) - rsUpdated := false - // 1. Add hash template label to the rs. This ensures that any newly created pods will have the new label. - updatedRS, rsUpdated, err = rsutil.UpdateRSWithRetries(dc.client.Extensions().ReplicaSets(namespace), updatedRS, - func(updated *extensions.ReplicaSet) error { - // Precondition: the RS doesn't contain the new hash in its pod template label. - if updated.Spec.Template.Labels[extensions.DefaultDeploymentUniqueLabelKey] == hash { - return utilerrors.ErrPreconditionViolated - } - updated.Spec.Template.Labels = labelsutil.AddLabel(updated.Spec.Template.Labels, extensions.DefaultDeploymentUniqueLabelKey, hash) - return nil - }) - if err != nil { - return nil, fmt.Errorf("error updating %s %s/%s pod template label with template hash: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, err) - } - if !rsUpdated { - // If RS wasn't updated but didn't return error in step 1, we've hit a RS not found error. - // Return here and retry in the next sync loop. - return &rs, nil - } - // Make sure rs pod template is updated so that it won't create pods without the new label (orphaned pods). - if updatedRS.Generation > updatedRS.Status.ObservedGeneration { - if err = deploymentutil.WaitForReplicaSetUpdated(dc.client, updatedRS.Generation, namespace, updatedRS.Name); err != nil { - return nil, fmt.Errorf("error waiting for %s %s/%s generation %d observed by controller: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, updatedRS.Generation, err) - } - } - glog.V(4).Infof("Observed the update of %s %s/%s's pod template with hash %s.", rs.Kind, rs.Namespace, rs.Name, hash) - - // 2. Update all pods managed by the rs to have the new hash label, so they will be correctly adopted. - selector, err := unversioned.LabelSelectorAsSelector(updatedRS.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("error in converting selector to label selector for replica set %s: %s", updatedRS.Name, err) - } - options := api.ListOptions{LabelSelector: selector} - podList, err := dc.podStore.Pods(namespace).List(options.LabelSelector) - if err != nil { - return nil, fmt.Errorf("error in getting pod list for namespace %s and list options %+v: %s", namespace, options, err) - } - allPodsLabeled := false - if allPodsLabeled, err = deploymentutil.LabelPodsWithHash(&podList, updatedRS, dc.client, namespace, hash); err != nil { - return nil, fmt.Errorf("error in adding template hash label %s to pods %+v: %s", hash, podList, err) - } - // If not all pods are labeled but didn't return error in step 2, we've hit at least one pod not found error. - // Return here and retry in the next sync loop. - if !allPodsLabeled { - return updatedRS, nil - } - - // We need to wait for the replicaset controller to observe the pods being - // labeled with pod template hash. Because previously we've called - // WaitForReplicaSetUpdated, the replicaset controller should have dropped - // FullyLabeledReplicas to 0 already, we only need to wait it to increase - // back to the number of replicas in the spec. - if err = deploymentutil.WaitForPodsHashPopulated(dc.client, updatedRS.Generation, namespace, updatedRS.Name); err != nil { - return nil, fmt.Errorf("%s %s/%s: error waiting for replicaset controller to observe pods being labeled with template hash: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, err) - } - - // 3. Update rs label and selector to include the new hash label - // Copy the old selector, so that we can scrub out any orphaned pods - if updatedRS, rsUpdated, err = rsutil.UpdateRSWithRetries(dc.client.Extensions().ReplicaSets(namespace), updatedRS, - func(updated *extensions.ReplicaSet) error { - // Precondition: the RS doesn't contain the new hash in its label or selector. - if updated.Labels[extensions.DefaultDeploymentUniqueLabelKey] == hash && updated.Spec.Selector.MatchLabels[extensions.DefaultDeploymentUniqueLabelKey] == hash { - return utilerrors.ErrPreconditionViolated - } - updated.Labels = labelsutil.AddLabel(updated.Labels, extensions.DefaultDeploymentUniqueLabelKey, hash) - updated.Spec.Selector = labelsutil.AddLabelToSelector(updated.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, hash) - return nil - }); err != nil { - return nil, fmt.Errorf("error updating %s %s/%s label and selector with template hash: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, err) - } - if rsUpdated { - glog.V(4).Infof("Updated %s %s/%s's selector and label with hash %s.", rs.Kind, rs.Namespace, rs.Name, hash) - } - // If the RS isn't actually updated in step 3, that's okay, we'll retry in the next sync loop since its selector isn't updated yet. - - // TODO: look for orphaned pods and label them in the background somewhere else periodically - - return updatedRS, nil -} - -// setNewReplicaSetAnnotations sets new replica set's annotations appropriately by updating its revision and -// copying required deployment annotations to it; it returns true if replica set's annotation is changed. -func setNewReplicaSetAnnotations(deployment *extensions.Deployment, newRS *extensions.ReplicaSet, newRevision string) bool { - // First, copy deployment's annotations (except for apply and revision annotations) - annotationChanged := copyDeploymentAnnotationsToReplicaSet(deployment, newRS) - // Then, update replica set's revision annotation - if newRS.Annotations == nil { - newRS.Annotations = make(map[string]string) - } - // The newRS's revision should be the greatest among all RSes. Usually, its revision number is newRevision (the max revision number - // of all old RSes + 1). However, it's possible that some of the old RSes are deleted after the newRS revision being updated, and - // newRevision becomes smaller than newRS's revision. We should only update newRS revision when it's smaller than newRevision. - if newRS.Annotations[deploymentutil.RevisionAnnotation] < newRevision { - newRS.Annotations[deploymentutil.RevisionAnnotation] = newRevision - annotationChanged = true - glog.V(4).Infof("updating replica set %q's revision to %s - %+v\n", newRS.Name, newRevision, newRS) - } - return annotationChanged -} - -// skipCopyAnnotation returns true if we should skip copying the annotation with the given annotation key -// TODO: How to decide which annotations should / should not be copied? -// See https://github.com/kubernetes/kubernetes/pull/20035#issuecomment-179558615 -func skipCopyAnnotation(key string) bool { - // Skip apply annotations and revision annotations. - return key == kubectl.LastAppliedConfigAnnotation || key == deploymentutil.RevisionAnnotation -} - -func getSkippedAnnotations(annotations map[string]string) map[string]string { - skippedAnnotations := make(map[string]string) - for k, v := range annotations { - if skipCopyAnnotation(k) { - skippedAnnotations[k] = v - } - } - return skippedAnnotations -} - -// copyDeploymentAnnotationsToReplicaSet copies deployment's annotations to replica set's annotations, -// and returns true if replica set's annotation is changed. -// Note that apply and revision annotations are not copied. -func copyDeploymentAnnotationsToReplicaSet(deployment *extensions.Deployment, rs *extensions.ReplicaSet) bool { - rsAnnotationsChanged := false - if rs.Annotations == nil { - rs.Annotations = make(map[string]string) - } - for k, v := range deployment.Annotations { - // newRS revision is updated automatically in getNewReplicaSet, and the deployment's revision number is then updated - // by copying its newRS revision number. We should not copy deployment's revision to its newRS, since the update of - // deployment revision number may fail (revision becomes stale) and the revision number in newRS is more reliable. - if skipCopyAnnotation(k) || rs.Annotations[k] == v { - continue - } - rs.Annotations[k] = v - rsAnnotationsChanged = true - } - return rsAnnotationsChanged -} - -// setDeploymentAnnotationsTo sets deployment's annotations as given RS's annotations. -// This action should be done if and only if the deployment is rolling back to this rs. -// Note that apply and revision annotations are not changed. -func setDeploymentAnnotationsTo(deployment *extensions.Deployment, rollbackToRS *extensions.ReplicaSet) { - deployment.Annotations = getSkippedAnnotations(deployment.Annotations) - for k, v := range rollbackToRS.Annotations { - if !skipCopyAnnotation(k) { - deployment.Annotations[k] = v - } - } -} - -func (dc *DeploymentController) updateDeploymentRevision(deployment *extensions.Deployment, revision string) error { - if deployment.Annotations == nil { - deployment.Annotations = make(map[string]string) - } - if deployment.Annotations[deploymentutil.RevisionAnnotation] != revision { - deployment.Annotations[deploymentutil.RevisionAnnotation] = revision - _, err := dc.updateDeployment(deployment) - return err - } - return nil -} - -func (dc *DeploymentController) reconcileNewReplicaSet(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { - if newRS.Spec.Replicas == deployment.Spec.Replicas { - // Scaling not required. - return false, nil - } - if newRS.Spec.Replicas > deployment.Spec.Replicas { - // Scale down. - scaled, _, err := dc.scaleReplicaSetAndRecordEvent(newRS, deployment.Spec.Replicas, deployment) - return scaled, err - } - newReplicasCount, err := deploymentutil.NewRSNewReplicas(deployment, allRSs, newRS) - if err != nil { - return false, err - } - scaled, _, err := dc.scaleReplicaSetAndRecordEvent(newRS, newReplicasCount, deployment) - return scaled, err -} - -func (dc *DeploymentController) reconcileOldReplicaSets(allRSs []*extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { - oldPodsCount := deploymentutil.GetReplicaCountForReplicaSets(oldRSs) - if oldPodsCount == 0 { - // Can't scale down further - return false, nil - } - - minReadySeconds := deployment.Spec.MinReadySeconds - allPodsCount := deploymentutil.GetReplicaCountForReplicaSets(allRSs) - newRSAvailablePodCount, err := deploymentutil.GetAvailablePodsForReplicaSets(dc.client, []*extensions.ReplicaSet{newRS}, minReadySeconds) - if err != nil { - return false, fmt.Errorf("could not find available pods: %v", err) - } - - _, maxUnavailable, err := deploymentutil.ResolveFenceposts(&deployment.Spec.Strategy.RollingUpdate.MaxSurge, &deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, deployment.Spec.Replicas) - if err != nil { - return false, err - } - - // Check if we can scale down. We can scale down in the following 2 cases: - // * Some old replica sets have unhealthy replicas, we could safely scale down those unhealthy replicas since that won't further - // increase unavailability. - // * New replica set has scaled up and it's replicas becomes ready, then we can scale down old replica sets in a further step. - // - // maxScaledDown := allPodsCount - minAvailable - newReplicaSetPodsUnavailable - // take into account not only maxUnavailable and any surge pods that have been created, but also unavailable pods from - // the newRS, so that the unavailable pods from the newRS would not make us scale down old replica sets in a further - // step(that will increase unavailability). - // - // Concrete example: - // - // * 10 replicas - // * 2 maxUnavailable (absolute number, not percent) - // * 3 maxSurge (absolute number, not percent) - // - // case 1: - // * Deployment is updated, newRS is created with 3 replicas, oldRS is scaled down to 8, and newRS is scaled up to 5. - // * The new replica set pods crashloop and never become available. - // * allPodsCount is 13. minAvailable is 8. newRSPodsUnavailable is 5. - // * A node fails and causes one of the oldRS pods to become unavailable. However, 13 - 8 - 5 = 0, so the oldRS won't be scaled down. - // * The user notices the crashloop and does kubectl rollout undo to rollback. - // * newRSPodsUnavailable is 1, since we rolled back to the good replica set, so maxScaledDown = 13 - 8 - 1 = 4. 4 of the crashlooping pods will be scaled down. - // * The total number of pods will then be 9 and the newRS can be scaled up to 10. - // - // case 2: - // Same example, but pushing a new pod template instead of rolling back (aka "roll over"): - // * The new replica set created must start with 0 replicas because allPodsCount is already at 13. - // * However, newRSPodsUnavailable would also be 0, so the 2 old replica sets could be scaled down by 5 (13 - 8 - 0), which would then - // allow the new replica set to be scaled up by 5. - minAvailable := deployment.Spec.Replicas - maxUnavailable - newRSUnavailablePodCount := newRS.Spec.Replicas - newRSAvailablePodCount - maxScaledDown := allPodsCount - minAvailable - newRSUnavailablePodCount - if maxScaledDown <= 0 { - return false, nil - } - - // Clean up unhealthy replicas first, otherwise unhealthy replicas will block deployment - // and cause timeout. See https://github.com/kubernetes/kubernetes/issues/16737 - oldRSs, cleanupCount, err := dc.cleanupUnhealthyReplicas(oldRSs, deployment, maxScaledDown) - if err != nil { - return false, nil - } - glog.V(4).Infof("Cleaned up unhealthy replicas from old RSes by %d", cleanupCount) - - // Scale down old replica sets, need check maxUnavailable to ensure we can scale down - allRSs = append(oldRSs, newRS) - scaledDownCount, err := dc.scaleDownOldReplicaSetsForRollingUpdate(allRSs, oldRSs, deployment) - if err != nil { - return false, nil - } - glog.V(4).Infof("Scaled down old RSes by %d", scaledDownCount) - - totalScaledDown := cleanupCount + scaledDownCount - return totalScaledDown > 0, nil -} - -// cleanupUnhealthyReplicas will scale down old replica sets with unhealthy replicas, so that all unhealthy replicas will be deleted. -func (dc *DeploymentController) cleanupUnhealthyReplicas(oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment, maxCleanupCount int32) ([]*extensions.ReplicaSet, int32, error) { - sort.Sort(controller.ReplicaSetsByCreationTimestamp(oldRSs)) - // Safely scale down all old replica sets with unhealthy replicas. Replica set will sort the pods in the order - // such that not-ready < ready, unscheduled < scheduled, and pending < running. This ensures that unhealthy replicas will - // been deleted first and won't increase unavailability. - totalScaledDown := int32(0) - for i, targetRS := range oldRSs { - if totalScaledDown >= maxCleanupCount { - break - } - if targetRS.Spec.Replicas == 0 { - // cannot scale down this replica set. - continue - } - readyPodCount, err := deploymentutil.GetAvailablePodsForReplicaSets(dc.client, []*extensions.ReplicaSet{targetRS}, 0) - if err != nil { - return nil, totalScaledDown, fmt.Errorf("could not find available pods: %v", err) - } - if targetRS.Spec.Replicas == readyPodCount { - // no unhealthy replicas found, no scaling required. - continue - } - - scaledDownCount := int32(integer.IntMin(int(maxCleanupCount-totalScaledDown), int(targetRS.Spec.Replicas-readyPodCount))) - newReplicasCount := targetRS.Spec.Replicas - scaledDownCount - if newReplicasCount > targetRS.Spec.Replicas { - return nil, 0, fmt.Errorf("when cleaning up unhealthy replicas, got invalid request to scale down %s/%s %d -> %d", targetRS.Namespace, targetRS.Name, targetRS.Spec.Replicas, newReplicasCount) - } - _, updatedOldRS, err := dc.scaleReplicaSetAndRecordEvent(targetRS, newReplicasCount, deployment) - if err != nil { - return nil, totalScaledDown, err - } - totalScaledDown += scaledDownCount - oldRSs[i] = updatedOldRS - } - return oldRSs, totalScaledDown, nil -} - -// scaleDownOldReplicaSetsForRollingUpdate scales down old replica sets when deployment strategy is "RollingUpdate". -// Need check maxUnavailable to ensure availability -func (dc *DeploymentController) scaleDownOldReplicaSetsForRollingUpdate(allRSs []*extensions.ReplicaSet, oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment) (int32, error) { - _, maxUnavailable, err := deploymentutil.ResolveFenceposts(&deployment.Spec.Strategy.RollingUpdate.MaxSurge, &deployment.Spec.Strategy.RollingUpdate.MaxUnavailable, deployment.Spec.Replicas) - if err != nil { - return 0, err - } - - // Check if we can scale down. - minAvailable := deployment.Spec.Replicas - maxUnavailable - minReadySeconds := deployment.Spec.MinReadySeconds - // Find the number of ready pods. - readyPodCount, err := deploymentutil.GetAvailablePodsForReplicaSets(dc.client, allRSs, minReadySeconds) - if err != nil { - return 0, fmt.Errorf("could not find available pods: %v", err) - } - if readyPodCount <= minAvailable { - // Cannot scale down. - return 0, nil - } - - sort.Sort(controller.ReplicaSetsByCreationTimestamp(oldRSs)) - - totalScaledDown := int32(0) - totalScaleDownCount := readyPodCount - minAvailable - for _, targetRS := range oldRSs { - if totalScaledDown >= totalScaleDownCount { - // No further scaling required. - break - } - if targetRS.Spec.Replicas == 0 { - // cannot scale down this ReplicaSet. - continue - } - // Scale down. - scaleDownCount := int32(integer.IntMin(int(targetRS.Spec.Replicas), int(totalScaleDownCount-totalScaledDown))) - newReplicasCount := targetRS.Spec.Replicas - scaleDownCount - if newReplicasCount > targetRS.Spec.Replicas { - return 0, fmt.Errorf("when scaling down old RS, got invalid request to scale down %s/%s %d -> %d", targetRS.Namespace, targetRS.Name, targetRS.Spec.Replicas, newReplicasCount) - } - _, _, err = dc.scaleReplicaSetAndRecordEvent(targetRS, newReplicasCount, deployment) - if err != nil { - return totalScaledDown, err - } - - totalScaledDown += scaleDownCount - } - - return totalScaledDown, nil -} - -// scaleDownOldReplicaSetsForRecreate scales down old replica sets when deployment strategy is "Recreate" -func (dc *DeploymentController) scaleDownOldReplicaSetsForRecreate(oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { - scaled := false - for _, rs := range oldRSs { - // Scaling not required. - if rs.Spec.Replicas == 0 { - continue - } - scaledRS, _, err := dc.scaleReplicaSetAndRecordEvent(rs, 0, deployment) - if err != nil { - return false, err - } - if scaledRS { - scaled = true - } - } - return scaled, nil -} - -// scaleUpNewReplicaSetForRecreate scales up new replica set when deployment strategy is "Recreate" -func (dc *DeploymentController) scaleUpNewReplicaSetForRecreate(newRS *extensions.ReplicaSet, deployment *extensions.Deployment) (bool, error) { - scaled, _, err := dc.scaleReplicaSetAndRecordEvent(newRS, deployment.Spec.Replicas, deployment) - return scaled, err -} - -func (dc *DeploymentController) cleanupOldReplicaSets(oldRSs []*extensions.ReplicaSet, deployment *extensions.Deployment) error { - diff := int32(len(oldRSs)) - *deployment.Spec.RevisionHistoryLimit - if diff <= 0 { - return nil - } - - sort.Sort(controller.ReplicaSetsByCreationTimestamp(oldRSs)) - - var errList []error - // TODO: This should be parallelized. - for i := int32(0); i < diff; i++ { - rs := oldRSs[i] - // Avoid delete replica set with non-zero replica counts - if rs.Status.Replicas != 0 || rs.Spec.Replicas != 0 || rs.Generation > rs.Status.ObservedGeneration { - continue - } - if err := dc.client.Extensions().ReplicaSets(rs.Namespace).Delete(rs.Name, nil); err != nil && !errors.IsNotFound(err) { - glog.V(2).Infof("Failed deleting old replica set %v for deployment %v: %v", rs.Name, deployment.Name, err) - errList = append(errList, err) - } - } - - return utilerrors.NewAggregate(errList) -} - -func (dc *DeploymentController) updateDeploymentStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment *extensions.Deployment) error { - totalActualReplicas, updatedReplicas, availableReplicas, unavailableReplicas, err := dc.calculateStatus(allRSs, newRS, deployment) - if err != nil { - return err - } - newDeployment := *deployment - // TODO: Reconcile this with API definition. API definition talks about ready pods, while this just computes created pods. - newDeployment.Status = extensions.DeploymentStatus{ - // TODO: Ensure that if we start retrying status updates, we won't pick up a new Generation value. - ObservedGeneration: deployment.Generation, - Replicas: totalActualReplicas, - UpdatedReplicas: updatedReplicas, - AvailableReplicas: availableReplicas, - UnavailableReplicas: unavailableReplicas, - } - _, err = dc.client.Extensions().Deployments(deployment.ObjectMeta.Namespace).UpdateStatus(&newDeployment) - return err -} - -func (dc *DeploymentController) calculateStatus(allRSs []*extensions.ReplicaSet, newRS *extensions.ReplicaSet, deployment *extensions.Deployment) (totalActualReplicas, updatedReplicas, availableReplicas, unavailableReplicas int32, err error) { - totalActualReplicas = deploymentutil.GetActualReplicaCountForReplicaSets(allRSs) - updatedReplicas = deploymentutil.GetActualReplicaCountForReplicaSets([]*extensions.ReplicaSet{newRS}) - minReadySeconds := deployment.Spec.MinReadySeconds - availableReplicas, err = deploymentutil.GetAvailablePodsForReplicaSets(dc.client, allRSs, minReadySeconds) - if err != nil { - err = fmt.Errorf("failed to count available pods: %v", err) - return - } - totalReplicas := deploymentutil.GetReplicaCountForReplicaSets(allRSs) - unavailableReplicas = totalReplicas - availableReplicas - return -} - -func (dc *DeploymentController) scaleReplicaSetAndRecordEvent(rs *extensions.ReplicaSet, newScale int32, deployment *extensions.Deployment) (bool, *extensions.ReplicaSet, error) { - // No need to scale - if rs.Spec.Replicas == newScale { - return false, rs, nil - } - var scalingOperation string - if rs.Spec.Replicas < newScale { - scalingOperation = "up" - } else { - scalingOperation = "down" - } - newRS, err := dc.scaleReplicaSet(rs, newScale) - if err == nil { - dc.eventRecorder.Eventf(deployment, api.EventTypeNormal, "ScalingReplicaSet", "Scaled %s replica set %s to %d", scalingOperation, rs.Name, newScale) - } else { - dc.enqueueDeployment(deployment) - } - return true, newRS, err -} - -func (dc *DeploymentController) scaleReplicaSet(rs *extensions.ReplicaSet, newScale int32) (*extensions.ReplicaSet, error) { - // TODO: Using client for now, update to use store when it is ready. - // NOTE: This mutates the ReplicaSet passed in. Not sure if that's a good idea. - rs.Spec.Replicas = newScale - return dc.client.Extensions().ReplicaSets(rs.ObjectMeta.Namespace).Update(rs) -} - -func (dc *DeploymentController) updateDeployment(deployment *extensions.Deployment) (*extensions.Deployment, error) { - // TODO: Using client for now, update to use store when it is ready. - return dc.client.Extensions().Deployments(deployment.ObjectMeta.Namespace).Update(deployment) -} - -func (dc *DeploymentController) rollbackToTemplate(deployment *extensions.Deployment, rs *extensions.ReplicaSet) (d *extensions.Deployment, performedRollback bool, err error) { - if !reflect.DeepEqual(deploymentutil.GetNewReplicaSetTemplate(deployment), rs.Spec.Template) { - glog.Infof("Rolling back deployment %s to template spec %+v", deployment.Name, rs.Spec.Template.Spec) - deploymentutil.SetFromReplicaSetTemplate(deployment, rs.Spec.Template) - // set RS (the old RS we'll rolling back to) annotations back to the deployment; - // otherwise, the deployment's current annotations (should be the same as current new RS) will be copied to the RS after the rollback. - // - // For example, - // A Deployment has old RS1 with annotation {change-cause:create}, and new RS2 {change-cause:edit}. - // Note that both annotations are copied from Deployment, and the Deployment should be annotated {change-cause:edit} as well. - // Now, rollback Deployment to RS1, we should update Deployment's pod-template and also copy annotation from RS1. - // Deployment is now annotated {change-cause:create}, and we have new RS1 {change-cause:create}, old RS2 {change-cause:edit}. - // - // If we don't copy the annotations back from RS to deployment on rollback, the Deployment will stay as {change-cause:edit}, - // and new RS1 becomes {change-cause:edit} (copied from deployment after rollback), old RS2 {change-cause:edit}, which is not correct. - setDeploymentAnnotationsTo(deployment, rs) - performedRollback = true - } else { - glog.V(4).Infof("Rolling back to a revision that contains the same template as current deployment %s, skipping rollback...", deployment.Name) - dc.emitRollbackWarningEvent(deployment, deploymentutil.RollbackTemplateUnchanged, fmt.Sprintf("The rollback revision contains the same template as current deployment %q", deployment.Name)) - } - d, err = dc.updateDeploymentAndClearRollbackTo(deployment) - return -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller_test.go deleted file mode 100644 index 0dc92fb93..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/deployment/deployment_controller_test.go +++ /dev/null @@ -1,820 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 deployment - -import ( - "fmt" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - exp "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func rs(name string, replicas int, selector map[string]string) *exp.ReplicaSet { - return &exp.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: name, - }, - Spec: exp.ReplicaSetSpec{ - Replicas: int32(replicas), - Selector: &unversioned.LabelSelector{MatchLabels: selector}, - Template: api.PodTemplateSpec{}, - }, - } -} - -func newRSWithStatus(name string, specReplicas, statusReplicas int, selector map[string]string) *exp.ReplicaSet { - rs := rs(name, specReplicas, selector) - rs.Status = exp.ReplicaSetStatus{ - Replicas: int32(statusReplicas), - } - return rs -} - -func deployment(name string, replicas int, maxSurge, maxUnavailable intstr.IntOrString) exp.Deployment { - return exp.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: name, - }, - Spec: exp.DeploymentSpec{ - Replicas: int32(replicas), - Strategy: exp.DeploymentStrategy{ - Type: exp.RollingUpdateDeploymentStrategyType, - RollingUpdate: &exp.RollingUpdateDeployment{ - MaxSurge: maxSurge, - MaxUnavailable: maxUnavailable, - }, - }, - }, - } -} - -var alwaysReady = func() bool { return true } - -func newDeployment(replicas int, revisionHistoryLimit *int) *exp.Deployment { - var v *int32 - if revisionHistoryLimit != nil { - v = new(int32) - *v = int32(*revisionHistoryLimit) - } - d := exp.Deployment{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Default.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - UID: util.NewUUID(), - Name: "foobar", - Namespace: api.NamespaceDefault, - ResourceVersion: "18", - }, - Spec: exp.DeploymentSpec{ - Strategy: exp.DeploymentStrategy{ - Type: exp.RollingUpdateDeploymentStrategyType, - RollingUpdate: &exp.RollingUpdateDeployment{}, - }, - Replicas: int32(replicas), - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "name": "foo", - "type": "production", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo/bar", - }, - }, - }, - }, - RevisionHistoryLimit: v, - }, - } - return &d -} - -func newReplicaSet(d *exp.Deployment, name string, replicas int) *exp.ReplicaSet { - return &exp.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: api.NamespaceDefault, - }, - Spec: exp.ReplicaSetSpec{ - Replicas: int32(replicas), - Template: d.Spec.Template, - }, - } - -} - -func newListOptions() api.ListOptions { - return api.ListOptions{} -} - -func TestDeploymentController_reconcileNewReplicaSet(t *testing.T) { - tests := []struct { - deploymentReplicas int - maxSurge intstr.IntOrString - oldReplicas int - newReplicas int - scaleExpected bool - expectedNewReplicas int - }{ - { - // Should not scale up. - deploymentReplicas: 10, - maxSurge: intstr.FromInt(0), - oldReplicas: 10, - newReplicas: 0, - scaleExpected: false, - }, - { - deploymentReplicas: 10, - maxSurge: intstr.FromInt(2), - oldReplicas: 10, - newReplicas: 0, - scaleExpected: true, - expectedNewReplicas: 2, - }, - { - deploymentReplicas: 10, - maxSurge: intstr.FromInt(2), - oldReplicas: 5, - newReplicas: 0, - scaleExpected: true, - expectedNewReplicas: 7, - }, - { - deploymentReplicas: 10, - maxSurge: intstr.FromInt(2), - oldReplicas: 10, - newReplicas: 2, - scaleExpected: false, - }, - { - // Should scale down. - deploymentReplicas: 10, - maxSurge: intstr.FromInt(2), - oldReplicas: 2, - newReplicas: 11, - scaleExpected: true, - expectedNewReplicas: 10, - }, - } - - for i, test := range tests { - t.Logf("executing scenario %d", i) - newRS := rs("foo-v2", test.newReplicas, nil) - oldRS := rs("foo-v2", test.oldReplicas, nil) - allRSs := []*exp.ReplicaSet{newRS, oldRS} - deployment := deployment("foo", test.deploymentReplicas, test.maxSurge, intstr.FromInt(0)) - fake := fake.Clientset{} - controller := &DeploymentController{ - client: &fake, - eventRecorder: &record.FakeRecorder{}, - } - scaled, err := controller.reconcileNewReplicaSet(allRSs, newRS, &deployment) - if err != nil { - t.Errorf("unexpected error: %v", err) - continue - } - if !test.scaleExpected { - if scaled || len(fake.Actions()) > 0 { - t.Errorf("unexpected scaling: %v", fake.Actions()) - } - continue - } - if test.scaleExpected && !scaled { - t.Errorf("expected scaling to occur") - continue - } - if len(fake.Actions()) != 1 { - t.Errorf("expected 1 action during scale, got: %v", fake.Actions()) - continue - } - updated := fake.Actions()[0].(core.UpdateAction).GetObject().(*exp.ReplicaSet) - if e, a := test.expectedNewReplicas, int(updated.Spec.Replicas); e != a { - t.Errorf("expected update to %d replicas, got %d", e, a) - } - } -} - -func TestDeploymentController_reconcileOldReplicaSets(t *testing.T) { - tests := []struct { - deploymentReplicas int - maxUnavailable intstr.IntOrString - oldReplicas int - newReplicas int - readyPodsFromOldRS int - readyPodsFromNewRS int - scaleExpected bool - expectedOldReplicas int - }{ - { - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(0), - oldReplicas: 10, - newReplicas: 0, - readyPodsFromOldRS: 10, - readyPodsFromNewRS: 0, - scaleExpected: true, - expectedOldReplicas: 9, - }, - { - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - oldReplicas: 10, - newReplicas: 0, - readyPodsFromOldRS: 10, - readyPodsFromNewRS: 0, - scaleExpected: true, - expectedOldReplicas: 8, - }, - { // expect unhealthy replicas from old replica sets been cleaned up - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - oldReplicas: 10, - newReplicas: 0, - readyPodsFromOldRS: 8, - readyPodsFromNewRS: 0, - scaleExpected: true, - expectedOldReplicas: 8, - }, - { // expect 1 unhealthy replica from old replica sets been cleaned up, and 1 ready pod been scaled down - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - oldReplicas: 10, - newReplicas: 0, - readyPodsFromOldRS: 9, - readyPodsFromNewRS: 0, - scaleExpected: true, - expectedOldReplicas: 8, - }, - { // the unavailable pods from the newRS would not make us scale down old RSs in a further step - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - oldReplicas: 8, - newReplicas: 2, - readyPodsFromOldRS: 8, - readyPodsFromNewRS: 0, - scaleExpected: false, - }, - } - for i, test := range tests { - t.Logf("executing scenario %d", i) - - newSelector := map[string]string{"foo": "new"} - oldSelector := map[string]string{"foo": "old"} - newRS := rs("foo-new", test.newReplicas, newSelector) - oldRS := rs("foo-old", test.oldReplicas, oldSelector) - oldRSs := []*exp.ReplicaSet{oldRS} - allRSs := []*exp.ReplicaSet{oldRS, newRS} - - deployment := deployment("foo", test.deploymentReplicas, intstr.FromInt(0), test.maxUnavailable) - fakeClientset := fake.Clientset{} - fakeClientset.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { - switch action.(type) { - case core.ListAction: - podList := &api.PodList{} - for podIndex := 0; podIndex < test.readyPodsFromOldRS; podIndex++ { - podList.Items = append(podList.Items, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s-oldReadyPod-%d", oldRS.Name, podIndex), - Labels: oldSelector, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionTrue, - }, - }, - }, - }) - } - for podIndex := 0; podIndex < test.oldReplicas-test.readyPodsFromOldRS; podIndex++ { - podList.Items = append(podList.Items, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s-oldUnhealthyPod-%d", oldRS.Name, podIndex), - Labels: oldSelector, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionFalse, - }, - }, - }, - }) - } - for podIndex := 0; podIndex < test.readyPodsFromNewRS; podIndex++ { - podList.Items = append(podList.Items, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s-newReadyPod-%d", oldRS.Name, podIndex), - Labels: newSelector, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionTrue, - }, - }, - }, - }) - } - for podIndex := 0; podIndex < test.oldReplicas-test.readyPodsFromOldRS; podIndex++ { - podList.Items = append(podList.Items, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s-newUnhealthyPod-%d", oldRS.Name, podIndex), - Labels: newSelector, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionFalse, - }, - }, - }, - }) - } - return true, podList, nil - } - return false, nil, nil - }) - controller := &DeploymentController{ - client: &fakeClientset, - eventRecorder: &record.FakeRecorder{}, - } - - scaled, err := controller.reconcileOldReplicaSets(allRSs, oldRSs, newRS, &deployment) - if err != nil { - t.Errorf("unexpected error: %v", err) - continue - } - if !test.scaleExpected && scaled { - t.Errorf("unexpected scaling: %v", fakeClientset.Actions()) - } - if test.scaleExpected && !scaled { - t.Errorf("expected scaling to occur") - continue - } - continue - } -} - -func TestDeploymentController_cleanupUnhealthyReplicas(t *testing.T) { - tests := []struct { - oldReplicas int - readyPods int - unHealthyPods int - maxCleanupCount int - cleanupCountExpected int - }{ - { - oldReplicas: 10, - readyPods: 8, - unHealthyPods: 2, - maxCleanupCount: 1, - cleanupCountExpected: 1, - }, - { - oldReplicas: 10, - readyPods: 8, - unHealthyPods: 2, - maxCleanupCount: 3, - cleanupCountExpected: 2, - }, - { - oldReplicas: 10, - readyPods: 8, - unHealthyPods: 2, - maxCleanupCount: 0, - cleanupCountExpected: 0, - }, - { - oldReplicas: 10, - readyPods: 10, - unHealthyPods: 0, - maxCleanupCount: 3, - cleanupCountExpected: 0, - }, - } - - for i, test := range tests { - t.Logf("executing scenario %d", i) - oldRS := rs("foo-v2", test.oldReplicas, nil) - oldRSs := []*exp.ReplicaSet{oldRS} - deployment := deployment("foo", 10, intstr.FromInt(2), intstr.FromInt(2)) - fakeClientset := fake.Clientset{} - fakeClientset.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { - switch action.(type) { - case core.ListAction: - podList := &api.PodList{} - for podIndex := 0; podIndex < test.readyPods; podIndex++ { - podList.Items = append(podList.Items, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s-readyPod-%d", oldRS.Name, podIndex), - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionTrue, - }, - }, - }, - }) - } - for podIndex := 0; podIndex < test.unHealthyPods; podIndex++ { - podList.Items = append(podList.Items, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s-unHealthyPod-%d", oldRS.Name, podIndex), - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionFalse, - }, - }, - }, - }) - } - return true, podList, nil - } - return false, nil, nil - }) - - controller := &DeploymentController{ - client: &fakeClientset, - eventRecorder: &record.FakeRecorder{}, - } - _, cleanupCount, err := controller.cleanupUnhealthyReplicas(oldRSs, &deployment, int32(test.maxCleanupCount)) - if err != nil { - t.Errorf("unexpected error: %v", err) - continue - } - if int(cleanupCount) != test.cleanupCountExpected { - t.Errorf("expected %v unhealthy replicas been cleaned up, got %v", test.cleanupCountExpected, cleanupCount) - continue - } - } -} - -func TestDeploymentController_scaleDownOldReplicaSetsForRollingUpdate(t *testing.T) { - tests := []struct { - deploymentReplicas int - maxUnavailable intstr.IntOrString - readyPods int - oldReplicas int - scaleExpected bool - expectedOldReplicas int - }{ - { - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(0), - readyPods: 10, - oldReplicas: 10, - scaleExpected: true, - expectedOldReplicas: 9, - }, - { - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - readyPods: 10, - oldReplicas: 10, - scaleExpected: true, - expectedOldReplicas: 8, - }, - { - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - readyPods: 8, - oldReplicas: 10, - scaleExpected: false, - }, - { - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - readyPods: 10, - oldReplicas: 0, - scaleExpected: false, - }, - { - deploymentReplicas: 10, - maxUnavailable: intstr.FromInt(2), - readyPods: 1, - oldReplicas: 10, - scaleExpected: false, - }, - } - - for i, test := range tests { - t.Logf("executing scenario %d", i) - oldRS := rs("foo-v2", test.oldReplicas, nil) - allRSs := []*exp.ReplicaSet{oldRS} - oldRSs := []*exp.ReplicaSet{oldRS} - deployment := deployment("foo", test.deploymentReplicas, intstr.FromInt(0), test.maxUnavailable) - fakeClientset := fake.Clientset{} - fakeClientset.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { - switch action.(type) { - case core.ListAction: - podList := &api.PodList{} - for podIndex := 0; podIndex < test.readyPods; podIndex++ { - podList.Items = append(podList.Items, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s-pod-%d", oldRS.Name, podIndex), - Labels: map[string]string{"foo": "bar"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionTrue, - }, - }, - }, - }) - } - return true, podList, nil - } - return false, nil, nil - }) - controller := &DeploymentController{ - client: &fakeClientset, - eventRecorder: &record.FakeRecorder{}, - } - scaled, err := controller.scaleDownOldReplicaSetsForRollingUpdate(allRSs, oldRSs, &deployment) - if err != nil { - t.Errorf("unexpected error: %v", err) - continue - } - if !test.scaleExpected { - if scaled != 0 { - t.Errorf("unexpected scaling: %v", fakeClientset.Actions()) - } - continue - } - if test.scaleExpected && scaled == 0 { - t.Errorf("expected scaling to occur; actions: %v", fakeClientset.Actions()) - continue - } - // There are both list and update actions logged, so extract the update - // action for verification. - var updateAction core.UpdateAction - for _, action := range fakeClientset.Actions() { - switch a := action.(type) { - case core.UpdateAction: - if updateAction != nil { - t.Errorf("expected only 1 update action; had %v and found %v", updateAction, a) - } else { - updateAction = a - } - } - } - if updateAction == nil { - t.Errorf("expected an update action") - continue - } - updated := updateAction.GetObject().(*exp.ReplicaSet) - if e, a := test.expectedOldReplicas, int(updated.Spec.Replicas); e != a { - t.Errorf("expected update to %d replicas, got %d", e, a) - } - } -} - -func TestDeploymentController_cleanupOldReplicaSets(t *testing.T) { - selector := map[string]string{"foo": "bar"} - - tests := []struct { - oldRSs []*exp.ReplicaSet - revisionHistoryLimit int - expectedDeletions int - }{ - { - oldRSs: []*exp.ReplicaSet{ - newRSWithStatus("foo-1", 0, 0, selector), - newRSWithStatus("foo-2", 0, 0, selector), - newRSWithStatus("foo-3", 0, 0, selector), - }, - revisionHistoryLimit: 1, - expectedDeletions: 2, - }, - { - // Only delete the replica set with Spec.Replicas = Status.Replicas = 0. - oldRSs: []*exp.ReplicaSet{ - newRSWithStatus("foo-1", 0, 0, selector), - newRSWithStatus("foo-2", 0, 1, selector), - newRSWithStatus("foo-3", 1, 0, selector), - newRSWithStatus("foo-4", 1, 1, selector), - }, - revisionHistoryLimit: 0, - expectedDeletions: 1, - }, - - { - oldRSs: []*exp.ReplicaSet{ - newRSWithStatus("foo-1", 0, 0, selector), - newRSWithStatus("foo-2", 0, 0, selector), - }, - revisionHistoryLimit: 0, - expectedDeletions: 2, - }, - { - oldRSs: []*exp.ReplicaSet{ - newRSWithStatus("foo-1", 1, 1, selector), - newRSWithStatus("foo-2", 1, 1, selector), - }, - revisionHistoryLimit: 0, - expectedDeletions: 0, - }, - } - - for i, test := range tests { - fake := &fake.Clientset{} - controller := NewDeploymentController(fake, controller.NoResyncPeriodFunc) - - controller.eventRecorder = &record.FakeRecorder{} - controller.rsStoreSynced = alwaysReady - controller.podStoreSynced = alwaysReady - for _, rs := range test.oldRSs { - controller.rsStore.Add(rs) - } - - d := newDeployment(1, &tests[i].revisionHistoryLimit) - controller.cleanupOldReplicaSets(test.oldRSs, d) - - gotDeletions := 0 - for _, action := range fake.Actions() { - if "delete" == action.GetVerb() { - gotDeletions++ - } - } - if gotDeletions != test.expectedDeletions { - t.Errorf("expect %v old replica sets been deleted, but got %v", test.expectedDeletions, gotDeletions) - continue - } - } -} - -func getKey(d *exp.Deployment, t *testing.T) string { - if key, err := controller.KeyFunc(d); err != nil { - t.Errorf("Unexpected error getting key for deployment %v: %v", d.Name, err) - return "" - } else { - return key - } -} - -type fixture struct { - t *testing.T - - client *fake.Clientset - // Objects to put in the store. - dStore []*exp.Deployment - rsStore []*exp.ReplicaSet - podStore []*api.Pod - - // Actions expected to happen on the client. Objects from here are also - // preloaded into NewSimpleFake. - actions []core.Action - objects *api.List -} - -func (f *fixture) expectUpdateDeploymentAction(d *exp.Deployment) { - f.actions = append(f.actions, core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "deployments"}, d.Namespace, d)) - f.objects.Items = append(f.objects.Items, d) -} - -func (f *fixture) expectCreateRSAction(rs *exp.ReplicaSet) { - f.actions = append(f.actions, core.NewCreateAction(unversioned.GroupVersionResource{Resource: "replicasets"}, rs.Namespace, rs)) - f.objects.Items = append(f.objects.Items, rs) -} - -func (f *fixture) expectUpdateRSAction(rs *exp.ReplicaSet) { - f.actions = append(f.actions, core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "replicasets"}, rs.Namespace, rs)) - f.objects.Items = append(f.objects.Items, rs) -} - -func (f *fixture) expectListPodAction(namespace string, opt api.ListOptions) { - f.actions = append(f.actions, core.NewListAction(unversioned.GroupVersionResource{Resource: "pods"}, namespace, opt)) -} - -func newFixture(t *testing.T) *fixture { - f := &fixture{} - f.t = t - f.objects = &api.List{} - return f -} - -func (f *fixture) run(deploymentName string) { - f.client = fake.NewSimpleClientset(f.objects) - c := NewDeploymentController(f.client, controller.NoResyncPeriodFunc) - c.eventRecorder = &record.FakeRecorder{} - c.rsStoreSynced = alwaysReady - c.podStoreSynced = alwaysReady - for _, d := range f.dStore { - c.dStore.Store.Add(d) - } - for _, rs := range f.rsStore { - c.rsStore.Store.Add(rs) - } - for _, pod := range f.podStore { - c.podStore.Indexer.Add(pod) - } - - err := c.syncDeployment(deploymentName) - if err != nil { - f.t.Errorf("error syncing deployment: %v", err) - } - - actions := f.client.Actions() - for i, action := range actions { - if len(f.actions) < i+1 { - f.t.Errorf("%d unexpected actions: %+v", len(actions)-len(f.actions), actions[i:]) - break - } - - expectedAction := f.actions[i] - if !expectedAction.Matches(action.GetVerb(), action.GetResource().Resource) { - f.t.Errorf("Expected\n\t%#v\ngot\n\t%#v", expectedAction, action) - continue - } - } - - if len(f.actions) > len(actions) { - f.t.Errorf("%d additional expected actions:%+v", len(f.actions)-len(actions), f.actions[len(actions):]) - } -} - -func TestSyncDeploymentCreatesReplicaSet(t *testing.T) { - f := newFixture(t) - - d := newDeployment(1, nil) - f.dStore = append(f.dStore, d) - - // expect that one ReplicaSet with zero replicas is created - // then is updated to 1 replica - rs := newReplicaSet(d, "deploymentrs-4186632231", 0) - updatedRS := newReplicaSet(d, "deploymentrs-4186632231", 1) - opt := newListOptions() - - f.expectCreateRSAction(rs) - f.expectUpdateDeploymentAction(d) - f.expectUpdateRSAction(updatedRS) - f.expectListPodAction(rs.Namespace, opt) - f.expectUpdateDeploymentAction(d) - - f.run(getKey(d, t)) -} - -// issue: https://github.com/kubernetes/kubernetes/issues/23218 -func TestDeploymentController_dontSyncDeploymentsWithEmptyPodSelector(t *testing.T) { - fake := &fake.Clientset{} - controller := NewDeploymentController(fake, controller.NoResyncPeriodFunc) - - controller.eventRecorder = &record.FakeRecorder{} - controller.rsStoreSynced = alwaysReady - controller.podStoreSynced = alwaysReady - - d := newDeployment(1, nil) - empty := unversioned.LabelSelector{} - d.Spec.Selector = &empty - controller.dStore.Store.Add(d) - // We expect the deployment controller to not take action here since it's configuration - // is invalid, even though no replicasets exist that match it's selector. - controller.syncDeployment(fmt.Sprintf("%s/%s", d.ObjectMeta.Namespace, d.ObjectMeta.Name)) - if len(fake.Actions()) == 0 { - return - } - for _, action := range fake.Actions() { - t.Logf("unexpected action: %#v", action) - } - t.Errorf("expected deployment controller to not take action") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/doc.go deleted file mode 100644 index c51ec6518..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 service provides EndpointController implementation -// to manage and sync service endpoints. -package endpoint diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller.go deleted file mode 100644 index 5bb9119f9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller.go +++ /dev/null @@ -1,500 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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. -*/ - -// CAUTION: If you update code in this file, you may need to also update code -// in contrib/mesos/pkg/service/endpoints_controller.go -package endpoint - -import ( - "reflect" - "time" - - "encoding/json" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/endpoints" - "k8s.io/kubernetes/pkg/api/errors" - podutil "k8s.io/kubernetes/pkg/api/pod" - utilpod "k8s.io/kubernetes/pkg/api/pod" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/controller/framework/informers" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" -) - -const ( - // We'll attempt to recompute EVERY service's endpoints at least this - // often. Higher numbers = lower CPU/network load; lower numbers = - // shorter amount of time before a mistaken endpoint is corrected. - FullServiceResyncPeriod = 30 * time.Second - - // We must avoid syncing service until the pod store has synced. If it hasn't synced, to - // avoid a hot loop, we'll wait this long between checks. - PodStoreSyncedPollPeriod = 100 * time.Millisecond -) - -var ( - keyFunc = framework.DeletionHandlingMetaNamespaceKeyFunc -) - -// NewEndpointController returns a new *EndpointController. -func NewEndpointController(podInformer framework.SharedIndexInformer, client *clientset.Clientset) *EndpointController { - if client != nil && client.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("endpoint_controller", client.Core().GetRESTClient().GetRateLimiter()) - } - e := &EndpointController{ - client: client, - queue: workqueue.New(), - } - - e.serviceStore.Store, e.serviceController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return e.client.Core().Services(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return e.client.Core().Services(api.NamespaceAll).Watch(options) - }, - }, - &api.Service{}, - // TODO: Can we have much longer period here? - FullServiceResyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: e.enqueueService, - UpdateFunc: func(old, cur interface{}) { - e.enqueueService(cur) - }, - DeleteFunc: e.enqueueService, - }, - ) - - podInformer.AddEventHandler(framework.ResourceEventHandlerFuncs{ - AddFunc: e.addPod, - UpdateFunc: e.updatePod, - DeleteFunc: e.deletePod, - }) - e.podStore.Indexer = podInformer.GetIndexer() - e.podController = podInformer.GetController() - e.podStoreSynced = podInformer.HasSynced - - return e -} - -// NewEndpointControllerFromClient returns a new *EndpointController that runs its own informer. -func NewEndpointControllerFromClient(client *clientset.Clientset, resyncPeriod controller.ResyncPeriodFunc) *EndpointController { - podInformer := informers.CreateSharedPodIndexInformer(client, resyncPeriod()) - e := NewEndpointController(podInformer, client) - e.internalPodInformer = podInformer - - return e -} - -// EndpointController manages selector-based service endpoints. -type EndpointController struct { - client *clientset.Clientset - - serviceStore cache.StoreToServiceLister - podStore cache.StoreToPodLister - - // internalPodInformer is used to hold a personal informer. If we're using - // a normal shared informer, then the informer will be started for us. If - // we have a personal informer, we must start it ourselves. If you start - // the controller using NewEndpointController(passing SharedInformer), this - // will be null - internalPodInformer framework.SharedIndexInformer - - // Services that need to be updated. A channel is inappropriate here, - // because it allows services with lots of pods to be serviced much - // more often than services with few pods; it also would cause a - // service that's inserted multiple times to be processed more than - // necessary. - queue *workqueue.Type - - // Since we join two objects, we'll watch both of them with - // controllers. - serviceController *framework.Controller - podController framework.ControllerInterface - // podStoreSynced returns true if the pod store has been synced at least once. - // Added as a member to the struct to allow injection for testing. - podStoreSynced func() bool -} - -// Runs e; will not return until stopCh is closed. workers determines how many -// endpoints will be handled in parallel. -func (e *EndpointController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - go e.serviceController.Run(stopCh) - go e.podController.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(e.worker, time.Second, stopCh) - } - go func() { - defer utilruntime.HandleCrash() - time.Sleep(5 * time.Minute) // give time for our cache to fill - e.checkLeftoverEndpoints() - }() - - if e.internalPodInformer != nil { - go e.internalPodInformer.Run(stopCh) - } - - <-stopCh - e.queue.ShutDown() -} - -func (e *EndpointController) getPodServiceMemberships(pod *api.Pod) (sets.String, error) { - set := sets.String{} - services, err := e.serviceStore.GetPodServices(pod) - if err != nil { - // don't log this error because this function makes pointless - // errors when no services match. - return set, nil - } - for i := range services { - key, err := keyFunc(&services[i]) - if err != nil { - return nil, err - } - set.Insert(key) - } - return set, nil -} - -// When a pod is added, figure out what services it will be a member of and -// enqueue them. obj must have *api.Pod type. -func (e *EndpointController) addPod(obj interface{}) { - pod := obj.(*api.Pod) - services, err := e.getPodServiceMemberships(pod) - if err != nil { - glog.Errorf("Unable to get pod %v/%v's service memberships: %v", pod.Namespace, pod.Name, err) - return - } - for key := range services { - e.queue.Add(key) - } -} - -// When a pod is updated, figure out what services it used to be a member of -// and what services it will be a member of, and enqueue the union of these. -// old and cur must be *api.Pod types. -func (e *EndpointController) updatePod(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - return - } - newPod := old.(*api.Pod) - services, err := e.getPodServiceMemberships(newPod) - if err != nil { - glog.Errorf("Unable to get pod %v/%v's service memberships: %v", newPod.Namespace, newPod.Name, err) - return - } - - oldPod := cur.(*api.Pod) - // Only need to get the old services if the labels changed. - if !reflect.DeepEqual(newPod.Labels, oldPod.Labels) || - !hostNameAndDomainAreEqual(newPod, oldPod) { - oldServices, err := e.getPodServiceMemberships(oldPod) - if err != nil { - glog.Errorf("Unable to get pod %v/%v's service memberships: %v", oldPod.Namespace, oldPod.Name, err) - return - } - services = services.Union(oldServices) - } - for key := range services { - e.queue.Add(key) - } -} - -func hostNameAndDomainAreEqual(pod1, pod2 *api.Pod) bool { - return getHostname(pod1) == getHostname(pod2) && - getSubdomain(pod1) == getSubdomain(pod2) -} - -func getHostname(pod *api.Pod) string { - if len(pod.Spec.Hostname) > 0 { - return pod.Spec.Hostname - } - if pod.Annotations != nil { - return pod.Annotations[utilpod.PodHostnameAnnotation] - } - return "" -} - -func getSubdomain(pod *api.Pod) string { - if len(pod.Spec.Subdomain) > 0 { - return pod.Spec.Subdomain - } - if pod.Annotations != nil { - return pod.Annotations[utilpod.PodSubdomainAnnotation] - } - return "" -} - -// When a pod is deleted, enqueue the services the pod used to be a member of. -// obj could be an *api.Pod, or a DeletionFinalStateUnknown marker item. -func (e *EndpointController) deletePod(obj interface{}) { - if _, ok := obj.(*api.Pod); ok { - // Enqueue all the services that the pod used to be a member - // of. This happens to be exactly the same thing we do when a - // pod is added. - e.addPod(obj) - return - } - podKey, err := keyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - } - glog.Infof("Pod %q was deleted but we don't have a record of its final state, so it will take up to %v before it will be removed from all endpoint records.", podKey, FullServiceResyncPeriod) - - // TODO: keep a map of pods to services to handle this condition. -} - -// obj could be an *api.Service, or a DeletionFinalStateUnknown marker item. -func (e *EndpointController) enqueueService(obj interface{}) { - key, err := keyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - } - - e.queue.Add(key) -} - -// worker runs a worker thread that just dequeues items, processes them, and -// marks them done. You may run as many of these in parallel as you wish; the -// workqueue guarantees that they will not end up processing the same service -// at the same time. -func (e *EndpointController) worker() { - for { - func() { - key, quit := e.queue.Get() - if quit { - return - } - // Use defer: in the unlikely event that there's a - // panic, we'd still like this to get marked done-- - // otherwise the controller will not be able to sync - // this service again until it is restarted. - defer e.queue.Done(key) - e.syncService(key.(string)) - }() - } -} - -func (e *EndpointController) syncService(key string) { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing service %q endpoints. (%v)", key, time.Now().Sub(startTime)) - }() - - if !e.podStoreSynced() { - // Sleep so we give the pod reflector goroutine a chance to run. - time.Sleep(PodStoreSyncedPollPeriod) - glog.Infof("Waiting for pods controller to sync, requeuing rc %v", key) - e.queue.Add(key) - return - } - - obj, exists, err := e.serviceStore.Store.GetByKey(key) - if err != nil || !exists { - // Delete the corresponding endpoint, as the service has been deleted. - // TODO: Please note that this will delete an endpoint when a - // service is deleted. However, if we're down at the time when - // the service is deleted, we will miss that deletion, so this - // doesn't completely solve the problem. See #6877. - namespace, name, err := cache.SplitMetaNamespaceKey(key) - if err != nil { - glog.Errorf("Need to delete endpoint with key %q, but couldn't understand the key: %v", key, err) - // Don't retry, as the key isn't going to magically become understandable. - return - } - err = e.client.Endpoints(namespace).Delete(name, nil) - if err != nil && !errors.IsNotFound(err) { - glog.Errorf("Error deleting endpoint %q: %v", key, err) - e.queue.Add(key) // Retry - } - return - } - - service := obj.(*api.Service) - if service.Spec.Selector == nil { - // services without a selector receive no endpoints from this controller; - // these services will receive the endpoints that are created out-of-band via the REST API. - return - } - - glog.V(5).Infof("About to update endpoints for service %q", key) - pods, err := e.podStore.Pods(service.Namespace).List(labels.Set(service.Spec.Selector).AsSelector()) - if err != nil { - // Since we're getting stuff from a local cache, it is - // basically impossible to get this error. - glog.Errorf("Error syncing service %q: %v", key, err) - e.queue.Add(key) // Retry - return - } - - subsets := []api.EndpointSubset{} - podHostNames := map[string]endpoints.HostRecord{} - - for i := range pods.Items { - pod := &pods.Items[i] - - for i := range service.Spec.Ports { - servicePort := &service.Spec.Ports[i] - - portName := servicePort.Name - portProto := servicePort.Protocol - portNum, err := podutil.FindPort(pod, servicePort) - if err != nil { - glog.V(4).Infof("Failed to find port for service %s/%s: %v", service.Namespace, service.Name, err) - continue - } - if len(pod.Status.PodIP) == 0 { - glog.V(5).Infof("Failed to find an IP for pod %s/%s", pod.Namespace, pod.Name) - continue - } - if pod.DeletionTimestamp != nil { - glog.V(5).Infof("Pod is being deleted %s/%s", pod.Namespace, pod.Name) - continue - } - - epp := api.EndpointPort{Name: portName, Port: int32(portNum), Protocol: portProto} - epa := api.EndpointAddress{ - IP: pod.Status.PodIP, - TargetRef: &api.ObjectReference{ - Kind: "Pod", - Namespace: pod.ObjectMeta.Namespace, - Name: pod.ObjectMeta.Name, - UID: pod.ObjectMeta.UID, - ResourceVersion: pod.ObjectMeta.ResourceVersion, - }} - - hostname := getHostname(pod) - if len(hostname) > 0 && - getSubdomain(pod) == service.Name && - service.Namespace == pod.Namespace { - hostRecord := endpoints.HostRecord{ - HostName: hostname, - } - // TODO: stop populating podHostNames annotation in 1.4 - podHostNames[string(pod.Status.PodIP)] = hostRecord - epa.Hostname = hostname - } - - if api.IsPodReady(pod) { - subsets = append(subsets, api.EndpointSubset{ - Addresses: []api.EndpointAddress{epa}, - Ports: []api.EndpointPort{epp}, - }) - } else { - glog.V(5).Infof("Pod is out of service: %v/%v", pod.Namespace, pod.Name) - subsets = append(subsets, api.EndpointSubset{ - NotReadyAddresses: []api.EndpointAddress{epa}, - Ports: []api.EndpointPort{epp}, - }) - } - } - } - subsets = endpoints.RepackSubsets(subsets) - - // See if there's actually an update here. - currentEndpoints, err := e.client.Endpoints(service.Namespace).Get(service.Name) - if err != nil { - if errors.IsNotFound(err) { - currentEndpoints = &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: service.Name, - Labels: service.Labels, - }, - } - } else { - glog.Errorf("Error getting endpoints: %v", err) - e.queue.Add(key) // Retry - return - } - } - - serializedPodHostNames := "" - if len(podHostNames) > 0 { - b, err := json.Marshal(podHostNames) - if err != nil { - glog.Errorf("Error updating endpoints. Marshalling of hostnames failed.: %v", err) - e.queue.Add(key) // Retry - return - } - serializedPodHostNames = string(b) - } - - newAnnotations := make(map[string]string) - newAnnotations[endpoints.PodHostnamesAnnotation] = serializedPodHostNames - if reflect.DeepEqual(currentEndpoints.Subsets, subsets) && - reflect.DeepEqual(currentEndpoints.Labels, service.Labels) { - glog.V(5).Infof("endpoints are equal for %s/%s, skipping update", service.Namespace, service.Name) - return - } - newEndpoints := currentEndpoints - newEndpoints.Subsets = subsets - newEndpoints.Labels = service.Labels - if newEndpoints.Annotations == nil { - newEndpoints.Annotations = make(map[string]string) - } - if len(serializedPodHostNames) == 0 { - delete(newEndpoints.Annotations, endpoints.PodHostnamesAnnotation) - } else { - newEndpoints.Annotations[endpoints.PodHostnamesAnnotation] = serializedPodHostNames - } - if len(currentEndpoints.ResourceVersion) == 0 { - // No previous endpoints, create them - _, err = e.client.Endpoints(service.Namespace).Create(newEndpoints) - } else { - // Pre-existing - _, err = e.client.Endpoints(service.Namespace).Update(newEndpoints) - } - if err != nil { - glog.Errorf("Error updating endpoints: %v", err) - e.queue.Add(key) // Retry - } -} - -// checkLeftoverEndpoints lists all currently existing endpoints and adds their -// service to the queue. This will detect endpoints that exist with no -// corresponding service; these endpoints need to be deleted. We only need to -// do this once on startup, because in steady-state these are detected (but -// some stragglers could have been left behind if the endpoint controller -// reboots). -func (e *EndpointController) checkLeftoverEndpoints() { - list, err := e.client.Endpoints(api.NamespaceAll).List(api.ListOptions{}) - if err != nil { - glog.Errorf("Unable to list endpoints (%v); orphaned endpoints will not be cleaned up. (They're pretty harmless, but you can restart this component if you want another attempt made.)", err) - return - } - for i := range list.Items { - ep := &list.Items[i] - key, err := keyFunc(ep) - if err != nil { - glog.Errorf("Unable to get key for endpoint %#v", ep) - continue - } - e.queue.Add(key) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller_test.go deleted file mode 100644 index e4097eb16..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/endpoint/endpoints_controller_test.go +++ /dev/null @@ -1,566 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 endpoint - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "k8s.io/kubernetes/pkg/api" - endptspkg "k8s.io/kubernetes/pkg/api/endpoints" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - _ "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/intstr" - utiltesting "k8s.io/kubernetes/pkg/util/testing" -) - -var alwaysReady = func() bool { return true } - -func addPods(store cache.Store, namespace string, nPods int, nPorts int, nNotReady int) { - for i := 0; i < nPods+nNotReady; i++ { - p := &api.Pod{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Default.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - Namespace: namespace, - Name: fmt.Sprintf("pod%d", i), - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{{Ports: []api.ContainerPort{}}}, - }, - Status: api.PodStatus{ - PodIP: fmt.Sprintf("1.2.3.%d", 4+i), - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: api.ConditionTrue, - }, - }, - }, - } - if i >= nPods { - p.Status.Conditions[0].Status = api.ConditionFalse - } - for j := 0; j < nPorts; j++ { - p.Spec.Containers[0].Ports = append(p.Spec.Containers[0].Ports, - api.ContainerPort{Name: fmt.Sprintf("port%d", i), ContainerPort: int32(8080 + j)}) - } - store.Add(p) - } -} - -type serverResponse struct { - statusCode int - obj interface{} -} - -func makeTestServer(t *testing.T, namespace string, endpointsResponse serverResponse) (*httptest.Server, *utiltesting.FakeHandler) { - fakeEndpointsHandler := utiltesting.FakeHandler{ - StatusCode: endpointsResponse.statusCode, - ResponseBody: runtime.EncodeOrDie(testapi.Default.Codec(), endpointsResponse.obj.(runtime.Object)), - } - mux := http.NewServeMux() - mux.Handle(testapi.Default.ResourcePath("endpoints", namespace, ""), &fakeEndpointsHandler) - mux.Handle(testapi.Default.ResourcePath("endpoints/", namespace, ""), &fakeEndpointsHandler) - mux.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) { - t.Errorf("unexpected request: %v", req.RequestURI) - res.WriteHeader(http.StatusNotFound) - }) - return httptest.NewServer(mux), &fakeEndpointsHandler -} - -func TestSyncEndpointsItemsPreserveNoSelector(t *testing.T) { - ns := api.NamespaceDefault - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, - Ports: []api.EndpointPort{{Port: 1000}}, - }}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{Ports: []api.ServicePort{{Port: 80}}}, - }) - endpoints.syncService(ns + "/foo") - endpointsHandler.ValidateRequestCount(t, 0) -} - -func TestCheckLeftoverEndpoints(t *testing.T) { - ns := api.NamespaceDefault - // Note that this requests *all* endpoints, therefore the NamespaceAll - // below. - testServer, _ := makeTestServer(t, api.NamespaceAll, - serverResponse{http.StatusOK, &api.EndpointsList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "1", - }, - Items: []api.Endpoints{{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, - Ports: []api.EndpointPort{{Port: 1000}}, - }}, - }}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - endpoints.checkLeftoverEndpoints() - - if e, a := 1, endpoints.queue.Len(); e != a { - t.Fatalf("Expected %v, got %v", e, a) - } - got, _ := endpoints.queue.Get() - if e, a := ns+"/foo", got; e != a { - t.Errorf("Expected %v, got %v", e, a) - } -} - -func TestSyncEndpointsProtocolTCP(t *testing.T) { - ns := "other" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, - Ports: []api.EndpointPort{{Port: 1000, Protocol: "TCP"}}, - }}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - - addPods(endpoints.podStore.Indexer, ns, 1, 1, 0) - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{ - Selector: map[string]string{}, - Ports: []api.ServicePort{{Port: 80, TargetPort: intstr.FromInt(8080), Protocol: "TCP"}}, - }, - }) - endpoints.syncService(ns + "/foo") - endpointsHandler.ValidateRequestCount(t, 2) - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, - }}, - }) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) -} - -func TestSyncEndpointsProtocolUDP(t *testing.T) { - ns := "other" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, - Ports: []api.EndpointPort{{Port: 1000, Protocol: "UDP"}}, - }}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 1, 1, 0) - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{ - Selector: map[string]string{}, - Ports: []api.ServicePort{{Port: 80, TargetPort: intstr.FromInt(8080), Protocol: "UDP"}}, - }, - }) - endpoints.syncService(ns + "/foo") - endpointsHandler.ValidateRequestCount(t, 2) - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "UDP"}}, - }}, - }) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) -} - -func TestSyncEndpointsItemsEmptySelectorSelectsAll(t *testing.T) { - ns := "other" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 1, 1, 0) - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{ - Selector: map[string]string{}, - Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}}, - }, - }) - endpoints.syncService(ns + "/foo") - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, - }}, - }) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) -} - -func TestSyncEndpointsItemsEmptySelectorSelectsAllNotReady(t *testing.T) { - ns := "other" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 0, 1, 1) - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{ - Selector: map[string]string{}, - Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}}, - }, - }) - endpoints.syncService(ns + "/foo") - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, - }}, - }) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) -} - -func TestSyncEndpointsItemsEmptySelectorSelectsAllMixed(t *testing.T) { - ns := "other" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 1, 1, 1) - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{ - Selector: map[string]string{}, - Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}}, - }, - }) - endpoints.syncService(ns + "/foo") - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod1", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, - }}, - }) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) -} - -func TestSyncEndpointsItemsPreexisting(t *testing.T) { - ns := "bar" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, - Ports: []api.EndpointPort{{Port: 1000}}, - }}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 1, 1, 0) - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"foo": "bar"}, - Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}}, - }, - }) - endpoints.syncService(ns + "/foo") - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, - }}, - }) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) -} - -func TestSyncEndpointsItemsPreexistingIdentical(t *testing.T) { - ns := api.NamespaceDefault - testServer, endpointsHandler := makeTestServer(t, api.NamespaceDefault, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "1", - Name: "foo", - Namespace: ns, - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, - }}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, api.NamespaceDefault, 1, 1, 0) - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"foo": "bar"}, - Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}}, - }, - }) - endpoints.syncService(ns + "/foo") - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", api.NamespaceDefault, "foo"), "GET", nil) -} - -func TestSyncEndpointsItems(t *testing.T) { - ns := "other" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{}}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 3, 2, 0) - addPods(endpoints.podStore.Indexer, "blah", 5, 2, 0) // make sure these aren't found! - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"foo": "bar"}, - Ports: []api.ServicePort{ - {Name: "port0", Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}, - {Name: "port1", Port: 88, Protocol: "TCP", TargetPort: intstr.FromInt(8088)}, - }, - }, - }) - endpoints.syncService("other/foo") - expectedSubsets := []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}, - {IP: "1.2.3.5", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod1", Namespace: ns}}, - {IP: "1.2.3.6", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod2", Namespace: ns}}, - }, - Ports: []api.EndpointPort{ - {Name: "port0", Port: 8080, Protocol: "TCP"}, - {Name: "port1", Port: 8088, Protocol: "TCP"}, - }, - }} - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "", - }, - Subsets: endptspkg.SortSubsets(expectedSubsets), - }) - // endpointsHandler should get 2 requests - one for "GET" and the next for "POST". - endpointsHandler.ValidateRequestCount(t, 2) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, ""), "POST", &data) -} - -func TestSyncEndpointsItemsWithLabels(t *testing.T) { - ns := "other" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{}}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 3, 2, 0) - serviceLabels := map[string]string{"foo": "bar"} - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - Labels: serviceLabels, - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{"foo": "bar"}, - Ports: []api.ServicePort{ - {Name: "port0", Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}, - {Name: "port1", Port: 88, Protocol: "TCP", TargetPort: intstr.FromInt(8088)}, - }, - }, - }) - endpoints.syncService(ns + "/foo") - expectedSubsets := []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{ - {IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}, - {IP: "1.2.3.5", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod1", Namespace: ns}}, - {IP: "1.2.3.6", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod2", Namespace: ns}}, - }, - Ports: []api.EndpointPort{ - {Name: "port0", Port: 8080, Protocol: "TCP"}, - {Name: "port1", Port: 8088, Protocol: "TCP"}, - }, - }} - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "", - Labels: serviceLabels, - }, - Subsets: endptspkg.SortSubsets(expectedSubsets), - }) - // endpointsHandler should get 2 requests - one for "GET" and the next for "POST". - endpointsHandler.ValidateRequestCount(t, 2) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, ""), "POST", &data) -} - -func TestSyncEndpointsItemsPreexistingLabelsChange(t *testing.T) { - ns := "bar" - testServer, endpointsHandler := makeTestServer(t, ns, - serverResponse{http.StatusOK, &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - Labels: map[string]string{ - "foo": "bar", - }, - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, - Ports: []api.EndpointPort{{Port: 1000}}, - }}, - }}) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - endpoints := NewEndpointControllerFromClient(client, controller.NoResyncPeriodFunc) - endpoints.podStoreSynced = alwaysReady - addPods(endpoints.podStore.Indexer, ns, 1, 1, 0) - serviceLabels := map[string]string{"baz": "blah"} - endpoints.serviceStore.Store.Add(&api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - Labels: serviceLabels, - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{"foo": "bar"}, - Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}}, - }, - }) - endpoints.syncService(ns + "/foo") - data := runtime.EncodeOrDie(testapi.Default.Codec(), &api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: ns, - ResourceVersion: "1", - Labels: serviceLabels, - }, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, - Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, - }}, - }) - endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/controller_test.go deleted file mode 100644 index fb132f8f3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/controller_test.go +++ /dev/null @@ -1,408 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 framework_test - -import ( - "fmt" - "math/rand" - "sync" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/cache" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" - - "github.com/google/gofuzz" -) - -func Example() { - // source simulates an apiserver object endpoint. - source := framework.NewFakeControllerSource() - - // This will hold the downstream state, as we know it. - downstream := cache.NewStore(framework.DeletionHandlingMetaNamespaceKeyFunc) - - // This will hold incoming changes. Note how we pass downstream in as a - // KeyLister, that way resync operations will result in the correct set - // of update/delete deltas. - fifo := cache.NewDeltaFIFO(cache.MetaNamespaceKeyFunc, nil, downstream) - - // Let's do threadsafe output to get predictable test results. - deletionCounter := make(chan string, 1000) - - cfg := &framework.Config{ - Queue: fifo, - ListerWatcher: source, - ObjectType: &api.Pod{}, - FullResyncPeriod: time.Millisecond * 100, - RetryOnError: false, - - // Let's implement a simple controller that just deletes - // everything that comes in. - Process: func(obj interface{}) error { - // Obj is from the Pop method of the Queue we make above. - newest := obj.(cache.Deltas).Newest() - - if newest.Type != cache.Deleted { - // Update our downstream store. - err := downstream.Add(newest.Object) - if err != nil { - return err - } - - // Delete this object. - source.Delete(newest.Object.(runtime.Object)) - } else { - // Update our downstream store. - err := downstream.Delete(newest.Object) - if err != nil { - return err - } - - // fifo's KeyOf is easiest, because it handles - // DeletedFinalStateUnknown markers. - key, err := fifo.KeyOf(newest.Object) - if err != nil { - return err - } - - // Report this deletion. - deletionCounter <- key - } - return nil - }, - } - - // Create the controller and run it until we close stop. - stop := make(chan struct{}) - defer close(stop) - go framework.New(cfg).Run(stop) - - // Let's add a few objects to the source. - testIDs := []string{"a-hello", "b-controller", "c-framework"} - for _, name := range testIDs { - // Note that these pods are not valid-- the fake source doesn't - // call validation or anything. - source.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: name}}) - } - - // Let's wait for the controller to process the things we just added. - outputSet := sets.String{} - for i := 0; i < len(testIDs); i++ { - outputSet.Insert(<-deletionCounter) - } - - for _, key := range outputSet.List() { - fmt.Println(key) - } - // Output: - // a-hello - // b-controller - // c-framework -} - -func ExampleInformer() { - // source simulates an apiserver object endpoint. - source := framework.NewFakeControllerSource() - - // Let's do threadsafe output to get predictable test results. - deletionCounter := make(chan string, 1000) - - // Make a controller that immediately deletes anything added to it, and - // logs anything deleted. - _, controller := framework.NewInformer( - source, - &api.Pod{}, - time.Millisecond*100, - framework.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - source.Delete(obj.(runtime.Object)) - }, - DeleteFunc: func(obj interface{}) { - key, err := framework.DeletionHandlingMetaNamespaceKeyFunc(obj) - if err != nil { - key = "oops something went wrong with the key" - } - - // Report this deletion. - deletionCounter <- key - }, - }, - ) - - // Run the controller and run it until we close stop. - stop := make(chan struct{}) - defer close(stop) - go controller.Run(stop) - - // Let's add a few objects to the source. - testIDs := []string{"a-hello", "b-controller", "c-framework"} - for _, name := range testIDs { - // Note that these pods are not valid-- the fake source doesn't - // call validation or anything. - source.Add(&api.Pod{ObjectMeta: api.ObjectMeta{Name: name}}) - } - - // Let's wait for the controller to process the things we just added. - outputSet := sets.String{} - for i := 0; i < len(testIDs); i++ { - outputSet.Insert(<-deletionCounter) - } - - for _, key := range outputSet.List() { - fmt.Println(key) - } - // Output: - // a-hello - // b-controller - // c-framework -} - -func TestHammerController(t *testing.T) { - // This test executes a bunch of requests through the fake source and - // controller framework to make sure there's no locking/threading - // errors. If an error happens, it should hang forever or trigger the - // race detector. - - // source simulates an apiserver object endpoint. - source := framework.NewFakeControllerSource() - - // Let's do threadsafe output to get predictable test results. - outputSetLock := sync.Mutex{} - // map of key to operations done on the key - outputSet := map[string][]string{} - - recordFunc := func(eventType string, obj interface{}) { - key, err := framework.DeletionHandlingMetaNamespaceKeyFunc(obj) - if err != nil { - t.Errorf("something wrong with key: %v", err) - key = "oops something went wrong with the key" - } - - // Record some output when items are deleted. - outputSetLock.Lock() - defer outputSetLock.Unlock() - outputSet[key] = append(outputSet[key], eventType) - } - - // Make a controller which just logs all the changes it gets. - _, controller := framework.NewInformer( - source, - &api.Pod{}, - time.Millisecond*100, - framework.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { recordFunc("add", obj) }, - UpdateFunc: func(oldObj, newObj interface{}) { recordFunc("update", newObj) }, - DeleteFunc: func(obj interface{}) { recordFunc("delete", obj) }, - }, - ) - - if controller.HasSynced() { - t.Errorf("Expected HasSynced() to return false before we started the controller") - } - - // Run the controller and run it until we close stop. - stop := make(chan struct{}) - go controller.Run(stop) - - // Let's wait for the controller to do its initial sync - wait.Poll(100*time.Millisecond, wait.ForeverTestTimeout, func() (bool, error) { - return controller.HasSynced(), nil - }) - if !controller.HasSynced() { - t.Errorf("Expected HasSynced() to return true after the initial sync") - } - - wg := sync.WaitGroup{} - const threads = 3 - wg.Add(threads) - for i := 0; i < threads; i++ { - go func() { - defer wg.Done() - // Let's add a few objects to the source. - currentNames := sets.String{} - rs := rand.NewSource(rand.Int63()) - f := fuzz.New().NilChance(.5).NumElements(0, 2).RandSource(rs) - r := rand.New(rs) // Mustn't use r and f concurrently! - for i := 0; i < 100; i++ { - var name string - var isNew bool - if currentNames.Len() == 0 || r.Intn(3) == 1 { - f.Fuzz(&name) - isNew = true - } else { - l := currentNames.List() - name = l[r.Intn(len(l))] - } - - pod := &api.Pod{} - f.Fuzz(pod) - pod.ObjectMeta.Name = name - pod.ObjectMeta.Namespace = "default" - // Add, update, or delete randomly. - // Note that these pods are not valid-- the fake source doesn't - // call validation or perform any other checking. - if isNew { - currentNames.Insert(name) - source.Add(pod) - continue - } - switch r.Intn(2) { - case 0: - currentNames.Insert(name) - source.Modify(pod) - case 1: - currentNames.Delete(name) - source.Delete(pod) - } - } - }() - } - wg.Wait() - - // Let's wait for the controller to finish processing the things we just added. - // TODO: look in the queue to see how many items need to be processed. - time.Sleep(100 * time.Millisecond) - close(stop) - - outputSetLock.Lock() - t.Logf("got: %#v", outputSet) -} - -func TestUpdate(t *testing.T) { - // This test is going to exercise the various paths that result in a - // call to update. - - // source simulates an apiserver object endpoint. - source := framework.NewFakeControllerSource() - - const ( - FROM = "from" - ADD_MISSED = "missed the add event" - TO = "to" - ) - - // These are the transitions we expect to see; because this is - // asynchronous, there are a lot of valid possibilities. - type pair struct{ from, to string } - allowedTransitions := map[pair]bool{ - pair{FROM, TO}: true, - pair{FROM, ADD_MISSED}: true, - pair{ADD_MISSED, TO}: true, - - // Because a resync can happen when we've already observed one - // of the above but before the item is deleted. - pair{TO, TO}: true, - // Because a resync could happen before we observe an update. - pair{FROM, FROM}: true, - } - - pod := func(name, check string, final bool) *api.Pod { - p := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Labels: map[string]string{"check": check}, - }, - } - if final { - p.Labels["final"] = "true" - } - return p - } - deletePod := func(p *api.Pod) bool { - return p.Labels["final"] == "true" - } - - tests := []func(string){ - func(name string) { - name = "a-" + name - source.Add(pod(name, FROM, false)) - source.Modify(pod(name, TO, true)) - }, - func(name string) { - name = "b-" + name - source.Add(pod(name, FROM, false)) - source.ModifyDropWatch(pod(name, TO, true)) - }, - func(name string) { - name = "c-" + name - source.AddDropWatch(pod(name, FROM, false)) - source.Modify(pod(name, ADD_MISSED, false)) - source.Modify(pod(name, TO, true)) - }, - func(name string) { - name = "d-" + name - source.Add(pod(name, FROM, true)) - }, - } - - const threads = 3 - - var testDoneWG sync.WaitGroup - testDoneWG.Add(threads * len(tests)) - - // Make a controller that deletes things once it observes an update. - // It calls Done() on the wait group on deletions so we can tell when - // everything we've added has been deleted. - _, controller := framework.NewInformer( - source, - &api.Pod{}, - time.Millisecond*1, - framework.ResourceEventHandlerFuncs{ - UpdateFunc: func(oldObj, newObj interface{}) { - o, n := oldObj.(*api.Pod), newObj.(*api.Pod) - from, to := o.Labels["check"], n.Labels["check"] - if !allowedTransitions[pair{from, to}] { - t.Errorf("observed transition %q -> %q for %v", from, to, n.Name) - } - if deletePod(n) { - source.Delete(n) - } - }, - DeleteFunc: func(obj interface{}) { - testDoneWG.Done() - }, - }, - ) - - // Run the controller and run it until we close stop. - // Once Run() is called, calls to testDoneWG.Done() might start, so - // all testDoneWG.Add() calls must happen before this point - stop := make(chan struct{}) - go controller.Run(stop) - - // run every test a few times, in parallel - var wg sync.WaitGroup - wg.Add(threads * len(tests)) - for i := 0; i < threads; i++ { - for j, f := range tests { - go func(name string, f func(string)) { - defer wg.Done() - f(name) - }(fmt.Sprintf("%v-%v", i, j), f) - } - } - wg.Wait() - - // Let's wait for the controller to process the things we just added. - testDoneWG.Wait() - close(stop) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/fake_controller_source_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/fake_controller_source_test.go deleted file mode 100644 index 01269ce64..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/fake_controller_source_test.go +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 framework - -import ( - "sync" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/watch" -) - -// ensure the watch delivers the requested and only the requested items. -func consume(t *testing.T, w watch.Interface, rvs []string, done *sync.WaitGroup) { - defer done.Done() - for _, rv := range rvs { - got, ok := <-w.ResultChan() - if !ok { - t.Errorf("%#v: unexpected channel close, wanted %v", rvs, rv) - return - } - gotRV := got.Object.(*api.Pod).ObjectMeta.ResourceVersion - if e, a := rv, gotRV; e != a { - t.Errorf("wanted %v, got %v", e, a) - } else { - t.Logf("Got %v as expected", gotRV) - } - } - // We should not get anything else. - got, open := <-w.ResultChan() - if open { - t.Errorf("%#v: unwanted object %#v", rvs, got) - } -} - -func TestRCNumber(t *testing.T) { - pod := func(name string) *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: name, - }, - } - } - - wg := &sync.WaitGroup{} - wg.Add(3) - - source := NewFakeControllerSource() - source.Add(pod("foo")) - source.Modify(pod("foo")) - source.Modify(pod("foo")) - - w, err := source.Watch(api.ListOptions{ResourceVersion: "1"}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - go consume(t, w, []string{"2", "3"}, wg) - - list, err := source.List(api.ListOptions{}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if e, a := "3", list.(*api.List).ResourceVersion; e != a { - t.Errorf("wanted %v, got %v", e, a) - } - - w2, err := source.Watch(api.ListOptions{ResourceVersion: "2"}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - go consume(t, w2, []string{"3"}, wg) - - w3, err := source.Watch(api.ListOptions{ResourceVersion: "3"}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - go consume(t, w3, []string{}, wg) - source.Shutdown() - wg.Wait() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/informers/factory.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/informers/factory.go deleted file mode 100644 index 3c3472cc5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/framework/informers/factory.go +++ /dev/null @@ -1,66 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 informers - -import ( - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/watch" -) - -// CreateSharedPodInformer returns a SharedIndexInformer that lists and watches all pods -func CreateSharedPodInformer(client clientset.Interface, resyncPeriod time.Duration) framework.SharedIndexInformer { - sharedInformer := framework.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return client.Core().Pods(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return client.Core().Pods(api.NamespaceAll).Watch(options) - }, - }, - &api.Pod{}, - resyncPeriod, - cache.Indexers{}, - ) - - return sharedInformer -} - -// CreateSharedPodIndexInformer returns a SharedIndexInformer that lists and watches all pods -func CreateSharedPodIndexInformer(client clientset.Interface, resyncPeriod time.Duration) framework.SharedIndexInformer { - sharedIndexInformer := framework.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return client.Core().Pods(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return client.Core().Pods(api.NamespaceAll).Watch(options) - }, - }, - &api.Pod{}, - resyncPeriod, - cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, - ) - - return sharedIndexInformer -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/doc.go deleted file mode 100644 index db08e7a36..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 gc contains a very simple pod "garbage collector" implementation, -// GCController, that runs in the controller manager. If the number of pods -// in terminated phases (right now either Failed or Succeeded) surpasses a -// configurable threshold, the controller will delete pods in terminated state -// until the system reaches the allowed threshold again. The GCController -// prioritizes pods to delete by sorting by creation timestamp and deleting the -// oldest objects first. The GCController will not delete non-terminated pods. -package gc diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/gc_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/gc_controller.go deleted file mode 100644 index 485c326c1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/gc_controller.go +++ /dev/null @@ -1,133 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 gc - -import ( - "sort" - "sync" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" - - "github.com/golang/glog" -) - -const ( - gcCheckPeriod = 20 * time.Second -) - -type GCController struct { - kubeClient clientset.Interface - podStore cache.StoreToPodLister - podStoreSyncer *framework.Controller - deletePod func(namespace, name string) error - threshold int -} - -func New(kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, threshold int) *GCController { - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("gc_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - gcc := &GCController{ - kubeClient: kubeClient, - threshold: threshold, - deletePod: func(namespace, name string) error { - return kubeClient.Core().Pods(namespace).Delete(name, api.NewDeleteOptions(0)) - }, - } - - terminatedSelector := fields.ParseSelectorOrDie("status.phase!=" + string(api.PodPending) + ",status.phase!=" + string(api.PodRunning) + ",status.phase!=" + string(api.PodUnknown)) - - gcc.podStore.Indexer, gcc.podStoreSyncer = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - options.FieldSelector = terminatedSelector - return gcc.kubeClient.Core().Pods(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - options.FieldSelector = terminatedSelector - return gcc.kubeClient.Core().Pods(api.NamespaceAll).Watch(options) - }, - }, - &api.Pod{}, - resyncPeriod(), - framework.ResourceEventHandlerFuncs{}, - // We don't need to build a index for podStore here actually, but build one for consistency. - // It will ensure that if people start making use of the podStore in more specific ways, - // they'll get the benefits they expect. It will also reserve the name for future refactorings. - cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, - ) - return gcc -} - -func (gcc *GCController) Run(stop <-chan struct{}) { - go gcc.podStoreSyncer.Run(stop) - go wait.Until(gcc.gc, gcCheckPeriod, stop) - <-stop -} - -func (gcc *GCController) gc() { - terminatedPods, _ := gcc.podStore.List(labels.Everything()) - terminatedPodCount := len(terminatedPods) - sort.Sort(byCreationTimestamp(terminatedPods)) - - deleteCount := terminatedPodCount - gcc.threshold - - if deleteCount > terminatedPodCount { - deleteCount = terminatedPodCount - } - if deleteCount > 0 { - glog.Infof("garbage collecting %v pods", deleteCount) - } - - var wait sync.WaitGroup - for i := 0; i < deleteCount; i++ { - wait.Add(1) - go func(namespace string, name string) { - defer wait.Done() - if err := gcc.deletePod(namespace, name); err != nil { - // ignore not founds - defer utilruntime.HandleError(err) - } - }(terminatedPods[i].Namespace, terminatedPods[i].Name) - } - wait.Wait() -} - -// byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker. -type byCreationTimestamp []*api.Pod - -func (o byCreationTimestamp) Len() int { return len(o) } -func (o byCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o byCreationTimestamp) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/gc_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/gc_controller_test.go deleted file mode 100644 index e28c9cf03..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/gc/gc_controller_test.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 gc - -import ( - "sync" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/util/sets" -) - -func TestGC(t *testing.T) { - type nameToPhase struct { - name string - phase api.PodPhase - } - - testCases := []struct { - pods []nameToPhase - threshold int - deletedPodNames sets.String - }{ - { - pods: []nameToPhase{ - {name: "a", phase: api.PodFailed}, - {name: "b", phase: api.PodSucceeded}, - }, - threshold: 0, - deletedPodNames: sets.NewString("a", "b"), - }, - { - pods: []nameToPhase{ - {name: "a", phase: api.PodFailed}, - {name: "b", phase: api.PodSucceeded}, - }, - threshold: 1, - deletedPodNames: sets.NewString("a"), - }, - { - pods: []nameToPhase{ - {name: "a", phase: api.PodFailed}, - {name: "b", phase: api.PodSucceeded}, - }, - threshold: 5, - deletedPodNames: sets.NewString(), - }, - } - - for i, test := range testCases { - client := fake.NewSimpleClientset() - gcc := New(client, controller.NoResyncPeriodFunc, test.threshold) - deletedPodNames := make([]string, 0) - var lock sync.Mutex - gcc.deletePod = func(_, name string) error { - lock.Lock() - defer lock.Unlock() - deletedPodNames = append(deletedPodNames, name) - return nil - } - - creationTime := time.Unix(0, 0) - for _, pod := range test.pods { - creationTime = creationTime.Add(1 * time.Hour) - gcc.podStore.Indexer.Add(&api.Pod{ - ObjectMeta: api.ObjectMeta{Name: pod.name, CreationTimestamp: unversioned.Time{Time: creationTime}}, - Status: api.PodStatus{Phase: pod.phase}, - }) - } - - gcc.gc() - - pass := true - for _, pod := range deletedPodNames { - if !test.deletedPodNames.Has(pod) { - pass = false - } - } - if len(deletedPodNames) != len(test.deletedPodNames) { - pass = false - } - if !pass { - t.Errorf("[%v]pod's deleted expected and actual did not match.\n\texpected: %v\n\tactual: %v", i, test.deletedPodNames, deletedPodNames) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/controller.go deleted file mode 100644 index 964a4ec14..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/controller.go +++ /dev/null @@ -1,582 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 job - -import ( - "reflect" - "sort" - "sync" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/controller/framework/informers" - replicationcontroller "k8s.io/kubernetes/pkg/controller/replication" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" -) - -type JobController struct { - kubeClient clientset.Interface - podControl controller.PodControlInterface - - // internalPodInformer is used to hold a personal informer. If we're using - // a normal shared informer, then the informer will be started for us. If - // we have a personal informer, we must start it ourselves. If you start - // the controller using NewJobController(passing SharedInformer), this - // will be null - internalPodInformer framework.SharedInformer - - // To allow injection of updateJobStatus for testing. - updateHandler func(job *batch.Job) error - syncHandler func(jobKey string) error - // podStoreSynced returns true if the pod store has been synced at least once. - // Added as a member to the struct to allow injection for testing. - podStoreSynced func() bool - - // A TTLCache of pod creates/deletes each rc expects to see - expectations controller.ControllerExpectationsInterface - - // A store of job, populated by the jobController - jobStore cache.StoreToJobLister - // Watches changes to all jobs - jobController *framework.Controller - - // A store of pods, populated by the podController - podStore cache.StoreToPodLister - - // Jobs that need to be updated - queue *workqueue.Type - - recorder record.EventRecorder -} - -func NewJobController(podInformer framework.SharedIndexInformer, kubeClient clientset.Interface) *JobController { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - // TODO: remove the wrapper when every clients have moved to use the clientset. - eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) - - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("job_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - - jm := &JobController{ - kubeClient: kubeClient, - podControl: controller.RealPodControl{ - KubeClient: kubeClient, - Recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "job-controller"}), - }, - expectations: controller.NewControllerExpectations(), - queue: workqueue.New(), - recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "job-controller"}), - } - - jm.jobStore.Store, jm.jobController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return jm.kubeClient.Batch().Jobs(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return jm.kubeClient.Batch().Jobs(api.NamespaceAll).Watch(options) - }, - }, - &batch.Job{}, - // TODO: Can we have much longer period here? - replicationcontroller.FullControllerResyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: jm.enqueueController, - UpdateFunc: func(old, cur interface{}) { - if job := cur.(*batch.Job); !isJobFinished(job) { - jm.enqueueController(job) - } - }, - DeleteFunc: jm.enqueueController, - }, - ) - - podInformer.AddEventHandler(framework.ResourceEventHandlerFuncs{ - AddFunc: jm.addPod, - UpdateFunc: jm.updatePod, - DeleteFunc: jm.deletePod, - }) - jm.podStore.Indexer = podInformer.GetIndexer() - jm.podStoreSynced = podInformer.HasSynced - - jm.updateHandler = jm.updateJobStatus - jm.syncHandler = jm.syncJob - return jm -} - -func NewJobControllerFromClient(kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc) *JobController { - podInformer := informers.CreateSharedPodIndexInformer(kubeClient, resyncPeriod()) - jm := NewJobController(podInformer, kubeClient) - jm.internalPodInformer = podInformer - - return jm -} - -// Run the main goroutine responsible for watching and syncing jobs. -func (jm *JobController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - go jm.jobController.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(jm.worker, time.Second, stopCh) - } - - if jm.internalPodInformer != nil { - go jm.internalPodInformer.Run(stopCh) - } - - <-stopCh - glog.Infof("Shutting down Job Manager") - jm.queue.ShutDown() -} - -// getPodJob returns the job managing the given pod. -func (jm *JobController) getPodJob(pod *api.Pod) *batch.Job { - jobs, err := jm.jobStore.GetPodJobs(pod) - if err != nil { - glog.V(4).Infof("No jobs found for pod %v, job controller will avoid syncing", pod.Name) - return nil - } - if len(jobs) > 1 { - glog.Errorf("user error! more than one job is selecting pods with labels: %+v", pod.Labels) - sort.Sort(byCreationTimestamp(jobs)) - } - return &jobs[0] -} - -// When a pod is created, enqueue the controller that manages it and update it's expectations. -func (jm *JobController) addPod(obj interface{}) { - pod := obj.(*api.Pod) - if pod.DeletionTimestamp != nil { - // on a restart of the controller controller, it's possible a new pod shows up in a state that - // is already pending deletion. Prevent the pod from being a creation observation. - jm.deletePod(pod) - return - } - if job := jm.getPodJob(pod); job != nil { - jobKey, err := controller.KeyFunc(job) - if err != nil { - glog.Errorf("Couldn't get key for job %#v: %v", job, err) - return - } - jm.expectations.CreationObserved(jobKey) - jm.enqueueController(job) - } -} - -// When a pod is updated, figure out what job/s manage it and wake them up. -// If the labels of the pod have changed we need to awaken both the old -// and new job. old and cur must be *api.Pod types. -func (jm *JobController) updatePod(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - // A periodic relist will send update events for all known pods. - return - } - curPod := cur.(*api.Pod) - if curPod.DeletionTimestamp != nil { - // when a pod is deleted gracefully it's deletion timestamp is first modified to reflect a grace period, - // and after such time has passed, the kubelet actually deletes it from the store. We receive an update - // for modification of the deletion timestamp and expect an job to create more pods asap, not wait - // until the kubelet actually deletes the pod. - jm.deletePod(curPod) - return - } - if job := jm.getPodJob(curPod); job != nil { - jm.enqueueController(job) - } - oldPod := old.(*api.Pod) - // Only need to get the old job if the labels changed. - if !reflect.DeepEqual(curPod.Labels, oldPod.Labels) { - // If the old and new job are the same, the first one that syncs - // will set expectations preventing any damage from the second. - if oldJob := jm.getPodJob(oldPod); oldJob != nil { - jm.enqueueController(oldJob) - } - } -} - -// When a pod is deleted, enqueue the job that manages the pod and update its expectations. -// obj could be an *api.Pod, or a DeletionFinalStateUnknown marker item. -func (jm *JobController) deletePod(obj interface{}) { - pod, ok := obj.(*api.Pod) - - // When a delete is dropped, the relist will notice a pod in the store not - // in the list, leading to the insertion of a tombstone object which contains - // the deleted key/value. Note that this value might be stale. If the pod - // changed labels the new job will not be woken up till the periodic resync. - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("Couldn't get object from tombstone %+v", obj) - return - } - pod, ok = tombstone.Obj.(*api.Pod) - if !ok { - glog.Errorf("Tombstone contained object that is not a pod %+v", obj) - return - } - } - if job := jm.getPodJob(pod); job != nil { - jobKey, err := controller.KeyFunc(job) - if err != nil { - glog.Errorf("Couldn't get key for job %#v: %v", job, err) - return - } - jm.expectations.DeletionObserved(jobKey) - jm.enqueueController(job) - } -} - -// obj could be an *batch.Job, or a DeletionFinalStateUnknown marker item. -func (jm *JobController) enqueueController(obj interface{}) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - return - } - - // TODO: Handle overlapping controllers better. Either disallow them at admission time or - // deterministically avoid syncing controllers that fight over pods. Currently, we only - // ensure that the same controller is synced for a given pod. When we periodically relist - // all controllers there will still be some replica instability. One way to handle this is - // by querying the store for all controllers that this rc overlaps, as well as all - // controllers that overlap this rc, and sorting them. - jm.queue.Add(key) -} - -// worker runs a worker thread that just dequeues items, processes them, and marks them done. -// It enforces that the syncHandler is never invoked concurrently with the same key. -func (jm *JobController) worker() { - for { - func() { - key, quit := jm.queue.Get() - if quit { - return - } - defer jm.queue.Done(key) - err := jm.syncHandler(key.(string)) - if err != nil { - glog.Errorf("Error syncing job: %v", err) - } - }() - } -} - -// syncJob will sync the job with the given key if it has had its expectations fulfilled, meaning -// it did not expect to see any more of its pods created or deleted. This function is not meant to be invoked -// concurrently with the same key. -func (jm *JobController) syncJob(key string) error { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing job %q (%v)", key, time.Now().Sub(startTime)) - }() - - if !jm.podStoreSynced() { - // Sleep so we give the pod reflector goroutine a chance to run. - time.Sleep(replicationcontroller.PodStoreSyncedPollPeriod) - glog.V(4).Infof("Waiting for pods controller to sync, requeuing job %v", key) - jm.queue.Add(key) - return nil - } - - obj, exists, err := jm.jobStore.Store.GetByKey(key) - if !exists { - glog.V(4).Infof("Job has been deleted: %v", key) - jm.expectations.DeleteExpectations(key) - return nil - } - if err != nil { - glog.Errorf("Unable to retrieve job %v from store: %v", key, err) - jm.queue.Add(key) - return err - } - job := *obj.(*batch.Job) - - // Check the expectations of the job before counting active pods, otherwise a new pod can sneak in - // and update the expectations after we've retrieved active pods from the store. If a new pod enters - // the store after we've checked the expectation, the job sync is just deferred till the next relist. - jobKey, err := controller.KeyFunc(&job) - if err != nil { - glog.Errorf("Couldn't get key for job %#v: %v", job, err) - return err - } - jobNeedsSync := jm.expectations.SatisfiedExpectations(jobKey) - selector, _ := unversioned.LabelSelectorAsSelector(job.Spec.Selector) - podList, err := jm.podStore.Pods(job.Namespace).List(selector) - if err != nil { - glog.Errorf("Error getting pods for job %q: %v", key, err) - jm.queue.Add(key) - return err - } - - activePods := controller.FilterActivePods(podList.Items) - active := int32(len(activePods)) - succeeded, failed := getStatus(podList.Items) - conditions := len(job.Status.Conditions) - if job.Status.StartTime == nil { - now := unversioned.Now() - job.Status.StartTime = &now - } - // if job was finished previously, we don't want to redo the termination - if isJobFinished(&job) { - return nil - } - if pastActiveDeadline(&job) { - // TODO: below code should be replaced with pod termination resulting in - // pod failures, rather than killing pods. Unfortunately none such solution - // exists ATM. There's an open discussion in the topic in - // https://github.com/kubernetes/kubernetes/issues/14602 which might give - // some sort of solution to above problem. - // kill remaining active pods - wait := sync.WaitGroup{} - wait.Add(int(active)) - for i := int32(0); i < active; i++ { - go func(ix int32) { - defer wait.Done() - if err := jm.podControl.DeletePod(job.Namespace, activePods[ix].Name, &job); err != nil { - defer utilruntime.HandleError(err) - } - }(i) - } - wait.Wait() - // update status values accordingly - failed += active - active = 0 - job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobFailed, "DeadlineExceeded", "Job was active longer than specified deadline")) - jm.recorder.Event(&job, api.EventTypeNormal, "DeadlineExceeded", "Job was active longer than specified deadline") - } else { - if jobNeedsSync { - active = jm.manageJob(activePods, succeeded, &job) - } - completions := succeeded - complete := false - if job.Spec.Completions == nil { - // This type of job is complete when any pod exits with success. - // Each pod is capable of - // determining whether or not the entire Job is done. Subsequent pods are - // not expected to fail, but if they do, the failure is ignored. Once any - // pod succeeds, the controller waits for remaining pods to finish, and - // then the job is complete. - if succeeded > 0 && active == 0 { - complete = true - } - } else { - // Job specifies a number of completions. This type of job signals - // success by having that number of successes. Since we do not - // start more pods than there are remaining completions, there should - // not be any remaining active pods once this count is reached. - if completions >= *job.Spec.Completions { - complete = true - if active > 0 { - jm.recorder.Event(&job, api.EventTypeWarning, "TooManyActivePods", "Too many active pods running after completion count reached") - } - if completions > *job.Spec.Completions { - jm.recorder.Event(&job, api.EventTypeWarning, "TooManySucceededPods", "Too many succeeded pods running after completion count reached") - } - } - } - if complete { - job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobComplete, "", "")) - now := unversioned.Now() - job.Status.CompletionTime = &now - } - } - - // no need to update the job if the status hasn't changed since last time - if job.Status.Active != active || job.Status.Succeeded != succeeded || job.Status.Failed != failed || len(job.Status.Conditions) != conditions { - job.Status.Active = active - job.Status.Succeeded = succeeded - job.Status.Failed = failed - - if err := jm.updateHandler(&job); err != nil { - glog.Errorf("Failed to update job %v, requeuing. Error: %v", job.Name, err) - jm.enqueueController(&job) - } - } - return nil -} - -// pastActiveDeadline checks if job has ActiveDeadlineSeconds field set and if it is exceeded. -func pastActiveDeadline(job *batch.Job) bool { - if job.Spec.ActiveDeadlineSeconds == nil || job.Status.StartTime == nil { - return false - } - now := unversioned.Now() - start := job.Status.StartTime.Time - duration := now.Time.Sub(start) - allowedDuration := time.Duration(*job.Spec.ActiveDeadlineSeconds) * time.Second - return duration >= allowedDuration -} - -func newCondition(conditionType batch.JobConditionType, reason, message string) batch.JobCondition { - return batch.JobCondition{ - Type: conditionType, - Status: api.ConditionTrue, - LastProbeTime: unversioned.Now(), - LastTransitionTime: unversioned.Now(), - Reason: reason, - Message: message, - } -} - -// getStatus returns no of succeeded and failed pods running a job -func getStatus(pods []api.Pod) (succeeded, failed int32) { - succeeded = int32(filterPods(pods, api.PodSucceeded)) - failed = int32(filterPods(pods, api.PodFailed)) - return -} - -// manageJob is the core method responsible for managing the number of running -// pods according to what is specified in the job.Spec. -func (jm *JobController) manageJob(activePods []*api.Pod, succeeded int32, job *batch.Job) int32 { - var activeLock sync.Mutex - active := int32(len(activePods)) - parallelism := *job.Spec.Parallelism - jobKey, err := controller.KeyFunc(job) - if err != nil { - glog.Errorf("Couldn't get key for job %#v: %v", job, err) - return 0 - } - - if active > parallelism { - diff := active - parallelism - jm.expectations.ExpectDeletions(jobKey, int(diff)) - glog.V(4).Infof("Too many pods running job %q, need %d, deleting %d", jobKey, parallelism, diff) - // Sort the pods in the order such that not-ready < ready, unscheduled - // < scheduled, and pending < running. This ensures that we delete pods - // in the earlier stages whenever possible. - sort.Sort(controller.ActivePods(activePods)) - - active -= diff - wait := sync.WaitGroup{} - wait.Add(int(diff)) - for i := int32(0); i < diff; i++ { - go func(ix int32) { - defer wait.Done() - if err := jm.podControl.DeletePod(job.Namespace, activePods[ix].Name, job); err != nil { - defer utilruntime.HandleError(err) - // Decrement the expected number of deletes because the informer won't observe this deletion - jm.expectations.DeletionObserved(jobKey) - activeLock.Lock() - active++ - activeLock.Unlock() - } - }(i) - } - wait.Wait() - - } else if active < parallelism { - wantActive := int32(0) - if job.Spec.Completions == nil { - // Job does not specify a number of completions. Therefore, number active - // should be equal to parallelism, unless the job has seen at least - // once success, in which leave whatever is running, running. - if succeeded > 0 { - wantActive = active - } else { - wantActive = parallelism - } - } else { - // Job specifies a specific number of completions. Therefore, number - // active should not ever exceed number of remaining completions. - wantActive = *job.Spec.Completions - succeeded - if wantActive > parallelism { - wantActive = parallelism - } - } - diff := wantActive - active - if diff < 0 { - glog.Errorf("More active than wanted: job %q, want %d, have %d", jobKey, wantActive, active) - diff = 0 - } - jm.expectations.ExpectCreations(jobKey, int(diff)) - glog.V(4).Infof("Too few pods running job %q, need %d, creating %d", jobKey, wantActive, diff) - - active += diff - wait := sync.WaitGroup{} - wait.Add(int(diff)) - for i := int32(0); i < diff; i++ { - go func() { - defer wait.Done() - if err := jm.podControl.CreatePods(job.Namespace, &job.Spec.Template, job); err != nil { - defer utilruntime.HandleError(err) - // Decrement the expected number of creates because the informer won't observe this pod - jm.expectations.CreationObserved(jobKey) - activeLock.Lock() - active-- - activeLock.Unlock() - } - }() - } - wait.Wait() - } - - return active -} - -func (jm *JobController) updateJobStatus(job *batch.Job) error { - _, err := jm.kubeClient.Batch().Jobs(job.Namespace).UpdateStatus(job) - return err -} - -// filterPods returns pods based on their phase. -func filterPods(pods []api.Pod, phase api.PodPhase) int { - result := 0 - for i := range pods { - if phase == pods[i].Status.Phase { - result++ - } - } - return result -} - -func isJobFinished(j *batch.Job) bool { - for _, c := range j.Status.Conditions { - if (c.Type == batch.JobComplete || c.Type == batch.JobFailed) && c.Status == api.ConditionTrue { - return true - } - } - return false -} - -// byCreationTimestamp sorts a list by creation timestamp, using their names as a tie breaker. -type byCreationTimestamp []batch.Job - -func (o byCreationTimestamp) Len() int { return len(o) } -func (o byCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o byCreationTimestamp) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/controller_test.go deleted file mode 100644 index 95f0432b6..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/controller_test.go +++ /dev/null @@ -1,711 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 job - -import ( - "fmt" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/client/unversioned/testclient" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/util/rand" - "k8s.io/kubernetes/pkg/watch" -) - -var alwaysReady = func() bool { return true } - -func newJob(parallelism, completions int32) *batch.Job { - j := &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foobar", - Namespace: api.NamespaceDefault, - }, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar"}, - }, - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - {Image: "foo/bar"}, - }, - }, - }, - }, - } - // Special case: -1 for either completions or parallelism means leave nil (negative is not allowed - // in practice by validation. - if completions >= 0 { - j.Spec.Completions = &completions - } else { - j.Spec.Completions = nil - } - if parallelism >= 0 { - j.Spec.Parallelism = ¶llelism - } else { - j.Spec.Parallelism = nil - } - return j -} - -func getKey(job *batch.Job, t *testing.T) string { - if key, err := controller.KeyFunc(job); err != nil { - t.Errorf("Unexpected error getting key for job %v: %v", job.Name, err) - return "" - } else { - return key - } -} - -// create count pods with the given phase for the given job -func newPodList(count int32, status api.PodPhase, job *batch.Job) []api.Pod { - pods := []api.Pod{} - for i := int32(0); i < count; i++ { - newPod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("pod-%v", rand.String(10)), - Labels: job.Spec.Selector.MatchLabels, - Namespace: job.Namespace, - }, - Status: api.PodStatus{Phase: status}, - } - pods = append(pods, newPod) - } - return pods -} - -func TestControllerSyncJob(t *testing.T) { - testCases := map[string]struct { - // job setup - parallelism int32 - completions int32 - - // pod setup - podControllerError error - activePods int32 - succeededPods int32 - failedPods int32 - - // expectations - expectedCreations int32 - expectedDeletions int32 - expectedActive int32 - expectedSucceeded int32 - expectedFailed int32 - expectedComplete bool - }{ - "job start": { - 2, 5, - nil, 0, 0, 0, - 2, 0, 2, 0, 0, false, - }, - "WQ job start": { - 2, -1, - nil, 0, 0, 0, - 2, 0, 2, 0, 0, false, - }, - "correct # of pods": { - 2, 5, - nil, 2, 0, 0, - 0, 0, 2, 0, 0, false, - }, - "WQ job: correct # of pods": { - 2, -1, - nil, 2, 0, 0, - 0, 0, 2, 0, 0, false, - }, - "too few active pods": { - 2, 5, - nil, 1, 1, 0, - 1, 0, 2, 1, 0, false, - }, - "too few active pods with a dynamic job": { - 2, -1, - nil, 1, 0, 0, - 1, 0, 2, 0, 0, false, - }, - "too few active pods, with controller error": { - 2, 5, - fmt.Errorf("Fake error"), 1, 1, 0, - 0, 0, 1, 1, 0, false, - }, - "too many active pods": { - 2, 5, - nil, 3, 0, 0, - 0, 1, 2, 0, 0, false, - }, - "too many active pods, with controller error": { - 2, 5, - fmt.Errorf("Fake error"), 3, 0, 0, - 0, 0, 3, 0, 0, false, - }, - "failed pod": { - 2, 5, - nil, 1, 1, 1, - 1, 0, 2, 1, 1, false, - }, - "job finish": { - 2, 5, - nil, 0, 5, 0, - 0, 0, 0, 5, 0, true, - }, - "WQ job finishing": { - 2, -1, - nil, 1, 1, 0, - 0, 0, 1, 1, 0, false, - }, - "WQ job all finished": { - 2, -1, - nil, 0, 2, 0, - 0, 0, 0, 2, 0, true, - }, - "WQ job all finished despite one failure": { - 2, -1, - nil, 0, 1, 1, - 0, 0, 0, 1, 1, true, - }, - "more active pods than completions": { - 2, 5, - nil, 10, 0, 0, - 0, 8, 2, 0, 0, false, - }, - "status change": { - 2, 5, - nil, 2, 2, 0, - 0, 0, 2, 2, 0, false, - }, - } - - for name, tc := range testCases { - // job manager setup - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - fakePodControl := controller.FakePodControl{Err: tc.podControllerError} - manager.podControl = &fakePodControl - manager.podStoreSynced = alwaysReady - var actual *batch.Job - manager.updateHandler = func(job *batch.Job) error { - actual = job - return nil - } - - // job & pods setup - job := newJob(tc.parallelism, tc.completions) - manager.jobStore.Store.Add(job) - for _, pod := range newPodList(tc.activePods, api.PodRunning, job) { - manager.podStore.Indexer.Add(&pod) - } - for _, pod := range newPodList(tc.succeededPods, api.PodSucceeded, job) { - manager.podStore.Indexer.Add(&pod) - } - for _, pod := range newPodList(tc.failedPods, api.PodFailed, job) { - manager.podStore.Indexer.Add(&pod) - } - - // run - err := manager.syncJob(getKey(job, t)) - if err != nil { - t.Errorf("%s: unexpected error when syncing jobs %v", name, err) - } - - // validate created/deleted pods - if int32(len(fakePodControl.Templates)) != tc.expectedCreations { - t.Errorf("%s: unexpected number of creates. Expected %d, saw %d\n", name, tc.expectedCreations, len(fakePodControl.Templates)) - } - if int32(len(fakePodControl.DeletePodName)) != tc.expectedDeletions { - t.Errorf("%s: unexpected number of deletes. Expected %d, saw %d\n", name, tc.expectedDeletions, len(fakePodControl.DeletePodName)) - } - // validate status - if actual.Status.Active != tc.expectedActive { - t.Errorf("%s: unexpected number of active pods. Expected %d, saw %d\n", name, tc.expectedActive, actual.Status.Active) - } - if actual.Status.Succeeded != tc.expectedSucceeded { - t.Errorf("%s: unexpected number of succeeded pods. Expected %d, saw %d\n", name, tc.expectedSucceeded, actual.Status.Succeeded) - } - if actual.Status.Failed != tc.expectedFailed { - t.Errorf("%s: unexpected number of failed pods. Expected %d, saw %d\n", name, tc.expectedFailed, actual.Status.Failed) - } - if actual.Status.StartTime == nil { - t.Errorf("%s: .status.startTime was not set", name) - } - // validate conditions - if tc.expectedComplete && !getCondition(actual, batch.JobComplete) { - t.Errorf("%s: expected completion condition. Got %#v", name, actual.Status.Conditions) - } - } -} - -func TestSyncJobPastDeadline(t *testing.T) { - testCases := map[string]struct { - // job setup - parallelism int32 - completions int32 - activeDeadlineSeconds int64 - startTime int64 - - // pod setup - activePods int32 - succeededPods int32 - failedPods int32 - - // expectations - expectedDeletions int32 - expectedActive int32 - expectedSucceeded int32 - expectedFailed int32 - }{ - "activeDeadlineSeconds less than single pod execution": { - 1, 1, 10, 15, - 1, 0, 0, - 1, 0, 0, 1, - }, - "activeDeadlineSeconds bigger than single pod execution": { - 1, 2, 10, 15, - 1, 1, 0, - 1, 0, 1, 1, - }, - "activeDeadlineSeconds times-out before any pod starts": { - 1, 1, 10, 10, - 0, 0, 0, - 0, 0, 0, 0, - }, - } - - for name, tc := range testCases { - // job manager setup - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.podStoreSynced = alwaysReady - var actual *batch.Job - manager.updateHandler = func(job *batch.Job) error { - actual = job - return nil - } - - // job & pods setup - job := newJob(tc.parallelism, tc.completions) - job.Spec.ActiveDeadlineSeconds = &tc.activeDeadlineSeconds - start := unversioned.Unix(unversioned.Now().Time.Unix()-tc.startTime, 0) - job.Status.StartTime = &start - manager.jobStore.Store.Add(job) - for _, pod := range newPodList(tc.activePods, api.PodRunning, job) { - manager.podStore.Indexer.Add(&pod) - } - for _, pod := range newPodList(tc.succeededPods, api.PodSucceeded, job) { - manager.podStore.Indexer.Add(&pod) - } - for _, pod := range newPodList(tc.failedPods, api.PodFailed, job) { - manager.podStore.Indexer.Add(&pod) - } - - // run - err := manager.syncJob(getKey(job, t)) - if err != nil { - t.Errorf("%s: unexpected error when syncing jobs %v", name, err) - } - - // validate created/deleted pods - if int32(len(fakePodControl.Templates)) != 0 { - t.Errorf("%s: unexpected number of creates. Expected 0, saw %d\n", name, len(fakePodControl.Templates)) - } - if int32(len(fakePodControl.DeletePodName)) != tc.expectedDeletions { - t.Errorf("%s: unexpected number of deletes. Expected %d, saw %d\n", name, tc.expectedDeletions, len(fakePodControl.DeletePodName)) - } - // validate status - if actual.Status.Active != tc.expectedActive { - t.Errorf("%s: unexpected number of active pods. Expected %d, saw %d\n", name, tc.expectedActive, actual.Status.Active) - } - if actual.Status.Succeeded != tc.expectedSucceeded { - t.Errorf("%s: unexpected number of succeeded pods. Expected %d, saw %d\n", name, tc.expectedSucceeded, actual.Status.Succeeded) - } - if actual.Status.Failed != tc.expectedFailed { - t.Errorf("%s: unexpected number of failed pods. Expected %d, saw %d\n", name, tc.expectedFailed, actual.Status.Failed) - } - if actual.Status.StartTime == nil { - t.Errorf("%s: .status.startTime was not set", name) - } - // validate conditions - if !getCondition(actual, batch.JobFailed) { - t.Errorf("%s: expected fail condition. Got %#v", name, actual.Status.Conditions) - } - } -} - -func getCondition(job *batch.Job, condition batch.JobConditionType) bool { - for _, v := range job.Status.Conditions { - if v.Type == condition && v.Status == api.ConditionTrue { - return true - } - } - return false -} - -func TestSyncPastDeadlineJobFinished(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.podStoreSynced = alwaysReady - var actual *batch.Job - manager.updateHandler = func(job *batch.Job) error { - actual = job - return nil - } - - job := newJob(1, 1) - activeDeadlineSeconds := int64(10) - job.Spec.ActiveDeadlineSeconds = &activeDeadlineSeconds - start := unversioned.Unix(unversioned.Now().Time.Unix()-15, 0) - job.Status.StartTime = &start - job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobFailed, "DeadlineExceeded", "Job was active longer than specified deadline")) - manager.jobStore.Store.Add(job) - err := manager.syncJob(getKey(job, t)) - if err != nil { - t.Errorf("Unexpected error when syncing jobs %v", err) - } - if len(fakePodControl.Templates) != 0 { - t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", 0, len(fakePodControl.Templates)) - } - if len(fakePodControl.DeletePodName) != 0 { - t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", 0, len(fakePodControl.DeletePodName)) - } - if actual != nil { - t.Error("Unexpected job modification") - } -} - -func TestSyncJobComplete(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.podStoreSynced = alwaysReady - - job := newJob(1, 1) - job.Status.Conditions = append(job.Status.Conditions, newCondition(batch.JobComplete, "", "")) - manager.jobStore.Store.Add(job) - err := manager.syncJob(getKey(job, t)) - if err != nil { - t.Fatalf("Unexpected error when syncing jobs %v", err) - } - uncastJob, _, err := manager.jobStore.Store.Get(job) - if err != nil { - t.Fatalf("Unexpected error when trying to get job from the store: %v", err) - } - actual := uncastJob.(*batch.Job) - // Verify that after syncing a complete job, the conditions are the same. - if got, expected := len(actual.Status.Conditions), 1; got != expected { - t.Fatalf("Unexpected job status conditions amount; expected %d, got %d", expected, got) - } -} - -func TestSyncJobDeleted(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.podStoreSynced = alwaysReady - manager.updateHandler = func(job *batch.Job) error { return nil } - job := newJob(2, 2) - err := manager.syncJob(getKey(job, t)) - if err != nil { - t.Errorf("Unexpected error when syncing jobs %v", err) - } - if len(fakePodControl.Templates) != 0 { - t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", 0, len(fakePodControl.Templates)) - } - if len(fakePodControl.DeletePodName) != 0 { - t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", 0, len(fakePodControl.DeletePodName)) - } -} - -func TestSyncJobUpdateRequeue(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.podStoreSynced = alwaysReady - manager.updateHandler = func(job *batch.Job) error { return fmt.Errorf("Fake error") } - job := newJob(2, 2) - manager.jobStore.Store.Add(job) - err := manager.syncJob(getKey(job, t)) - if err != nil { - t.Errorf("Unxpected error when syncing jobs, got %v", err) - } - t.Log("Waiting for a job in the queue") - key, _ := manager.queue.Get() - expectedKey := getKey(job, t) - if key != expectedKey { - t.Errorf("Expected requeue of job with key %s got %s", expectedKey, key) - } -} - -func TestJobPodLookup(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - manager.podStoreSynced = alwaysReady - testCases := []struct { - job *batch.Job - pod *api.Pod - - expectedName string - }{ - // pods without labels don't match any job - { - job: &batch.Job{ - ObjectMeta: api.ObjectMeta{Name: "basic"}, - }, - pod: &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo1", Namespace: api.NamespaceAll}, - }, - expectedName: "", - }, - // matching labels, different namespace - { - job: &batch.Job{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar"}, - }, - }, - }, - pod: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo2", - Namespace: "ns", - Labels: map[string]string{"foo": "bar"}, - }, - }, - expectedName: "", - }, - // matching ns and labels returns - { - job: &batch.Job{ - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchExpressions: []unversioned.LabelSelectorRequirement{ - { - Key: "foo", - Operator: unversioned.LabelSelectorOpIn, - Values: []string{"bar"}, - }, - }, - }, - }, - }, - pod: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo3", - Namespace: "ns", - Labels: map[string]string{"foo": "bar"}, - }, - }, - expectedName: "bar", - }, - } - for _, tc := range testCases { - manager.jobStore.Add(tc.job) - if job := manager.getPodJob(tc.pod); job != nil { - if tc.expectedName != job.Name { - t.Errorf("Got job %+v expected %+v", job.Name, tc.expectedName) - } - } else if tc.expectedName != "" { - t.Errorf("Expected a job %v pod %v, found none", tc.expectedName, tc.pod.Name) - } - } -} - -type FakeJobExpectations struct { - *controller.ControllerExpectations - satisfied bool - expSatisfied func() -} - -func (fe FakeJobExpectations) SatisfiedExpectations(controllerKey string) bool { - fe.expSatisfied() - return fe.satisfied -} - -// TestSyncJobExpectations tests that a pod cannot sneak in between counting active pods -// and checking expectations. -func TestSyncJobExpectations(t *testing.T) { - clientset := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.podStoreSynced = alwaysReady - manager.updateHandler = func(job *batch.Job) error { return nil } - - job := newJob(2, 2) - manager.jobStore.Store.Add(job) - pods := newPodList(2, api.PodPending, job) - manager.podStore.Indexer.Add(&pods[0]) - - manager.expectations = FakeJobExpectations{ - controller.NewControllerExpectations(), true, func() { - // If we check active pods before checking expectataions, the job - // will create a new replica because it doesn't see this pod, but - // has fulfilled its expectations. - manager.podStore.Indexer.Add(&pods[1]) - }, - } - manager.syncJob(getKey(job, t)) - if len(fakePodControl.Templates) != 0 { - t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", 0, len(fakePodControl.Templates)) - } - if len(fakePodControl.DeletePodName) != 0 { - t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", 0, len(fakePodControl.DeletePodName)) - } -} - -type FakeWatcher struct { - w *watch.FakeWatcher - *testclient.Fake -} - -func TestWatchJobs(t *testing.T) { - clientset := fake.NewSimpleClientset() - fakeWatch := watch.NewFake() - clientset.PrependWatchReactor("jobs", core.DefaultWatchReactor(fakeWatch, nil)) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - manager.podStoreSynced = alwaysReady - - var testJob batch.Job - received := make(chan struct{}) - - // The update sent through the fakeWatcher should make its way into the workqueue, - // and eventually into the syncHandler. - manager.syncHandler = func(key string) error { - - obj, exists, err := manager.jobStore.Store.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find job under key %v", key) - } - job, ok := obj.(*batch.Job) - if !ok { - t.Fatalf("unexpected type: %v %#v", reflect.TypeOf(obj), obj) - } - if !api.Semantic.DeepDerivative(*job, testJob) { - t.Errorf("Expected %#v, but got %#v", testJob, *job) - } - close(received) - return nil - } - // Start only the job watcher and the workqueue, send a watch event, - // and make sure it hits the sync method. - stopCh := make(chan struct{}) - defer close(stopCh) - go manager.Run(1, stopCh) - - // We're sending new job to see if it reaches syncHandler. - testJob.Name = "foo" - fakeWatch.Add(&testJob) - t.Log("Waiting for job to reach syncHandler") - <-received -} - -func TestIsJobFinished(t *testing.T) { - job := &batch.Job{ - Status: batch.JobStatus{ - Conditions: []batch.JobCondition{{ - Type: batch.JobComplete, - Status: api.ConditionTrue, - }}, - }, - } - - if !isJobFinished(job) { - t.Error("Job was expected to be finished") - } - - job.Status.Conditions[0].Status = api.ConditionFalse - if isJobFinished(job) { - t.Error("Job was not expected to be finished") - } - - job.Status.Conditions[0].Status = api.ConditionUnknown - if isJobFinished(job) { - t.Error("Job was not expected to be finished") - } -} - -func TestWatchPods(t *testing.T) { - testJob := newJob(2, 2) - clientset := fake.NewSimpleClientset(testJob) - fakeWatch := watch.NewFake() - clientset.PrependWatchReactor("pods", core.DefaultWatchReactor(fakeWatch, nil)) - manager := NewJobControllerFromClient(clientset, controller.NoResyncPeriodFunc) - manager.podStoreSynced = alwaysReady - - // Put one job and one pod into the store - manager.jobStore.Store.Add(testJob) - received := make(chan struct{}) - // The pod update sent through the fakeWatcher should figure out the managing job and - // send it into the syncHandler. - manager.syncHandler = func(key string) error { - obj, exists, err := manager.jobStore.Store.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find job under key %v", key) - close(received) - return nil - } - job, ok := obj.(*batch.Job) - if !ok { - t.Errorf("unexpected type: %v %#v", reflect.TypeOf(obj), obj) - close(received) - return nil - } - if !api.Semantic.DeepDerivative(job, testJob) { - t.Errorf("\nExpected %#v,\nbut got %#v", testJob, job) - close(received) - return nil - } - close(received) - return nil - } - // Start only the pod watcher and the workqueue, send a watch event, - // and make sure it hits the sync method for the right job. - stopCh := make(chan struct{}) - defer close(stopCh) - go manager.Run(1, stopCh) - - pods := newPodList(1, api.PodRunning, testJob) - testPod := pods[0] - testPod.Status.Phase = api.PodFailed - fakeWatch.Add(&testPod) - - t.Log("Waiting for pod to reach syncHandler") - <-received -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/doc.go deleted file mode 100644 index 9c569bfc0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/job/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 job contains logic for watching and synchronizing jobs. -package job diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/doc.go deleted file mode 100644 index fea657af5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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. -*/ - -// namespace contains a controller that handles namespace lifecycle -package namespace diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller.go deleted file mode 100644 index 23d7fefeb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller.go +++ /dev/null @@ -1,180 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 namespace - -import ( - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/typed/dynamic" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" - - "github.com/golang/glog" -) - -// NamespaceController is responsible for performing actions dependent upon a namespace phase -type NamespaceController struct { - // client that purges namespace content, must have list/delete privileges on all content - kubeClient clientset.Interface - // clientPool manages a pool of dynamic clients - clientPool dynamic.ClientPool - // store that holds the namespaces - store cache.Store - // controller that observes the namespaces - controller *framework.Controller - // namespaces that have been queued up for processing by workers - queue *workqueue.Type - // list of preferred group versions and their corresponding resource set for namespace deletion - groupVersionResources []unversioned.GroupVersionResource - // opCache is a cache to remember if a particular operation is not supported to aid dynamic client. - opCache operationNotSupportedCache - // finalizerToken is the finalizer token managed by this controller - finalizerToken api.FinalizerName -} - -// NewNamespaceController creates a new NamespaceController -func NewNamespaceController( - kubeClient clientset.Interface, - clientPool dynamic.ClientPool, - groupVersionResources []unversioned.GroupVersionResource, - resyncPeriod time.Duration, - finalizerToken api.FinalizerName) *NamespaceController { - // create the controller so we can inject the enqueue function - namespaceController := &NamespaceController{ - kubeClient: kubeClient, - clientPool: clientPool, - queue: workqueue.New(), - groupVersionResources: groupVersionResources, - opCache: operationNotSupportedCache{}, - finalizerToken: finalizerToken, - } - - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("namespace_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - - // configure the backing store/controller - store, controller := framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().Namespaces().List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return kubeClient.Core().Namespaces().Watch(options) - }, - }, - &api.Namespace{}, - resyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - namespace := obj.(*api.Namespace) - namespaceController.enqueueNamespace(namespace) - }, - UpdateFunc: func(oldObj, newObj interface{}) { - namespace := newObj.(*api.Namespace) - namespaceController.enqueueNamespace(namespace) - }, - }, - ) - - namespaceController.store = store - namespaceController.controller = controller - return namespaceController -} - -// enqueueNamespace adds an object to the controller work queue -// obj could be an *api.Namespace, or a DeletionFinalStateUnknown item. -func (nm *NamespaceController) enqueueNamespace(obj interface{}) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - return - } - nm.queue.Add(key) -} - -// worker processes the queue of namespace objects. -// Each namespace can be in the queue at most once. -// The system ensures that no two workers can process -// the same namespace at the same time. -func (nm *NamespaceController) worker() { - for { - func() { - key, quit := nm.queue.Get() - if quit { - return - } - defer nm.queue.Done(key) - if err := nm.syncNamespaceFromKey(key.(string)); err != nil { - if estimate, ok := err.(*contentRemainingError); ok { - go func() { - defer utilruntime.HandleCrash() - t := estimate.Estimate/2 + 1 - glog.V(4).Infof("Content remaining in namespace %s, waiting %d seconds", key, t) - time.Sleep(time.Duration(t) * time.Second) - nm.queue.Add(key) - }() - } else { - // rather than wait for a full resync, re-add the namespace to the queue to be processed - nm.queue.Add(key) - utilruntime.HandleError(err) - } - } - }() - } -} - -// syncNamespaceFromKey looks for a namespace with the specified key in its store and synchronizes it -func (nm *NamespaceController) syncNamespaceFromKey(key string) (err error) { - startTime := time.Now() - defer glog.V(4).Infof("Finished syncing namespace %q (%v)", key, time.Now().Sub(startTime)) - - obj, exists, err := nm.store.GetByKey(key) - if !exists { - glog.Infof("Namespace has been deleted %v", key) - return nil - } - if err != nil { - glog.Infof("Unable to retrieve namespace %v from store: %v", key, err) - nm.queue.Add(key) - return err - } - namespace := obj.(*api.Namespace) - return syncNamespace(nm.kubeClient, nm.clientPool, nm.opCache, nm.groupVersionResources, namespace, nm.finalizerToken) -} - -// Run starts observing the system with the specified number of workers. -func (nm *NamespaceController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - go nm.controller.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(nm.worker, time.Second, stopCh) - } - <-stopCh - glog.Infof("Shutting down NamespaceController") - nm.queue.ShutDown() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller_test.go deleted file mode 100644 index b0dcd3fcf..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller_test.go +++ /dev/null @@ -1,282 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 namespace - -import ( - "fmt" - "net/http" - "net/http/httptest" - "path" - "strings" - "sync" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/client/typed/dynamic" - "k8s.io/kubernetes/pkg/util/sets" -) - -func TestFinalized(t *testing.T) { - testNamespace := &api.Namespace{ - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"a", "b"}, - }, - } - if finalized(testNamespace) { - t.Errorf("Unexpected result, namespace is not finalized") - } - testNamespace.Spec.Finalizers = []api.FinalizerName{} - if !finalized(testNamespace) { - t.Errorf("Expected object to be finalized") - } -} - -func TestFinalizeNamespaceFunc(t *testing.T) { - mockClient := &fake.Clientset{} - testNamespace := &api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - ResourceVersion: "1", - }, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"kubernetes", "other"}, - }, - } - finalizeNamespace(mockClient, testNamespace, api.FinalizerKubernetes) - actions := mockClient.Actions() - if len(actions) != 1 { - t.Errorf("Expected 1 mock client action, but got %v", len(actions)) - } - if !actions[0].Matches("create", "namespaces") || actions[0].GetSubresource() != "finalize" { - t.Errorf("Expected finalize-namespace action %v", actions[0]) - } - finalizers := actions[0].(core.CreateAction).GetObject().(*api.Namespace).Spec.Finalizers - if len(finalizers) != 1 { - t.Errorf("There should be a single finalizer remaining") - } - if "other" != string(finalizers[0]) { - t.Errorf("Unexpected finalizer value, %v", finalizers[0]) - } -} - -func testSyncNamespaceThatIsTerminating(t *testing.T, versions *unversioned.APIVersions) { - now := unversioned.Now() - namespaceName := "test" - testNamespacePendingFinalize := &api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: namespaceName, - ResourceVersion: "1", - DeletionTimestamp: &now, - }, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"kubernetes"}, - }, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - } - testNamespaceFinalizeComplete := &api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: namespaceName, - ResourceVersion: "1", - DeletionTimestamp: &now, - }, - Spec: api.NamespaceSpec{}, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - } - - // when doing a delete all of content, we will do a GET of a collection, and DELETE of a collection by default - dynamicClientActionSet := sets.NewString() - groupVersionResources := testGroupVersionResources() - for _, groupVersionResource := range groupVersionResources { - urlPath := path.Join([]string{ - dynamic.LegacyAPIPathResolverFunc(groupVersionResource.GroupVersion()), - groupVersionResource.Group, - groupVersionResource.Version, - "namespaces", - namespaceName, - groupVersionResource.Resource, - }...) - dynamicClientActionSet.Insert((&fakeAction{method: "GET", path: urlPath}).String()) - dynamicClientActionSet.Insert((&fakeAction{method: "DELETE", path: urlPath}).String()) - } - - scenarios := map[string]struct { - testNamespace *api.Namespace - kubeClientActionSet sets.String - dynamicClientActionSet sets.String - }{ - "pending-finalize": { - testNamespace: testNamespacePendingFinalize, - kubeClientActionSet: sets.NewString( - strings.Join([]string{"get", "namespaces", ""}, "-"), - strings.Join([]string{"list", "pods", ""}, "-"), - strings.Join([]string{"create", "namespaces", "finalize"}, "-"), - ), - dynamicClientActionSet: dynamicClientActionSet, - }, - "complete-finalize": { - testNamespace: testNamespaceFinalizeComplete, - kubeClientActionSet: sets.NewString( - strings.Join([]string{"get", "namespaces", ""}, "-"), - strings.Join([]string{"delete", "namespaces", ""}, "-"), - ), - dynamicClientActionSet: sets.NewString(), - }, - } - - for scenario, testInput := range scenarios { - testHandler := &fakeActionHandler{statusCode: 200} - srv, clientConfig := testServerAndClientConfig(testHandler.ServeHTTP) - defer srv.Close() - - mockClient := fake.NewSimpleClientset(testInput.testNamespace) - clientPool := dynamic.NewClientPool(clientConfig, dynamic.LegacyAPIPathResolverFunc) - - err := syncNamespace(mockClient, clientPool, operationNotSupportedCache{}, groupVersionResources, testInput.testNamespace, api.FinalizerKubernetes) - if err != nil { - t.Errorf("scenario %s - Unexpected error when synching namespace %v", scenario, err) - } - - // validate traffic from kube client - actionSet := sets.NewString() - for _, action := range mockClient.Actions() { - actionSet.Insert(strings.Join([]string{action.GetVerb(), action.GetResource().Resource, action.GetSubresource()}, "-")) - } - if !actionSet.Equal(testInput.kubeClientActionSet) { - t.Errorf("scenario %s - mock client expected actions:\n%v\n but got:\n%v\nDifference:\n%v", scenario, - testInput.kubeClientActionSet, actionSet, testInput.kubeClientActionSet.Difference(actionSet)) - } - - // validate traffic from dynamic client - actionSet = sets.NewString() - for _, action := range testHandler.actions { - actionSet.Insert(action.String()) - } - if !actionSet.Equal(testInput.dynamicClientActionSet) { - t.Errorf("scenario %s - dynamic client expected actions:\n%v\n but got:\n%v\nDifference:\n%v", scenario, - testInput.dynamicClientActionSet, actionSet, testInput.dynamicClientActionSet.Difference(actionSet)) - } - } -} - -func TestRetryOnConflictError(t *testing.T) { - mockClient := &fake.Clientset{} - numTries := 0 - retryOnce := func(kubeClient clientset.Interface, namespace *api.Namespace) (*api.Namespace, error) { - numTries++ - if numTries <= 1 { - return namespace, errors.NewConflict(api.Resource("namespaces"), namespace.Name, fmt.Errorf("ERROR!")) - } - return namespace, nil - } - namespace := &api.Namespace{} - _, err := retryOnConflictError(mockClient, namespace, retryOnce) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - if numTries != 2 { - t.Errorf("Expected %v, but got %v", 2, numTries) - } -} - -func TestSyncNamespaceThatIsTerminatingNonExperimental(t *testing.T) { - testSyncNamespaceThatIsTerminating(t, &unversioned.APIVersions{}) -} - -func TestSyncNamespaceThatIsTerminatingV1Beta1(t *testing.T) { - testSyncNamespaceThatIsTerminating(t, &unversioned.APIVersions{Versions: []string{"extensions/v1beta1"}}) -} - -func TestSyncNamespaceThatIsActive(t *testing.T) { - mockClient := &fake.Clientset{} - testNamespace := &api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - ResourceVersion: "1", - }, - Spec: api.NamespaceSpec{ - Finalizers: []api.FinalizerName{"kubernetes"}, - }, - Status: api.NamespaceStatus{ - Phase: api.NamespaceActive, - }, - } - err := syncNamespace(mockClient, nil, operationNotSupportedCache{}, testGroupVersionResources(), testNamespace, api.FinalizerKubernetes) - if err != nil { - t.Errorf("Unexpected error when synching namespace %v", err) - } - if len(mockClient.Actions()) != 0 { - t.Errorf("Expected no action from controller, but got: %v", mockClient.Actions()) - } -} - -// testServerAndClientConfig returns a server that listens and a config that can reference it -func testServerAndClientConfig(handler func(http.ResponseWriter, *http.Request)) (*httptest.Server, *restclient.Config) { - srv := httptest.NewServer(http.HandlerFunc(handler)) - config := &restclient.Config{ - Host: srv.URL, - } - return srv, config -} - -// fakeAction records information about requests to aid in testing. -type fakeAction struct { - method string - path string -} - -// String returns method=path to aid in testing -func (f *fakeAction) String() string { - return strings.Join([]string{f.method, f.path}, "=") -} - -// fakeActionHandler holds a list of fakeActions received -type fakeActionHandler struct { - // statusCode returned by this handler - statusCode int - - lock sync.Mutex - actions []fakeAction -} - -// ServeHTTP logs the action that occurred and always returns the associated status code -func (f *fakeActionHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) { - f.lock.Lock() - defer f.lock.Unlock() - - f.actions = append(f.actions, fakeAction{method: request.Method, path: request.URL.Path}) - response.WriteHeader(f.statusCode) - response.Write([]byte("{\"kind\": \"List\"}")) -} - -// testGroupVersionResources returns a mocked up set of resources across different api groups for testing namespace controller. -func testGroupVersionResources() []unversioned.GroupVersionResource { - results := []unversioned.GroupVersionResource{} - results = append(results, unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}) - results = append(results, unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}) - results = append(results, unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"}) - return results -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller_utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller_utils.go deleted file mode 100644 index dcc8b243d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/namespace/namespace_controller_utils.go +++ /dev/null @@ -1,484 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 namespace - -import ( - "fmt" - "strings" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/typed/discovery" - "k8s.io/kubernetes/pkg/client/typed/dynamic" - "k8s.io/kubernetes/pkg/runtime" - utilerrors "k8s.io/kubernetes/pkg/util/errors" - "k8s.io/kubernetes/pkg/util/sets" - - "github.com/golang/glog" -) - -// contentRemainingError is used to inform the caller that content is not fully removed from the namespace -type contentRemainingError struct { - Estimate int64 -} - -func (e *contentRemainingError) Error() string { - return fmt.Sprintf("some content remains in the namespace, estimate %d seconds before it is removed", e.Estimate) -} - -// operation is used for caching if an operation is supported on a dynamic client. -type operation string - -const ( - operationDeleteCollection operation = "deleteCollection" - operationList operation = "list" -) - -// operationKey is an entry in a cache. -type operationKey struct { - op operation - gvr unversioned.GroupVersionResource -} - -// operationNotSupportedCache is a simple cache to remember if an operation is not supported for a resource. -// if the operationKey maps to true, it means the operation is not supported. -type operationNotSupportedCache map[operationKey]bool - -// isSupported returns true if the operation is supported -func (o operationNotSupportedCache) isSupported(key operationKey) bool { - return !o[key] -} - -// updateNamespaceFunc is a function that makes an update to a namespace -type updateNamespaceFunc func(kubeClient clientset.Interface, namespace *api.Namespace) (*api.Namespace, error) - -// retryOnConflictError retries the specified fn if there was a conflict error -// TODO RetryOnConflict should be a generic concept in client code -func retryOnConflictError(kubeClient clientset.Interface, namespace *api.Namespace, fn updateNamespaceFunc) (result *api.Namespace, err error) { - latestNamespace := namespace - for { - result, err = fn(kubeClient, latestNamespace) - if err == nil { - return result, nil - } - if !errors.IsConflict(err) { - return nil, err - } - latestNamespace, err = kubeClient.Core().Namespaces().Get(latestNamespace.Name) - if err != nil { - return nil, err - } - } -} - -// updateNamespaceStatusFunc will verify that the status of the namespace is correct -func updateNamespaceStatusFunc(kubeClient clientset.Interface, namespace *api.Namespace) (*api.Namespace, error) { - if namespace.DeletionTimestamp.IsZero() || namespace.Status.Phase == api.NamespaceTerminating { - return namespace, nil - } - newNamespace := api.Namespace{} - newNamespace.ObjectMeta = namespace.ObjectMeta - newNamespace.Status = namespace.Status - newNamespace.Status.Phase = api.NamespaceTerminating - return kubeClient.Core().Namespaces().UpdateStatus(&newNamespace) -} - -// finalized returns true if the namespace.Spec.Finalizers is an empty list -func finalized(namespace *api.Namespace) bool { - return len(namespace.Spec.Finalizers) == 0 -} - -// finalizeNamespaceFunc returns a function that knows how to finalize a namespace for specified token. -func finalizeNamespaceFunc(finalizerToken api.FinalizerName) updateNamespaceFunc { - return func(kubeClient clientset.Interface, namespace *api.Namespace) (*api.Namespace, error) { - return finalizeNamespace(kubeClient, namespace, finalizerToken) - } -} - -// finalizeNamespace removes the specified finalizerToken and finalizes the namespace -func finalizeNamespace(kubeClient clientset.Interface, namespace *api.Namespace, finalizerToken api.FinalizerName) (*api.Namespace, error) { - namespaceFinalize := api.Namespace{} - namespaceFinalize.ObjectMeta = namespace.ObjectMeta - namespaceFinalize.Spec = namespace.Spec - finalizerSet := sets.NewString() - for i := range namespace.Spec.Finalizers { - if namespace.Spec.Finalizers[i] != finalizerToken { - finalizerSet.Insert(string(namespace.Spec.Finalizers[i])) - } - } - namespaceFinalize.Spec.Finalizers = make([]api.FinalizerName, 0, len(finalizerSet)) - for _, value := range finalizerSet.List() { - namespaceFinalize.Spec.Finalizers = append(namespaceFinalize.Spec.Finalizers, api.FinalizerName(value)) - } - namespace, err := kubeClient.Core().Namespaces().Finalize(&namespaceFinalize) - if err != nil { - // it was removed already, so life is good - if errors.IsNotFound(err) { - return namespace, nil - } - } - return namespace, err -} - -// deleteCollection is a helper function that will delete the collection of resources -// it returns true if the operation was supported on the server. -// it returns an error if the operation was supported on the server but was unable to complete. -func deleteCollection( - dynamicClient *dynamic.Client, - opCache operationNotSupportedCache, - gvr unversioned.GroupVersionResource, - namespace string, -) (bool, error) { - glog.V(5).Infof("namespace controller - deleteCollection - namespace: %s, gvr: %v", namespace, gvr) - - key := operationKey{op: operationDeleteCollection, gvr: gvr} - if !opCache.isSupported(key) { - glog.V(5).Infof("namespace controller - deleteCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr) - return false, nil - } - - apiResource := unversioned.APIResource{Name: gvr.Resource, Namespaced: true} - err := dynamicClient.Resource(&apiResource, namespace).DeleteCollection(nil, v1.ListOptions{}) - - if err == nil { - return true, nil - } - - // this is strange, but we need to special case for both MethodNotSupported and NotFound errors - // TODO: https://github.com/kubernetes/kubernetes/issues/22413 - // we have a resource returned in the discovery API that supports no top-level verbs: - // /apis/extensions/v1beta1/namespaces/default/replicationcontrollers - // when working with this resource type, we will get a literal not found error rather than expected method not supported - // remember next time that this resource does not support delete collection... - if errors.IsMethodNotSupported(err) || errors.IsNotFound(err) { - glog.V(5).Infof("namespace controller - deleteCollection not supported - namespace: %s, gvr: %v", namespace, gvr) - opCache[key] = true - return false, nil - } - - glog.V(5).Infof("namespace controller - deleteCollection unexpected error - namespace: %s, gvr: %v, error: %v", namespace, gvr, err) - return true, err -} - -// listCollection will list the items in the specified namespace -// it returns the following: -// the list of items in the collection (if found) -// a boolean if the operation is supported -// an error if the operation is supported but could not be completed. -func listCollection( - dynamicClient *dynamic.Client, - opCache operationNotSupportedCache, - gvr unversioned.GroupVersionResource, - namespace string, -) (*runtime.UnstructuredList, bool, error) { - glog.V(5).Infof("namespace controller - listCollection - namespace: %s, gvr: %v", namespace, gvr) - - key := operationKey{op: operationList, gvr: gvr} - if !opCache.isSupported(key) { - glog.V(5).Infof("namespace controller - listCollection ignored since not supported - namespace: %s, gvr: %v", namespace, gvr) - return nil, false, nil - } - - apiResource := unversioned.APIResource{Name: gvr.Resource, Namespaced: true} - unstructuredList, err := dynamicClient.Resource(&apiResource, namespace).List(v1.ListOptions{}) - if err == nil { - return unstructuredList, true, nil - } - - // this is strange, but we need to special case for both MethodNotSupported and NotFound errors - // TODO: https://github.com/kubernetes/kubernetes/issues/22413 - // we have a resource returned in the discovery API that supports no top-level verbs: - // /apis/extensions/v1beta1/namespaces/default/replicationcontrollers - // when working with this resource type, we will get a literal not found error rather than expected method not supported - // remember next time that this resource does not support delete collection... - if errors.IsMethodNotSupported(err) || errors.IsNotFound(err) { - glog.V(5).Infof("namespace controller - listCollection not supported - namespace: %s, gvr: %v", namespace, gvr) - opCache[key] = true - return nil, false, nil - } - - return nil, true, err -} - -// deleteEachItem is a helper function that will list the collection of resources and delete each item 1 by 1. -func deleteEachItem( - dynamicClient *dynamic.Client, - opCache operationNotSupportedCache, - gvr unversioned.GroupVersionResource, - namespace string, -) error { - glog.V(5).Infof("namespace controller - deleteEachItem - namespace: %s, gvr: %v", namespace, gvr) - - unstructuredList, listSupported, err := listCollection(dynamicClient, opCache, gvr, namespace) - if err != nil { - return err - } - if !listSupported { - return nil - } - apiResource := unversioned.APIResource{Name: gvr.Resource, Namespaced: true} - for _, item := range unstructuredList.Items { - if err = dynamicClient.Resource(&apiResource, namespace).Delete(item.GetName(), nil); err != nil && !errors.IsNotFound(err) && !errors.IsMethodNotSupported(err) { - return err - } - } - return nil -} - -// deleteAllContentForGroupVersionResource will use the dynamic client to delete each resource identified in gvr. -// It returns an estimate of the time remaining before the remaining resources are deleted. -// If estimate > 0, not all resources are guaranteed to be gone. -func deleteAllContentForGroupVersionResource( - kubeClient clientset.Interface, - clientPool dynamic.ClientPool, - opCache operationNotSupportedCache, - gvr unversioned.GroupVersionResource, - namespace string, - namespaceDeletedAt unversioned.Time, -) (int64, error) { - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - namespace: %s, gvr: %v", namespace, gvr) - - // estimate how long it will take for the resource to be deleted (needed for objects that support graceful delete) - estimate, err := estimateGracefulTermination(kubeClient, gvr, namespace, namespaceDeletedAt) - if err != nil { - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - unable to estimate - namespace: %s, gvr: %v, err: %v", namespace, gvr, err) - return estimate, err - } - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - estimate - namespace: %s, gvr: %v, estimate: %v", namespace, gvr, estimate) - - // get a client for this group version... - dynamicClient, err := clientPool.ClientForGroupVersion(gvr.GroupVersion()) - if err != nil { - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - unable to get client - namespace: %s, gvr: %v, err: %v", namespace, gvr, err) - return estimate, err - } - - // first try to delete the entire collection - deleteCollectionSupported, err := deleteCollection(dynamicClient, opCache, gvr, namespace) - if err != nil { - return estimate, err - } - - // delete collection was not supported, so we list and delete each item... - if !deleteCollectionSupported { - err = deleteEachItem(dynamicClient, opCache, gvr, namespace) - if err != nil { - return estimate, err - } - } - - // verify there are no more remaining items - // it is not an error condition for there to be remaining items if local estimate is non-zero - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - checking for no more items in namespace: %s, gvr: %v", namespace, gvr) - unstructuredList, listSupported, err := listCollection(dynamicClient, opCache, gvr, namespace) - if err != nil { - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - error verifying no items in namespace: %s, gvr: %v, err: %v", namespace, gvr, err) - return estimate, err - } - if !listSupported { - return estimate, nil - } - glog.V(5).Infof("namespace controller - deleteAllContentForGroupVersionResource - items remaining - namespace: %s, gvr: %v, items: %v", namespace, gvr, len(unstructuredList.Items)) - if len(unstructuredList.Items) != 0 && estimate == int64(0) { - return estimate, fmt.Errorf("unexpected items still remain in namespace: %s for gvr: %v", namespace, gvr) - } - return estimate, nil -} - -// deleteAllContent will use the dynamic client to delete each resource identified in groupVersionResources. -// It returns an estimate of the time remaining before the remaining resources are deleted. -// If estimate > 0, not all resources are guaranteed to be gone. -func deleteAllContent( - kubeClient clientset.Interface, - clientPool dynamic.ClientPool, - opCache operationNotSupportedCache, - groupVersionResources []unversioned.GroupVersionResource, - namespace string, - namespaceDeletedAt unversioned.Time, -) (int64, error) { - estimate := int64(0) - glog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s, gvrs: %v", namespace, groupVersionResources) - // iterate over each group version, and attempt to delete all of its resources - for _, gvr := range groupVersionResources { - gvrEstimate, err := deleteAllContentForGroupVersionResource(kubeClient, clientPool, opCache, gvr, namespace, namespaceDeletedAt) - if err != nil { - return estimate, err - } - if gvrEstimate > estimate { - estimate = gvrEstimate - } - } - glog.V(4).Infof("namespace controller - deleteAllContent - namespace: %s, estimate: %v", namespace, estimate) - return estimate, nil -} - -// syncNamespace orchestrates deletion of a Namespace and its associated content. -func syncNamespace( - kubeClient clientset.Interface, - clientPool dynamic.ClientPool, - opCache operationNotSupportedCache, - groupVersionResources []unversioned.GroupVersionResource, - namespace *api.Namespace, - finalizerToken api.FinalizerName, -) error { - if namespace.DeletionTimestamp == nil { - return nil - } - - // multiple controllers may edit a namespace during termination - // first get the latest state of the namespace before proceeding - // if the namespace was deleted already, don't do anything - namespace, err := kubeClient.Core().Namespaces().Get(namespace.Name) - if err != nil { - if errors.IsNotFound(err) { - return nil - } - return err - } - - glog.V(5).Infof("namespace controller - syncNamespace - namespace: %s, finalizerToken: %s", namespace.Name, finalizerToken) - - // ensure that the status is up to date on the namespace - // if we get a not found error, we assume the namespace is truly gone - namespace, err = retryOnConflictError(kubeClient, namespace, updateNamespaceStatusFunc) - if err != nil { - if errors.IsNotFound(err) { - return nil - } - return err - } - - // if the namespace is already finalized, delete it - if finalized(namespace) { - err = kubeClient.Core().Namespaces().Delete(namespace.Name, nil) - if err != nil && !errors.IsNotFound(err) { - return err - } - return nil - } - - // there may still be content for us to remove - estimate, err := deleteAllContent(kubeClient, clientPool, opCache, groupVersionResources, namespace.Name, *namespace.DeletionTimestamp) - if err != nil { - return err - } - if estimate > 0 { - return &contentRemainingError{estimate} - } - - // we have removed content, so mark it finalized by us - result, err := retryOnConflictError(kubeClient, namespace, finalizeNamespaceFunc(finalizerToken)) - if err != nil { - // in normal practice, this should not be possible, but if a deployment is running - // two controllers to do namespace deletion that share a common finalizer token it's - // possible that a not found could occur since the other controller would have finished the delete. - if errors.IsNotFound(err) { - return nil - } - return err - } - - // now check if all finalizers have reported that we delete now - if finalized(result) { - err = kubeClient.Core().Namespaces().Delete(namespace.Name, nil) - if err != nil && !errors.IsNotFound(err) { - return err - } - } - - return nil -} - -// estimateGrracefulTermination will estimate the graceful termination required for the specific entity in the namespace -func estimateGracefulTermination(kubeClient clientset.Interface, groupVersionResource unversioned.GroupVersionResource, ns string, namespaceDeletedAt unversioned.Time) (int64, error) { - groupResource := groupVersionResource.GroupResource() - glog.V(5).Infof("namespace controller - estimateGracefulTermination - group %s, resource: %s", groupResource.Group, groupResource.Resource) - estimate := int64(0) - var err error - switch groupResource { - case unversioned.GroupResource{Group: "", Resource: "pods"}: - estimate, err = estimateGracefulTerminationForPods(kubeClient, ns) - } - if err != nil { - return estimate, err - } - // determine if the estimate is greater than the deletion timestamp - duration := time.Since(namespaceDeletedAt.Time) - allowedEstimate := time.Duration(estimate) * time.Second - if duration >= allowedEstimate { - estimate = int64(0) - } - return estimate, nil -} - -// estimateGracefulTerminationForPods determines the graceful termination period for pods in the namespace -func estimateGracefulTerminationForPods(kubeClient clientset.Interface, ns string) (int64, error) { - glog.V(5).Infof("namespace controller - estimateGracefulTerminationForPods - namespace %s", ns) - estimate := int64(0) - items, err := kubeClient.Core().Pods(ns).List(api.ListOptions{}) - if err != nil { - return estimate, err - } - for i := range items.Items { - // filter out terminal pods - phase := items.Items[i].Status.Phase - if api.PodSucceeded == phase || api.PodFailed == phase { - continue - } - if items.Items[i].Spec.TerminationGracePeriodSeconds != nil { - grace := *items.Items[i].Spec.TerminationGracePeriodSeconds - if grace > estimate { - estimate = grace - } - } - } - return estimate, nil -} - -// ServerPreferredNamespacedGroupVersionResources uses the specified client to discover the set of preferred groupVersionResources that are namespaced -func ServerPreferredNamespacedGroupVersionResources(discoveryClient discovery.DiscoveryInterface) ([]unversioned.GroupVersionResource, error) { - results := []unversioned.GroupVersionResource{} - serverGroupList, err := discoveryClient.ServerGroups() - if err != nil { - return results, err - } - - allErrs := []error{} - for _, apiGroup := range serverGroupList.Groups { - preferredVersion := apiGroup.PreferredVersion - apiResourceList, err := discoveryClient.ServerResourcesForGroupVersion(preferredVersion.GroupVersion) - if err != nil { - allErrs = append(allErrs, err) - continue - } - groupVersion := unversioned.GroupVersion{Group: apiGroup.Name, Version: preferredVersion.Version} - for _, apiResource := range apiResourceList.APIResources { - if !apiResource.Namespaced { - continue - } - if strings.Contains(apiResource.Name, "/") { - continue - } - results = append(results, groupVersion.WithResource(apiResource.Name)) - } - } - return results, utilerrors.NewAggregate(allErrs) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/doc.go deleted file mode 100644 index 084754e69..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 node contains code for syncing cloud instances with -// node registry -package node diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/nodecontroller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/nodecontroller.go deleted file mode 100644 index af87c3688..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/nodecontroller.go +++ /dev/null @@ -1,949 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 node - -import ( - "errors" - "fmt" - "net" - "strings" - "sync" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/kubelet/util/format" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/flowcontrol" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/version" - "k8s.io/kubernetes/pkg/watch" -) - -var ( - ErrCloudInstance = errors.New("cloud provider doesn't support instances.") -) - -const ( - // nodeStatusUpdateRetry controls the number of retries of writing NodeStatus update. - nodeStatusUpdateRetry = 5 - // controls how often NodeController will try to evict Pods from non-responsive Nodes. - nodeEvictionPeriod = 100 * time.Millisecond -) - -type nodeStatusData struct { - probeTimestamp unversioned.Time - readyTransitionTimestamp unversioned.Time - status api.NodeStatus -} - -type NodeController struct { - allocateNodeCIDRs bool - cloud cloudprovider.Interface - clusterCIDR *net.IPNet - deletingPodsRateLimiter flowcontrol.RateLimiter - knownNodeSet sets.String - kubeClient clientset.Interface - // Method for easy mocking in unittest. - lookupIP func(host string) ([]net.IP, error) - // Value used if sync_nodes_status=False. NodeController will not proactively - // sync node status in this case, but will monitor node status updated from kubelet. If - // it doesn't receive update for this amount of time, it will start posting "NodeReady== - // ConditionUnknown". The amount of time before which NodeController start evicting pods - // is controlled via flag 'pod-eviction-timeout'. - // Note: be cautious when changing the constant, it must work with nodeStatusUpdateFrequency - // in kubelet. There are several constraints: - // 1. nodeMonitorGracePeriod must be N times more than nodeStatusUpdateFrequency, where - // N means number of retries allowed for kubelet to post node status. It is pointless - // to make nodeMonitorGracePeriod be less than nodeStatusUpdateFrequency, since there - // will only be fresh values from Kubelet at an interval of nodeStatusUpdateFrequency. - // The constant must be less than podEvictionTimeout. - // 2. nodeMonitorGracePeriod can't be too large for user experience - larger value takes - // longer for user to see up-to-date node status. - nodeMonitorGracePeriod time.Duration - // Value controlling NodeController monitoring period, i.e. how often does NodeController - // check node status posted from kubelet. This value should be lower than nodeMonitorGracePeriod. - // TODO: Change node status monitor to watch based. - nodeMonitorPeriod time.Duration - // Value used if sync_nodes_status=False, only for node startup. When node - // is just created, e.g. cluster bootstrap or node creation, we give a longer grace period. - nodeStartupGracePeriod time.Duration - // per Node map storing last observed Status together with a local time when it was observed. - // This timestamp is to be used instead of LastProbeTime stored in Condition. We do this - // to aviod the problem with time skew across the cluster. - nodeStatusMap map[string]nodeStatusData - now func() unversioned.Time - // Lock to access evictor workers - evictorLock *sync.Mutex - // workers that evicts pods from unresponsive nodes. - podEvictor *RateLimitedTimedQueue - terminationEvictor *RateLimitedTimedQueue - podEvictionTimeout time.Duration - // The maximum duration before a pod evicted from a node can be forcefully terminated. - maximumGracePeriod time.Duration - recorder record.EventRecorder - // Pod framework and store - podController *framework.Controller - podStore cache.StoreToPodLister - // Node framework and store - nodeController *framework.Controller - nodeStore cache.StoreToNodeLister - // DaemonSet framework and store - daemonSetController *framework.Controller - daemonSetStore cache.StoreToDaemonSetLister - - forcefullyDeletePod func(*api.Pod) error - nodeExistsInCloudProvider func(string) (bool, error) -} - -// NewNodeController returns a new node controller to sync instances from cloudprovider. -func NewNodeController( - cloud cloudprovider.Interface, - kubeClient clientset.Interface, - podEvictionTimeout time.Duration, - deletionEvictionLimiter flowcontrol.RateLimiter, - terminationEvictionLimiter flowcontrol.RateLimiter, - nodeMonitorGracePeriod time.Duration, - nodeStartupGracePeriod time.Duration, - nodeMonitorPeriod time.Duration, - clusterCIDR *net.IPNet, - allocateNodeCIDRs bool) *NodeController { - eventBroadcaster := record.NewBroadcaster() - recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "controllermanager"}) - eventBroadcaster.StartLogging(glog.Infof) - if kubeClient != nil { - glog.Infof("Sending events to api server.") - eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) - } else { - glog.Infof("No api server defined - no events will be sent to API server.") - } - - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("node_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - - if allocateNodeCIDRs && clusterCIDR == nil { - glog.Fatal("NodeController: Must specify clusterCIDR if allocateNodeCIDRs == true.") - } - evictorLock := sync.Mutex{} - - nc := &NodeController{ - cloud: cloud, - knownNodeSet: make(sets.String), - kubeClient: kubeClient, - recorder: recorder, - podEvictionTimeout: podEvictionTimeout, - maximumGracePeriod: 5 * time.Minute, - evictorLock: &evictorLock, - podEvictor: NewRateLimitedTimedQueue(deletionEvictionLimiter), - terminationEvictor: NewRateLimitedTimedQueue(terminationEvictionLimiter), - nodeStatusMap: make(map[string]nodeStatusData), - nodeMonitorGracePeriod: nodeMonitorGracePeriod, - nodeMonitorPeriod: nodeMonitorPeriod, - nodeStartupGracePeriod: nodeStartupGracePeriod, - lookupIP: net.LookupIP, - now: unversioned.Now, - clusterCIDR: clusterCIDR, - allocateNodeCIDRs: allocateNodeCIDRs, - forcefullyDeletePod: func(p *api.Pod) error { return forcefullyDeletePod(kubeClient, p) }, - nodeExistsInCloudProvider: func(nodeName string) (bool, error) { return nodeExistsInCloudProvider(cloud, nodeName) }, - } - - nc.podStore.Indexer, nc.podController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return nc.kubeClient.Core().Pods(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return nc.kubeClient.Core().Pods(api.NamespaceAll).Watch(options) - }, - }, - &api.Pod{}, - controller.NoResyncPeriodFunc(), - framework.ResourceEventHandlerFuncs{ - AddFunc: nc.maybeDeleteTerminatingPod, - UpdateFunc: func(_, obj interface{}) { nc.maybeDeleteTerminatingPod(obj) }, - }, - // We don't need to build a index for podStore here actually, but build one for consistency. - // It will ensure that if people start making use of the podStore in more specific ways, - // they'll get the benefits they expect. It will also reserve the name for future refactorings. - cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, - ) - nc.nodeStore.Store, nc.nodeController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return nc.kubeClient.Core().Nodes().List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return nc.kubeClient.Core().Nodes().Watch(options) - }, - }, - &api.Node{}, - controller.NoResyncPeriodFunc(), - framework.ResourceEventHandlerFuncs{}, - ) - nc.daemonSetStore.Store, nc.daemonSetController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return nc.kubeClient.Extensions().DaemonSets(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return nc.kubeClient.Extensions().DaemonSets(api.NamespaceAll).Watch(options) - }, - }, - &extensions.DaemonSet{}, - controller.NoResyncPeriodFunc(), - framework.ResourceEventHandlerFuncs{}, - ) - return nc -} - -// Run starts an asynchronous loop that monitors the status of cluster nodes. -func (nc *NodeController) Run(period time.Duration) { - go nc.nodeController.Run(wait.NeverStop) - go nc.podController.Run(wait.NeverStop) - go nc.daemonSetController.Run(wait.NeverStop) - - // Incorporate the results of node status pushed from kubelet to master. - go wait.Until(func() { - if err := nc.monitorNodeStatus(); err != nil { - glog.Errorf("Error monitoring node status: %v", err) - } - }, nc.nodeMonitorPeriod, wait.NeverStop) - - // Managing eviction of nodes: - // 1. when we delete pods off a node, if the node was not empty at the time we then - // queue a termination watcher - // a. If we hit an error, retry deletion - // 2. The terminator loop ensures that pods are eventually cleaned and we never - // terminate a pod in a time period less than nc.maximumGracePeriod. AddedAt - // is the time from which we measure "has this pod been terminating too long", - // after which we will delete the pod with grace period 0 (force delete). - // a. If we hit errors, retry instantly - // b. If there are no pods left terminating, exit - // c. If there are pods still terminating, wait for their estimated completion - // before retrying - go wait.Until(func() { - nc.evictorLock.Lock() - defer nc.evictorLock.Unlock() - nc.podEvictor.Try(func(value TimedValue) (bool, time.Duration) { - remaining, err := nc.deletePods(value.Value) - if err != nil { - utilruntime.HandleError(fmt.Errorf("unable to evict node %q: %v", value.Value, err)) - return false, 0 - } - - if remaining { - nc.terminationEvictor.Add(value.Value) - } - return true, 0 - }) - }, nodeEvictionPeriod, wait.NeverStop) - - // TODO: replace with a controller that ensures pods that are terminating complete - // in a particular time period - go wait.Until(func() { - nc.evictorLock.Lock() - defer nc.evictorLock.Unlock() - nc.terminationEvictor.Try(func(value TimedValue) (bool, time.Duration) { - completed, remaining, err := nc.terminatePods(value.Value, value.AddedAt) - if err != nil { - utilruntime.HandleError(fmt.Errorf("unable to terminate pods on node %q: %v", value.Value, err)) - return false, 0 - } - - if completed { - glog.Infof("All pods terminated on %s", value.Value) - nc.recordNodeEvent(value.Value, api.EventTypeNormal, "TerminatedAllPods", fmt.Sprintf("Terminated all Pods on Node %s.", value.Value)) - return true, 0 - } - - glog.V(2).Infof("Pods terminating since %s on %q, estimated completion %s", value.AddedAt, value.Value, remaining) - // clamp very short intervals - if remaining < nodeEvictionPeriod { - remaining = nodeEvictionPeriod - } - return false, remaining - }) - }, nodeEvictionPeriod, wait.NeverStop) - - go wait.Until(nc.cleanupOrphanedPods, 30*time.Second, wait.NeverStop) -} - -// Generates num pod CIDRs that could be assigned to nodes. -func generateCIDRs(clusterCIDR *net.IPNet, num int) sets.String { - res := sets.NewString() - cidrIP := clusterCIDR.IP.To4() - for i := 0; i < num; i++ { - // TODO: Make the CIDRs configurable. - b1 := byte(i >> 8) - b2 := byte(i % 256) - res.Insert(fmt.Sprintf("%d.%d.%d.0/24", cidrIP[0], cidrIP[1]+b1, cidrIP[2]+b2)) - } - return res -} - -// getCondition returns a condition object for the specific condition -// type, nil if the condition is not set. -func (nc *NodeController) getCondition(status *api.NodeStatus, conditionType api.NodeConditionType) *api.NodeCondition { - if status == nil { - return nil - } - for i := range status.Conditions { - if status.Conditions[i].Type == conditionType { - return &status.Conditions[i] - } - } - return nil -} - -var gracefulDeletionVersion = version.MustParse("v1.1.0") - -// maybeDeleteTerminatingPod non-gracefully deletes pods that are terminating -// that should not be gracefully terminated. -func (nc *NodeController) maybeDeleteTerminatingPod(obj interface{}) { - pod, ok := obj.(*api.Pod) - if !ok { - return - } - - // consider only terminating pods - if pod.DeletionTimestamp == nil { - return - } - - // delete terminating pods that have not yet been scheduled - if len(pod.Spec.NodeName) == 0 { - utilruntime.HandleError(nc.forcefullyDeletePod(pod)) - return - } - - nodeObj, found, err := nc.nodeStore.GetByKey(pod.Spec.NodeName) - if err != nil { - // this can only happen if the Store.KeyFunc has a problem creating - // a key for the pod. If it happens once, it will happen again so - // don't bother requeuing the pod. - utilruntime.HandleError(err) - return - } - - // delete terminating pods that have been scheduled on - // nonexistent nodes - if !found { - utilruntime.HandleError(nc.forcefullyDeletePod(pod)) - return - } - - // delete terminating pods that have been scheduled on - // nodes that do not support graceful termination - // TODO(mikedanese): this can be removed when we no longer - // guarantee backwards compatibility of master API to kubelets with - // versions less than 1.1.0 - node := nodeObj.(*api.Node) - v, err := version.Parse(node.Status.NodeInfo.KubeletVersion) - if err != nil { - glog.Infof("couldn't parse verions %q of minion: %v", node.Status.NodeInfo.KubeletVersion, err) - utilruntime.HandleError(nc.forcefullyDeletePod(pod)) - return - } - if gracefulDeletionVersion.GT(v) { - utilruntime.HandleError(nc.forcefullyDeletePod(pod)) - return - } -} - -// cleanupOrphanedPods deletes pods that are bound to nodes that don't -// exist. -func (nc *NodeController) cleanupOrphanedPods() { - pods, err := nc.podStore.List(labels.Everything()) - if err != nil { - utilruntime.HandleError(err) - return - } - - for _, pod := range pods { - if pod.Spec.NodeName == "" { - continue - } - if _, exists, _ := nc.nodeStore.Store.GetByKey(pod.Spec.NodeName); exists { - continue - } - if err := nc.forcefullyDeletePod(pod); err != nil { - utilruntime.HandleError(err) - } - } -} - -func forcefullyDeletePod(c clientset.Interface, pod *api.Pod) error { - var zero int64 - err := c.Core().Pods(pod.Namespace).Delete(pod.Name, &api.DeleteOptions{GracePeriodSeconds: &zero}) - if err == nil { - glog.Infof("forceful deletion of %s succeeded", pod.Name) - } - return err -} - -// monitorNodeStatus verifies node status are constantly updated by kubelet, and if not, -// post "NodeReady==ConditionUnknown". It also evicts all pods if node is not ready or -// not reachable for a long period of time. -func (nc *NodeController) monitorNodeStatus() error { - nodes, err := nc.kubeClient.Core().Nodes().List(api.ListOptions{}) - if err != nil { - return err - } - for _, node := range nodes.Items { - if !nc.knownNodeSet.Has(node.Name) { - glog.V(1).Infof("NodeController observed a new Node: %#v", node) - nc.recordNodeEvent(node.Name, api.EventTypeNormal, "RegisteredNode", fmt.Sprintf("Registered Node %v in NodeController", node.Name)) - nc.cancelPodEviction(node.Name) - nc.knownNodeSet.Insert(node.Name) - } - } - // If there's a difference between lengths of known Nodes and observed nodes - // we must have removed some Node. - if len(nc.knownNodeSet) != len(nodes.Items) { - observedSet := make(sets.String) - for _, node := range nodes.Items { - observedSet.Insert(node.Name) - } - deleted := nc.knownNodeSet.Difference(observedSet) - for nodeName := range deleted { - glog.V(1).Infof("NodeController observed a Node deletion: %v", nodeName) - nc.recordNodeEvent(nodeName, api.EventTypeNormal, "RemovingNode", fmt.Sprintf("Removing Node %v from NodeController", nodeName)) - nc.evictPods(nodeName) - nc.knownNodeSet.Delete(nodeName) - } - } - - if nc.allocateNodeCIDRs { - // TODO (cjcullen): Use pkg/controller/framework to watch nodes and - // reduce lists/decouple this from monitoring status. - nc.reconcileNodeCIDRs(nodes) - } - for i := range nodes.Items { - var gracePeriod time.Duration - var lastReadyCondition api.NodeCondition - var readyCondition *api.NodeCondition - node := &nodes.Items[i] - for rep := 0; rep < nodeStatusUpdateRetry; rep++ { - gracePeriod, lastReadyCondition, readyCondition, err = nc.tryUpdateNodeStatus(node) - if err == nil { - break - } - name := node.Name - node, err = nc.kubeClient.Core().Nodes().Get(name) - if err != nil { - glog.Errorf("Failed while getting a Node to retry updating NodeStatus. Probably Node %s was deleted.", name) - break - } - } - if err != nil { - glog.Errorf("Update status of Node %v from NodeController exceeds retry count."+ - "Skipping - no pods will be evicted.", node.Name) - continue - } - - decisionTimestamp := nc.now() - - if readyCondition != nil { - // Check eviction timeout against decisionTimestamp - if lastReadyCondition.Status == api.ConditionFalse && - decisionTimestamp.After(nc.nodeStatusMap[node.Name].readyTransitionTimestamp.Add(nc.podEvictionTimeout)) { - if nc.evictPods(node.Name) { - glog.V(4).Infof("Evicting pods on node %s: %v is later than %v + %v", node.Name, decisionTimestamp, nc.nodeStatusMap[node.Name].readyTransitionTimestamp, nc.podEvictionTimeout) - } - } - if lastReadyCondition.Status == api.ConditionUnknown && - decisionTimestamp.After(nc.nodeStatusMap[node.Name].probeTimestamp.Add(nc.podEvictionTimeout)) { - if nc.evictPods(node.Name) { - glog.V(4).Infof("Evicting pods on node %s: %v is later than %v + %v", node.Name, decisionTimestamp, nc.nodeStatusMap[node.Name].readyTransitionTimestamp, nc.podEvictionTimeout-gracePeriod) - } - } - if lastReadyCondition.Status == api.ConditionTrue { - if nc.cancelPodEviction(node.Name) { - glog.V(2).Infof("Node %s is ready again, cancelled pod eviction", node.Name) - } - } - - // Report node event. - if readyCondition.Status != api.ConditionTrue && lastReadyCondition.Status == api.ConditionTrue { - nc.recordNodeStatusChange(node, "NodeNotReady") - if err = nc.markAllPodsNotReady(node.Name); err != nil { - utilruntime.HandleError(fmt.Errorf("Unable to mark all pods NotReady on node %v: %v", node.Name, err)) - } - } - - // Check with the cloud provider to see if the node still exists. If it - // doesn't, delete the node immediately. - if readyCondition.Status != api.ConditionTrue && nc.cloud != nil { - exists, err := nc.nodeExistsInCloudProvider(node.Name) - if err != nil { - glog.Errorf("Error determining if node %v exists in cloud: %v", node.Name, err) - continue - } - if !exists { - glog.Infof("Deleting node (no longer present in cloud provider): %s", node.Name) - nc.recordNodeEvent(node.Name, api.EventTypeNormal, "DeletingNode", fmt.Sprintf("Deleting Node %v because it's not present according to cloud provider", node.Name)) - go func(nodeName string) { - defer utilruntime.HandleCrash() - // Kubelet is not reporting and Cloud Provider says node - // is gone. Delete it without worrying about grace - // periods. - if err := nc.forcefullyDeleteNode(nodeName); err != nil { - glog.Errorf("Unable to forcefully delete node %q: %v", nodeName, err) - } - }(node.Name) - continue - } - } - } - } - return nil -} - -func nodeExistsInCloudProvider(cloud cloudprovider.Interface, nodeName string) (bool, error) { - instances, ok := cloud.Instances() - if !ok { - return false, fmt.Errorf("%v", ErrCloudInstance) - } - if _, err := instances.ExternalID(nodeName); err != nil { - if err == cloudprovider.InstanceNotFound { - return false, nil - } - return false, err - } - return true, nil -} - -// forcefullyDeleteNode immediately deletes all pods on the node, and then -// deletes the node itself. -func (nc *NodeController) forcefullyDeleteNode(nodeName string) error { - selector := fields.OneTermEqualSelector(api.PodHostField, nodeName) - options := api.ListOptions{FieldSelector: selector} - pods, err := nc.kubeClient.Core().Pods(api.NamespaceAll).List(options) - if err != nil { - return fmt.Errorf("unable to list pods on node %q: %v", nodeName, err) - } - for _, pod := range pods.Items { - if pod.Spec.NodeName != nodeName { - continue - } - if err := nc.forcefullyDeletePod(&pod); err != nil { - return fmt.Errorf("unable to delete pod %q on node %q: %v", pod.Name, nodeName, err) - } - } - if err := nc.kubeClient.Core().Nodes().Delete(nodeName, nil); err != nil { - return fmt.Errorf("unable to delete node %q: %v", nodeName, err) - } - return nil -} - -// reconcileNodeCIDRs looks at each node and assigns it a valid CIDR -// if it doesn't currently have one. -func (nc *NodeController) reconcileNodeCIDRs(nodes *api.NodeList) { - glog.V(4).Infof("Reconciling cidrs for %d nodes", len(nodes.Items)) - // TODO(roberthbailey): This seems inefficient. Why re-calculate CIDRs - // on each sync period? - availableCIDRs := generateCIDRs(nc.clusterCIDR, len(nodes.Items)) - for _, node := range nodes.Items { - if node.Spec.PodCIDR != "" { - glog.V(4).Infof("CIDR %s is already being used by node %s", node.Spec.PodCIDR, node.Name) - availableCIDRs.Delete(node.Spec.PodCIDR) - } - } - for _, node := range nodes.Items { - if node.Spec.PodCIDR == "" { - // Re-GET node (because ours might be stale by now). - n, err := nc.kubeClient.Core().Nodes().Get(node.Name) - if err != nil { - glog.Errorf("Failed to get node %q: %v", node.Name, err) - continue - } - podCIDR, found := availableCIDRs.PopAny() - if !found { - nc.recordNodeStatusChange(n, "CIDRNotAvailable") - continue - } - glog.V(1).Infof("Assigning node %s CIDR %s", n.Name, podCIDR) - n.Spec.PodCIDR = podCIDR - if _, err := nc.kubeClient.Core().Nodes().Update(n); err != nil { - nc.recordNodeStatusChange(&node, "CIDRAssignmentFailed") - } - } - - } -} - -func (nc *NodeController) recordNodeEvent(nodeName, eventtype, reason, event string) { - ref := &api.ObjectReference{ - Kind: "Node", - Name: nodeName, - UID: types.UID(nodeName), - Namespace: "", - } - glog.V(2).Infof("Recording %s event message for node %s", event, nodeName) - nc.recorder.Eventf(ref, eventtype, reason, "Node %s event: %s", nodeName, event) -} - -func (nc *NodeController) recordNodeStatusChange(node *api.Node, new_status string) { - ref := &api.ObjectReference{ - Kind: "Node", - Name: node.Name, - UID: types.UID(node.Name), - Namespace: "", - } - glog.V(2).Infof("Recording status change %s event message for node %s", new_status, node.Name) - // TODO: This requires a transaction, either both node status is updated - // and event is recorded or neither should happen, see issue #6055. - nc.recorder.Eventf(ref, api.EventTypeNormal, new_status, "Node %s status is now: %s", node.Name, new_status) -} - -// For a given node checks its conditions and tries to update it. Returns grace period to which given node -// is entitled, state of current and last observed Ready Condition, and an error if it occurred. -func (nc *NodeController) tryUpdateNodeStatus(node *api.Node) (time.Duration, api.NodeCondition, *api.NodeCondition, error) { - var err error - var gracePeriod time.Duration - var lastReadyCondition api.NodeCondition - readyCondition := nc.getCondition(&node.Status, api.NodeReady) - if readyCondition == nil { - // If ready condition is nil, then kubelet (or nodecontroller) never posted node status. - // A fake ready condition is created, where LastProbeTime and LastTransitionTime is set - // to node.CreationTimestamp to avoid handle the corner case. - lastReadyCondition = api.NodeCondition{ - Type: api.NodeReady, - Status: api.ConditionUnknown, - LastHeartbeatTime: node.CreationTimestamp, - LastTransitionTime: node.CreationTimestamp, - } - gracePeriod = nc.nodeStartupGracePeriod - nc.nodeStatusMap[node.Name] = nodeStatusData{ - status: node.Status, - probeTimestamp: node.CreationTimestamp, - readyTransitionTimestamp: node.CreationTimestamp, - } - } else { - // If ready condition is not nil, make a copy of it, since we may modify it in place later. - lastReadyCondition = *readyCondition - gracePeriod = nc.nodeMonitorGracePeriod - } - - savedNodeStatus, found := nc.nodeStatusMap[node.Name] - // There are following cases to check: - // - both saved and new status have no Ready Condition set - we leave everything as it is, - // - saved status have no Ready Condition, but current one does - NodeController was restarted with Node data already present in etcd, - // - saved status have some Ready Condition, but current one does not - it's an error, but we fill it up because that's probably a good thing to do, - // - both saved and current statuses have Ready Conditions and they have the same LastProbeTime - nothing happened on that Node, it may be - // unresponsive, so we leave it as it is, - // - both saved and current statuses have Ready Conditions, they have different LastProbeTimes, but the same Ready Condition State - - // everything's in order, no transition occurred, we update only probeTimestamp, - // - both saved and current statuses have Ready Conditions, different LastProbeTimes and different Ready Condition State - - // Ready Condition changed it state since we last seen it, so we update both probeTimestamp and readyTransitionTimestamp. - // TODO: things to consider: - // - if 'LastProbeTime' have gone back in time its probably an error, currently we ignore it, - // - currently only correct Ready State transition outside of Node Controller is marking it ready by Kubelet, we don't check - // if that's the case, but it does not seem necessary. - var savedCondition *api.NodeCondition - if found { - savedCondition = nc.getCondition(&savedNodeStatus.status, api.NodeReady) - } - observedCondition := nc.getCondition(&node.Status, api.NodeReady) - if !found { - glog.Warningf("Missing timestamp for Node %s. Assuming now as a timestamp.", node.Name) - savedNodeStatus = nodeStatusData{ - status: node.Status, - probeTimestamp: nc.now(), - readyTransitionTimestamp: nc.now(), - } - nc.nodeStatusMap[node.Name] = savedNodeStatus - } else if savedCondition == nil && observedCondition != nil { - glog.V(1).Infof("Creating timestamp entry for newly observed Node %s", node.Name) - savedNodeStatus = nodeStatusData{ - status: node.Status, - probeTimestamp: nc.now(), - readyTransitionTimestamp: nc.now(), - } - nc.nodeStatusMap[node.Name] = savedNodeStatus - } else if savedCondition != nil && observedCondition == nil { - glog.Errorf("ReadyCondition was removed from Status of Node %s", node.Name) - // TODO: figure out what to do in this case. For now we do the same thing as above. - savedNodeStatus = nodeStatusData{ - status: node.Status, - probeTimestamp: nc.now(), - readyTransitionTimestamp: nc.now(), - } - nc.nodeStatusMap[node.Name] = savedNodeStatus - } else if savedCondition != nil && observedCondition != nil && savedCondition.LastHeartbeatTime != observedCondition.LastHeartbeatTime { - var transitionTime unversioned.Time - // If ReadyCondition changed since the last time we checked, we update the transition timestamp to "now", - // otherwise we leave it as it is. - if savedCondition.LastTransitionTime != observedCondition.LastTransitionTime { - glog.V(3).Infof("ReadyCondition for Node %s transitioned from %v to %v", node.Name, savedCondition.Status, observedCondition) - - transitionTime = nc.now() - } else { - transitionTime = savedNodeStatus.readyTransitionTimestamp - } - if glog.V(5) { - glog.Infof("Node %s ReadyCondition updated. Updating timestamp: %+v vs %+v.", node.Name, savedNodeStatus.status, node.Status) - } else { - glog.V(3).Infof("Node %s ReadyCondition updated. Updating timestamp.", node.Name) - } - savedNodeStatus = nodeStatusData{ - status: node.Status, - probeTimestamp: nc.now(), - readyTransitionTimestamp: transitionTime, - } - nc.nodeStatusMap[node.Name] = savedNodeStatus - } - - if nc.now().After(savedNodeStatus.probeTimestamp.Add(gracePeriod)) { - // NodeReady condition was last set longer ago than gracePeriod, so update it to Unknown - // (regardless of its current value) in the master. - if readyCondition == nil { - glog.V(2).Infof("node %v is never updated by kubelet", node.Name) - node.Status.Conditions = append(node.Status.Conditions, api.NodeCondition{ - Type: api.NodeReady, - Status: api.ConditionUnknown, - Reason: "NodeStatusNeverUpdated", - Message: fmt.Sprintf("Kubelet never posted node status."), - LastHeartbeatTime: node.CreationTimestamp, - LastTransitionTime: nc.now(), - }) - } else { - glog.V(4).Infof("node %v hasn't been updated for %+v. Last ready condition is: %+v", - node.Name, nc.now().Time.Sub(savedNodeStatus.probeTimestamp.Time), lastReadyCondition) - if lastReadyCondition.Status != api.ConditionUnknown { - readyCondition.Status = api.ConditionUnknown - readyCondition.Reason = "NodeStatusUnknown" - readyCondition.Message = fmt.Sprintf("Kubelet stopped posting node status.") - // LastProbeTime is the last time we heard from kubelet. - readyCondition.LastHeartbeatTime = lastReadyCondition.LastHeartbeatTime - readyCondition.LastTransitionTime = nc.now() - } - } - - // Like NodeReady condition, NodeOutOfDisk was last set longer ago than gracePeriod, so update - // it to Unknown (regardless of its current value) in the master. - // TODO(madhusudancs): Refactor this with readyCondition to remove duplicated code. - oodCondition := nc.getCondition(&node.Status, api.NodeOutOfDisk) - if oodCondition == nil { - glog.V(2).Infof("Out of disk condition of node %v is never updated by kubelet", node.Name) - node.Status.Conditions = append(node.Status.Conditions, api.NodeCondition{ - Type: api.NodeOutOfDisk, - Status: api.ConditionUnknown, - Reason: "NodeStatusNeverUpdated", - Message: fmt.Sprintf("Kubelet never posted node status."), - LastHeartbeatTime: node.CreationTimestamp, - LastTransitionTime: nc.now(), - }) - } else { - glog.V(4).Infof("node %v hasn't been updated for %+v. Last out of disk condition is: %+v", - node.Name, nc.now().Time.Sub(savedNodeStatus.probeTimestamp.Time), oodCondition) - if oodCondition.Status != api.ConditionUnknown { - oodCondition.Status = api.ConditionUnknown - oodCondition.Reason = "NodeStatusUnknown" - oodCondition.Message = fmt.Sprintf("Kubelet stopped posting node status.") - oodCondition.LastTransitionTime = nc.now() - } - } - - if !api.Semantic.DeepEqual(nc.getCondition(&node.Status, api.NodeReady), &lastReadyCondition) { - if _, err = nc.kubeClient.Core().Nodes().UpdateStatus(node); err != nil { - glog.Errorf("Error updating node %s: %v", node.Name, err) - return gracePeriod, lastReadyCondition, readyCondition, err - } else { - nc.nodeStatusMap[node.Name] = nodeStatusData{ - status: node.Status, - probeTimestamp: nc.nodeStatusMap[node.Name].probeTimestamp, - readyTransitionTimestamp: nc.now(), - } - return gracePeriod, lastReadyCondition, readyCondition, nil - } - } - } - - return gracePeriod, lastReadyCondition, readyCondition, err -} - -// evictPods queues an eviction for the provided node name, and returns false if the node is already -// queued for eviction. -func (nc *NodeController) evictPods(nodeName string) bool { - nc.evictorLock.Lock() - defer nc.evictorLock.Unlock() - return nc.podEvictor.Add(nodeName) -} - -// cancelPodEviction removes any queued evictions, typically because the node is available again. It -// returns true if an eviction was queued. -func (nc *NodeController) cancelPodEviction(nodeName string) bool { - nc.evictorLock.Lock() - defer nc.evictorLock.Unlock() - wasDeleting := nc.podEvictor.Remove(nodeName) - wasTerminating := nc.terminationEvictor.Remove(nodeName) - if wasDeleting || wasTerminating { - glog.V(2).Infof("Cancelling pod Eviction on Node: %v", nodeName) - return true - } - return false -} - -// deletePods will delete all pods from master running on given node, and return true -// if any pods were deleted. -func (nc *NodeController) deletePods(nodeName string) (bool, error) { - remaining := false - selector := fields.OneTermEqualSelector(api.PodHostField, nodeName) - options := api.ListOptions{FieldSelector: selector} - pods, err := nc.kubeClient.Core().Pods(api.NamespaceAll).List(options) - if err != nil { - return remaining, err - } - - if len(pods.Items) > 0 { - nc.recordNodeEvent(nodeName, api.EventTypeNormal, "DeletingAllPods", fmt.Sprintf("Deleting all Pods from Node %v.", nodeName)) - } - - for _, pod := range pods.Items { - // Defensive check, also needed for tests. - if pod.Spec.NodeName != nodeName { - continue - } - // if the pod has already been deleted, ignore it - if pod.DeletionGracePeriodSeconds != nil { - continue - } - // if the pod is managed by a daemonset, ignore it - _, err := nc.daemonSetStore.GetPodDaemonSets(&pod) - if err == nil { // No error means at least one daemonset was found - continue - } - - glog.V(2).Infof("Starting deletion of pod %v", pod.Name) - nc.recorder.Eventf(&pod, api.EventTypeNormal, "NodeControllerEviction", "Marking for deletion Pod %s from Node %s", pod.Name, nodeName) - if err := nc.kubeClient.Core().Pods(pod.Namespace).Delete(pod.Name, nil); err != nil { - return false, err - } - remaining = true - } - return remaining, nil -} - -// update ready status of all pods running on given node from master -// return true if success -func (nc *NodeController) markAllPodsNotReady(nodeName string) error { - glog.V(2).Infof("Update ready status of pods on node [%v]", nodeName) - opts := api.ListOptions{FieldSelector: fields.OneTermEqualSelector(api.PodHostField, nodeName)} - pods, err := nc.kubeClient.Core().Pods(api.NamespaceAll).List(opts) - if err != nil { - return err - } - - errMsg := []string{} - for _, pod := range pods.Items { - // Defensive check, also needed for tests. - if pod.Spec.NodeName != nodeName { - continue - } - - for i, cond := range pod.Status.Conditions { - if cond.Type == api.PodReady { - pod.Status.Conditions[i].Status = api.ConditionFalse - glog.V(2).Infof("Updating ready status of pod %v to false", pod.Name) - pod, err := nc.kubeClient.Core().Pods(pod.Namespace).UpdateStatus(&pod) - if err != nil { - glog.Warningf("Failed to update status for pod %q: %v", format.Pod(pod), err) - errMsg = append(errMsg, fmt.Sprintf("%v", err)) - } - break - } - } - } - if len(errMsg) == 0 { - return nil - } - return fmt.Errorf("%v", strings.Join(errMsg, "; ")) -} - -// terminatePods will ensure all pods on the given node that are in terminating state are eventually -// cleaned up. Returns true if the node has no pods in terminating state, a duration that indicates how -// long before we should check again (the next deadline for a pod to complete), or an error. -func (nc *NodeController) terminatePods(nodeName string, since time.Time) (bool, time.Duration, error) { - // the time before we should try again - nextAttempt := time.Duration(0) - // have we deleted all pods - complete := true - - selector := fields.OneTermEqualSelector(api.PodHostField, nodeName) - options := api.ListOptions{FieldSelector: selector} - pods, err := nc.kubeClient.Core().Pods(api.NamespaceAll).List(options) - if err != nil { - return false, nextAttempt, err - } - - now := time.Now() - elapsed := now.Sub(since) - for _, pod := range pods.Items { - // Defensive check, also needed for tests. - if pod.Spec.NodeName != nodeName { - continue - } - // only clean terminated pods - if pod.DeletionGracePeriodSeconds == nil { - continue - } - - // the user's requested grace period - grace := time.Duration(*pod.DeletionGracePeriodSeconds) * time.Second - if grace > nc.maximumGracePeriod { - grace = nc.maximumGracePeriod - } - - // the time remaining before the pod should have been deleted - remaining := grace - elapsed - if remaining < 0 { - remaining = 0 - glog.V(2).Infof("Removing pod %v after %s grace period", pod.Name, grace) - nc.recordNodeEvent(nodeName, api.EventTypeNormal, "TerminatingEvictedPod", fmt.Sprintf("Pod %s has exceeded the grace period for deletion after being evicted from Node %q and is being force killed", pod.Name, nodeName)) - if err := nc.kubeClient.Core().Pods(pod.Namespace).Delete(pod.Name, api.NewDeleteOptions(0)); err != nil { - glog.Errorf("Error completing deletion of pod %s: %v", pod.Name, err) - complete = false - } - } else { - glog.V(2).Infof("Pod %v still terminating, requested grace period %s, %s remaining", pod.Name, grace, remaining) - complete = false - } - - if nextAttempt < remaining { - nextAttempt = remaining - } - } - return complete, nextAttempt, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/nodecontroller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/nodecontroller_test.go deleted file mode 100644 index 4f43ac6af..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/nodecontroller_test.go +++ /dev/null @@ -1,1189 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 node - -import ( - "errors" - "sync" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - apierrors "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/cache" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - fakecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" - "k8s.io/kubernetes/pkg/util/diff" - "k8s.io/kubernetes/pkg/util/flowcontrol" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" -) - -const ( - testNodeMonitorGracePeriod = 40 * time.Second - testNodeStartupGracePeriod = 60 * time.Second - testNodeMonitorPeriod = 5 * time.Second -) - -// FakeNodeHandler is a fake implementation of NodesInterface and NodeInterface. It -// allows test cases to have fine-grained control over mock behaviors. We also need -// PodsInterface and PodInterface to test list & delet pods, which is implemented in -// the embedded client.Fake field. -type FakeNodeHandler struct { - *fake.Clientset - - // Input: Hooks determine if request is valid or not - CreateHook func(*FakeNodeHandler, *api.Node) bool - Existing []*api.Node - - // Output - CreatedNodes []*api.Node - DeletedNodes []*api.Node - UpdatedNodes []*api.Node - UpdatedNodeStatuses []*api.Node - RequestCount int - - // Synchronization - createLock sync.Mutex - deleteWaitChan chan struct{} -} - -type FakeLegacyHandler struct { - unversionedcore.CoreInterface - n *FakeNodeHandler -} - -func (c *FakeNodeHandler) Core() unversionedcore.CoreInterface { - return &FakeLegacyHandler{c.Clientset.Core(), c} -} - -func (m *FakeLegacyHandler) Nodes() unversionedcore.NodeInterface { - return m.n -} - -func (m *FakeNodeHandler) Create(node *api.Node) (*api.Node, error) { - m.createLock.Lock() - defer func() { - m.RequestCount++ - m.createLock.Unlock() - }() - for _, n := range m.Existing { - if n.Name == node.Name { - return nil, apierrors.NewAlreadyExists(api.Resource("nodes"), node.Name) - } - } - if m.CreateHook == nil || m.CreateHook(m, node) { - nodeCopy := *node - m.CreatedNodes = append(m.CreatedNodes, &nodeCopy) - return node, nil - } else { - return nil, errors.New("Create error.") - } -} - -func (m *FakeNodeHandler) Get(name string) (*api.Node, error) { - return nil, nil -} - -func (m *FakeNodeHandler) List(opts api.ListOptions) (*api.NodeList, error) { - defer func() { m.RequestCount++ }() - var nodes []*api.Node - for i := 0; i < len(m.UpdatedNodes); i++ { - if !contains(m.UpdatedNodes[i], m.DeletedNodes) { - nodes = append(nodes, m.UpdatedNodes[i]) - } - } - for i := 0; i < len(m.Existing); i++ { - if !contains(m.Existing[i], m.DeletedNodes) && !contains(m.Existing[i], nodes) { - nodes = append(nodes, m.Existing[i]) - } - } - for i := 0; i < len(m.CreatedNodes); i++ { - if !contains(m.Existing[i], m.DeletedNodes) && !contains(m.CreatedNodes[i], nodes) { - nodes = append(nodes, m.CreatedNodes[i]) - } - } - nodeList := &api.NodeList{} - for _, node := range nodes { - nodeList.Items = append(nodeList.Items, *node) - } - return nodeList, nil -} - -func (m *FakeNodeHandler) Delete(id string, opt *api.DeleteOptions) error { - defer func() { - if m.deleteWaitChan != nil { - m.deleteWaitChan <- struct{}{} - } - }() - m.DeletedNodes = append(m.DeletedNodes, newNode(id)) - m.RequestCount++ - return nil -} - -func (m *FakeNodeHandler) DeleteCollection(opt *api.DeleteOptions, listOpts api.ListOptions) error { - return nil -} - -func (m *FakeNodeHandler) Update(node *api.Node) (*api.Node, error) { - nodeCopy := *node - m.UpdatedNodes = append(m.UpdatedNodes, &nodeCopy) - m.RequestCount++ - return node, nil -} - -func (m *FakeNodeHandler) UpdateStatus(node *api.Node) (*api.Node, error) { - nodeCopy := *node - m.UpdatedNodeStatuses = append(m.UpdatedNodeStatuses, &nodeCopy) - m.RequestCount++ - return node, nil -} - -func (m *FakeNodeHandler) Watch(opts api.ListOptions) (watch.Interface, error) { - return nil, nil -} - -func TestMonitorNodeStatusEvictPods(t *testing.T) { - fakeNow := unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC) - evictionTimeout := 10 * time.Minute - - table := []struct { - fakeNodeHandler *FakeNodeHandler - daemonSets []extensions.DaemonSet - timeToPass time.Duration - newNodeStatus api.NodeStatus - expectedEvictPods bool - description string - }{ - // Node created recently, with no status (happens only at cluster startup). - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: fakeNow, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - daemonSets: nil, - timeToPass: 0, - newNodeStatus: api.NodeStatus{}, - expectedEvictPods: false, - description: "Node created recently, with no status.", - }, - // Node created long time ago, and kubelet posted NotReady for a short period of time. - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionFalse, - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - daemonSets: nil, - timeToPass: evictionTimeout, - newNodeStatus: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionFalse, - // Node status has just been updated, and is NotReady for 10min. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 9, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - expectedEvictPods: false, - description: "Node created long time ago, and kubelet posted NotReady for a short period of time.", - }, - // Pod is ds-managed, and kubelet posted NotReady for a long period of time. - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionFalse, - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset( - &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "pod0", - Namespace: "default", - Labels: map[string]string{"daemon": "yes"}, - }, - Spec: api.PodSpec{ - NodeName: "node0", - }, - }, - }, - }, - ), - }, - daemonSets: []extensions.DaemonSet{ - { - ObjectMeta: api.ObjectMeta{ - Name: "ds0", - Namespace: "default", - }, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"daemon": "yes"}, - }, - }, - }, - }, - timeToPass: time.Hour, - newNodeStatus: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionFalse, - // Node status has just been updated, and is NotReady for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 59, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - expectedEvictPods: false, - description: "Pod is ds-managed, and kubelet posted NotReady for a long period of time.", - }, - // Node created long time ago, and kubelet posted NotReady for a long period of time. - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionFalse, - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - daemonSets: nil, - timeToPass: time.Hour, - newNodeStatus: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionFalse, - // Node status has just been updated, and is NotReady for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 59, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - expectedEvictPods: true, - description: "Node created long time ago, and kubelet posted NotReady for a long period of time.", - }, - // Node created long time ago, node controller posted Unknown for a short period of time. - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionUnknown, - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - daemonSets: nil, - timeToPass: evictionTimeout - testNodeMonitorGracePeriod, - newNodeStatus: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionUnknown, - // Node status was updated by nodecontroller 10min ago - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - expectedEvictPods: false, - description: "Node created long time ago, node controller posted Unknown for a short period of time.", - }, - // Node created long time ago, node controller posted Unknown for a long period of time. - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionUnknown, - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - daemonSets: nil, - timeToPass: 60 * time.Minute, - newNodeStatus: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionUnknown, - // Node status was updated by nodecontroller 1hr ago - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - expectedEvictPods: true, - description: "Node created long time ago, node controller posted Unknown for a long period of time.", - }, - } - - for _, item := range table { - nodeController := NewNodeController(nil, item.fakeNodeHandler, - evictionTimeout, flowcontrol.NewFakeAlwaysRateLimiter(), flowcontrol.NewFakeAlwaysRateLimiter(), testNodeMonitorGracePeriod, - testNodeStartupGracePeriod, testNodeMonitorPeriod, nil, false) - nodeController.now = func() unversioned.Time { return fakeNow } - for _, ds := range item.daemonSets { - nodeController.daemonSetStore.Add(&ds) - } - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("unexpected error: %v", err) - } - if item.timeToPass > 0 { - nodeController.now = func() unversioned.Time { return unversioned.Time{Time: fakeNow.Add(item.timeToPass)} } - item.fakeNodeHandler.Existing[0].Status = item.newNodeStatus - } - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("unexpected error: %v", err) - } - - nodeController.podEvictor.Try(func(value TimedValue) (bool, time.Duration) { - remaining, _ := nodeController.deletePods(value.Value) - if remaining { - nodeController.terminationEvictor.Add(value.Value) - } - return true, 0 - }) - nodeController.podEvictor.Try(func(value TimedValue) (bool, time.Duration) { - nodeController.terminatePods(value.Value, value.AddedAt) - return true, 0 - }) - podEvicted := false - for _, action := range item.fakeNodeHandler.Actions() { - if action.GetVerb() == "delete" && action.GetResource().Resource == "pods" { - podEvicted = true - } - } - - if item.expectedEvictPods != podEvicted { - t.Errorf("expected pod eviction: %+v, got %+v for %+v", item.expectedEvictPods, - podEvicted, item.description) - } - } -} - -// TestCloudProviderNoRateLimit tests that monitorNodes() immediately deletes -// pods and the node when kubelet has not reported, and the cloudprovider says -// the node is gone. -func TestCloudProviderNoRateLimit(t *testing.T) { - fnh := &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionUnknown, - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0"), *newPod("pod1", "node0")}}), - deleteWaitChan: make(chan struct{}), - } - nodeController := NewNodeController(nil, fnh, 10*time.Minute, - flowcontrol.NewFakeAlwaysRateLimiter(), flowcontrol.NewFakeAlwaysRateLimiter(), - testNodeMonitorGracePeriod, testNodeStartupGracePeriod, - testNodeMonitorPeriod, nil, false) - nodeController.cloud = &fakecloud.FakeCloud{} - nodeController.now = func() unversioned.Time { return unversioned.Date(2016, 1, 1, 12, 0, 0, 0, time.UTC) } - nodeController.nodeExistsInCloudProvider = func(nodeName string) (bool, error) { - return false, nil - } - // monitorNodeStatus should allow this node to be immediately deleted - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("unexpected error: %v", err) - } - select { - case <-fnh.deleteWaitChan: - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Timed out waiting %v for node to be deleted", wait.ForeverTestTimeout) - } - if len(fnh.DeletedNodes) != 1 || fnh.DeletedNodes[0].Name != "node0" { - t.Errorf("Node was not deleted") - } - if nodeOnQueue := nodeController.podEvictor.Remove("node0"); nodeOnQueue { - t.Errorf("Node was queued for eviction. Should have been immediately deleted.") - } -} - -func TestMonitorNodeStatusUpdateStatus(t *testing.T) { - fakeNow := unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC) - table := []struct { - fakeNodeHandler *FakeNodeHandler - timeToPass time.Duration - newNodeStatus api.NodeStatus - expectedEvictPods bool - expectedRequestCount int - expectedNodes []*api.Node - }{ - // Node created long time ago, without status: - // Expect Unknown status posted from node controller. - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - expectedRequestCount: 2, // List+Update - expectedNodes: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionUnknown, - Reason: "NodeStatusNeverUpdated", - Message: "Kubelet never posted node status.", - LastHeartbeatTime: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - LastTransitionTime: fakeNow, - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionUnknown, - Reason: "NodeStatusNeverUpdated", - Message: "Kubelet never posted node status.", - LastHeartbeatTime: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - LastTransitionTime: fakeNow, - }, - }, - }, - }, - }, - }, - // Node created recently, without status. - // Expect no action from node controller (within startup grace period). - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: fakeNow, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - expectedRequestCount: 1, // List - expectedNodes: nil, - }, - // Node created long time ago, with status updated by kubelet exceeds grace period. - // Expect Unknown status posted from node controller. - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionFalse, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "node0", - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - expectedRequestCount: 3, // (List+)List+Update - timeToPass: time.Hour, - newNodeStatus: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionFalse, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - expectedNodes: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionUnknown, - Reason: "NodeStatusUnknown", - Message: "Kubelet stopped posting node status.", - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Time{Time: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC).Add(time.Hour)}, - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionUnknown, - Reason: "NodeStatusUnknown", - Message: "Kubelet stopped posting node status.", - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Time{Time: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC).Add(time.Hour)}, - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "node0", - }, - }, - }, - }, - // Node created long time ago, with status updated recently. - // Expect no action from node controller (within monitor grace period). - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status has just been updated. - LastHeartbeatTime: fakeNow, - LastTransitionTime: fakeNow, - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "node0", - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - expectedRequestCount: 1, // List - expectedNodes: nil, - }, - } - - for i, item := range table { - nodeController := NewNodeController(nil, item.fakeNodeHandler, 5*time.Minute, flowcontrol.NewFakeAlwaysRateLimiter(), - flowcontrol.NewFakeAlwaysRateLimiter(), testNodeMonitorGracePeriod, testNodeStartupGracePeriod, testNodeMonitorPeriod, nil, false) - nodeController.now = func() unversioned.Time { return fakeNow } - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("unexpected error: %v", err) - } - if item.timeToPass > 0 { - nodeController.now = func() unversioned.Time { return unversioned.Time{Time: fakeNow.Add(item.timeToPass)} } - item.fakeNodeHandler.Existing[0].Status = item.newNodeStatus - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("unexpected error: %v", err) - } - } - if item.expectedRequestCount != item.fakeNodeHandler.RequestCount { - t.Errorf("expected %v call, but got %v.", item.expectedRequestCount, item.fakeNodeHandler.RequestCount) - } - if len(item.fakeNodeHandler.UpdatedNodes) > 0 && !api.Semantic.DeepEqual(item.expectedNodes, item.fakeNodeHandler.UpdatedNodes) { - t.Errorf("Case[%d] unexpected nodes: %s", i, diff.ObjectDiff(item.expectedNodes[0], item.fakeNodeHandler.UpdatedNodes[0])) - } - if len(item.fakeNodeHandler.UpdatedNodeStatuses) > 0 && !api.Semantic.DeepEqual(item.expectedNodes, item.fakeNodeHandler.UpdatedNodeStatuses) { - t.Errorf("Case[%d] unexpected nodes: %s", i, diff.ObjectDiff(item.expectedNodes[0], item.fakeNodeHandler.UpdatedNodeStatuses[0])) - } - } -} - -func TestMonitorNodeStatusMarkPodsNotReady(t *testing.T) { - fakeNow := unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC) - table := []struct { - fakeNodeHandler *FakeNodeHandler - timeToPass time.Duration - newNodeStatus api.NodeStatus - expectedPodStatusUpdate bool - }{ - // Node created recently, without status. - // Expect no action from node controller (within startup grace period). - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: fakeNow, - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - expectedPodStatusUpdate: false, - }, - // Node created long time ago, with status updated recently. - // Expect no action from node controller (within monitor grace period). - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status has just been updated. - LastHeartbeatTime: fakeNow, - LastTransitionTime: fakeNow, - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "node0", - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - expectedPodStatusUpdate: false, - }, - // Node created long time ago, with status updated by kubelet exceeds grace period. - // Expect pods status updated and Unknown node status posted from node controller - { - fakeNodeHandler: &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionFalse, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "node0", - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0")}}), - }, - timeToPass: 1 * time.Minute, - newNodeStatus: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - { - Type: api.NodeOutOfDisk, - Status: api.ConditionFalse, - // Node status hasn't been updated for 1hr. - LastHeartbeatTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - LastTransitionTime: unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - expectedPodStatusUpdate: true, - }, - } - - for i, item := range table { - nodeController := NewNodeController(nil, item.fakeNodeHandler, 5*time.Minute, flowcontrol.NewFakeAlwaysRateLimiter(), - flowcontrol.NewFakeAlwaysRateLimiter(), testNodeMonitorGracePeriod, testNodeStartupGracePeriod, testNodeMonitorPeriod, nil, false) - nodeController.now = func() unversioned.Time { return fakeNow } - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("Case[%d] unexpected error: %v", i, err) - } - if item.timeToPass > 0 { - nodeController.now = func() unversioned.Time { return unversioned.Time{Time: fakeNow.Add(item.timeToPass)} } - item.fakeNodeHandler.Existing[0].Status = item.newNodeStatus - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("Case[%d] unexpected error: %v", i, err) - } - } - - podStatusUpdated := false - for _, action := range item.fakeNodeHandler.Actions() { - if action.GetVerb() == "update" && action.GetResource().Resource == "pods" && action.GetSubresource() == "status" { - podStatusUpdated = true - } - } - if podStatusUpdated != item.expectedPodStatusUpdate { - t.Errorf("Case[%d] expect pod status updated to be %v, but got %v", i, item.expectedPodStatusUpdate, podStatusUpdated) - } - } -} - -func TestNodeDeletion(t *testing.T) { - fakeNow := unversioned.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC) - fakeNodeHandler := &FakeNodeHandler{ - Existing: []*api.Node{ - { - ObjectMeta: api.ObjectMeta{ - Name: "node0", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status has just been updated. - LastHeartbeatTime: fakeNow, - LastTransitionTime: fakeNow, - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "node0", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "node1", - CreationTimestamp: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), - }, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - { - Type: api.NodeReady, - Status: api.ConditionTrue, - // Node status has just been updated. - LastHeartbeatTime: fakeNow, - LastTransitionTime: fakeNow, - }, - }, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - Spec: api.NodeSpec{ - ExternalID: "node0", - }, - }, - }, - Clientset: fake.NewSimpleClientset(&api.PodList{Items: []api.Pod{*newPod("pod0", "node0"), *newPod("pod1", "node1")}}), - } - - nodeController := NewNodeController(nil, fakeNodeHandler, 5*time.Minute, flowcontrol.NewFakeAlwaysRateLimiter(), flowcontrol.NewFakeAlwaysRateLimiter(), - testNodeMonitorGracePeriod, testNodeStartupGracePeriod, testNodeMonitorPeriod, nil, false) - nodeController.now = func() unversioned.Time { return fakeNow } - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("unexpected error: %v", err) - } - fakeNodeHandler.Delete("node1", nil) - if err := nodeController.monitorNodeStatus(); err != nil { - t.Errorf("unexpected error: %v", err) - } - nodeController.podEvictor.Try(func(value TimedValue) (bool, time.Duration) { - nodeController.deletePods(value.Value) - return true, 0 - }) - podEvicted := false - for _, action := range fakeNodeHandler.Actions() { - if action.GetVerb() == "delete" && action.GetResource().Resource == "pods" { - podEvicted = true - } - } - if !podEvicted { - t.Error("expected pods to be evicted from the deleted node") - } -} - -func TestCheckPod(t *testing.T) { - - tcs := []struct { - pod api.Pod - prune bool - }{ - - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: nil}, - Spec: api.PodSpec{NodeName: "new"}, - }, - prune: false, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: nil}, - Spec: api.PodSpec{NodeName: "old"}, - }, - prune: false, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: nil}, - Spec: api.PodSpec{NodeName: ""}, - }, - prune: false, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: nil}, - Spec: api.PodSpec{NodeName: "nonexistant"}, - }, - prune: false, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: &unversioned.Time{}}, - Spec: api.PodSpec{NodeName: "new"}, - }, - prune: false, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: &unversioned.Time{}}, - Spec: api.PodSpec{NodeName: "old"}, - }, - prune: true, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: &unversioned.Time{}}, - Spec: api.PodSpec{NodeName: "older"}, - }, - prune: true, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: &unversioned.Time{}}, - Spec: api.PodSpec{NodeName: "oldest"}, - }, - prune: true, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: &unversioned.Time{}}, - Spec: api.PodSpec{NodeName: ""}, - }, - prune: true, - }, - { - pod: api.Pod{ - ObjectMeta: api.ObjectMeta{DeletionTimestamp: &unversioned.Time{}}, - Spec: api.PodSpec{NodeName: "nonexistant"}, - }, - prune: true, - }, - } - - nc := NewNodeController(nil, nil, 0, nil, nil, 0, 0, 0, nil, false) - nc.nodeStore.Store = cache.NewStore(cache.MetaNamespaceKeyFunc) - nc.nodeStore.Store.Add(&api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "new", - }, - Status: api.NodeStatus{ - NodeInfo: api.NodeSystemInfo{ - KubeletVersion: "v1.1.0", - }, - }, - }) - nc.nodeStore.Store.Add(&api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "old", - }, - Status: api.NodeStatus{ - NodeInfo: api.NodeSystemInfo{ - KubeletVersion: "v1.0.0", - }, - }, - }) - nc.nodeStore.Store.Add(&api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "older", - }, - Status: api.NodeStatus{ - NodeInfo: api.NodeSystemInfo{ - KubeletVersion: "v0.21.4", - }, - }, - }) - nc.nodeStore.Store.Add(&api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "oldest", - }, - Status: api.NodeStatus{ - NodeInfo: api.NodeSystemInfo{ - KubeletVersion: "v0.19.3", - }, - }, - }) - - for i, tc := range tcs { - var deleteCalls int - nc.forcefullyDeletePod = func(_ *api.Pod) error { - deleteCalls++ - return nil - } - - nc.maybeDeleteTerminatingPod(&tc.pod) - - if tc.prune && deleteCalls != 1 { - t.Errorf("[%v] expected number of delete calls to be 1 but got %v", i, deleteCalls) - } - if !tc.prune && deleteCalls != 0 { - t.Errorf("[%v] expected number of delete calls to be 0 but got %v", i, deleteCalls) - } - } -} - -func TestCleanupOrphanedPods(t *testing.T) { - newPod := func(name, node string) api.Pod { - return api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: name, - }, - Spec: api.PodSpec{ - NodeName: node, - }, - } - } - pods := []api.Pod{ - newPod("a", "foo"), - newPod("b", "bar"), - newPod("c", "gone"), - } - nc := NewNodeController(nil, nil, 0, nil, nil, 0, 0, 0, nil, false) - - nc.nodeStore.Store.Add(newNode("foo")) - nc.nodeStore.Store.Add(newNode("bar")) - for _, pod := range pods { - p := pod - nc.podStore.Indexer.Add(&p) - } - - var deleteCalls int - var deletedPodName string - nc.forcefullyDeletePod = func(p *api.Pod) error { - deleteCalls++ - deletedPodName = p.ObjectMeta.Name - return nil - } - nc.cleanupOrphanedPods() - - if deleteCalls != 1 { - t.Fatalf("expected one delete, got: %v", deleteCalls) - } - if deletedPodName != "c" { - t.Fatalf("expected deleted pod name to be 'c', but got: %q", deletedPodName) - } -} - -func newNode(name string) *api.Node { - return &api.Node{ - ObjectMeta: api.ObjectMeta{Name: name}, - Spec: api.NodeSpec{ - ExternalID: name, - }, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("10"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - } -} - -func newPod(name, host string) *api.Pod { - return &api.Pod{ObjectMeta: api.ObjectMeta{Name: name}, Spec: api.PodSpec{NodeName: host}, - Status: api.PodStatus{Conditions: []api.PodCondition{{Type: api.PodReady, Status: api.ConditionTrue}}}} -} - -func contains(node *api.Node, nodes []*api.Node) bool { - for i := 0; i < len(nodes); i++ { - if node.Name == nodes[i].Name { - return true - } - } - return false -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/rate_limited_queue.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/rate_limited_queue.go deleted file mode 100644 index a3f007565..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/rate_limited_queue.go +++ /dev/null @@ -1,201 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 node - -import ( - "container/heap" - "sync" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/util/flowcontrol" - "k8s.io/kubernetes/pkg/util/sets" -) - -// TimedValue is a value that should be processed at a designated time. -type TimedValue struct { - Value string - AddedAt time.Time - ProcessAt time.Time -} - -// now is used to test time -var now func() time.Time = time.Now - -// TimedQueue is a priority heap where the lowest ProcessAt is at the front of the queue -type TimedQueue []*TimedValue - -func (h TimedQueue) Len() int { return len(h) } -func (h TimedQueue) Less(i, j int) bool { return h[i].ProcessAt.Before(h[j].ProcessAt) } -func (h TimedQueue) Swap(i, j int) { h[i], h[j] = h[j], h[i] } - -func (h *TimedQueue) Push(x interface{}) { - *h = append(*h, x.(*TimedValue)) -} - -func (h *TimedQueue) Pop() interface{} { - old := *h - n := len(old) - x := old[n-1] - *h = old[0 : n-1] - return x -} - -// A FIFO queue which additionally guarantees that any element can be added only once until -// it is removed. -type UniqueQueue struct { - lock sync.Mutex - queue TimedQueue - set sets.String -} - -// Adds a new value to the queue if it wasn't added before, or was explicitly removed by the -// Remove call. Returns true if new value was added. -func (q *UniqueQueue) Add(value TimedValue) bool { - q.lock.Lock() - defer q.lock.Unlock() - - if q.set.Has(value.Value) { - return false - } - heap.Push(&q.queue, &value) - q.set.Insert(value.Value) - return true -} - -// Replace replaces an existing value in the queue if it already exists, otherwise it does nothing. -// Returns true if the item was found. -func (q *UniqueQueue) Replace(value TimedValue) bool { - q.lock.Lock() - defer q.lock.Unlock() - - for i := range q.queue { - if q.queue[i].Value != value.Value { - continue - } - heap.Remove(&q.queue, i) - heap.Push(&q.queue, &value) - return true - } - return false -} - -// Removes the value from the queue, so Get() call won't return it, and allow subsequent addition -// of the given value. If the value is not present does nothing and returns false. -func (q *UniqueQueue) Remove(value string) bool { - q.lock.Lock() - defer q.lock.Unlock() - - q.set.Delete(value) - for i, val := range q.queue { - if val.Value == value { - heap.Remove(&q.queue, i) - return true - } - } - return false -} - -// Returns the oldest added value that wasn't returned yet. -func (q *UniqueQueue) Get() (TimedValue, bool) { - q.lock.Lock() - defer q.lock.Unlock() - if len(q.queue) == 0 { - return TimedValue{}, false - } - result := heap.Pop(&q.queue).(*TimedValue) - q.set.Delete(result.Value) - return *result, true -} - -// Head returns the oldest added value that wasn't returned yet without removing it. -func (q *UniqueQueue) Head() (TimedValue, bool) { - q.lock.Lock() - defer q.lock.Unlock() - if len(q.queue) == 0 { - return TimedValue{}, false - } - result := q.queue[0] - return *result, true -} - -// RateLimitedTimedQueue is a unique item priority queue ordered by the expected next time -// of execution. It is also rate limited. -type RateLimitedTimedQueue struct { - queue UniqueQueue - limiter flowcontrol.RateLimiter -} - -// Creates new queue which will use given RateLimiter to oversee execution. -func NewRateLimitedTimedQueue(limiter flowcontrol.RateLimiter) *RateLimitedTimedQueue { - return &RateLimitedTimedQueue{ - queue: UniqueQueue{ - queue: TimedQueue{}, - set: sets.NewString(), - }, - limiter: limiter, - } -} - -// ActionFunc takes a timed value and returns false if the item must be retried, with an optional -// time.Duration if some minimum wait interval should be used. -type ActionFunc func(TimedValue) (bool, time.Duration) - -// Try processes the queue. Ends prematurely if RateLimiter forbids an action and leak is true. -// Otherwise, requeues the item to be processed. Each value is processed once if fn returns true, -// otherwise it is added back to the queue. The returned remaining is used to identify the minimum -// time to execute the next item in the queue. -func (q *RateLimitedTimedQueue) Try(fn ActionFunc) { - val, ok := q.queue.Head() - for ok { - // rate limit the queue checking - if !q.limiter.TryAccept() { - glog.V(10).Info("Try rate limited...") - // Try again later - break - } - - now := now() - if now.Before(val.ProcessAt) { - break - } - - if ok, wait := fn(val); !ok { - val.ProcessAt = now.Add(wait + 1) - q.queue.Replace(val) - } else { - q.queue.Remove(val.Value) - } - val, ok = q.queue.Head() - } -} - -// Adds value to the queue to be processed. Won't add the same value a second time if it was already -// added and not removed. -func (q *RateLimitedTimedQueue) Add(value string) bool { - now := now() - return q.queue.Add(TimedValue{ - Value: value, - AddedAt: now, - ProcessAt: now, - }) -} - -// Removes Node from the Evictor. The Node won't be processed until added again. -func (q *RateLimitedTimedQueue) Remove(value string) bool { - return q.queue.Remove(value) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/rate_limited_queue_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/rate_limited_queue_test.go deleted file mode 100644 index e6ed0bd12..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/node/rate_limited_queue_test.go +++ /dev/null @@ -1,263 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 node - -import ( - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/util/flowcontrol" - "k8s.io/kubernetes/pkg/util/sets" -) - -func CheckQueueEq(lhs []string, rhs TimedQueue) bool { - for i := 0; i < len(lhs); i++ { - if rhs[i].Value != lhs[i] { - return false - } - } - return true -} - -func CheckSetEq(lhs, rhs sets.String) bool { - return lhs.HasAll(rhs.List()...) && rhs.HasAll(lhs.List()...) -} - -func TestAddNode(t *testing.T) { - evictor := NewRateLimitedTimedQueue(flowcontrol.NewFakeAlwaysRateLimiter()) - evictor.Add("first") - evictor.Add("second") - evictor.Add("third") - - queuePattern := []string{"first", "second", "third"} - if len(evictor.queue.queue) != len(queuePattern) { - t.Fatalf("Queue %v should have length %d", evictor.queue.queue, len(queuePattern)) - } - if !CheckQueueEq(queuePattern, evictor.queue.queue) { - t.Errorf("Invalid queue. Got %v, expected %v", evictor.queue.queue, queuePattern) - } - - setPattern := sets.NewString("first", "second", "third") - if len(evictor.queue.set) != len(setPattern) { - t.Fatalf("Map %v should have length %d", evictor.queue.set, len(setPattern)) - } - if !CheckSetEq(setPattern, evictor.queue.set) { - t.Errorf("Invalid map. Got %v, expected %v", evictor.queue.set, setPattern) - } -} - -func TestDelNode(t *testing.T) { - evictor := NewRateLimitedTimedQueue(flowcontrol.NewFakeAlwaysRateLimiter()) - evictor.Add("first") - evictor.Add("second") - evictor.Add("third") - evictor.Remove("first") - - queuePattern := []string{"second", "third"} - if len(evictor.queue.queue) != len(queuePattern) { - t.Fatalf("Queue %v should have length %d", evictor.queue.queue, len(queuePattern)) - } - if !CheckQueueEq(queuePattern, evictor.queue.queue) { - t.Errorf("Invalid queue. Got %v, expected %v", evictor.queue.queue, queuePattern) - } - - setPattern := sets.NewString("second", "third") - if len(evictor.queue.set) != len(setPattern) { - t.Fatalf("Map %v should have length %d", evictor.queue.set, len(setPattern)) - } - if !CheckSetEq(setPattern, evictor.queue.set) { - t.Errorf("Invalid map. Got %v, expected %v", evictor.queue.set, setPattern) - } - - evictor = NewRateLimitedTimedQueue(flowcontrol.NewFakeAlwaysRateLimiter()) - evictor.Add("first") - evictor.Add("second") - evictor.Add("third") - evictor.Remove("second") - - queuePattern = []string{"first", "third"} - if len(evictor.queue.queue) != len(queuePattern) { - t.Fatalf("Queue %v should have length %d", evictor.queue.queue, len(queuePattern)) - } - if !CheckQueueEq(queuePattern, evictor.queue.queue) { - t.Errorf("Invalid queue. Got %v, expected %v", evictor.queue.queue, queuePattern) - } - - setPattern = sets.NewString("first", "third") - if len(evictor.queue.set) != len(setPattern) { - t.Fatalf("Map %v should have length %d", evictor.queue.set, len(setPattern)) - } - if !CheckSetEq(setPattern, evictor.queue.set) { - t.Errorf("Invalid map. Got %v, expected %v", evictor.queue.set, setPattern) - } - - evictor = NewRateLimitedTimedQueue(flowcontrol.NewFakeAlwaysRateLimiter()) - evictor.Add("first") - evictor.Add("second") - evictor.Add("third") - evictor.Remove("third") - - queuePattern = []string{"first", "second"} - if len(evictor.queue.queue) != len(queuePattern) { - t.Fatalf("Queue %v should have length %d", evictor.queue.queue, len(queuePattern)) - } - if !CheckQueueEq(queuePattern, evictor.queue.queue) { - t.Errorf("Invalid queue. Got %v, expected %v", evictor.queue.queue, queuePattern) - } - - setPattern = sets.NewString("first", "second") - if len(evictor.queue.set) != len(setPattern) { - t.Fatalf("Map %v should have length %d", evictor.queue.set, len(setPattern)) - } - if !CheckSetEq(setPattern, evictor.queue.set) { - t.Errorf("Invalid map. Got %v, expected %v", evictor.queue.set, setPattern) - } -} - -func TestTry(t *testing.T) { - evictor := NewRateLimitedTimedQueue(flowcontrol.NewFakeAlwaysRateLimiter()) - evictor.Add("first") - evictor.Add("second") - evictor.Add("third") - evictor.Remove("second") - - deletedMap := sets.NewString() - evictor.Try(func(value TimedValue) (bool, time.Duration) { - deletedMap.Insert(value.Value) - return true, 0 - }) - - setPattern := sets.NewString("first", "third") - if len(deletedMap) != len(setPattern) { - t.Fatalf("Map %v should have length %d", evictor.queue.set, len(setPattern)) - } - if !CheckSetEq(setPattern, deletedMap) { - t.Errorf("Invalid map. Got %v, expected %v", deletedMap, setPattern) - } -} - -func TestTryOrdering(t *testing.T) { - defer func() { now = time.Now }() - current := time.Unix(0, 0) - delay := 0 - // the current time is incremented by 1ms every time now is invoked - now = func() time.Time { - if delay > 0 { - delay-- - } else { - current = current.Add(time.Millisecond) - } - t.Logf("time %d", current.UnixNano()) - return current - } - evictor := NewRateLimitedTimedQueue(flowcontrol.NewFakeAlwaysRateLimiter()) - evictor.Add("first") - evictor.Add("second") - evictor.Add("third") - - order := []string{} - count := 0 - hasQueued := false - evictor.Try(func(value TimedValue) (bool, time.Duration) { - count++ - t.Logf("eviction %d", count) - if value.ProcessAt.IsZero() { - t.Fatalf("processAt should not be zero") - } - switch value.Value { - case "first": - if !value.AddedAt.Equal(time.Unix(0, time.Millisecond.Nanoseconds())) { - t.Fatalf("added time for %s is %d", value.Value, value.AddedAt) - } - - case "second": - if !value.AddedAt.Equal(time.Unix(0, 2*time.Millisecond.Nanoseconds())) { - t.Fatalf("added time for %s is %d", value.Value, value.AddedAt) - } - if hasQueued { - if !value.ProcessAt.Equal(time.Unix(0, 6*time.Millisecond.Nanoseconds())) { - t.Fatalf("process time for %s is %d", value.Value, value.ProcessAt) - } - break - } - hasQueued = true - delay = 1 - t.Logf("going to delay") - return false, 2 * time.Millisecond - - case "third": - if !value.AddedAt.Equal(time.Unix(0, 3*time.Millisecond.Nanoseconds())) { - t.Fatalf("added time for %s is %d", value.Value, value.AddedAt) - } - } - order = append(order, value.Value) - return true, 0 - }) - if !reflect.DeepEqual(order, []string{"first", "third"}) { - t.Fatalf("order was wrong: %v", order) - } - if count != 3 { - t.Fatalf("unexpected iterations: %d", count) - } -} - -func TestTryRemovingWhileTry(t *testing.T) { - evictor := NewRateLimitedTimedQueue(flowcontrol.NewFakeAlwaysRateLimiter()) - evictor.Add("first") - evictor.Add("second") - evictor.Add("third") - - processing := make(chan struct{}) - wait := make(chan struct{}) - order := []string{} - count := 0 - queued := false - - // while the Try function is processing "second", remove it from the queue - // we should not see "second" retried. - go func() { - <-processing - evictor.Remove("second") - close(wait) - }() - - evictor.Try(func(value TimedValue) (bool, time.Duration) { - count++ - if value.AddedAt.IsZero() { - t.Fatalf("added should not be zero") - } - if value.ProcessAt.IsZero() { - t.Fatalf("next should not be zero") - } - if !queued && value.Value == "second" { - queued = true - close(processing) - <-wait - return false, time.Millisecond - } - order = append(order, value.Value) - return true, 0 - }) - - if !reflect.DeepEqual(order, []string{"first", "third"}) { - t.Fatalf("order was wrong: %v", order) - } - if count != 3 { - t.Fatalf("unexpected iterations: %d", count) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/OWNERS b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/OWNERS deleted file mode 100644 index b9e1568ab..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -assignees: - - saad-ali - - thockin diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/options/options.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/options/options.go deleted file mode 100644 index c3b6c175a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/options/options.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 options - -import ( - "time" - - "github.com/spf13/pflag" -) - -// VolumeConfigFlags is used to bind CLI flags to variables. This top-level struct contains *all* enumerated -// CLI flags meant to configure all volume plugins. From this config, the binary will create many instances -// of volume.VolumeConfig which are then passed to the appropriate plugin. The ControllerManager binary is the only -// part of the code which knows what plugins are supported and which CLI flags correspond to each plugin. -type VolumeConfigFlags struct { - PersistentVolumeRecyclerMaximumRetry int - PersistentVolumeRecyclerMinimumTimeoutNFS int - PersistentVolumeRecyclerPodTemplateFilePathNFS string - PersistentVolumeRecyclerIncrementTimeoutNFS int - PersistentVolumeRecyclerPodTemplateFilePathHostPath string - PersistentVolumeRecyclerMinimumTimeoutHostPath int - PersistentVolumeRecyclerIncrementTimeoutHostPath int - EnableHostPathProvisioning bool -} - -type PersistentVolumeControllerOptions struct { - PVClaimBinderSyncPeriod time.Duration - VolumeConfigFlags VolumeConfigFlags -} - -func NewPersistentVolumeControllerOptions() PersistentVolumeControllerOptions { - return PersistentVolumeControllerOptions{ - PVClaimBinderSyncPeriod: 10 * time.Minute, - VolumeConfigFlags: VolumeConfigFlags{ - // default values here - PersistentVolumeRecyclerMaximumRetry: 3, - PersistentVolumeRecyclerMinimumTimeoutNFS: 300, - PersistentVolumeRecyclerIncrementTimeoutNFS: 30, - PersistentVolumeRecyclerMinimumTimeoutHostPath: 60, - PersistentVolumeRecyclerIncrementTimeoutHostPath: 30, - EnableHostPathProvisioning: false, - }, - } -} - -func (o *PersistentVolumeControllerOptions) AddFlags(fs *pflag.FlagSet) { - fs.DurationVar(&o.PVClaimBinderSyncPeriod, "pvclaimbinder-sync-period", o.PVClaimBinderSyncPeriod, - "The period for syncing persistent volumes and persistent volume claims") - fs.StringVar(&o.VolumeConfigFlags.PersistentVolumeRecyclerPodTemplateFilePathNFS, - "pv-recycler-pod-template-filepath-nfs", o.VolumeConfigFlags.PersistentVolumeRecyclerPodTemplateFilePathNFS, - "The file path to a pod definition used as a template for NFS persistent volume recycling") - fs.IntVar(&o.VolumeConfigFlags.PersistentVolumeRecyclerMinimumTimeoutNFS, "pv-recycler-minimum-timeout-nfs", - o.VolumeConfigFlags.PersistentVolumeRecyclerMinimumTimeoutNFS, "The minimum ActiveDeadlineSeconds to use for an NFS Recycler pod") - fs.IntVar(&o.VolumeConfigFlags.PersistentVolumeRecyclerIncrementTimeoutNFS, "pv-recycler-increment-timeout-nfs", - o.VolumeConfigFlags.PersistentVolumeRecyclerIncrementTimeoutNFS, "the increment of time added per Gi to ActiveDeadlineSeconds for an NFS scrubber pod") - fs.StringVar(&o.VolumeConfigFlags.PersistentVolumeRecyclerPodTemplateFilePathHostPath, "pv-recycler-pod-template-filepath-hostpath", - o.VolumeConfigFlags.PersistentVolumeRecyclerPodTemplateFilePathHostPath, - "The file path to a pod definition used as a template for HostPath persistent volume recycling. "+ - "This is for development and testing only and will not work in a multi-node cluster.") - fs.IntVar(&o.VolumeConfigFlags.PersistentVolumeRecyclerMinimumTimeoutHostPath, "pv-recycler-minimum-timeout-hostpath", - o.VolumeConfigFlags.PersistentVolumeRecyclerMinimumTimeoutHostPath, - "The minimum ActiveDeadlineSeconds to use for a HostPath Recycler pod. This is for development and testing only and will not work in a multi-node cluster.") - fs.IntVar(&o.VolumeConfigFlags.PersistentVolumeRecyclerIncrementTimeoutHostPath, "pv-recycler-timeout-increment-hostpath", - o.VolumeConfigFlags.PersistentVolumeRecyclerIncrementTimeoutHostPath, - "the increment of time added per Gi to ActiveDeadlineSeconds for a HostPath scrubber pod. "+ - "This is for development and testing only and will not work in a multi-node cluster.") - fs.IntVar(&o.VolumeConfigFlags.PersistentVolumeRecyclerMaximumRetry, "pv-recycler-maximum-retry", - o.VolumeConfigFlags.PersistentVolumeRecyclerMaximumRetry, - "Maximum number of attempts to recycle or delete a persistent volume") - fs.BoolVar(&o.VolumeConfigFlags.EnableHostPathProvisioning, "enable-hostpath-provisioner", o.VolumeConfigFlags.EnableHostPathProvisioning, - "Enable HostPath PV provisioning when running without a cloud provider. This allows testing and development of provisioning features. "+ - "HostPath provisioning is not supported in any way, won't work in a multi-node cluster, and should not be used for anything other than testing or development.") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller.go deleted file mode 100644 index a0e105a09..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller.go +++ /dev/null @@ -1,530 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 persistentvolume - -import ( - "fmt" - "sync" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - "k8s.io/kubernetes/pkg/watch" - - "github.com/golang/glog" -) - -// PersistentVolumeClaimBinder is a controller that synchronizes PersistentVolumeClaims. -type PersistentVolumeClaimBinder struct { - volumeIndex *persistentVolumeOrderedIndex - volumeController *framework.Controller - claimController *framework.Controller - client binderClient - stopChannels map[string]chan struct{} - lock sync.RWMutex -} - -// NewPersistentVolumeClaimBinder creates a new PersistentVolumeClaimBinder -func NewPersistentVolumeClaimBinder(kubeClient clientset.Interface, syncPeriod time.Duration) *PersistentVolumeClaimBinder { - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("pv_claim_binder_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - volumeIndex := NewPersistentVolumeOrderedIndex() - binderClient := NewBinderClient(kubeClient) - binder := &PersistentVolumeClaimBinder{ - volumeIndex: volumeIndex, - client: binderClient, - } - - _, volumeController := framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().PersistentVolumes().List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return kubeClient.Core().PersistentVolumes().Watch(options) - }, - }, - &api.PersistentVolume{}, - // TODO: Can we have much longer period here? - syncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: binder.addVolume, - UpdateFunc: binder.updateVolume, - DeleteFunc: binder.deleteVolume, - }, - ) - _, claimController := framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().PersistentVolumeClaims(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return kubeClient.Core().PersistentVolumeClaims(api.NamespaceAll).Watch(options) - }, - }, - &api.PersistentVolumeClaim{}, - // TODO: Can we have much longer period here? - syncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: binder.addClaim, - UpdateFunc: binder.updateClaim, - DeleteFunc: binder.deleteClaim, - }, - ) - - binder.claimController = claimController - binder.volumeController = volumeController - - return binder -} -func (binder *PersistentVolumeClaimBinder) addVolume(obj interface{}) { - binder.lock.Lock() - defer binder.lock.Unlock() - pv, ok := obj.(*api.PersistentVolume) - if !ok { - glog.Errorf("Expected PersistentVolume but handler received %+v", obj) - return - } - if err := syncVolume(binder.volumeIndex, binder.client, pv); err != nil { - glog.Errorf("PVClaimBinder could not add volume %s: %+v", pv.Name, err) - } -} - -func (binder *PersistentVolumeClaimBinder) updateVolume(oldObj, newObj interface{}) { - binder.lock.Lock() - defer binder.lock.Unlock() - newVolume, ok := newObj.(*api.PersistentVolume) - if !ok { - glog.Errorf("Expected PersistentVolume but handler received %+v", newObj) - return - } - if err := binder.volumeIndex.Update(newVolume); err != nil { - glog.Errorf("Error updating volume %s in index: %v", newVolume.Name, err) - return - } - if err := syncVolume(binder.volumeIndex, binder.client, newVolume); err != nil { - glog.Errorf("PVClaimBinder could not update volume %s: %+v", newVolume.Name, err) - } -} - -func (binder *PersistentVolumeClaimBinder) deleteVolume(obj interface{}) { - binder.lock.Lock() - defer binder.lock.Unlock() - volume, ok := obj.(*api.PersistentVolume) - if !ok { - glog.Errorf("Expected PersistentVolume but handler received %+v", obj) - return - } - if err := binder.volumeIndex.Delete(volume); err != nil { - glog.Errorf("Error deleting volume %s from index: %v", volume.Name, err) - } -} - -func (binder *PersistentVolumeClaimBinder) addClaim(obj interface{}) { - binder.lock.Lock() - defer binder.lock.Unlock() - claim, ok := obj.(*api.PersistentVolumeClaim) - if !ok { - glog.Errorf("Expected PersistentVolumeClaim but handler received %+v", obj) - return - } - if err := syncClaim(binder.volumeIndex, binder.client, claim); err != nil { - glog.Errorf("PVClaimBinder could not add claim %s: %+v", claim.Name, err) - } -} - -func (binder *PersistentVolumeClaimBinder) updateClaim(oldObj, newObj interface{}) { - binder.lock.Lock() - defer binder.lock.Unlock() - newClaim, ok := newObj.(*api.PersistentVolumeClaim) - if !ok { - glog.Errorf("Expected PersistentVolumeClaim but handler received %+v", newObj) - return - } - if err := syncClaim(binder.volumeIndex, binder.client, newClaim); err != nil { - glog.Errorf("PVClaimBinder could not update claim %s: %+v", newClaim.Name, err) - } -} - -func (binder *PersistentVolumeClaimBinder) deleteClaim(obj interface{}) { - binder.lock.Lock() - defer binder.lock.Unlock() - var volume *api.PersistentVolume - if pvc, ok := obj.(*api.PersistentVolumeClaim); ok { - if pvObj, exists, _ := binder.volumeIndex.GetByKey(pvc.Spec.VolumeName); exists { - if pv, ok := pvObj.(*api.PersistentVolume); ok { - volume = pv - } - } - } - if unk, ok := obj.(cache.DeletedFinalStateUnknown); ok && unk.Obj != nil { - if pv, ok := unk.Obj.(*api.PersistentVolume); ok { - volume = pv - } - } - - // sync the volume when its claim is deleted. Explicitly sync'ing the volume here in response to - // claim deletion prevents the volume from waiting until the next sync period for its Release. - if volume != nil { - err := syncVolume(binder.volumeIndex, binder.client, volume) - if err != nil { - glog.Errorf("PVClaimBinder could not update volume %s from deleteClaim handler: %+v", volume.Name, err) - } - } -} - -func syncVolume(volumeIndex *persistentVolumeOrderedIndex, binderClient binderClient, volume *api.PersistentVolume) (err error) { - glog.V(5).Infof("Synchronizing PersistentVolume[%s], current phase: %s\n", volume.Name, volume.Status.Phase) - - // The PV may have been modified by parallel call to syncVolume, load - // the current version. - newPv, err := binderClient.GetPersistentVolume(volume.Name) - if err != nil { - return fmt.Errorf("Cannot reload volume %s: %v", volume.Name, err) - } - volume = newPv - - // volumes can be in one of the following states: - // - // VolumePending -- default value -- not bound to a claim and not yet processed through this controller. - // VolumeAvailable -- not bound to a claim, but processed at least once and found in this controller's volumeIndex. - // VolumeBound -- bound to a claim because volume.Spec.ClaimRef != nil. Claim status may not be correct. - // VolumeReleased -- volume.Spec.ClaimRef != nil but the claim has been deleted by the user. - // VolumeFailed -- volume.Spec.ClaimRef != nil and the volume failed processing in the recycler - currentPhase := volume.Status.Phase - nextPhase := currentPhase - - // Always store the newest volume state in local cache. - _, exists, err := volumeIndex.Get(volume) - if err != nil { - return err - } - if !exists { - volumeIndex.Add(volume) - } else { - volumeIndex.Update(volume) - } - - if isBeingProvisioned(volume) { - glog.V(4).Infof("Skipping PersistentVolume[%s], waiting for provisioning to finish", volume.Name) - return nil - } - - switch currentPhase { - case api.VolumePending: - - // 4 possible states: - // 1. ClaimRef != nil, Claim exists, Claim UID == ClaimRef UID: Prebound to claim. Make volume available for binding (it will match PVC). - // 2. ClaimRef != nil, Claim exists, Claim UID != ClaimRef UID: Recently recycled. Remove bind. Make volume available for new claim. - // 3. ClaimRef != nil, Claim !exists: Recently recycled. Remove bind. Make volume available for new claim. - // 4. ClaimRef == nil: Neither recycled nor prebound. Make volume available for binding. - nextPhase = api.VolumeAvailable - - if volume.Spec.ClaimRef != nil { - claim, err := binderClient.GetPersistentVolumeClaim(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name) - switch { - case err != nil && !errors.IsNotFound(err): - return fmt.Errorf("Error getting PersistentVolumeClaim[%s/%s]: %v", volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name, err) - case errors.IsNotFound(err) || (claim != nil && claim.UID != volume.Spec.ClaimRef.UID): - glog.V(5).Infof("PersistentVolume[%s] has a claim ref to a claim which does not exist", volume.Name) - if volume.Spec.PersistentVolumeReclaimPolicy == api.PersistentVolumeReclaimRecycle { - // Pending volumes that have a ClaimRef where the claim is missing were recently recycled. - // The Recycler set the phase to VolumePending to start the volume at the beginning of this lifecycle. - // removing ClaimRef unbinds the volume - clone, err := conversion.NewCloner().DeepCopy(volume) - if err != nil { - return fmt.Errorf("Error cloning pv: %v", err) - } - volumeClone, ok := clone.(*api.PersistentVolume) - if !ok { - return fmt.Errorf("Unexpected pv cast error : %v\n", volumeClone) - } - glog.V(5).Infof("PersistentVolume[%s] is recently recycled; remove claimRef.", volume.Name) - volumeClone.Spec.ClaimRef = nil - - if updatedVolume, err := binderClient.UpdatePersistentVolume(volumeClone); err != nil { - return fmt.Errorf("Unexpected error saving PersistentVolume: %+v", err) - } else { - volume = updatedVolume - volumeIndex.Update(volume) - } - } else { - // Pending volumes that has a ClaimRef and the claim is missing and is was not recycled. - // It must have been freshly provisioned and the claim was deleted during the provisioning. - // Mark the volume as Released, it will be deleted. - nextPhase = api.VolumeReleased - } - } - - // Dynamically provisioned claims remain Pending until its volume is completely provisioned. - // The provisioner updates the PV and triggers this update for the volume. Explicitly sync'ing - // the claim here prevents the need to wait until the next sync period when the claim would normally - // advance to Bound phase. Otherwise, the maximum wait time for the claim to be Bound is the default sync period. - if claim != nil && claim.Status.Phase == api.ClaimPending && keyExists(qosProvisioningKey, claim.Annotations) && isProvisioningComplete(volume) { - syncClaim(volumeIndex, binderClient, claim) - } - } - glog.V(5).Infof("PersistentVolume[%s] is available\n", volume.Name) - - // available volumes await a claim - case api.VolumeAvailable: - if volume.Spec.ClaimRef != nil { - _, err := binderClient.GetPersistentVolumeClaim(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name) - if err == nil { - // change of phase will trigger an update event with the newly bound volume - glog.V(5).Infof("PersistentVolume[%s] is now bound\n", volume.Name) - nextPhase = api.VolumeBound - } else { - if errors.IsNotFound(err) { - nextPhase = api.VolumeReleased - } - } - } - - //bound volumes require verification of their bound claims - case api.VolumeBound: - if volume.Spec.ClaimRef == nil { - return fmt.Errorf("PersistentVolume[%s] expected to be bound but found nil claimRef: %+v", volume.Name, volume) - } else { - claim, err := binderClient.GetPersistentVolumeClaim(volume.Spec.ClaimRef.Namespace, volume.Spec.ClaimRef.Name) - - // A volume is Released when its bound claim cannot be found in the API server. - // A claim by the same name can be found if deleted and recreated before this controller can release - // the volume from the original claim, so a UID check is necessary. - if err != nil { - if errors.IsNotFound(err) { - nextPhase = api.VolumeReleased - } else { - return err - } - } else if claim != nil && claim.UID != volume.Spec.ClaimRef.UID { - nextPhase = api.VolumeReleased - } - } - - // released volumes require recycling - case api.VolumeReleased: - if volume.Spec.ClaimRef == nil { - return fmt.Errorf("PersistentVolume[%s] expected to be bound but found nil claimRef: %+v", volume.Name, volume) - } else { - // another process is watching for released volumes. - // PersistentVolumeReclaimPolicy is set per PersistentVolume - // Recycle - sets the PV to Pending and back under this controller's management - // Delete - delete events are handled by this controller's watch. PVs are removed from the index. - } - - // volumes are removed by processes external to this binder and must be removed from the cluster - case api.VolumeFailed: - if volume.Spec.ClaimRef == nil { - return fmt.Errorf("PersistentVolume[%s] expected to be bound but found nil claimRef: %+v", volume.Name, volume) - } else { - glog.V(5).Infof("PersistentVolume[%s] previously failed recycling. Skipping.\n", volume.Name) - } - } - - if currentPhase != nextPhase { - volume.Status.Phase = nextPhase - - // a change in state will trigger another update through this controller. - // each pass through this controller evaluates current phase and decides whether or not to change to the next phase - glog.V(5).Infof("PersistentVolume[%s] changing phase from %s to %s\n", volume.Name, currentPhase, nextPhase) - volume, err := binderClient.UpdatePersistentVolumeStatus(volume) - if err != nil { - // Rollback to previous phase - volume.Status.Phase = currentPhase - } - volumeIndex.Update(volume) - } - - return nil -} - -func syncClaim(volumeIndex *persistentVolumeOrderedIndex, binderClient binderClient, claim *api.PersistentVolumeClaim) (err error) { - glog.V(5).Infof("Synchronizing PersistentVolumeClaim[%s] for binding", claim.Name) - - // The claim may have been modified by parallel call to syncClaim, load - // the current version. - newClaim, err := binderClient.GetPersistentVolumeClaim(claim.Namespace, claim.Name) - if err != nil { - return fmt.Errorf("Cannot reload claim %s/%s: %v", claim.Namespace, claim.Name, err) - } - claim = newClaim - - switch claim.Status.Phase { - case api.ClaimPending: - // claims w/ a storage-class annotation for provisioning with *only* match volumes with a ClaimRef of the claim. - volume, err := volumeIndex.findBestMatchForClaim(claim) - if err != nil { - return err - } - - if volume == nil { - glog.V(5).Infof("A volume match does not exist for persistent claim: %s", claim.Name) - return nil - } - - if isBeingProvisioned(volume) { - glog.V(5).Infof("PersistentVolume[%s] for PersistentVolumeClaim[%s/%s] is still being provisioned.", volume.Name, claim.Namespace, claim.Name) - return nil - } - - claimRef, err := api.GetReference(claim) - if err != nil { - return fmt.Errorf("Unexpected error getting claim reference: %v\n", err) - } - - // Make a binding reference to the claim by persisting claimRef on the volume. - // The local cache must be updated with the new bind to prevent subsequent - // claims from binding to the volume. - if volume.Spec.ClaimRef == nil { - clone, err := conversion.NewCloner().DeepCopy(volume) - if err != nil { - return fmt.Errorf("Error cloning pv: %v", err) - } - volumeClone, ok := clone.(*api.PersistentVolume) - if !ok { - return fmt.Errorf("Unexpected pv cast error : %v\n", volumeClone) - } - volumeClone.Spec.ClaimRef = claimRef - if updatedVolume, err := binderClient.UpdatePersistentVolume(volumeClone); err != nil { - return fmt.Errorf("Unexpected error saving PersistentVolume.Status: %+v", err) - } else { - volume = updatedVolume - volumeIndex.Update(updatedVolume) - } - } - - // the bind is persisted on the volume above and will always match the claim in a search. - // claim would remain Pending if the update fails, so processing this state is idempotent. - // this only needs to be processed once. - if claim.Spec.VolumeName != volume.Name { - claim.Spec.VolumeName = volume.Name - claim, err = binderClient.UpdatePersistentVolumeClaim(claim) - if err != nil { - return fmt.Errorf("Error updating claim with VolumeName %s: %+v\n", volume.Name, err) - } - } - - claim.Status.Phase = api.ClaimBound - claim.Status.AccessModes = volume.Spec.AccessModes - claim.Status.Capacity = volume.Spec.Capacity - _, err = binderClient.UpdatePersistentVolumeClaimStatus(claim) - if err != nil { - return fmt.Errorf("Unexpected error saving claim status: %+v", err) - } - - case api.ClaimBound: - // no-op. Claim is bound, values from PV are set. PVCs are technically mutable in the API server - // and we don't want to handle those changes at this time. - - default: - return fmt.Errorf("Unknown state for PVC: %#v", claim) - - } - - glog.V(5).Infof("PersistentVolumeClaim[%s] is bound\n", claim.Name) - return nil -} - -func isBeingProvisioned(volume *api.PersistentVolume) bool { - value, found := volume.Annotations[pvProvisioningRequiredAnnotationKey] - if found && value != pvProvisioningCompletedAnnotationValue { - return true - } - return false -} - -// Run starts all of this binder's control loops -func (controller *PersistentVolumeClaimBinder) Run() { - glog.V(5).Infof("Starting PersistentVolumeClaimBinder\n") - if controller.stopChannels == nil { - controller.stopChannels = make(map[string]chan struct{}) - } - - if _, exists := controller.stopChannels["volumes"]; !exists { - controller.stopChannels["volumes"] = make(chan struct{}) - go controller.volumeController.Run(controller.stopChannels["volumes"]) - } - - if _, exists := controller.stopChannels["claims"]; !exists { - controller.stopChannels["claims"] = make(chan struct{}) - go controller.claimController.Run(controller.stopChannels["claims"]) - } -} - -// Stop gracefully shuts down this binder -func (controller *PersistentVolumeClaimBinder) Stop() { - glog.V(5).Infof("Stopping PersistentVolumeClaimBinder\n") - for name, stopChan := range controller.stopChannels { - close(stopChan) - delete(controller.stopChannels, name) - } -} - -// binderClient abstracts access to PVs and PVCs -type binderClient interface { - GetPersistentVolume(name string) (*api.PersistentVolume, error) - UpdatePersistentVolume(volume *api.PersistentVolume) (*api.PersistentVolume, error) - DeletePersistentVolume(volume *api.PersistentVolume) error - UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) - GetPersistentVolumeClaim(namespace, name string) (*api.PersistentVolumeClaim, error) - UpdatePersistentVolumeClaim(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) - UpdatePersistentVolumeClaimStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) -} - -func NewBinderClient(c clientset.Interface) binderClient { - return &realBinderClient{c} -} - -type realBinderClient struct { - client clientset.Interface -} - -func (c *realBinderClient) GetPersistentVolume(name string) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().Get(name) -} - -func (c *realBinderClient) UpdatePersistentVolume(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().Update(volume) -} - -func (c *realBinderClient) DeletePersistentVolume(volume *api.PersistentVolume) error { - return c.client.Core().PersistentVolumes().Delete(volume.Name, nil) -} - -func (c *realBinderClient) UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().UpdateStatus(volume) -} - -func (c *realBinderClient) GetPersistentVolumeClaim(namespace, name string) (*api.PersistentVolumeClaim, error) { - return c.client.Core().PersistentVolumeClaims(namespace).Get(name) -} - -func (c *realBinderClient) UpdatePersistentVolumeClaim(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - return c.client.Core().PersistentVolumeClaims(claim.Namespace).Update(claim) -} - -func (c *realBinderClient) UpdatePersistentVolumeClaimStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - return c.client.Core().PersistentVolumeClaims(claim.Namespace).UpdateStatus(claim) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go deleted file mode 100644 index f01908c7f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go +++ /dev/null @@ -1,732 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 persistentvolume - -import ( - "fmt" - "os" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/client/cache" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/types" - utiltesting "k8s.io/kubernetes/pkg/util/testing" - "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/host_path" - volumetest "k8s.io/kubernetes/pkg/volume/testing" -) - -func TestRunStop(t *testing.T) { - clientset := fake.NewSimpleClientset() - binder := NewPersistentVolumeClaimBinder(clientset, 1*time.Second) - - if len(binder.stopChannels) != 0 { - t.Errorf("Non-running binder should not have any stopChannels. Got %v", len(binder.stopChannels)) - } - - binder.Run() - - if len(binder.stopChannels) != 2 { - t.Errorf("Running binder should have exactly 2 stopChannels. Got %v", len(binder.stopChannels)) - } - - binder.Stop() - - if len(binder.stopChannels) != 0 { - t.Errorf("Non-running binder should not have any stopChannels. Got %v", len(binder.stopChannels)) - } -} - -func TestClaimRace(t *testing.T) { - tmpDir, err := utiltesting.MkTmpdir("claimbinder-test") - if err != nil { - t.Fatalf("error creating temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - c1 := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "c1", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("3Gi"), - }, - }, - }, - Status: api.PersistentVolumeClaimStatus{ - Phase: api.ClaimPending, - }, - } - c1.ObjectMeta.SelfLink = testapi.Default.SelfLink("pvc", "") - - c2 := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "c2", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("3Gi"), - }, - }, - }, - Status: api.PersistentVolumeClaimStatus{ - Phase: api.ClaimPending, - }, - } - c2.ObjectMeta.SelfLink = testapi.Default.SelfLink("pvc", "") - - v := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PersistentVolumeSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10Gi"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: fmt.Sprintf("%s/data01", tmpDir), - }, - }, - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, - }, - } - - volumeIndex := NewPersistentVolumeOrderedIndex() - mockClient := &mockBinderClient{} - mockClient.volume = v - - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(host_path.ProbeRecyclableVolumePlugins(newMockRecycler, volume.VolumeConfig{}), volumetest.NewFakeVolumeHost(tmpDir, nil, nil)) - // adds the volume to the index, making the volume available - syncVolume(volumeIndex, mockClient, v) - if mockClient.volume.Status.Phase != api.VolumeAvailable { - t.Errorf("Expected phase %s but got %s", api.VolumeAvailable, mockClient.volume.Status.Phase) - } - if _, exists, _ := volumeIndex.Get(v); !exists { - t.Errorf("Expected to find volume in index but it did not exist") - } - - // add the claim to fake API server - mockClient.UpdatePersistentVolumeClaim(c1) - // an initial sync for a claim matches the volume - err = syncClaim(volumeIndex, mockClient, c1) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - if c1.Status.Phase != api.ClaimBound { - t.Errorf("Expected phase %s but got %s", api.ClaimBound, c1.Status.Phase) - } - - // before the volume gets updated w/ claimRef, a 2nd claim can attempt to bind and find the same volume - // add the 2nd claim to fake API server - mockClient.UpdatePersistentVolumeClaim(c2) - err = syncClaim(volumeIndex, mockClient, c2) - if err != nil { - t.Errorf("unexpected error for unmatched claim: %v", err) - } - if c2.Status.Phase != api.ClaimPending { - t.Errorf("Expected phase %s but got %s", api.ClaimPending, c2.Status.Phase) - } -} - -func TestNewClaimWithSameNameAsOldClaim(t *testing.T) { - c1 := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "c1", - Namespace: "foo", - UID: "12345", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("3Gi"), - }, - }, - }, - Status: api.PersistentVolumeClaimStatus{ - Phase: api.ClaimBound, - }, - } - c1.ObjectMeta.SelfLink = testapi.Default.SelfLink("pvc", "") - - v := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PersistentVolumeSpec{ - ClaimRef: &api.ObjectReference{ - Name: c1.Name, - Namespace: c1.Namespace, - UID: "45678", - }, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10Gi"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: "/tmp/data01", - }, - }, - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - }, - } - - volumeIndex := NewPersistentVolumeOrderedIndex() - mockClient := &mockBinderClient{ - claim: c1, - volume: v, - } - - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(host_path.ProbeRecyclableVolumePlugins(newMockRecycler, volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil)) - - syncVolume(volumeIndex, mockClient, v) - if mockClient.volume.Status.Phase != api.VolumeReleased { - t.Errorf("Expected phase %s but got %s", api.VolumeReleased, mockClient.volume.Status.Phase) - } - -} - -func TestClaimSyncAfterVolumeProvisioning(t *testing.T) { - tmpDir, err := utiltesting.MkTmpdir("claimbinder-test") - if err != nil { - t.Fatalf("error creating temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - - // Tests that binder.syncVolume will also syncClaim if the PV has completed - // provisioning but the claim is still Pending. We want to advance to Bound - // without having to wait until the binder's next sync period. - claim := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "bar", - Annotations: map[string]string{ - qosProvisioningKey: "foo", - }, - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("3Gi"), - }, - }, - }, - Status: api.PersistentVolumeClaimStatus{ - Phase: api.ClaimPending, - }, - } - claim.ObjectMeta.SelfLink = testapi.Default.SelfLink("pvc", "") - claimRef, _ := api.GetReference(claim) - - pv := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Annotations: map[string]string{ - pvProvisioningRequiredAnnotationKey: pvProvisioningCompletedAnnotationValue, - }, - }, - Spec: api.PersistentVolumeSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10Gi"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: fmt.Sprintf("%s/data01", tmpDir), - }, - }, - ClaimRef: claimRef, - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, - }, - } - - volumeIndex := NewPersistentVolumeOrderedIndex() - mockClient := &mockBinderClient{ - claim: claim, - volume: pv, - } - - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(host_path.ProbeRecyclableVolumePlugins(newMockRecycler, volume.VolumeConfig{}), volumetest.NewFakeVolumeHost(tmpDir, nil, nil)) - - // adds the volume to the index, making the volume available. - // pv also completed provisioning, so syncClaim should cause claim's phase to advance to Bound - syncVolume(volumeIndex, mockClient, pv) - if mockClient.volume.Status.Phase != api.VolumeAvailable { - t.Errorf("Expected phase %s but got %s", api.VolumeAvailable, mockClient.volume.Status.Phase) - } - if mockClient.claim.Status.Phase != api.ClaimBound { - t.Errorf("Expected phase %s but got %s", api.ClaimBound, claim.Status.Phase) - } -} - -func TestExampleObjects(t *testing.T) { - scenarios := map[string]struct { - expected interface{} - }{ - "claims/claim-01.yaml": { - expected: &api.PersistentVolumeClaim{ - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("3Gi"), - }, - }, - }, - }, - }, - "claims/claim-02.yaml": { - expected: &api.PersistentVolumeClaim{ - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("8Gi"), - }, - }, - }, - }, - }, - "volumes/local-01.yaml": { - expected: &api.PersistentVolume{ - Spec: api.PersistentVolumeSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10Gi"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: "/somepath/data01", - }, - }, - }, - }, - }, - "volumes/local-02.yaml": { - expected: &api.PersistentVolume{ - Spec: api.PersistentVolumeSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("8Gi"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: "/somepath/data02", - }, - }, - PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRecycle, - }, - }, - }, - } - - for name, scenario := range scenarios { - codec := api.Codecs.UniversalDecoder() - o := core.NewObjects(api.Scheme, codec) - if err := core.AddObjectsFromPath("../../../docs/user-guide/persistent-volumes/"+name, o, codec); err != nil { - t.Fatal(err) - } - - clientset := &fake.Clientset{} - clientset.AddReactor("*", "*", core.ObjectReaction(o, registered.RESTMapper())) - - if reflect.TypeOf(scenario.expected) == reflect.TypeOf(&api.PersistentVolumeClaim{}) { - pvc, err := clientset.Core().PersistentVolumeClaims("ns").Get("doesntmatter") - if err != nil { - t.Fatalf("Error retrieving object: %v", err) - } - - expected := scenario.expected.(*api.PersistentVolumeClaim) - if pvc.Spec.AccessModes[0] != expected.Spec.AccessModes[0] { - t.Errorf("Unexpected mismatch. Got %v wanted %v", pvc.Spec.AccessModes[0], expected.Spec.AccessModes[0]) - } - - aQty := pvc.Spec.Resources.Requests[api.ResourceStorage] - bQty := expected.Spec.Resources.Requests[api.ResourceStorage] - aSize := aQty.Value() - bSize := bQty.Value() - - if aSize != bSize { - t.Errorf("Unexpected mismatch. Got %v wanted %v", aSize, bSize) - } - } - - if reflect.TypeOf(scenario.expected) == reflect.TypeOf(&api.PersistentVolume{}) { - pv, err := clientset.Core().PersistentVolumes().Get("doesntmatter") - if err != nil { - t.Fatalf("Error retrieving object: %v", err) - } - - expected := scenario.expected.(*api.PersistentVolume) - if pv.Spec.AccessModes[0] != expected.Spec.AccessModes[0] { - t.Errorf("Unexpected mismatch. Got %v wanted %v", pv.Spec.AccessModes[0], expected.Spec.AccessModes[0]) - } - - aQty := pv.Spec.Capacity[api.ResourceStorage] - bQty := expected.Spec.Capacity[api.ResourceStorage] - aSize := aQty.Value() - bSize := bQty.Value() - - if aSize != bSize { - t.Errorf("Unexpected mismatch. Got %v wanted %v", aSize, bSize) - } - - if pv.Spec.HostPath.Path != expected.Spec.HostPath.Path { - t.Errorf("Unexpected mismatch. Got %v wanted %v", pv.Spec.HostPath.Path, expected.Spec.HostPath.Path) - } - } - } -} - -func TestBindingWithExamples(t *testing.T) { - tmpDir, err := utiltesting.MkTmpdir("claimbinder-test") - if err != nil { - t.Fatalf("error creating temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - - codec := api.Codecs.UniversalDecoder() - o := core.NewObjects(api.Scheme, codec) - if err := core.AddObjectsFromPath("../../../docs/user-guide/persistent-volumes/claims/claim-01.yaml", o, codec); err != nil { - t.Fatal(err) - } - if err := core.AddObjectsFromPath("../../../docs/user-guide/persistent-volumes/volumes/local-01.yaml", o, codec); err != nil { - t.Fatal(err) - } - - clientset := &fake.Clientset{} - clientset.AddReactor("*", "*", core.ObjectReaction(o, registered.RESTMapper())) - - pv, err := clientset.Core().PersistentVolumes().Get("any") - if err != nil { - t.Errorf("Unexpected error getting PV from client: %v", err) - } - pv.Spec.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimRecycle - if err != nil { - t.Errorf("Unexpected error getting PV from client: %v", err) - } - pv.ObjectMeta.SelfLink = testapi.Default.SelfLink("pv", "") - - // the default value of the PV is Pending. if processed at least once, its status in etcd is Available. - // There was a bug where only Pending volumes were being indexed and made ready for claims. - // Test that !Pending gets correctly added - pv.Status.Phase = api.VolumeAvailable - - claim, error := clientset.Core().PersistentVolumeClaims("ns").Get("any") - if error != nil { - t.Errorf("Unexpected error getting PVC from client: %v", err) - } - claim.ObjectMeta.SelfLink = testapi.Default.SelfLink("pvc", "") - - volumeIndex := NewPersistentVolumeOrderedIndex() - mockClient := &mockBinderClient{ - volume: pv, - claim: claim, - } - - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(host_path.ProbeRecyclableVolumePlugins(newMockRecycler, volume.VolumeConfig{}), volumetest.NewFakeVolumeHost(tmpDir, nil, nil)) - - recycler := &PersistentVolumeRecycler{ - kubeClient: clientset, - client: mockClient, - pluginMgr: plugMgr, - } - - // adds the volume to the index, making the volume available - syncVolume(volumeIndex, mockClient, pv) - if mockClient.volume.Status.Phase != api.VolumeAvailable { - t.Errorf("Expected phase %s but got %s", api.VolumeAvailable, mockClient.volume.Status.Phase) - } - - // add the claim to fake API server - mockClient.UpdatePersistentVolumeClaim(claim) - // an initial sync for a claim will bind it to an unbound volume - syncClaim(volumeIndex, mockClient, claim) - - // bind expected on pv.Spec but status update hasn't happened yet - if mockClient.volume.Spec.ClaimRef == nil { - t.Errorf("Expected ClaimRef but got nil for pv.Status.ClaimRef\n") - } - if mockClient.volume.Status.Phase != api.VolumeAvailable { - t.Errorf("Expected phase %s but got %s", api.VolumeAvailable, mockClient.volume.Status.Phase) - } - if mockClient.claim.Spec.VolumeName != pv.Name { - t.Errorf("Expected claim.Spec.VolumeName %s but got %s", mockClient.claim.Spec.VolumeName, pv.Name) - } - if mockClient.claim.Status.Phase != api.ClaimBound { - t.Errorf("Expected phase %s but got %s", api.ClaimBound, claim.Status.Phase) - } - - // state changes in pvc triggers sync that sets pv attributes to pvc.Status - syncClaim(volumeIndex, mockClient, claim) - if len(mockClient.claim.Status.AccessModes) == 0 { - t.Errorf("Expected %d access modes but got 0", len(pv.Spec.AccessModes)) - } - - // persisting the bind to pv.Spec.ClaimRef triggers a sync - syncVolume(volumeIndex, mockClient, mockClient.volume) - if mockClient.volume.Status.Phase != api.VolumeBound { - t.Errorf("Expected phase %s but got %s", api.VolumeBound, mockClient.volume.Status.Phase) - } - - // pretend the user deleted their claim. periodic resync picks it up. - mockClient.claim = nil - syncVolume(volumeIndex, mockClient, mockClient.volume) - - if mockClient.volume.Status.Phase != api.VolumeReleased { - t.Errorf("Expected phase %s but got %s", api.VolumeReleased, mockClient.volume.Status.Phase) - } - - // released volumes with a PersistentVolumeReclaimPolicy (recycle/delete) can have further processing - err = recycler.reclaimVolume(mockClient.volume) - if err != nil { - t.Errorf("Unexpected error reclaiming volume: %+v", err) - } - if mockClient.volume.Status.Phase != api.VolumePending { - t.Errorf("Expected phase %s but got %s", api.VolumePending, mockClient.volume.Status.Phase) - } - - // after the recycling changes the phase to Pending, the binder picks up again - // to remove any vestiges of binding and make the volume Available again - syncVolume(volumeIndex, mockClient, mockClient.volume) - - if mockClient.volume.Status.Phase != api.VolumeAvailable { - t.Errorf("Expected phase %s but got %s", api.VolumeAvailable, mockClient.volume.Status.Phase) - } - if mockClient.volume.Spec.ClaimRef != nil { - t.Errorf("Expected nil ClaimRef: %+v", mockClient.volume.Spec.ClaimRef) - } -} - -func TestCasting(t *testing.T) { - clientset := fake.NewSimpleClientset() - binder := NewPersistentVolumeClaimBinder(clientset, 1*time.Second) - - pv := &api.PersistentVolume{} - unk := cache.DeletedFinalStateUnknown{} - pvc := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Status: api.PersistentVolumeClaimStatus{Phase: api.ClaimBound}, - } - - // Inject mockClient into the binder. This prevents weird errors on stderr - // as the binder wants to load PV/PVC from API server. - mockClient := &mockBinderClient{ - volume: pv, - claim: pvc, - } - binder.client = mockClient - - // none of these should fail casting. - // the real test is not failing when passed DeletedFinalStateUnknown in the deleteHandler - binder.addVolume(pv) - binder.updateVolume(pv, pv) - binder.deleteVolume(pv) - binder.deleteVolume(unk) - binder.addClaim(pvc) - binder.updateClaim(pvc, pvc) -} - -func TestRecycledPersistentVolumeUID(t *testing.T) { - tmpDir, err := utiltesting.MkTmpdir("claimbinder-test") - if err != nil { - t.Fatalf("error creating temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - - codec := api.Codecs.UniversalDecoder() - o := core.NewObjects(api.Scheme, codec) - if err := core.AddObjectsFromPath("../../../docs/user-guide/persistent-volumes/claims/claim-01.yaml", o, codec); err != nil { - t.Fatal(err) - } - if err := core.AddObjectsFromPath("../../../docs/user-guide/persistent-volumes/volumes/local-01.yaml", o, codec); err != nil { - t.Fatal(err) - } - - clientset := &fake.Clientset{} - clientset.AddReactor("*", "*", core.ObjectReaction(o, registered.RESTMapper())) - - pv, err := clientset.Core().PersistentVolumes().Get("any") - if err != nil { - t.Errorf("Unexpected error getting PV from client: %v", err) - } - pv.Spec.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimRecycle - if err != nil { - t.Errorf("Unexpected error getting PV from client: %v", err) - } - pv.ObjectMeta.SelfLink = testapi.Default.SelfLink("pv", "") - - // the default value of the PV is Pending. if processed at least once, its status in etcd is Available. - // There was a bug where only Pending volumes were being indexed and made ready for claims. - // Test that !Pending gets correctly added - pv.Status.Phase = api.VolumeAvailable - - claim, error := clientset.Core().PersistentVolumeClaims("ns").Get("any") - if error != nil { - t.Errorf("Unexpected error getting PVC from client: %v", err) - } - claim.ObjectMeta.SelfLink = testapi.Default.SelfLink("pvc", "") - claim.ObjectMeta.UID = types.UID("uid1") - - volumeIndex := NewPersistentVolumeOrderedIndex() - mockClient := &mockBinderClient{ - volume: pv, - claim: claim, - } - - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(host_path.ProbeRecyclableVolumePlugins(newMockRecycler, volume.VolumeConfig{}), volumetest.NewFakeVolumeHost(tmpDir, nil, nil)) - - recycler := &PersistentVolumeRecycler{ - kubeClient: clientset, - client: mockClient, - pluginMgr: plugMgr, - } - - // adds the volume to the index, making the volume available - syncVolume(volumeIndex, mockClient, pv) - if mockClient.volume.Status.Phase != api.VolumeAvailable { - t.Errorf("Expected phase %s but got %s", api.VolumeAvailable, mockClient.volume.Status.Phase) - } - - // add the claim to fake API server - mockClient.UpdatePersistentVolumeClaim(claim) - // an initial sync for a claim will bind it to an unbound volume - syncClaim(volumeIndex, mockClient, claim) - - // pretend the user deleted their claim. periodic resync picks it up. - mockClient.claim = nil - syncVolume(volumeIndex, mockClient, mockClient.volume) - - if mockClient.volume.Status.Phase != api.VolumeReleased { - t.Errorf("Expected phase %s but got %s", api.VolumeReleased, mockClient.volume.Status.Phase) - } - - // released volumes with a PersistentVolumeReclaimPolicy (recycle/delete) can have further processing - err = recycler.reclaimVolume(mockClient.volume) - if err != nil { - t.Errorf("Unexpected error reclaiming volume: %+v", err) - } - if mockClient.volume.Status.Phase != api.VolumePending { - t.Errorf("Expected phase %s but got %s", api.VolumePending, mockClient.volume.Status.Phase) - } - - // after the recycling changes the phase to Pending, the binder picks up again - // to remove any vestiges of binding and make the volume Available again - // - // explicitly set the claim's UID to a different value to ensure that a new claim with the same - // name as what the PV was previously bound still yields an available volume - claim.ObjectMeta.UID = types.UID("uid2") - mockClient.claim = claim - syncVolume(volumeIndex, mockClient, mockClient.volume) - - if mockClient.volume.Status.Phase != api.VolumeAvailable { - t.Errorf("Expected phase %s but got %s", api.VolumeAvailable, mockClient.volume.Status.Phase) - } - if mockClient.volume.Spec.ClaimRef != nil { - t.Errorf("Expected nil ClaimRef: %+v", mockClient.volume.Spec.ClaimRef) - } -} - -type mockBinderClient struct { - volume *api.PersistentVolume - claim *api.PersistentVolumeClaim -} - -func (c *mockBinderClient) GetPersistentVolume(name string) (*api.PersistentVolume, error) { - return c.volume, nil -} - -func (c *mockBinderClient) UpdatePersistentVolume(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - c.volume = volume - return c.volume, nil -} - -func (c *mockBinderClient) DeletePersistentVolume(volume *api.PersistentVolume) error { - c.volume = nil - return nil -} - -func (c *mockBinderClient) UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - c.volume = volume - return c.volume, nil -} - -func (c *mockBinderClient) GetPersistentVolumeClaim(namespace, name string) (*api.PersistentVolumeClaim, error) { - if c.claim != nil { - return c.claim, nil - } else { - return nil, errors.NewNotFound(api.Resource("persistentvolumes"), name) - } -} - -func (c *mockBinderClient) UpdatePersistentVolumeClaim(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - c.claim = claim - return c.claim, nil -} - -func (c *mockBinderClient) UpdatePersistentVolumeClaimStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - c.claim = claim - return c.claim, nil -} - -func newMockRecycler(spec *volume.Spec, host volume.VolumeHost, config volume.VolumeConfig) (volume.Recycler, error) { - return &mockRecycler{ - path: spec.PersistentVolume.Spec.HostPath.Path, - }, nil -} - -type mockRecycler struct { - path string - host volume.VolumeHost - volume.MetricsNil -} - -func (r *mockRecycler) GetPath() string { - return r.path -} - -func (r *mockRecycler) Recycle() error { - // return nil means recycle passed - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_index_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_index_test.go deleted file mode 100644 index 7bb6c5387..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_index_test.go +++ /dev/null @@ -1,549 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 persistentvolume - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" -) - -func TestMatchVolume(t *testing.T) { - volList := NewPersistentVolumeOrderedIndex() - for _, pv := range createTestVolumes() { - volList.Add(pv) - } - - scenarios := map[string]struct { - expectedMatch string - claim *api.PersistentVolumeClaim - }{ - "successful-match-gce-10": { - expectedMatch: "gce-pd-10", - claim: &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "claim01", - Namespace: "myns", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany, api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("8G"), - }, - }, - }, - }, - }, - "successful-match-nfs-5": { - expectedMatch: "nfs-5", - claim: &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "claim01", - Namespace: "myns", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany, api.ReadWriteOnce, api.ReadWriteMany}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("5G"), - }, - }, - }, - }, - }, - "successful-skip-1g-bound-volume": { - expectedMatch: "gce-pd-5", - claim: &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "claim01", - Namespace: "myns", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany, api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("1G"), - }, - }, - }, - }, - }, - "successful-no-match": { - expectedMatch: "", - claim: &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "claim01", - Namespace: "myns", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany, api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("999G"), - }, - }, - }, - }, - }, - } - - for name, scenario := range scenarios { - volume, err := volList.findBestMatchForClaim(scenario.claim) - if err != nil { - t.Errorf("Unexpected error matching volume by claim: %v", err) - } - if len(scenario.expectedMatch) != 0 && volume == nil { - t.Errorf("Expected match but received nil volume for scenario: %s", name) - } - if len(scenario.expectedMatch) != 0 && volume != nil && string(volume.UID) != scenario.expectedMatch { - t.Errorf("Expected %s but got volume %s in scenario %s", scenario.expectedMatch, volume.UID, name) - } - if len(scenario.expectedMatch) == 0 && volume != nil { - t.Errorf("Unexpected match for scenario: %s", name) - } - } -} - -func TestMatchingWithBoundVolumes(t *testing.T) { - volumeIndex := NewPersistentVolumeOrderedIndex() - // two similar volumes, one is bound - pv1 := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - UID: "gce-pd-1", - Name: "gce001", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("1G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce, api.ReadOnlyMany}, - // this one we're pretending is already bound - ClaimRef: &api.ObjectReference{UID: "abc123"}, - }, - } - - pv2 := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - UID: "gce-pd-2", - Name: "gce002", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("1G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce, api.ReadOnlyMany}, - }, - } - - volumeIndex.Add(pv1) - volumeIndex.Add(pv2) - - claim := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "claim01", - Namespace: "myns", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadOnlyMany, api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("1G"), - }, - }, - }, - } - - volume, err := volumeIndex.findBestMatchForClaim(claim) - if err != nil { - t.Fatalf("Unexpected error matching volume by claim: %v", err) - } - if volume == nil { - t.Fatalf("Unexpected nil volume. Expected %s", pv2.Name) - } - if pv2.Name != volume.Name { - t.Errorf("Expected %s but got volume %s instead", pv2.Name, volume.Name) - } -} - -func TestSort(t *testing.T) { - volList := NewPersistentVolumeOrderedIndex() - for _, pv := range createTestVolumes() { - volList.Add(pv) - } - - volumes, err := volList.ListByAccessModes([]api.PersistentVolumeAccessMode{api.ReadWriteOnce, api.ReadOnlyMany}) - if err != nil { - t.Error("Unexpected error retrieving volumes by access modes:", err) - } - - for i, expected := range []string{"gce-pd-1", "gce-pd-5", "gce-pd-10"} { - if string(volumes[i].UID) != expected { - t.Errorf("Incorrect ordering of persistent volumes. Expected %s but got %s", expected, volumes[i].UID) - } - } - - volumes, err = volList.ListByAccessModes([]api.PersistentVolumeAccessMode{api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany}) - if err != nil { - t.Error("Unexpected error retrieving volumes by access modes:", err) - } - - for i, expected := range []string{"nfs-1", "nfs-5", "nfs-10"} { - if string(volumes[i].UID) != expected { - t.Errorf("Incorrect ordering of persistent volumes. Expected %s but got %s", expected, volumes[i].UID) - } - } -} - -func TestAllPossibleAccessModes(t *testing.T) { - index := NewPersistentVolumeOrderedIndex() - for _, pv := range createTestVolumes() { - index.Add(pv) - } - - // the mock PVs creates contain 2 types of accessmodes: RWO+ROX and RWO+ROW+RWX - possibleModes := index.allPossibleMatchingAccessModes([]api.PersistentVolumeAccessMode{api.ReadWriteOnce}) - if len(possibleModes) != 2 { - t.Errorf("Expected 2 arrays of modes that match RWO, but got %v", len(possibleModes)) - } - for _, m := range possibleModes { - if !contains(m, api.ReadWriteOnce) { - t.Errorf("AccessModes does not contain %s", api.ReadWriteOnce) - } - } - - possibleModes = index.allPossibleMatchingAccessModes([]api.PersistentVolumeAccessMode{api.ReadWriteMany}) - if len(possibleModes) != 1 { - t.Errorf("Expected 1 array of modes that match RWX, but got %v", len(possibleModes)) - } - if !contains(possibleModes[0], api.ReadWriteMany) { - t.Errorf("AccessModes does not contain %s", api.ReadWriteOnce) - } - -} - -func TestFindingVolumeWithDifferentAccessModes(t *testing.T) { - gce := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{UID: "001", Name: "gce"}, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse("10G")}, - PersistentVolumeSource: api.PersistentVolumeSource{GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}}, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - }, - } - - ebs := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{UID: "002", Name: "ebs"}, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse("10G")}, - PersistentVolumeSource: api.PersistentVolumeSource{AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{}}, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - }, - }, - } - - nfs := &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{UID: "003", Name: "nfs"}, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse("10G")}, - PersistentVolumeSource: api.PersistentVolumeSource{NFS: &api.NFSVolumeSource{}}, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - api.ReadWriteMany, - }, - }, - } - - claim := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "claim01", - Namespace: "myns", - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{Requests: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse("1G")}}, - }, - } - - index := NewPersistentVolumeOrderedIndex() - index.Add(gce) - index.Add(ebs) - index.Add(nfs) - - volume, _ := index.findBestMatchForClaim(claim) - if volume.Name != ebs.Name { - t.Errorf("Expected %s but got volume %s instead", ebs.Name, volume.Name) - } - - claim.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadWriteOnce, api.ReadOnlyMany} - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != gce.Name { - t.Errorf("Expected %s but got volume %s instead", gce.Name, volume.Name) - } - - // order of the requested modes should not matter - claim.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadWriteMany, api.ReadWriteOnce, api.ReadOnlyMany} - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != nfs.Name { - t.Errorf("Expected %s but got volume %s instead", nfs.Name, volume.Name) - } - - // fewer modes requested should still match - claim.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadWriteMany} - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != nfs.Name { - t.Errorf("Expected %s but got volume %s instead", nfs.Name, volume.Name) - } - - // pretend the exact match is bound. should get the next level up of modes. - ebs.Spec.ClaimRef = &api.ObjectReference{} - claim.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadWriteOnce} - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != gce.Name { - t.Errorf("Expected %s but got volume %s instead", gce.Name, volume.Name) - } - - // continue up the levels of modes. - gce.Spec.ClaimRef = &api.ObjectReference{} - claim.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadWriteOnce} - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != nfs.Name { - t.Errorf("Expected %s but got volume %s instead", nfs.Name, volume.Name) - } - - // partial mode request - gce.Spec.ClaimRef = nil - claim.Spec.AccessModes = []api.PersistentVolumeAccessMode{api.ReadOnlyMany} - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != gce.Name { - t.Errorf("Expected %s but got volume %s instead", gce.Name, volume.Name) - } -} - -func createTestVolumes() []*api.PersistentVolume { - // these volumes are deliberately out-of-order to test indexing and sorting - return []*api.PersistentVolume{ - { - ObjectMeta: api.ObjectMeta{ - UID: "gce-pd-10", - Name: "gce003", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - UID: "gce-pd-20", - Name: "gce004", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("20G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - // this one we're pretending is already bound - ClaimRef: &api.ObjectReference{UID: "def456"}, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - UID: "nfs-5", - Name: "nfs002", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("5G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - Glusterfs: &api.GlusterfsVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - api.ReadWriteMany, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - UID: "gce-pd-1", - Name: "gce001", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("1G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - // this one we're pretending is already bound - ClaimRef: &api.ObjectReference{UID: "abc123"}, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - UID: "nfs-10", - Name: "nfs003", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - Glusterfs: &api.GlusterfsVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - api.ReadWriteMany, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - UID: "gce-pd-5", - Name: "gce002", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("5G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - UID: "nfs-1", - Name: "nfs001", - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("1G"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - Glusterfs: &api.GlusterfsVolumeSource{}, - }, - AccessModes: []api.PersistentVolumeAccessMode{ - api.ReadWriteOnce, - api.ReadOnlyMany, - api.ReadWriteMany, - }, - }, - }, - } -} - -func testVolume(name, size string) *api.PersistentVolume { - return &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Annotations: map[string]string{}, - }, - Spec: api.PersistentVolumeSpec{ - Capacity: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse(size)}, - PersistentVolumeSource: api.PersistentVolumeSource{HostPath: &api.HostPathVolumeSource{}}, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - }, - } -} - -func TestFindingPreboundVolumes(t *testing.T) { - claim := &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: "claim01", - Namespace: "myns", - SelfLink: testapi.Default.SelfLink("pvc", ""), - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{Requests: api.ResourceList{api.ResourceName(api.ResourceStorage): resource.MustParse("1Gi")}}, - }, - } - claimRef, err := api.GetReference(claim) - if err != nil { - t.Errorf("error getting claimRef: %v", err) - } - - pv1 := testVolume("pv1", "1Gi") - pv5 := testVolume("pv5", "5Gi") - pv8 := testVolume("pv8", "8Gi") - - index := NewPersistentVolumeOrderedIndex() - index.Add(pv1) - index.Add(pv5) - index.Add(pv8) - - // expected exact match on size - volume, _ := index.findBestMatchForClaim(claim) - if volume.Name != pv1.Name { - t.Errorf("Expected %s but got volume %s instead", pv1.Name, volume.Name) - } - - // pretend the exact match is pre-bound. should get the next size up. - pv1.Spec.ClaimRef = &api.ObjectReference{Name: "foo", Namespace: "bar"} - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != pv5.Name { - t.Errorf("Expected %s but got volume %s instead", pv5.Name, volume.Name) - } - - // pretend the exact match is available but the largest volume is pre-bound to the claim. - pv1.Spec.ClaimRef = nil - pv8.Spec.ClaimRef = claimRef - volume, _ = index.findBestMatchForClaim(claim) - if volume.Name != pv8.Name { - t.Errorf("Expected %s but got volume %s instead", pv8.Name, volume.Name) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_provisioner_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_provisioner_controller.go deleted file mode 100644 index fdb7804a3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_provisioner_controller.go +++ /dev/null @@ -1,536 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 persistentvolume - -import ( - "fmt" - "sync" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/io" - "k8s.io/kubernetes/pkg/util/mount" - "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/watch" - - "github.com/golang/glog" -) - -// PersistentVolumeProvisionerController reconciles the state of all PersistentVolumes and PersistentVolumeClaims. -type PersistentVolumeProvisionerController struct { - volumeController *framework.Controller - volumeStore cache.Store - claimController *framework.Controller - claimStore cache.Store - client controllerClient - cloud cloudprovider.Interface - provisioner volume.ProvisionableVolumePlugin - pluginMgr volume.VolumePluginMgr - stopChannels map[string]chan struct{} - mutex sync.RWMutex - clusterName string -} - -// constant name values for the controllers stopChannels map. -// the controller uses these for graceful shutdown -const volumesStopChannel = "volumes" -const claimsStopChannel = "claims" - -// NewPersistentVolumeProvisionerController creates a new PersistentVolumeProvisionerController -func NewPersistentVolumeProvisionerController(client controllerClient, syncPeriod time.Duration, clusterName string, plugins []volume.VolumePlugin, provisioner volume.ProvisionableVolumePlugin, cloud cloudprovider.Interface) (*PersistentVolumeProvisionerController, error) { - controller := &PersistentVolumeProvisionerController{ - client: client, - cloud: cloud, - provisioner: provisioner, - clusterName: clusterName, - } - - if err := controller.pluginMgr.InitPlugins(plugins, controller); err != nil { - return nil, fmt.Errorf("Could not initialize volume plugins for PersistentVolumeProvisionerController: %+v", err) - } - - glog.V(5).Infof("Initializing provisioner: %s", controller.provisioner.Name()) - controller.provisioner.Init(controller) - - controller.volumeStore, controller.volumeController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return client.ListPersistentVolumes(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return client.WatchPersistentVolumes(options) - }, - }, - &api.PersistentVolume{}, - syncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: controller.handleAddVolume, - UpdateFunc: controller.handleUpdateVolume, - // delete handler not needed in this controller. - // volume deletion is handled by the recycler controller - }, - ) - controller.claimStore, controller.claimController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return client.ListPersistentVolumeClaims(api.NamespaceAll, options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return client.WatchPersistentVolumeClaims(api.NamespaceAll, options) - }, - }, - &api.PersistentVolumeClaim{}, - syncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: controller.handleAddClaim, - UpdateFunc: controller.handleUpdateClaim, - // delete handler not needed. - // normal recycling applies when a claim is deleted. - // recycling is handled by the binding controller. - }, - ) - - return controller, nil -} - -func (controller *PersistentVolumeProvisionerController) handleAddVolume(obj interface{}) { - controller.mutex.Lock() - defer controller.mutex.Unlock() - cachedPv, _, _ := controller.volumeStore.Get(obj) - if pv, ok := cachedPv.(*api.PersistentVolume); ok { - err := controller.reconcileVolume(pv) - if err != nil { - glog.Errorf("Error reconciling volume %s: %+v", pv.Name, err) - } - } -} - -func (controller *PersistentVolumeProvisionerController) handleUpdateVolume(oldObj, newObj interface{}) { - // The flow for Update is the same as Add. - // A volume is only provisioned if not done so already. - controller.handleAddVolume(newObj) -} - -func (controller *PersistentVolumeProvisionerController) handleAddClaim(obj interface{}) { - controller.mutex.Lock() - defer controller.mutex.Unlock() - cachedPvc, exists, _ := controller.claimStore.Get(obj) - if !exists { - glog.Errorf("PersistentVolumeClaim does not exist in the local cache: %+v", obj) - return - } - if pvc, ok := cachedPvc.(*api.PersistentVolumeClaim); ok { - err := controller.reconcileClaim(pvc) - if err != nil { - glog.Errorf("Error encoutered reconciling claim %s: %+v", pvc.Name, err) - } - } -} - -func (controller *PersistentVolumeProvisionerController) handleUpdateClaim(oldObj, newObj interface{}) { - // The flow for Update is the same as Add. - // A volume is only provisioned for a claim if not done so already. - controller.handleAddClaim(newObj) -} - -func (controller *PersistentVolumeProvisionerController) reconcileClaim(claim *api.PersistentVolumeClaim) error { - glog.V(5).Infof("Synchronizing PersistentVolumeClaim[%s] for dynamic provisioning", claim.Name) - - // The claim may have been modified by parallel call to reconcileClaim, load - // the current version. - newClaim, err := controller.client.GetPersistentVolumeClaim(claim.Namespace, claim.Name) - if err != nil { - return fmt.Errorf("Cannot reload claim %s/%s: %v", claim.Namespace, claim.Name, err) - } - claim = newClaim - err = controller.claimStore.Update(claim) - if err != nil { - return fmt.Errorf("Cannot update claim %s/%s: %v", claim.Namespace, claim.Name, err) - } - - if controller.provisioner == nil { - return fmt.Errorf("No provisioner configured for controller") - } - - // no provisioning requested, return Pending. Claim may be pending indefinitely without a match. - if !keyExists(qosProvisioningKey, claim.Annotations) { - glog.V(5).Infof("PersistentVolumeClaim[%s] no provisioning required", claim.Name) - return nil - } - if len(claim.Spec.VolumeName) != 0 { - glog.V(5).Infof("PersistentVolumeClaim[%s] already bound. No provisioning required", claim.Name) - return nil - } - if isAnnotationMatch(pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue, claim.Annotations) { - glog.V(5).Infof("PersistentVolumeClaim[%s] is already provisioned.", claim.Name) - return nil - } - - glog.V(5).Infof("PersistentVolumeClaim[%s] provisioning", claim.Name) - provisioner, err := controller.newProvisioner(controller.provisioner, claim, nil) - if err != nil { - return fmt.Errorf("Unexpected error getting new provisioner for claim %s: %v\n", claim.Name, err) - } - newVolume, err := provisioner.NewPersistentVolumeTemplate() - if err != nil { - return fmt.Errorf("Unexpected error getting new volume template for claim %s: %v\n", claim.Name, err) - } - - claimRef, err := api.GetReference(claim) - if err != nil { - return fmt.Errorf("Unexpected error getting claim reference for %s: %v\n", claim.Name, err) - } - - storageClass, _ := claim.Annotations[qosProvisioningKey] - - // the creation of this volume is the bind to the claim. - // The claim will match the volume during the next sync period when the volume is in the local cache - newVolume.Spec.ClaimRef = claimRef - newVolume.Annotations[pvProvisioningRequiredAnnotationKey] = "true" - newVolume.Annotations[qosProvisioningKey] = storageClass - newVolume, err = controller.client.CreatePersistentVolume(newVolume) - glog.V(5).Infof("Unprovisioned PersistentVolume[%s] created for PVC[%s], which will be fulfilled in the storage provider", newVolume.Name, claim.Name) - if err != nil { - return fmt.Errorf("PersistentVolumeClaim[%s] failed provisioning: %+v", claim.Name, err) - } - - claim.Annotations[pvProvisioningRequiredAnnotationKey] = pvProvisioningCompletedAnnotationValue - _, err = controller.client.UpdatePersistentVolumeClaim(claim) - if err != nil { - glog.Errorf("error updating persistent volume claim: %v", err) - } - - return nil -} - -func (controller *PersistentVolumeProvisionerController) reconcileVolume(pv *api.PersistentVolume) error { - glog.V(5).Infof("PersistentVolume[%s] reconciling", pv.Name) - - // The PV may have been modified by parallel call to reconcileVolume, load - // the current version. - newPv, err := controller.client.GetPersistentVolume(pv.Name) - if err != nil { - return fmt.Errorf("Cannot reload volume %s: %v", pv.Name, err) - } - pv = newPv - - if pv.Spec.ClaimRef == nil { - glog.V(5).Infof("PersistentVolume[%s] is not bound to a claim. No provisioning required", pv.Name) - return nil - } - - // TODO: fix this leaky abstraction. Had to make our own store key because ClaimRef fails the default keyfunc (no Meta on object). - obj, exists, _ := controller.claimStore.GetByKey(fmt.Sprintf("%s/%s", pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)) - if !exists { - return fmt.Errorf("PersistentVolumeClaim[%s/%s] not found in local cache", pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name) - } - - claim, ok := obj.(*api.PersistentVolumeClaim) - if !ok { - return fmt.Errorf("PersistentVolumeClaim expected, but got %v", obj) - } - - // no provisioning required, volume is ready and Bound - if !keyExists(pvProvisioningRequiredAnnotationKey, pv.Annotations) { - glog.V(5).Infof("PersistentVolume[%s] does not require provisioning", pv.Name) - return nil - } - - // provisioning is completed, volume is ready. - if isProvisioningComplete(pv) { - glog.V(5).Infof("PersistentVolume[%s] is bound and provisioning is complete", pv.Name) - if pv.Spec.ClaimRef.Namespace != claim.Namespace || pv.Spec.ClaimRef.Name != claim.Name { - return fmt.Errorf("pre-bind mismatch - expected %s but found %s/%s", claimToClaimKey(claim), pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name) - } - return nil - } - - // provisioning is incomplete. Attempt to provision the volume. - glog.V(5).Infof("PersistentVolume[%s] provisioning in progress", pv.Name) - err = provisionVolume(pv, controller) - if err != nil { - return fmt.Errorf("Error provisioning PersistentVolume[%s]: %v", pv.Name, err) - } - - return nil -} - -// provisionVolume provisions a volume that has been created in the cluster but not yet fulfilled by -// the storage provider. -func provisionVolume(pv *api.PersistentVolume, controller *PersistentVolumeProvisionerController) error { - if isProvisioningComplete(pv) { - return fmt.Errorf("PersistentVolume[%s] is already provisioned", pv.Name) - } - - if _, exists := pv.Annotations[qosProvisioningKey]; !exists { - return fmt.Errorf("PersistentVolume[%s] does not contain a provisioning request. Provisioning not required.", pv.Name) - } - - if controller.provisioner == nil { - return fmt.Errorf("No provisioner found for volume: %s", pv.Name) - } - - // Find the claim in local cache - obj, exists, _ := controller.claimStore.GetByKey(fmt.Sprintf("%s/%s", pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)) - if !exists { - return fmt.Errorf("Could not find PersistentVolumeClaim[%s/%s] in local cache", pv.Spec.ClaimRef.Name, pv.Name) - } - claim := obj.(*api.PersistentVolumeClaim) - - provisioner, _ := controller.newProvisioner(controller.provisioner, claim, pv) - err := provisioner.Provision(pv) - if err != nil { - glog.Errorf("Could not provision %s", pv.Name) - pv.Status.Phase = api.VolumeFailed - pv.Status.Message = err.Error() - if pv, apiErr := controller.client.UpdatePersistentVolumeStatus(pv); apiErr != nil { - return fmt.Errorf("PersistentVolume[%s] failed provisioning and also failed status update: %v - %v", pv.Name, err, apiErr) - } - return fmt.Errorf("PersistentVolume[%s] failed provisioning: %v", pv.Name, err) - } - - clone, err := conversion.NewCloner().DeepCopy(pv) - volumeClone, ok := clone.(*api.PersistentVolume) - if !ok { - return fmt.Errorf("Unexpected pv cast error : %v\n", volumeClone) - } - volumeClone.Annotations[pvProvisioningRequiredAnnotationKey] = pvProvisioningCompletedAnnotationValue - - pv, err = controller.client.UpdatePersistentVolume(volumeClone) - if err != nil { - // TODO: https://github.com/kubernetes/kubernetes/issues/14443 - // the volume was created in the infrastructure and likely has a PV name on it, - // but we failed to save the annotation that marks the volume as provisioned. - return fmt.Errorf("Error updating PersistentVolume[%s] with provisioning completed annotation. There is a potential for dupes and orphans.", volumeClone.Name) - } - return nil -} - -// Run starts all of this controller's control loops -func (controller *PersistentVolumeProvisionerController) Run() { - glog.V(5).Infof("Starting PersistentVolumeProvisionerController\n") - if controller.stopChannels == nil { - controller.stopChannels = make(map[string]chan struct{}) - } - - if _, exists := controller.stopChannels[volumesStopChannel]; !exists { - controller.stopChannels[volumesStopChannel] = make(chan struct{}) - go controller.volumeController.Run(controller.stopChannels[volumesStopChannel]) - } - - if _, exists := controller.stopChannels[claimsStopChannel]; !exists { - controller.stopChannels[claimsStopChannel] = make(chan struct{}) - go controller.claimController.Run(controller.stopChannels[claimsStopChannel]) - } -} - -// Stop gracefully shuts down this controller -func (controller *PersistentVolumeProvisionerController) Stop() { - glog.V(5).Infof("Stopping PersistentVolumeProvisionerController\n") - for name, stopChan := range controller.stopChannels { - close(stopChan) - delete(controller.stopChannels, name) - } -} - -func (controller *PersistentVolumeProvisionerController) newProvisioner(plugin volume.ProvisionableVolumePlugin, claim *api.PersistentVolumeClaim, pv *api.PersistentVolume) (volume.Provisioner, error) { - tags := make(map[string]string) - tags[cloudVolumeCreatedForClaimNamespaceTag] = claim.Namespace - tags[cloudVolumeCreatedForClaimNameTag] = claim.Name - - // pv can be nil when the provisioner has not created the PV yet - if pv != nil { - tags[cloudVolumeCreatedForVolumeNameTag] = pv.Name - } - - volumeOptions := volume.VolumeOptions{ - Capacity: claim.Spec.Resources.Requests[api.ResourceName(api.ResourceStorage)], - AccessModes: claim.Spec.AccessModes, - PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimDelete, - CloudTags: &tags, - ClusterName: controller.clusterName, - } - - if pv != nil { - volumeOptions.PVName = pv.Name - } - - provisioner, err := plugin.NewProvisioner(volumeOptions) - return provisioner, err -} - -// controllerClient abstracts access to PVs and PVCs. Easy to mock for testing and wrap for real client. -type controllerClient interface { - CreatePersistentVolume(pv *api.PersistentVolume) (*api.PersistentVolume, error) - ListPersistentVolumes(options api.ListOptions) (*api.PersistentVolumeList, error) - WatchPersistentVolumes(options api.ListOptions) (watch.Interface, error) - GetPersistentVolume(name string) (*api.PersistentVolume, error) - UpdatePersistentVolume(volume *api.PersistentVolume) (*api.PersistentVolume, error) - DeletePersistentVolume(volume *api.PersistentVolume) error - UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) - - GetPersistentVolumeClaim(namespace, name string) (*api.PersistentVolumeClaim, error) - ListPersistentVolumeClaims(namespace string, options api.ListOptions) (*api.PersistentVolumeClaimList, error) - WatchPersistentVolumeClaims(namespace string, options api.ListOptions) (watch.Interface, error) - UpdatePersistentVolumeClaim(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) - UpdatePersistentVolumeClaimStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) - - // provided to give VolumeHost and plugins access to the kube client - GetKubeClient() clientset.Interface -} - -func NewControllerClient(c clientset.Interface) controllerClient { - return &realControllerClient{c} -} - -var _ controllerClient = &realControllerClient{} - -type realControllerClient struct { - client clientset.Interface -} - -func (c *realControllerClient) GetPersistentVolume(name string) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().Get(name) -} - -func (c *realControllerClient) ListPersistentVolumes(options api.ListOptions) (*api.PersistentVolumeList, error) { - return c.client.Core().PersistentVolumes().List(options) -} - -func (c *realControllerClient) WatchPersistentVolumes(options api.ListOptions) (watch.Interface, error) { - return c.client.Core().PersistentVolumes().Watch(options) -} - -func (c *realControllerClient) CreatePersistentVolume(pv *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().Create(pv) -} - -func (c *realControllerClient) UpdatePersistentVolume(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().Update(volume) -} - -func (c *realControllerClient) DeletePersistentVolume(volume *api.PersistentVolume) error { - return c.client.Core().PersistentVolumes().Delete(volume.Name, nil) -} - -func (c *realControllerClient) UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().UpdateStatus(volume) -} - -func (c *realControllerClient) GetPersistentVolumeClaim(namespace, name string) (*api.PersistentVolumeClaim, error) { - return c.client.Core().PersistentVolumeClaims(namespace).Get(name) -} - -func (c *realControllerClient) ListPersistentVolumeClaims(namespace string, options api.ListOptions) (*api.PersistentVolumeClaimList, error) { - return c.client.Core().PersistentVolumeClaims(namespace).List(options) -} - -func (c *realControllerClient) WatchPersistentVolumeClaims(namespace string, options api.ListOptions) (watch.Interface, error) { - return c.client.Core().PersistentVolumeClaims(namespace).Watch(options) -} - -func (c *realControllerClient) UpdatePersistentVolumeClaim(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - return c.client.Core().PersistentVolumeClaims(claim.Namespace).Update(claim) -} - -func (c *realControllerClient) UpdatePersistentVolumeClaimStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - return c.client.Core().PersistentVolumeClaims(claim.Namespace).UpdateStatus(claim) -} - -func (c *realControllerClient) GetKubeClient() clientset.Interface { - return c.client -} - -func keyExists(key string, haystack map[string]string) bool { - _, exists := haystack[key] - return exists -} - -func isProvisioningComplete(pv *api.PersistentVolume) bool { - return isAnnotationMatch(pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue, pv.Annotations) -} - -func isAnnotationMatch(key, needle string, haystack map[string]string) bool { - value, exists := haystack[key] - if !exists { - return false - } - return value == needle -} - -func isRecyclable(policy api.PersistentVolumeReclaimPolicy) bool { - return policy == api.PersistentVolumeReclaimDelete || policy == api.PersistentVolumeReclaimRecycle -} - -// VolumeHost implementation -// PersistentVolumeRecycler is host to the volume plugins, but does not actually mount any volumes. -// Because no mounting is performed, most of the VolumeHost methods are not implemented. -func (c *PersistentVolumeProvisionerController) GetPluginDir(podUID string) string { - return "" -} - -func (c *PersistentVolumeProvisionerController) GetPodVolumeDir(podUID types.UID, pluginName, volumeName string) string { - return "" -} - -func (c *PersistentVolumeProvisionerController) GetPodPluginDir(podUID types.UID, pluginName string) string { - return "" -} - -func (c *PersistentVolumeProvisionerController) GetKubeClient() clientset.Interface { - return c.client.GetKubeClient() -} - -func (c *PersistentVolumeProvisionerController) NewWrapperMounter(volName string, spec volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Mounter, error) { - return nil, fmt.Errorf("NewWrapperMounter not supported by PVClaimBinder's VolumeHost implementation") -} - -func (c *PersistentVolumeProvisionerController) NewWrapperUnmounter(volName string, spec volume.Spec, podUID types.UID) (volume.Unmounter, error) { - return nil, fmt.Errorf("NewWrapperUnmounter not supported by PVClaimBinder's VolumeHost implementation") -} - -func (c *PersistentVolumeProvisionerController) GetCloudProvider() cloudprovider.Interface { - return c.cloud -} - -func (c *PersistentVolumeProvisionerController) GetMounter() mount.Interface { - return nil -} - -func (c *PersistentVolumeProvisionerController) GetWriter() io.Writer { - return nil -} - -func (c *PersistentVolumeProvisionerController) GetHostName() string { - return "" -} - -const ( - // these pair of constants are used by the provisioner. - // The key is a kube namespaced key that denotes a volume requires provisioning. - // The value is set only when provisioning is completed. Any other value will tell the provisioner - // that provisioning has not yet occurred. - pvProvisioningRequiredAnnotationKey = "volume.experimental.kubernetes.io/provisioning-required" - pvProvisioningCompletedAnnotationValue = "volume.experimental.kubernetes.io/provisioning-completed" -) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_provisioner_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_provisioner_controller_test.go deleted file mode 100644 index c72e8e447..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_provisioner_controller_test.go +++ /dev/null @@ -1,295 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 persistentvolume - -import ( - "fmt" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - fake_cloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" - "k8s.io/kubernetes/pkg/util" - volumetest "k8s.io/kubernetes/pkg/volume/testing" - "k8s.io/kubernetes/pkg/watch" -) - -func TestProvisionerRunStop(t *testing.T) { - controller, _, _ := makeTestController() - - if len(controller.stopChannels) != 0 { - t.Errorf("Non-running provisioner should not have any stopChannels. Got %v", len(controller.stopChannels)) - } - - controller.Run() - - if len(controller.stopChannels) != 2 { - t.Errorf("Running provisioner should have exactly 2 stopChannels. Got %v", len(controller.stopChannels)) - } - - controller.Stop() - - if len(controller.stopChannels) != 0 { - t.Errorf("Non-running provisioner should not have any stopChannels. Got %v", len(controller.stopChannels)) - } -} - -func makeTestVolume() *api.PersistentVolume { - return &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{}, - Name: "pv01", - }, - Spec: api.PersistentVolumeSpec{ - PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimDelete, - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("10Gi"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: "/somepath/data01", - }, - }, - }, - } -} - -func makeTestClaim() *api.PersistentVolumeClaim { - return &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{}, - Name: "claim01", - Namespace: "ns", - SelfLink: testapi.Default.SelfLink("pvc", ""), - }, - Spec: api.PersistentVolumeClaimSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("8G"), - }, - }, - }, - } -} - -func makeTestController() (*PersistentVolumeProvisionerController, *mockControllerClient, *volumetest.FakeVolumePlugin) { - mockClient := &mockControllerClient{} - mockVolumePlugin := &volumetest.FakeVolumePlugin{} - controller, _ := NewPersistentVolumeProvisionerController(mockClient, 1*time.Second, "fake-kubernetes", nil, mockVolumePlugin, &fake_cloud.FakeCloud{}) - return controller, mockClient, mockVolumePlugin -} - -func TestReconcileClaim(t *testing.T) { - controller, mockClient, _ := makeTestController() - pvc := makeTestClaim() - - // watch would have added the claim to the store - controller.claimStore.Add(pvc) - // store it in fake API server - mockClient.UpdatePersistentVolumeClaim(pvc) - - err := controller.reconcileClaim(pvc) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // non-provisionable PVC should not have created a volume on reconciliation - if mockClient.volume != nil { - t.Error("Unexpected volume found in mock client. Expected nil") - } - - pvc.Annotations[qosProvisioningKey] = "foo" - // store it in fake API server - mockClient.UpdatePersistentVolumeClaim(pvc) - - err = controller.reconcileClaim(pvc) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // PVC requesting provisioning should have a PV created for it - if mockClient.volume == nil { - t.Error("Expected to find bound volume but got nil") - } - - if mockClient.volume.Spec.ClaimRef.Name != pvc.Name { - t.Errorf("Expected PV to be bound to %s but got %s", mockClient.volume.Spec.ClaimRef.Name, pvc.Name) - } - - // the PVC should have correct annotation - if mockClient.claim.Annotations[pvProvisioningRequiredAnnotationKey] != pvProvisioningCompletedAnnotationValue { - t.Errorf("Annotation %q not set", pvProvisioningRequiredAnnotationKey) - } - - // Run the syncClaim 2nd time to simulate periodic sweep running in parallel - // to the previous syncClaim. There is a lock in handleUpdateVolume(), so - // they will be called sequentially, but the second call will have old - // version of the claim. - oldPVName := mockClient.volume.Name - - // Make the "old" claim - pvc2 := makeTestClaim() - pvc2.Annotations[qosProvisioningKey] = "foo" - // Add a dummy annotation so we recognize the claim was updated (i.e. - // stored in mockClient) - pvc2.Annotations["test"] = "test" - - err = controller.reconcileClaim(pvc2) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // The 2nd PVC should be ignored, no new PV was created - if val, found := pvc2.Annotations[pvProvisioningRequiredAnnotationKey]; found { - t.Errorf("2nd PVC got unexpected annotation %q: %q", pvProvisioningRequiredAnnotationKey, val) - } - if mockClient.volume.Name != oldPVName { - t.Errorf("2nd PVC unexpectedly provisioned a new volume") - } - if _, found := mockClient.claim.Annotations["test"]; found { - t.Errorf("2nd PVC was unexpectedly updated") - } -} - -func checkTagValue(t *testing.T, tags map[string]string, tag string, expectedValue string) { - value, found := tags[tag] - if !found || value != expectedValue { - t.Errorf("Expected tag value %s = %s but value %s found", tag, expectedValue, value) - } -} - -func TestReconcileVolume(t *testing.T) { - - controller, mockClient, mockVolumePlugin := makeTestController() - pv := makeTestVolume() - pvc := makeTestClaim() - mockClient.volume = pv - - err := controller.reconcileVolume(pv) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - - // watch adds claim to the store. - // we need to add it to our mock client to mimic normal Get call - controller.claimStore.Add(pvc) - mockClient.claim = pvc - - // pretend the claim and volume are bound, no provisioning required - claimRef, _ := api.GetReference(pvc) - pv.Spec.ClaimRef = claimRef - mockClient.volume = pv - err = controller.reconcileVolume(pv) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - - pv.Annotations[pvProvisioningRequiredAnnotationKey] = "!pvProvisioningCompleted" - pv.Annotations[qosProvisioningKey] = "foo" - mockClient.volume = pv - err = controller.reconcileVolume(pv) - - if !isAnnotationMatch(pvProvisioningRequiredAnnotationKey, pvProvisioningCompletedAnnotationValue, mockClient.volume.Annotations) { - t.Errorf("Expected %s but got %s", pvProvisioningRequiredAnnotationKey, mockClient.volume.Annotations[pvProvisioningRequiredAnnotationKey]) - } - - // Check that the volume plugin was called with correct tags - tags := *mockVolumePlugin.LastProvisionerOptions.CloudTags - checkTagValue(t, tags, cloudVolumeCreatedForClaimNamespaceTag, pvc.Namespace) - checkTagValue(t, tags, cloudVolumeCreatedForClaimNameTag, pvc.Name) - checkTagValue(t, tags, cloudVolumeCreatedForVolumeNameTag, pv.Name) - -} - -var _ controllerClient = &mockControllerClient{} - -type mockControllerClient struct { - volume *api.PersistentVolume - claim *api.PersistentVolumeClaim -} - -func (c *mockControllerClient) GetPersistentVolume(name string) (*api.PersistentVolume, error) { - return c.volume, nil -} - -func (c *mockControllerClient) CreatePersistentVolume(pv *api.PersistentVolume) (*api.PersistentVolume, error) { - if pv.GenerateName != "" && pv.Name == "" { - pv.Name = fmt.Sprintf(pv.GenerateName, util.NewUUID()) - } - c.volume = pv - return c.volume, nil -} - -func (c *mockControllerClient) ListPersistentVolumes(options api.ListOptions) (*api.PersistentVolumeList, error) { - return &api.PersistentVolumeList{ - Items: []api.PersistentVolume{*c.volume}, - }, nil -} - -func (c *mockControllerClient) WatchPersistentVolumes(options api.ListOptions) (watch.Interface, error) { - return watch.NewFake(), nil -} - -func (c *mockControllerClient) UpdatePersistentVolume(pv *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.CreatePersistentVolume(pv) -} - -func (c *mockControllerClient) DeletePersistentVolume(volume *api.PersistentVolume) error { - c.volume = nil - return nil -} - -func (c *mockControllerClient) UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - return volume, nil -} - -func (c *mockControllerClient) GetPersistentVolumeClaim(namespace, name string) (*api.PersistentVolumeClaim, error) { - if c.claim != nil { - return c.claim, nil - } else { - return nil, errors.NewNotFound(api.Resource("persistentvolumes"), name) - } -} - -func (c *mockControllerClient) ListPersistentVolumeClaims(namespace string, options api.ListOptions) (*api.PersistentVolumeClaimList, error) { - return &api.PersistentVolumeClaimList{ - Items: []api.PersistentVolumeClaim{*c.claim}, - }, nil -} - -func (c *mockControllerClient) WatchPersistentVolumeClaims(namespace string, options api.ListOptions) (watch.Interface, error) { - return watch.NewFake(), nil -} - -func (c *mockControllerClient) UpdatePersistentVolumeClaim(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - c.claim = claim - return c.claim, nil -} - -func (c *mockControllerClient) UpdatePersistentVolumeClaimStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { - return claim, nil -} - -func (c *mockControllerClient) GetKubeClient() clientset.Interface { - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_recycler_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_recycler_controller.go deleted file mode 100644 index e73a5b9eb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_recycler_controller.go +++ /dev/null @@ -1,415 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 persistentvolume - -import ( - "fmt" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/types" - ioutil "k8s.io/kubernetes/pkg/util/io" - "k8s.io/kubernetes/pkg/util/metrics" - "k8s.io/kubernetes/pkg/util/mount" - "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/watch" -) - -var _ volume.VolumeHost = &PersistentVolumeRecycler{} - -// PersistentVolumeRecycler is a controller that watches for PersistentVolumes that are released from their claims. -// This controller will Recycle those volumes whose reclaim policy is set to PersistentVolumeReclaimRecycle and make them -// available again for a new claim. -type PersistentVolumeRecycler struct { - volumeController *framework.Controller - stopChannel chan struct{} - client recyclerClient - kubeClient clientset.Interface - pluginMgr volume.VolumePluginMgr - cloud cloudprovider.Interface - maximumRetry int - syncPeriod time.Duration - // Local cache of failed recycle / delete operations. Map volume.Name -> status of the volume. - // Only PVs in Released state have an entry here. - releasedVolumes map[string]releasedVolumeStatus -} - -// releasedVolumeStatus holds state of failed delete/recycle operation on a -// volume. The controller re-tries the operation several times and it stores -// retry count + timestamp of the last attempt here. -type releasedVolumeStatus struct { - // How many recycle/delete operations failed. - retryCount int - // Timestamp of the last attempt. - lastAttempt time.Time -} - -// NewPersistentVolumeRecycler creates a new PersistentVolumeRecycler -func NewPersistentVolumeRecycler(kubeClient clientset.Interface, syncPeriod time.Duration, maximumRetry int, plugins []volume.VolumePlugin, cloud cloudprovider.Interface) (*PersistentVolumeRecycler, error) { - recyclerClient := NewRecyclerClient(kubeClient) - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("pv_recycler_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - recycler := &PersistentVolumeRecycler{ - client: recyclerClient, - kubeClient: kubeClient, - cloud: cloud, - maximumRetry: maximumRetry, - syncPeriod: syncPeriod, - releasedVolumes: make(map[string]releasedVolumeStatus), - } - - if err := recycler.pluginMgr.InitPlugins(plugins, recycler); err != nil { - return nil, fmt.Errorf("Could not initialize volume plugins for PVClaimBinder: %+v", err) - } - - _, volumeController := framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return kubeClient.Core().PersistentVolumes().List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return kubeClient.Core().PersistentVolumes().Watch(options) - }, - }, - &api.PersistentVolume{}, - syncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - pv, ok := obj.(*api.PersistentVolume) - if !ok { - glog.Errorf("Error casting object to PersistentVolume: %v", obj) - return - } - recycler.reclaimVolume(pv) - }, - UpdateFunc: func(oldObj, newObj interface{}) { - pv, ok := newObj.(*api.PersistentVolume) - if !ok { - glog.Errorf("Error casting object to PersistentVolume: %v", newObj) - return - } - recycler.reclaimVolume(pv) - }, - DeleteFunc: func(obj interface{}) { - pv, ok := obj.(*api.PersistentVolume) - if !ok { - glog.Errorf("Error casting object to PersistentVolume: %v", obj) - return - } - recycler.reclaimVolume(pv) - recycler.removeReleasedVolume(pv) - }, - }, - ) - - recycler.volumeController = volumeController - return recycler, nil -} - -// shouldRecycle checks a volume and returns nil, if the volume should be -// recycled right now. Otherwise it returns an error with reason why it should -// not be recycled. -func (recycler *PersistentVolumeRecycler) shouldRecycle(pv *api.PersistentVolume) error { - if pv.Spec.ClaimRef == nil { - return fmt.Errorf("Volume does not have a reference to claim") - } - if pv.Status.Phase != api.VolumeReleased { - return fmt.Errorf("The volume is not in 'Released' phase") - } - - // The volume is Released, should we retry recycling? - status, found := recycler.releasedVolumes[pv.Name] - if !found { - // We don't know anything about this volume. The controller has been - // restarted or the volume has been marked as Released by another - // controller. Recycle/delete this volume as if it was just Released. - glog.V(5).Infof("PersistentVolume[%s] not found in local cache, recycling", pv.Name) - return nil - } - - // Check the timestamp - expectedRetry := status.lastAttempt.Add(recycler.syncPeriod) - if time.Now().After(expectedRetry) { - glog.V(5).Infof("PersistentVolume[%s] retrying recycle after timeout", pv.Name) - return nil - } - // It's too early - glog.V(5).Infof("PersistentVolume[%s] skipping recycle, it's too early: now: %v, next retry: %v", pv.Name, time.Now(), expectedRetry) - return fmt.Errorf("Too early after previous failure") -} - -func (recycler *PersistentVolumeRecycler) reclaimVolume(pv *api.PersistentVolume) error { - glog.V(5).Infof("Recycler: checking PersistentVolume[%s]\n", pv.Name) - // Always load the latest version of the volume - newPV, err := recycler.client.GetPersistentVolume(pv.Name) - if err != nil { - return fmt.Errorf("Could not find PersistentVolume %s", pv.Name) - } - pv = newPV - - err = recycler.shouldRecycle(pv) - if err == nil { - glog.V(5).Infof("Reclaiming PersistentVolume[%s]\n", pv.Name) - - // both handleRecycle and handleDelete block until completion - // TODO: allow parallel recycling operations to increase throughput - switch pv.Spec.PersistentVolumeReclaimPolicy { - case api.PersistentVolumeReclaimRecycle: - err = recycler.handleRecycle(pv) - case api.PersistentVolumeReclaimDelete: - err = recycler.handleDelete(pv) - case api.PersistentVolumeReclaimRetain: - glog.V(5).Infof("Volume %s is set to retain after release. Skipping.\n", pv.Name) - default: - err = fmt.Errorf("No PersistentVolumeReclaimPolicy defined for spec: %+v", pv) - } - if err != nil { - errMsg := fmt.Sprintf("Could not recycle volume spec: %+v", err) - glog.Errorf(errMsg) - return fmt.Errorf(errMsg) - } - return nil - } - glog.V(3).Infof("PersistentVolume[%s] phase %s - skipping: %v", pv.Name, pv.Status.Phase, err) - return nil -} - -// handleReleaseFailure evaluates a failed Recycle/Delete operation, updates -// internal controller state with new nr. of attempts and timestamp of the last -// attempt. Based on the number of failures it returns the next state of the -// volume (Released / Failed). -func (recycler *PersistentVolumeRecycler) handleReleaseFailure(pv *api.PersistentVolume) api.PersistentVolumePhase { - status, found := recycler.releasedVolumes[pv.Name] - if !found { - // First failure, set retryCount to 0 (will be inceremented few lines below) - status = releasedVolumeStatus{} - } - status.retryCount += 1 - - if status.retryCount > recycler.maximumRetry { - // This was the last attempt. Remove any internal state and mark the - // volume as Failed. - glog.V(3).Infof("PersistentVolume[%s] failed %d times - marking Failed", pv.Name, status.retryCount) - recycler.removeReleasedVolume(pv) - return api.VolumeFailed - } - - status.lastAttempt = time.Now() - recycler.releasedVolumes[pv.Name] = status - return api.VolumeReleased -} - -func (recycler *PersistentVolumeRecycler) removeReleasedVolume(pv *api.PersistentVolume) { - delete(recycler.releasedVolumes, pv.Name) -} - -func (recycler *PersistentVolumeRecycler) handleRecycle(pv *api.PersistentVolume) error { - glog.V(5).Infof("Recycling PersistentVolume[%s]\n", pv.Name) - - currentPhase := pv.Status.Phase - nextPhase := currentPhase - - spec := volume.NewSpecFromPersistentVolume(pv, false) - plugin, err := recycler.pluginMgr.FindRecyclablePluginBySpec(spec) - if err != nil { - nextPhase = api.VolumeFailed - pv.Status.Message = fmt.Sprintf("%v", err) - } - - // an error above means a suitable plugin for this volume was not found. - // we don't need to attempt recycling when plugin is nil, but we do need to persist the next/failed phase - // of the volume so that subsequent syncs won't attempt recycling through this handler func. - if plugin != nil { - volRecycler, err := plugin.NewRecycler(spec) - if err != nil { - return fmt.Errorf("Could not obtain Recycler for spec: %#v error: %v", spec, err) - } - // blocks until completion - if err := volRecycler.Recycle(); err != nil { - glog.Errorf("PersistentVolume[%s] failed recycling: %+v", pv.Name, err) - pv.Status.Message = fmt.Sprintf("Recycling error: %s", err) - nextPhase = recycler.handleReleaseFailure(pv) - } else { - glog.V(5).Infof("PersistentVolume[%s] successfully recycled\n", pv.Name) - // The volume has been recycled. Remove any internal state to make - // any subsequent bind+recycle cycle working. - recycler.removeReleasedVolume(pv) - nextPhase = api.VolumePending - } - } - - if currentPhase != nextPhase { - glog.V(5).Infof("PersistentVolume[%s] changing phase from %s to %s\n", pv.Name, currentPhase, nextPhase) - pv.Status.Phase = nextPhase - _, err := recycler.client.UpdatePersistentVolumeStatus(pv) - if err != nil { - // Rollback to previous phase - pv.Status.Phase = currentPhase - } - } - - return nil -} - -func (recycler *PersistentVolumeRecycler) handleDelete(pv *api.PersistentVolume) error { - glog.V(5).Infof("Deleting PersistentVolume[%s]\n", pv.Name) - - currentPhase := pv.Status.Phase - nextPhase := currentPhase - - spec := volume.NewSpecFromPersistentVolume(pv, false) - plugin, err := recycler.pluginMgr.FindDeletablePluginBySpec(spec) - if err != nil { - nextPhase = api.VolumeFailed - pv.Status.Message = fmt.Sprintf("%v", err) - } - - // an error above means a suitable plugin for this volume was not found. - // we don't need to attempt deleting when plugin is nil, but we do need to persist the next/failed phase - // of the volume so that subsequent syncs won't attempt deletion through this handler func. - if plugin != nil { - deleter, err := plugin.NewDeleter(spec) - if err != nil { - return fmt.Errorf("Could not obtain Deleter for spec: %#v error: %v", spec, err) - } - // blocks until completion - err = deleter.Delete() - if err != nil { - glog.Errorf("PersistentVolume[%s] failed deletion: %+v", pv.Name, err) - pv.Status.Message = fmt.Sprintf("Deletion error: %s", err) - nextPhase = recycler.handleReleaseFailure(pv) - } else { - glog.V(5).Infof("PersistentVolume[%s] successfully deleted through plugin\n", pv.Name) - recycler.removeReleasedVolume(pv) - // after successful deletion through the plugin, we can also remove the PV from the cluster - if err := recycler.client.DeletePersistentVolume(pv); err != nil { - return fmt.Errorf("error deleting persistent volume: %+v", err) - } - } - } - - if currentPhase != nextPhase { - glog.V(5).Infof("PersistentVolume[%s] changing phase from %s to %s\n", pv.Name, currentPhase, nextPhase) - pv.Status.Phase = nextPhase - _, err := recycler.client.UpdatePersistentVolumeStatus(pv) - if err != nil { - // Rollback to previous phase - pv.Status.Phase = currentPhase - } - } - - return nil -} - -// Run starts this recycler's control loops -func (recycler *PersistentVolumeRecycler) Run() { - glog.V(5).Infof("Starting PersistentVolumeRecycler\n") - if recycler.stopChannel == nil { - recycler.stopChannel = make(chan struct{}) - go recycler.volumeController.Run(recycler.stopChannel) - } -} - -// Stop gracefully shuts down this binder -func (recycler *PersistentVolumeRecycler) Stop() { - glog.V(5).Infof("Stopping PersistentVolumeRecycler\n") - if recycler.stopChannel != nil { - close(recycler.stopChannel) - recycler.stopChannel = nil - } -} - -// recyclerClient abstracts access to PVs -type recyclerClient interface { - GetPersistentVolume(name string) (*api.PersistentVolume, error) - UpdatePersistentVolume(volume *api.PersistentVolume) (*api.PersistentVolume, error) - DeletePersistentVolume(volume *api.PersistentVolume) error - UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) -} - -func NewRecyclerClient(c clientset.Interface) recyclerClient { - return &realRecyclerClient{c} -} - -type realRecyclerClient struct { - client clientset.Interface -} - -func (c *realRecyclerClient) GetPersistentVolume(name string) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().Get(name) -} - -func (c *realRecyclerClient) UpdatePersistentVolume(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().Update(volume) -} - -func (c *realRecyclerClient) DeletePersistentVolume(volume *api.PersistentVolume) error { - return c.client.Core().PersistentVolumes().Delete(volume.Name, nil) -} - -func (c *realRecyclerClient) UpdatePersistentVolumeStatus(volume *api.PersistentVolume) (*api.PersistentVolume, error) { - return c.client.Core().PersistentVolumes().UpdateStatus(volume) -} - -// PersistentVolumeRecycler is host to the volume plugins, but does not actually mount any volumes. -// Because no mounting is performed, most of the VolumeHost methods are not implemented. -func (f *PersistentVolumeRecycler) GetPluginDir(podUID string) string { - return "" -} - -func (f *PersistentVolumeRecycler) GetPodVolumeDir(podUID types.UID, pluginName, volumeName string) string { - return "" -} - -func (f *PersistentVolumeRecycler) GetPodPluginDir(podUID types.UID, pluginName string) string { - return "" -} - -func (f *PersistentVolumeRecycler) GetKubeClient() clientset.Interface { - return f.kubeClient -} - -func (f *PersistentVolumeRecycler) NewWrapperMounter(volName string, spec volume.Spec, pod *api.Pod, opts volume.VolumeOptions) (volume.Mounter, error) { - return nil, fmt.Errorf("NewWrapperMounter not supported by PVClaimBinder's VolumeHost implementation") -} - -func (f *PersistentVolumeRecycler) NewWrapperUnmounter(volName string, spec volume.Spec, podUID types.UID) (volume.Unmounter, error) { - return nil, fmt.Errorf("NewWrapperUnmounter not supported by PVClaimBinder's VolumeHost implementation") -} - -func (f *PersistentVolumeRecycler) GetCloudProvider() cloudprovider.Interface { - return f.cloud -} - -func (f *PersistentVolumeRecycler) GetMounter() mount.Interface { - return nil -} - -func (f *PersistentVolumeRecycler) GetWriter() ioutil.Writer { - return nil -} - -func (f *PersistentVolumeRecycler) GetHostName() string { - return "" -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_recycler_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_recycler_controller_test.go deleted file mode 100644 index 8312fd322..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/persistentvolume_recycler_controller_test.go +++ /dev/null @@ -1,265 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 persistentvolume - -import ( - "fmt" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/host_path" - volumetest "k8s.io/kubernetes/pkg/volume/testing" -) - -const ( - mySyncPeriod = 2 * time.Second - myMaximumRetry = 3 -) - -func TestFailedRecycling(t *testing.T) { - pv := preparePV() - - mockClient := &mockBinderClient{ - volume: pv, - } - - // no Init called for pluginMgr and no plugins are available. Volume should fail recycling. - plugMgr := volume.VolumePluginMgr{} - - recycler := &PersistentVolumeRecycler{ - kubeClient: fake.NewSimpleClientset(), - client: mockClient, - pluginMgr: plugMgr, - releasedVolumes: make(map[string]releasedVolumeStatus), - } - - err := recycler.reclaimVolume(pv) - if err != nil { - t.Errorf("Unexpected non-nil error: %v", err) - } - - if mockClient.volume.Status.Phase != api.VolumeFailed { - t.Errorf("Expected %s but got %s", api.VolumeFailed, mockClient.volume.Status.Phase) - } - - // Use a new volume for the next test - pv = preparePV() - mockClient.volume = pv - - pv.Spec.PersistentVolumeReclaimPolicy = api.PersistentVolumeReclaimDelete - err = recycler.reclaimVolume(pv) - if err != nil { - t.Errorf("Unexpected non-nil error: %v", err) - } - - if mockClient.volume.Status.Phase != api.VolumeFailed { - t.Errorf("Expected %s but got %s", api.VolumeFailed, mockClient.volume.Status.Phase) - } -} - -func TestRecyclingRetry(t *testing.T) { - // Test that recycler controller retries to recycle a volume several times, which succeeds eventually - pv := preparePV() - - mockClient := &mockBinderClient{ - volume: pv, - } - - plugMgr := volume.VolumePluginMgr{} - // Use a fake NewRecycler function - plugMgr.InitPlugins(host_path.ProbeRecyclableVolumePlugins(newFailingMockRecycler, volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil)) - // Reset a global call counter - failedCallCount = 0 - - recycler := &PersistentVolumeRecycler{ - kubeClient: fake.NewSimpleClientset(), - client: mockClient, - pluginMgr: plugMgr, - syncPeriod: mySyncPeriod, - maximumRetry: myMaximumRetry, - releasedVolumes: make(map[string]releasedVolumeStatus), - } - - // All but the last attempt will fail - testRecycleFailures(t, recycler, mockClient, pv, myMaximumRetry-1) - - // The last attempt should succeed - err := recycler.reclaimVolume(pv) - if err != nil { - t.Errorf("Last step: Recycler failed: %v", err) - } - - if mockClient.volume.Status.Phase != api.VolumePending { - t.Errorf("Last step: The volume should be Pending, but is %s instead", mockClient.volume.Status.Phase) - } - // Check the cache, it should not have any entry - status, found := recycler.releasedVolumes[pv.Name] - if found { - t.Errorf("Last step: Expected PV to be removed from cache, got %v", status) - } -} - -func TestRecyclingRetryAlwaysFail(t *testing.T) { - // Test that recycler controller retries to recycle a volume several times, which always fails. - pv := preparePV() - - mockClient := &mockBinderClient{ - volume: pv, - } - - plugMgr := volume.VolumePluginMgr{} - // Use a fake NewRecycler function - plugMgr.InitPlugins(host_path.ProbeRecyclableVolumePlugins(newAlwaysFailingMockRecycler, volume.VolumeConfig{}), volumetest.NewFakeVolumeHost("/tmp/fake", nil, nil)) - // Reset a global call counter - failedCallCount = 0 - - recycler := &PersistentVolumeRecycler{ - kubeClient: fake.NewSimpleClientset(), - client: mockClient, - pluginMgr: plugMgr, - syncPeriod: mySyncPeriod, - maximumRetry: myMaximumRetry, - releasedVolumes: make(map[string]releasedVolumeStatus), - } - - // myMaximumRetry recycle attempts will fail - testRecycleFailures(t, recycler, mockClient, pv, myMaximumRetry) - - // The volume should be failed after myMaximumRetry attempts - err := recycler.reclaimVolume(pv) - if err != nil { - t.Errorf("Last step: Recycler failed: %v", err) - } - - if mockClient.volume.Status.Phase != api.VolumeFailed { - t.Errorf("Last step: The volume should be Failed, but is %s instead", mockClient.volume.Status.Phase) - } - // Check the cache, it should not have any entry - status, found := recycler.releasedVolumes[pv.Name] - if found { - t.Errorf("Last step: Expected PV to be removed from cache, got %v", status) - } -} - -func preparePV() *api.PersistentVolume { - return &api.PersistentVolume{ - Spec: api.PersistentVolumeSpec{ - AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce}, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): resource.MustParse("8Gi"), - }, - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: "/tmp/data02", - }, - }, - PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRecycle, - ClaimRef: &api.ObjectReference{ - Name: "foo", - Namespace: "bar", - }, - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeReleased, - }, - } -} - -// Test that `count` attempts to recycle a PV fails. -func testRecycleFailures(t *testing.T, recycler *PersistentVolumeRecycler, mockClient *mockBinderClient, pv *api.PersistentVolume, count int) { - for i := 1; i <= count; i++ { - err := recycler.reclaimVolume(pv) - if err != nil { - t.Errorf("STEP %d: Recycler faled: %v", i, err) - } - - // Check the status, it should be failed - if mockClient.volume.Status.Phase != api.VolumeReleased { - t.Errorf("STEP %d: The volume should be Released, but is %s instead", i, mockClient.volume.Status.Phase) - } - - // Check the failed volume cache - status, found := recycler.releasedVolumes[pv.Name] - if !found { - t.Errorf("STEP %d: cannot find released volume status", i) - } - if status.retryCount != i { - t.Errorf("STEP %d: Expected nr. of attempts to be %d, got %d", i, i, status.retryCount) - } - - // call reclaimVolume too early, it should not increment the retryCount - time.Sleep(mySyncPeriod / 2) - err = recycler.reclaimVolume(pv) - if err != nil { - t.Errorf("STEP %d: Recycler failed: %v", i, err) - } - - status, found = recycler.releasedVolumes[pv.Name] - if !found { - t.Errorf("STEP %d: cannot find released volume status", i) - } - if status.retryCount != i { - t.Errorf("STEP %d: Expected nr. of attempts to be %d, got %d", i, i, status.retryCount) - } - - // Call the next reclaimVolume() after full pvRecycleRetryPeriod - time.Sleep(mySyncPeriod / 2) - } -} - -func newFailingMockRecycler(spec *volume.Spec, host volume.VolumeHost, config volume.VolumeConfig) (volume.Recycler, error) { - return &failingMockRecycler{ - path: spec.PersistentVolume.Spec.HostPath.Path, - errorCount: myMaximumRetry - 1, // fail two times and then successfully recycle the volume - }, nil -} - -func newAlwaysFailingMockRecycler(spec *volume.Spec, host volume.VolumeHost, config volume.VolumeConfig) (volume.Recycler, error) { - return &failingMockRecycler{ - path: spec.PersistentVolume.Spec.HostPath.Path, - errorCount: 1000, // always fail - }, nil -} - -type failingMockRecycler struct { - path string - // How many times should the recycler fail before returning success. - errorCount int - volume.MetricsNil -} - -// Counter of failingMockRecycler.Recycle() calls. Global variable just for -// testing. It's too much code to create a custom volume plugin, which would -// hold this variable. -var failedCallCount = 0 - -func (r *failingMockRecycler) GetPath() string { - return r.path -} - -func (r *failingMockRecycler) Recycle() error { - failedCallCount += 1 - if failedCallCount <= r.errorCount { - return fmt.Errorf("Failing for %d. time", failedCallCount) - } - // return nil means recycle passed - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/types.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/types.go deleted file mode 100644 index 42ca36801..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/persistentvolume/types.go +++ /dev/null @@ -1,267 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 persistentvolume - -import ( - "fmt" - "sort" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/cache" -) - -const ( - // A PVClaim can request a quality of service tier by adding this annotation. The value of the annotation - // is arbitrary. The values are pre-defined by a cluster admin and known to users when requesting a QoS. - // For example tiers might be gold, silver, and tin and the admin configures what that means for each volume plugin that can provision a volume. - // Values in the alpha version of this feature are not meaningful, but will be in the full version of this feature. - qosProvisioningKey = "volume.alpha.kubernetes.io/storage-class" - // Name of a tag attached to a real volume in cloud (e.g. AWS EBS or GCE PD) - // with namespace of a persistent volume claim used to create this volume. - cloudVolumeCreatedForClaimNamespaceTag = "kubernetes.io/created-for/pvc/namespace" - // Name of a tag attached to a real volume in cloud (e.g. AWS EBS or GCE PD) - // with name of a persistent volume claim used to create this volume. - cloudVolumeCreatedForClaimNameTag = "kubernetes.io/created-for/pvc/name" - // Name of a tag attached to a real volume in cloud (e.g. AWS EBS or GCE PD) - // with name of appropriate Kubernetes persistent volume . - cloudVolumeCreatedForVolumeNameTag = "kubernetes.io/created-for/pv/name" -) - -// persistentVolumeOrderedIndex is a cache.Store that keeps persistent volumes indexed by AccessModes and ordered by storage capacity. -type persistentVolumeOrderedIndex struct { - cache.Indexer -} - -var _ cache.Store = &persistentVolumeOrderedIndex{} // persistentVolumeOrderedIndex is a Store - -func NewPersistentVolumeOrderedIndex() *persistentVolumeOrderedIndex { - return &persistentVolumeOrderedIndex{ - cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"accessmodes": accessModesIndexFunc}), - } -} - -// accessModesIndexFunc is an indexing function that returns a persistent volume's AccessModes as a string -func accessModesIndexFunc(obj interface{}) ([]string, error) { - if pv, ok := obj.(*api.PersistentVolume); ok { - modes := api.GetAccessModesAsString(pv.Spec.AccessModes) - return []string{modes}, nil - } - return []string{""}, fmt.Errorf("object is not a persistent volume: %v", obj) -} - -// ListByAccessModes returns all volumes with the given set of AccessModeTypes *in order* of their storage capacity (low to high) -func (pvIndex *persistentVolumeOrderedIndex) ListByAccessModes(modes []api.PersistentVolumeAccessMode) ([]*api.PersistentVolume, error) { - pv := &api.PersistentVolume{ - Spec: api.PersistentVolumeSpec{ - AccessModes: modes, - }, - } - - objs, err := pvIndex.Index("accessmodes", pv) - if err != nil { - return nil, err - } - - volumes := make([]*api.PersistentVolume, len(objs)) - for i, obj := range objs { - volumes[i] = obj.(*api.PersistentVolume) - } - - sort.Sort(byCapacity{volumes}) - return volumes, nil -} - -// matchPredicate is a function that indicates that a persistent volume matches another -type matchPredicate func(compareThis, toThis *api.PersistentVolume) bool - -// find returns the nearest PV from the ordered list or nil if a match is not found -func (pvIndex *persistentVolumeOrderedIndex) findByClaim(claim *api.PersistentVolumeClaim, matchPredicate matchPredicate) (*api.PersistentVolume, error) { - // PVs are indexed by their access modes to allow easier searching. Each index is the string representation of a set of access modes. - // There is a finite number of possible sets and PVs will only be indexed in one of them (whichever index matches the PV's modes). - // - // A request for resources will always specify its desired access modes. Any matching PV must have at least that number - // of access modes, but it can have more. For example, a user asks for ReadWriteOnce but a GCEPD is available, which is ReadWriteOnce+ReadOnlyMany. - // - // Searches are performed against a set of access modes, so we can attempt not only the exact matching modes but also - // potential matches (the GCEPD example above). - allPossibleModes := pvIndex.allPossibleMatchingAccessModes(claim.Spec.AccessModes) - - for _, modes := range allPossibleModes { - volumes, err := pvIndex.ListByAccessModes(modes) - if err != nil { - return nil, err - } - - // volumes are sorted by size but some may be bound or earmarked for a specific claim. - // filter those volumes for easy binary search by size - // return the exact pre-binding match, if found - unboundVolumes := []*api.PersistentVolume{} - for _, volume := range volumes { - // volume isn't currently bound or pre-bound. - if volume.Spec.ClaimRef == nil { - unboundVolumes = append(unboundVolumes, volume) - continue - } - - if claim.Name == volume.Spec.ClaimRef.Name && claim.Namespace == volume.Spec.ClaimRef.Namespace && claim.UID == volume.Spec.ClaimRef.UID { - // exact match! No search required. - return volume, nil - } - } - - // a claim requesting provisioning will have an exact match pre-bound to the claim. - // no need to search through unbound volumes. The matching volume will be created by the provisioner - // and will match above when the claim is re-processed by the binder. - if keyExists(qosProvisioningKey, claim.Annotations) { - return nil, nil - } - - searchPV := &api.PersistentVolume{ - Spec: api.PersistentVolumeSpec{ - AccessModes: claim.Spec.AccessModes, - Capacity: api.ResourceList{ - api.ResourceName(api.ResourceStorage): claim.Spec.Resources.Requests[api.ResourceName(api.ResourceStorage)], - }, - }, - } - - i := sort.Search(len(unboundVolumes), func(i int) bool { return matchPredicate(searchPV, unboundVolumes[i]) }) - if i < len(unboundVolumes) { - return unboundVolumes[i], nil - } - } - return nil, nil -} - -// findBestMatchForClaim is a convenience method that finds a volume by the claim's AccessModes and requests for Storage -func (pvIndex *persistentVolumeOrderedIndex) findBestMatchForClaim(claim *api.PersistentVolumeClaim) (*api.PersistentVolume, error) { - return pvIndex.findByClaim(claim, matchStorageCapacity) -} - -// byCapacity is used to order volumes by ascending storage size -type byCapacity struct { - volumes []*api.PersistentVolume -} - -func (c byCapacity) Less(i, j int) bool { - return matchStorageCapacity(c.volumes[i], c.volumes[j]) -} - -func (c byCapacity) Swap(i, j int) { - c.volumes[i], c.volumes[j] = c.volumes[j], c.volumes[i] -} - -func (c byCapacity) Len() int { - return len(c.volumes) -} - -// matchStorageCapacity is a matchPredicate used to sort and find volumes -func matchStorageCapacity(pvA, pvB *api.PersistentVolume) bool { - aQty := pvA.Spec.Capacity[api.ResourceStorage] - bQty := pvB.Spec.Capacity[api.ResourceStorage] - aSize := aQty.Value() - bSize := bQty.Value() - return aSize <= bSize -} - -// allPossibleMatchingAccessModes returns an array of AccessMode arrays that can satisfy a user's requested modes. -// -// see comments in the Find func above regarding indexing. -// -// allPossibleMatchingAccessModes gets all stringified accessmodes from the index and returns all those that -// contain at least all of the requested mode. -// -// For example, assume the index contains 2 types of PVs where the stringified accessmodes are: -// -// "RWO,ROX" -- some number of GCEPDs -// "RWO,ROX,RWX" -- some number of NFS volumes -// -// A request for RWO could be satisfied by both sets of indexed volumes, so allPossibleMatchingAccessModes returns: -// -// [][]api.PersistentVolumeAccessMode { -// []api.PersistentVolumeAccessMode { -// api.ReadWriteOnce, api.ReadOnlyMany, -// }, -// []api.PersistentVolumeAccessMode { -// api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany, -// }, -// } -// -// A request for RWX can be satisfied by only one set of indexed volumes, so the return is: -// -// [][]api.PersistentVolumeAccessMode { -// []api.PersistentVolumeAccessMode { -// api.ReadWriteOnce, api.ReadOnlyMany, api.ReadWriteMany, -// }, -// } -// -// This func returns modes with ascending levels of modes to give the user what is closest to what they actually asked for. -// -func (pvIndex *persistentVolumeOrderedIndex) allPossibleMatchingAccessModes(requestedModes []api.PersistentVolumeAccessMode) [][]api.PersistentVolumeAccessMode { - matchedModes := [][]api.PersistentVolumeAccessMode{} - keys := pvIndex.Indexer.ListIndexFuncValues("accessmodes") - for _, key := range keys { - indexedModes := api.GetAccessModesFromString(key) - if containedInAll(indexedModes, requestedModes) { - matchedModes = append(matchedModes, indexedModes) - } - } - - // sort by the number of modes in each array with the fewest number of modes coming first. - // this allows searching for volumes by the minimum number of modes required of the possible matches. - sort.Sort(byAccessModes{matchedModes}) - return matchedModes -} - -func contains(modes []api.PersistentVolumeAccessMode, mode api.PersistentVolumeAccessMode) bool { - for _, m := range modes { - if m == mode { - return true - } - } - return false -} - -func containedInAll(indexedModes []api.PersistentVolumeAccessMode, requestedModes []api.PersistentVolumeAccessMode) bool { - for _, mode := range requestedModes { - if !contains(indexedModes, mode) { - return false - } - } - return true -} - -// byAccessModes is used to order access modes by size, with the fewest modes first -type byAccessModes struct { - modes [][]api.PersistentVolumeAccessMode -} - -func (c byAccessModes) Less(i, j int) bool { - return len(c.modes[i]) < len(c.modes[j]) -} - -func (c byAccessModes) Swap(i, j int) { - c.modes[i], c.modes[j] = c.modes[j], c.modes[i] -} - -func (c byAccessModes) Len() int { - return len(c.modes) -} - -func claimToClaimKey(claim *api.PersistentVolumeClaim) string { - return fmt.Sprintf("%s/%s", claim.Namespace, claim.Name) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/fakes.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/fakes.go deleted file mode 100644 index ddbaff1b0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/fakes.go +++ /dev/null @@ -1,324 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - "time" - - "k8s.io/kubernetes/pkg/api" - api_pod "k8s.io/kubernetes/pkg/api/pod" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/sets" - "speter.net/go/exp/math/dec/inf" -) - -func dec(i int64, exponent int) *inf.Dec { - return inf.NewDec(i, inf.Scale(-exponent)) -} - -func newPVC(name string) api.PersistentVolumeClaim { - return api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{ - Name: name, - }, - Spec: api.PersistentVolumeClaimSpec{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceStorage: resource.Quantity{ - Amount: dec(1, 0), - Format: resource.BinarySI, - }, - }, - }, - }, - } -} - -func newPetSetWithVolumes(replicas int, name string, petMounts []api.VolumeMount, podMounts []api.VolumeMount) *apps.PetSet { - mounts := append(petMounts, podMounts...) - claims := []api.PersistentVolumeClaim{} - for _, m := range petMounts { - claims = append(claims, newPVC(m.Name)) - } - - vols := []api.Volume{} - for _, m := range podMounts { - vols = append(vols, api.Volume{ - Name: m.Name, - VolumeSource: api.VolumeSource{ - HostPath: &api.HostPathVolumeSource{ - Path: fmt.Sprintf("/tmp/%v", m.Name), - }, - }, - }) - } - - return &apps.PetSet{ - TypeMeta: unversioned.TypeMeta{ - Kind: "PetSet", - APIVersion: "apps/v1beta1", - }, - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: api.NamespaceDefault, - UID: types.UID("test"), - }, - Spec: apps.PetSetSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar"}, - }, - Replicas: replicas, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "nginx", - Image: "nginx", - VolumeMounts: mounts, - }, - }, - Volumes: vols, - }, - }, - VolumeClaimTemplates: claims, - ServiceName: "governingsvc", - }, - } -} - -func runningPod(ns, name string) *api.Pod { - p := &api.Pod{Status: api.PodStatus{Phase: api.PodRunning}} - p.Namespace = ns - p.Name = name - return p -} - -func newPodList(ps *apps.PetSet, num int) []*api.Pod { - // knownPods are pods in the system - knownPods := []*api.Pod{} - for i := 0; i < num; i++ { - k, _ := newPCB(fmt.Sprintf("%v", i), ps) - knownPods = append(knownPods, k.pod) - } - return knownPods -} - -func newPetSet(replicas int) *apps.PetSet { - petMounts := []api.VolumeMount{ - {Name: "datadir", MountPath: "/tmp/zookeeper"}, - } - podMounts := []api.VolumeMount{ - {Name: "home", MountPath: "/home"}, - } - return newPetSetWithVolumes(replicas, "foo", petMounts, podMounts) -} - -func checkPodForMount(pod *api.Pod, mountName string) error { - for _, c := range pod.Spec.Containers { - for _, v := range c.VolumeMounts { - if v.Name == mountName { - return nil - } - } - } - return fmt.Errorf("Found volume but no associated mount %v in pod %v", mountName, pod.Name) -} - -func newFakePetClient() *fakePetClient { - return &fakePetClient{ - pets: []*pcb{}, - claims: []api.PersistentVolumeClaim{}, - recorder: &record.FakeRecorder{}, - petHealthChecker: &defaultPetHealthChecker{}, - } -} - -type fakePetClient struct { - pets []*pcb - claims []api.PersistentVolumeClaim - petsCreated, petsDeleted int - claimsCreated, claimsDeleted int - recorder record.EventRecorder - petHealthChecker -} - -// Delete fakes pet client deletion. -func (f *fakePetClient) Delete(p *pcb) error { - pets := []*pcb{} - found := false - for i, pet := range f.pets { - if p.pod.Name == pet.pod.Name { - found = true - f.recorder.Eventf(pet.parent, api.EventTypeNormal, "SuccessfulDelete", "pet: %v", pet.pod.Name) - continue - } - pets = append(pets, f.pets[i]) - } - if !found { - // TODO: Return proper not found error - return fmt.Errorf("Delete failed: pet %v doesn't exist", p.pod.Name) - } - f.pets = pets - f.petsDeleted++ - return nil -} - -// Get fakes getting pets. -func (f *fakePetClient) Get(p *pcb) (*pcb, bool, error) { - for i, pet := range f.pets { - if p.pod.Name == pet.pod.Name { - return f.pets[i], true, nil - } - } - return nil, false, nil -} - -// Create fakes pet creation. -func (f *fakePetClient) Create(p *pcb) error { - for _, pet := range f.pets { - if p.pod.Name == pet.pod.Name { - return fmt.Errorf("Create failed: pet %v already exists", p.pod.Name) - } - } - f.recorder.Eventf(p.parent, api.EventTypeNormal, "SuccessfulCreate", "pet: %v", p.pod.Name) - f.pets = append(f.pets, p) - f.petsCreated++ - return nil -} - -// Update fakes pet updates. -func (f *fakePetClient) Update(expected, wanted *pcb) error { - found := false - pets := []*pcb{} - for i, pet := range f.pets { - if wanted.pod.Name == pet.pod.Name { - f.pets[i].pod.Annotations[api_pod.PodHostnameAnnotation] = wanted.pod.Annotations[api_pod.PodHostnameAnnotation] - f.pets[i].pod.Annotations[api_pod.PodSubdomainAnnotation] = wanted.pod.Annotations[api_pod.PodSubdomainAnnotation] - f.pets[i].pod.Spec = wanted.pod.Spec - found = true - } - pets = append(pets, f.pets[i]) - } - f.pets = pets - if !found { - return fmt.Errorf("Cannot update pet %v not found", wanted.pod.Name) - } - // TODO: Delete pvcs/volumes that are in wanted but not in expected. - return nil -} - -func (f *fakePetClient) getPodList() []*api.Pod { - p := []*api.Pod{} - for i, pet := range f.pets { - if pet.pod == nil { - continue - } - p = append(p, f.pets[i].pod) - } - return p -} - -func (f *fakePetClient) deletePetAtIndex(index int) { - p := []*pcb{} - for i := range f.pets { - if i != index { - p = append(p, f.pets[i]) - } - } - f.pets = p -} - -func (f *fakePetClient) setHealthy(index int) error { - if len(f.pets) < index { - return fmt.Errorf("Index out of range, len %v index %v", len(f.pets), index) - } - f.pets[index].pod.Status.Phase = api.PodRunning - f.pets[index].pod.Annotations[PetSetInitAnnotation] = "true" - return nil -} - -// isHealthy is a convenience wrapper around the default health checker. -// The first invocation returns not-healthy, but marks the pet healthy so -// subsequent invocations see it as healthy. -func (f *fakePetClient) isHealthy(pod *api.Pod) bool { - if f.petHealthChecker.isHealthy(pod) { - return true - } - return false -} - -func (f *fakePetClient) setDeletionTimestamp(index int) error { - if len(f.pets) < index { - return fmt.Errorf("Index out of range, len %v index %v", len(f.pets), index) - } - f.pets[index].pod.DeletionTimestamp = &unversioned.Time{Time: time.Now()} - return nil -} - -// SyncPVCs fakes pvc syncing. -func (f *fakePetClient) SyncPVCs(pet *pcb) error { - v := pet.pvcs - updateClaims := map[string]api.PersistentVolumeClaim{} - for i, update := range v { - updateClaims[update.Name] = v[i] - } - claimList := []api.PersistentVolumeClaim{} - for i, existing := range f.claims { - if update, ok := updateClaims[existing.Name]; ok { - claimList = append(claimList, update) - delete(updateClaims, existing.Name) - } else { - claimList = append(claimList, f.claims[i]) - } - } - for _, remaining := range updateClaims { - claimList = append(claimList, remaining) - f.claimsCreated++ - f.recorder.Eventf(pet.parent, api.EventTypeNormal, "SuccessfulCreate", "pvc: %v", remaining.Name) - } - f.claims = claimList - return nil -} - -// DeletePVCs fakes pvc deletion. -func (f *fakePetClient) DeletePVCs(pet *pcb) error { - claimsToDelete := pet.pvcs - deleteClaimNames := sets.NewString() - for _, c := range claimsToDelete { - deleteClaimNames.Insert(c.Name) - } - pvcs := []api.PersistentVolumeClaim{} - for i, existing := range f.claims { - if deleteClaimNames.Has(existing.Name) { - deleteClaimNames.Delete(existing.Name) - f.claimsDeleted++ - f.recorder.Eventf(pet.parent, api.EventTypeNormal, "SuccessfulDelete", "pvc: %v", existing.Name) - continue - } - pvcs = append(pvcs, f.claims[i]) - } - f.claims = pvcs - if deleteClaimNames.Len() != 0 { - return fmt.Errorf("Claims %+v don't exist. Failed deletion.", deleteClaimNames) - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/identity_mappers.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/identity_mappers.go deleted file mode 100644 index ae72ef2a8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/identity_mappers.go +++ /dev/null @@ -1,247 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "crypto/md5" - "fmt" - "sort" - "strings" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - podapi "k8s.io/kubernetes/pkg/api/pod" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/util/sets" -) - -// identityMapper is an interface for assigning identities to a pet. -// All existing identity mappers just append "-(index)" to the petset name to -// generate a unique identity. This is used in claims/DNS/hostname/petname -// etc. There's a more elegant way to achieve this mapping, but we're -// taking the simplest route till we have data on whether users will need -// more customization. -// Note that running a single identity mapper is not guaranteed to give -// your pet a unique identity. You must run them all. Order doesn't matter. -type identityMapper interface { - // SetIdentity takes an id and assigns the given pet an identity based - // on the pet set spec. The is must be unique amongst members of the - // pet set. - SetIdentity(id string, pet *api.Pod) - - // Identity returns the identity of the pet. - Identity(pod *api.Pod) string -} - -func newIdentityMappers(ps *apps.PetSet) []identityMapper { - return []identityMapper{ - &NameIdentityMapper{ps}, - &NetworkIdentityMapper{ps}, - &VolumeIdentityMapper{ps}, - } -} - -// NetworkIdentityMapper assigns network identity to pets. -type NetworkIdentityMapper struct { - ps *apps.PetSet -} - -// SetIdentity sets network identity on the pet. -func (n *NetworkIdentityMapper) SetIdentity(id string, pet *api.Pod) { - pet.Annotations[podapi.PodHostnameAnnotation] = fmt.Sprintf("%v-%v", n.ps.Name, id) - pet.Annotations[podapi.PodSubdomainAnnotation] = n.ps.Spec.ServiceName - return -} - -// Identity returns the network identity of the pet. -func (n *NetworkIdentityMapper) Identity(pet *api.Pod) string { - return n.String(pet) -} - -// String is a string function for the network identity of the pet. -func (n *NetworkIdentityMapper) String(pet *api.Pod) string { - hostname := pet.Annotations[podapi.PodHostnameAnnotation] - subdomain := pet.Annotations[podapi.PodSubdomainAnnotation] - return strings.Join([]string{hostname, subdomain, n.ps.Namespace}, ".") -} - -// VolumeIdentityMapper assigns storage identity to pets. -type VolumeIdentityMapper struct { - ps *apps.PetSet -} - -// SetIdentity sets storge identity on the pet. -func (v *VolumeIdentityMapper) SetIdentity(id string, pet *api.Pod) { - petVolumes := []api.Volume{} - petClaims := v.GetClaims(id) - - // These volumes will all go down with the pod. If a name matches one of - // the claims in the pet set, it gets clobbered. - podVolumes := map[string]api.Volume{} - for _, podVol := range pet.Spec.Volumes { - podVolumes[podVol.Name] = podVol - } - - // Insert claims for the idempotent petSet volumes - for name, claim := range petClaims { - // Volumes on a pet for which there are no associated claims on the - // petset are pod local, and die with the pod. - podVol, ok := podVolumes[name] - if ok { - // TODO: Validate and reject this. - glog.V(4).Infof("Overwriting existing volume source %v", podVol.Name) - } - newVol := api.Volume{ - Name: name, - VolumeSource: api.VolumeSource{ - PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{ - ClaimName: claim.Name, - // TODO: Use source definition to set this value when we have one. - ReadOnly: false, - }, - }, - } - petVolumes = append(petVolumes, newVol) - } - - // Transfer any ephemeral pod volumes - for name, vol := range podVolumes { - if _, ok := petClaims[name]; !ok { - petVolumes = append(petVolumes, vol) - } - } - pet.Spec.Volumes = petVolumes - return -} - -// Identity returns the storage identity of the pet. -func (v *VolumeIdentityMapper) Identity(pet *api.Pod) string { - // TODO: Make this a hash? - return v.String(pet) -} - -// String is a string function for the network identity of the pet. -func (v *VolumeIdentityMapper) String(pet *api.Pod) string { - ids := []string{} - petVols := sets.NewString() - for _, petVol := range v.ps.Spec.VolumeClaimTemplates { - petVols.Insert(petVol.Name) - } - for _, podVol := range pet.Spec.Volumes { - // Volumes on a pet for which there are no associated claims on the - // petset are pod local, and die with the pod. - if !petVols.Has(podVol.Name) { - continue - } - if podVol.VolumeSource.PersistentVolumeClaim == nil { - // TODO: Is this a part of the identity? - ids = append(ids, fmt.Sprintf("%v:None", podVol.Name)) - continue - } - ids = append(ids, fmt.Sprintf("%v:%v", podVol.Name, podVol.VolumeSource.PersistentVolumeClaim.ClaimName)) - } - sort.Strings(ids) - return strings.Join(ids, "") -} - -// GetClaims returns the volume claims associated with the given id. -// The claims belong to the petset. The id should be unique within a petset. -func (v *VolumeIdentityMapper) GetClaims(id string) map[string]api.PersistentVolumeClaim { - petClaims := map[string]api.PersistentVolumeClaim{} - for _, pvc := range v.ps.Spec.VolumeClaimTemplates { - claim := pvc - // TODO: Name length checking in validation. - claim.Name = fmt.Sprintf("%v-%v-%v", claim.Name, v.ps.Name, id) - claim.Namespace = v.ps.Namespace - claim.Labels = v.ps.Spec.Selector.MatchLabels - - // TODO: We're assuming that the claim template has a volume QoS key, eg: - // volume.alpha.kubernetes.io/storage-class: anything - petClaims[pvc.Name] = claim - } - return petClaims -} - -// GetClaimsForPet returns the pvcs for the given pet. -func (v *VolumeIdentityMapper) GetClaimsForPet(pet *api.Pod) []api.PersistentVolumeClaim { - // Strip out the "-(index)" from the pet name and use it to generate - // claim names. - id := strings.Split(pet.Name, "-") - petID := id[len(id)-1] - pvcs := []api.PersistentVolumeClaim{} - for _, pvc := range v.GetClaims(petID) { - pvcs = append(pvcs, pvc) - } - return pvcs -} - -// NameIdentityMapper assigns names to pets. -// It also puts the pet in the same namespace as the parent. -type NameIdentityMapper struct { - ps *apps.PetSet -} - -// SetIdentity sets the pet namespace and name. -func (n *NameIdentityMapper) SetIdentity(id string, pet *api.Pod) { - pet.Name = fmt.Sprintf("%v-%v", n.ps.Name, id) - pet.Namespace = n.ps.Namespace - return -} - -// Identity returns the name identity of the pet. -func (n *NameIdentityMapper) Identity(pet *api.Pod) string { - return n.String(pet) -} - -// String is a string function for the name identity of the pet. -func (n *NameIdentityMapper) String(pet *api.Pod) string { - return fmt.Sprintf("%v/%v", pet.Namespace, pet.Name) -} - -// identityHash computes a hash of the pet by running all the above identity -// mappers. -func identityHash(ps *apps.PetSet, pet *api.Pod) string { - id := "" - for _, idMapper := range newIdentityMappers(ps) { - id += idMapper.Identity(pet) - } - return fmt.Sprintf("%x", md5.Sum([]byte(id))) -} - -// copyPetID gives the realPet the same identity as the expectedPet. -// Note that this is *not* a literal copy, but a copy of the fields that -// contribute to the pet's identity. The returned boolean 'needsUpdate' will -// be false if the realPet already has the same identity as the expectedPet. -func copyPetID(realPet, expectedPet *pcb) (pod api.Pod, needsUpdate bool, err error) { - if realPet.pod == nil || expectedPet.pod == nil { - return pod, false, fmt.Errorf("Need a valid to and from pet for copy") - } - if realPet.parent.UID != expectedPet.parent.UID { - return pod, false, fmt.Errorf("Cannot copy pets with different parents") - } - ps := realPet.parent - if identityHash(ps, realPet.pod) == identityHash(ps, expectedPet.pod) { - return *realPet.pod, false, nil - } - copyPod := *realPet.pod - // This is the easiest way to give an identity to a pod. It won't work - // when we stop using names for id. - for _, idMapper := range newIdentityMappers(ps) { - idMapper.SetIdentity(expectedPet.id, ©Pod) - } - return copyPod, true, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/identity_mappers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/identity_mappers_test.go deleted file mode 100644 index f9a736fc3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/identity_mappers_test.go +++ /dev/null @@ -1,179 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - "reflect" - "strings" - - "k8s.io/kubernetes/pkg/api" - api_pod "k8s.io/kubernetes/pkg/api/pod" - "testing" -) - -func TestPetIDName(t *testing.T) { - replicas := 3 - ps := newPetSet(replicas) - for i := 0; i < replicas; i++ { - petName := fmt.Sprintf("%v-%d", ps.Name, i) - pcb, err := newPCB(fmt.Sprintf("%d", i), ps) - if err != nil { - t.Fatalf("Failed to generate pet %v", err) - } - pod := pcb.pod - if pod.Name != petName || pod.Namespace != ps.Namespace { - t.Errorf("Wrong name identity, expected %v", pcb.pod.Name) - } - } -} - -func TestPetIDDNS(t *testing.T) { - replicas := 3 - ps := newPetSet(replicas) - for i := 0; i < replicas; i++ { - petName := fmt.Sprintf("%v-%d", ps.Name, i) - petSubdomain := ps.Spec.ServiceName - pcb, err := newPCB(fmt.Sprintf("%d", i), ps) - pod := pcb.pod - if err != nil { - t.Fatalf("Failed to generate pet %v", err) - } - if hostname, ok := pod.Annotations[api_pod.PodHostnameAnnotation]; !ok || hostname != petName { - t.Errorf("Wrong hostname: %v", petName) - } - // TODO: Check this against the governing service. - if subdomain, ok := pod.Annotations[api_pod.PodSubdomainAnnotation]; !ok || subdomain != petSubdomain { - t.Errorf("Wrong subdomain: %v", petName) - } - } -} -func TestPetIDVolume(t *testing.T) { - replicas := 3 - ps := newPetSet(replicas) - for i := 0; i < replicas; i++ { - pcb, err := newPCB(fmt.Sprintf("%d", i), ps) - if err != nil { - t.Fatalf("Failed to generate pet %v", err) - } - pod := pcb.pod - petName := fmt.Sprintf("%v-%d", ps.Name, i) - claimName := fmt.Sprintf("datadir-%v", petName) - for _, v := range pod.Spec.Volumes { - switch v.Name { - case "datadir": - c := v.VolumeSource.PersistentVolumeClaim - if c == nil || c.ClaimName != claimName { - t.Fatalf("Unexpected claim %v", c) - } - if err := checkPodForMount(pod, "datadir"); err != nil { - t.Errorf("Expected pod mount: %v", err) - } - case "home": - h := v.VolumeSource.HostPath - if h == nil || h.Path != "/tmp/home" { - t.Errorf("Unexpected modification to hostpath, expected /tmp/home got %+v", h) - } - default: - t.Errorf("Unexpected volume %v", v.Name) - } - } - } - // TODO: Check volume mounts. -} - -func TestPetIDVolumeClaims(t *testing.T) { - replicas := 3 - ps := newPetSet(replicas) - for i := 0; i < replicas; i++ { - pcb, err := newPCB(fmt.Sprintf("%v", i), ps) - if err != nil { - t.Fatalf("Failed to generate pet %v", err) - } - pvcs := pcb.pvcs - petName := fmt.Sprintf("%v-%d", ps.Name, i) - claimName := fmt.Sprintf("datadir-%v", petName) - if len(pvcs) != 1 || pvcs[0].Name != claimName { - t.Errorf("Wrong pvc expected %v got %v", claimName, pvcs[0].Name) - } - } -} - -func TestPetIDCrossAssignment(t *testing.T) { - replicas := 3 - ps := newPetSet(replicas) - - nameMapper := &NameIdentityMapper{ps} - volumeMapper := &VolumeIdentityMapper{ps} - networkMapper := &NetworkIdentityMapper{ps} - - // Check that the name is consistent across identity. - for i := 0; i < replicas; i++ { - pet, _ := newPCB(fmt.Sprintf("%v", i), ps) - p := pet.pod - name := strings.Split(nameMapper.Identity(p), "/")[1] - network := networkMapper.Identity(p) - volume := volumeMapper.Identity(p) - - petVolume := strings.Split(volume, ":")[1] - - if petVolume != fmt.Sprintf("datadir-%v", name) { - t.Errorf("Unexpected pet volume name %v, expected %v", petVolume, name) - } - if network != fmt.Sprintf("%v.%v.%v", name, ps.Spec.ServiceName, ps.Namespace) { - t.Errorf("Unexpected pet network ID %v, expected %v", network, name) - } - t.Logf("[%v] volume: %+v, network: %+v, name: %+v", i, volume, network, name) - } -} - -func TestPetIDReset(t *testing.T) { - replicas := 2 - ps := newPetSet(replicas) - firstPCB, err := newPCB("1", ps) - secondPCB, err := newPCB("2", ps) - if identityHash(ps, firstPCB.pod) == identityHash(ps, secondPCB.pod) { - t.Fatalf("Failed to generate uniquey identities:\n%+v\n%+v", firstPCB.pod.Spec, secondPCB.pod.Spec) - } - userAdded := api.Volume{ - Name: "test", - VolumeSource: api.VolumeSource{ - EmptyDir: &api.EmptyDirVolumeSource{Medium: api.StorageMediumMemory}, - }, - } - firstPCB.pod.Spec.Volumes = append(firstPCB.pod.Spec.Volumes, userAdded) - pod, needsUpdate, err := copyPetID(firstPCB, secondPCB) - if err != nil { - t.Errorf("%v", err) - } - if !needsUpdate { - t.Errorf("expected update since identity of %v was reset", secondPCB.pod.Name) - } - if identityHash(ps, &pod) != identityHash(ps, secondPCB.pod) { - t.Errorf("Failed to copy identity for pod %v -> %v", firstPCB.pod.Name, secondPCB.pod.Name) - } - foundVol := false - for _, v := range pod.Spec.Volumes { - if reflect.DeepEqual(v, userAdded) { - foundVol = true - break - } - } - if !foundVol { - t.Errorf("User added volume was corrupted by reset action.") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/iterator.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/iterator.go deleted file mode 100644 index 81df6814c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/iterator.go +++ /dev/null @@ -1,163 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - "sort" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/controller" -) - -// newPCB generates a new PCB using the id string as a unique qualifier -func newPCB(id string, ps *apps.PetSet) (*pcb, error) { - petPod, err := controller.GetPodFromTemplate(&ps.Spec.Template, ps) - if err != nil { - return nil, err - } - for _, im := range newIdentityMappers(ps) { - im.SetIdentity(id, petPod) - } - petPVCs := []api.PersistentVolumeClaim{} - vMapper := &VolumeIdentityMapper{ps} - for _, c := range vMapper.GetClaims(id) { - petPVCs = append(petPVCs, c) - } - // TODO: Replace id field with IdentityHash, since id is more than just an index. - return &pcb{pod: petPod, pvcs: petPVCs, id: id, parent: ps}, nil -} - -// petQueue is a custom datastructure that's resembles a queue of pets. -type petQueue struct { - pets []*pcb - idMapper identityMapper -} - -// enqueue enqueues the given pet, evicting any pets with the same id -func (pt *petQueue) enqueue(p *pcb) { - if p == nil { - pt.pets = append(pt.pets, nil) - return - } - // Pop an existing pet from the know list, append the new pet to the end. - petList := []*pcb{} - petID := pt.idMapper.Identity(p.pod) - for i := range pt.pets { - if petID != pt.idMapper.Identity(pt.pets[i].pod) { - petList = append(petList, pt.pets[i]) - } - } - pt.pets = petList - p.event = syncPet - pt.pets = append(pt.pets, p) -} - -// dequeue returns the last element of the queue -func (pt *petQueue) dequeue() *pcb { - if pt.empty() { - glog.Warningf("Dequeue invoked on an empty queue") - return nil - } - l := len(pt.pets) - 1 - pet := pt.pets[l] - pt.pets = pt.pets[:l] - return pet -} - -// empty returns true if the pet queue is empty. -func (pt *petQueue) empty() bool { - return len(pt.pets) == 0 -} - -// NewPetQueue returns a queue for tracking pets -func NewPetQueue(ps *apps.PetSet, podList []*api.Pod) *petQueue { - pt := petQueue{pets: []*pcb{}, idMapper: &NameIdentityMapper{ps}} - // Seed the queue with existing pets. Assume all pets are scheduled for - // deletion, enqueuing a pet will "undelete" it. We always want to delete - // from the higher ids, so sort by creation timestamp. - - sort.Sort(PodsByCreationTimestamp(podList)) - vMapper := VolumeIdentityMapper{ps} - for i := range podList { - pod := podList[i] - pt.pets = append(pt.pets, &pcb{pod: pod, pvcs: vMapper.GetClaimsForPet(pod), parent: ps, event: deletePet, id: fmt.Sprintf("%v", i)}) - } - return &pt -} - -// petsetIterator implements a simple iterator over pets in the given petset. -type petSetIterator struct { - // ps is the petset for this iterator. - ps *apps.PetSet - // queue contains the elements to iterate over. - queue *petQueue - // errs is a list because we always want the iterator to drain. - errs []error - // petCount is the number of pets iterated over. - petCount int -} - -// Next returns true for as long as there are elements in the underlying queue. -func (pi *petSetIterator) Next() bool { - var pet *pcb - var err error - if pi.petCount < pi.ps.Spec.Replicas { - pet, err = newPCB(fmt.Sprintf("%d", pi.petCount), pi.ps) - if err != nil { - pi.errs = append(pi.errs, err) - // Don't stop iterating over the set on errors. Caller handles nil. - pet = nil - } - pi.queue.enqueue(pet) - pi.petCount++ - } - // Keep the iterator running till we've deleted pets in the queue. - return !pi.queue.empty() -} - -// Value dequeues an element from the queue. -func (pi *petSetIterator) Value() *pcb { - return pi.queue.dequeue() -} - -// NewPetSetIterator returns a new iterator. All pods in the given podList -// are used to seed the queue of the iterator. -func NewPetSetIterator(ps *apps.PetSet, podList []*api.Pod) *petSetIterator { - pi := &petSetIterator{ - ps: ps, - queue: NewPetQueue(ps, podList), - errs: []error{}, - petCount: 0, - } - return pi -} - -// PodsByCreationTimestamp sorts a list of Pods by creation timestamp, using their names as a tie breaker. -type PodsByCreationTimestamp []*api.Pod - -func (o PodsByCreationTimestamp) Len() int { return len(o) } -func (o PodsByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o PodsByCreationTimestamp) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/iterator_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/iterator_test.go deleted file mode 100644 index ab07c4223..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/iterator_test.go +++ /dev/null @@ -1,149 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/util/sets" - "testing" -) - -func TestPetQueueCreates(t *testing.T) { - replicas := 3 - ps := newPetSet(replicas) - q := NewPetQueue(ps, []*api.Pod{}) - for i := 0; i < replicas; i++ { - pet, _ := newPCB(fmt.Sprintf("%v", i), ps) - q.enqueue(pet) - p := q.dequeue() - if p.event != syncPet { - t.Errorf("Failed to retrieve sync event from queue") - } - } - if q.dequeue() != nil { - t.Errorf("Expected no pets") - } -} - -func TestPetQueueScaleDown(t *testing.T) { - replicas := 1 - ps := newPetSet(replicas) - - // knownPods are the pods in the system - knownPods := newPodList(ps, 3) - - q := NewPetQueue(ps, knownPods) - - // The iterator will insert a single replica, the enqueue - // mimics that behavior. - pet, _ := newPCB(fmt.Sprintf("%v", 0), ps) - q.enqueue(pet) - - deletes := sets.NewString(fmt.Sprintf("%v-1", ps.Name), fmt.Sprintf("%v-2", ps.Name)) - syncs := sets.NewString(fmt.Sprintf("%v-0", ps.Name)) - - // Confirm that 2 known pods are deleted - for i := 0; i < 3; i++ { - p := q.dequeue() - switch p.event { - case syncPet: - if !syncs.Has(p.pod.Name) { - t.Errorf("Unexpected sync %v expecting %+v", p.pod.Name, syncs) - } - case deletePet: - if !deletes.Has(p.pod.Name) { - t.Errorf("Unexpected deletes %v expecting %+v", p.pod.Name, deletes) - } - } - } - if q.dequeue() != nil { - t.Errorf("Expected no pets") - } -} - -func TestPetQueueScaleUp(t *testing.T) { - replicas := 5 - ps := newPetSet(replicas) - - // knownPods are pods in the system - knownPods := newPodList(ps, 2) - - q := NewPetQueue(ps, knownPods) - for i := 0; i < 5; i++ { - pet, _ := newPCB(fmt.Sprintf("%v", i), ps) - q.enqueue(pet) - } - for i := 4; i >= 0; i-- { - pet := q.dequeue() - expectedName := fmt.Sprintf("%v-%d", ps.Name, i) - if pet.event != syncPet || pet.pod.Name != expectedName { - t.Errorf("Unexpected pet %+v, expected %v", pet.pod.Name, expectedName) - } - } -} - -func TestPetSetIteratorRelist(t *testing.T) { - replicas := 5 - ps := newPetSet(replicas) - - // knownPods are pods in the system - knownPods := newPodList(ps, 5) - for i := range knownPods { - knownPods[i].Spec.NodeName = fmt.Sprintf("foo-node-%v", i) - knownPods[i].Status.Phase = api.PodRunning - } - pi := NewPetSetIterator(ps, knownPods) - - // A simple resync should not change identity of pods in the system - i := 0 - for pi.Next() { - p := pi.Value() - if identityHash(ps, p.pod) != identityHash(ps, knownPods[i]) { - t.Errorf("Got unexpected identity hash from iterator.") - } - if p.event != syncPet { - t.Errorf("Got unexpected sync event for %v: %v", p.pod.Name, p.event) - } - i++ - } - if i != 5 { - t.Errorf("Unexpected iterations %v, this probably means too many/few pets", i) - } - - // Scale to 0 should delete all pods in system - ps.Spec.Replicas = 0 - pi = NewPetSetIterator(ps, knownPods) - i = 0 - for pi.Next() { - p := pi.Value() - if p.event != deletePet { - t.Errorf("Got unexpected sync event for %v: %v", p.pod.Name, p.event) - } - i++ - } - if i != 5 { - t.Errorf("Unexpected iterations %v, this probably means too many/few pets", i) - } - - // Relist with 0 replicas should no-op - pi = NewPetSetIterator(ps, []*api.Pod{}) - if pi.Next() != false { - t.Errorf("Unexpected iteration without any replicas or pods in system") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet.go deleted file mode 100644 index 685e3d6e0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet.go +++ /dev/null @@ -1,310 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - "strconv" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/client/record" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/runtime" - - "github.com/golang/glog" -) - -// petLifeCycleEvent is used to communicate high level actions the controller -// needs to take on a given pet. It's recorded in the pcb. The recognized values -// are listed below. -type petLifeCycleEvent string - -const ( - syncPet petLifeCycleEvent = "sync" - deletePet petLifeCycleEvent = "delete" - // updateRetries is the number of Get/Update cycles we perform when an - // update fails. - updateRetries = 3 - // PetSetInitAnnotation is an annotation which when set, indicates that the - // pet has finished initializing itself. - // TODO: Replace this with init container status. - PetSetInitAnnotation = "pod.alpha.kubernetes.io/initialized" -) - -// pcb is the control block used to transmit all updates about a single pet. -// It serves as the manifest for a single pet. Users must populate the pod -// and parent fields to pass it around safely. -type pcb struct { - // pod is the desired pet pod. - pod *api.Pod - // pvcs is a list of desired persistent volume claims for the pet pod. - pvcs []api.PersistentVolumeClaim - // event is the lifecycle event associated with this update. - event petLifeCycleEvent - // id is the identity index of this pet. - id string - // parent is a pointer to the parent petset. - parent *apps.PetSet -} - -// pvcClient is a client for managing persistent volume claims. -type pvcClient interface { - // DeletePVCs deletes the pvcs in the given pcb. - DeletePVCs(*pcb) error - // SyncPVCs creates/updates pvcs in the given pcb. - SyncPVCs(*pcb) error -} - -// petSyncer syncs a single pet. -type petSyncer struct { - petClient - - // blockingPet is an unhealthy pet either from this iteration or a previous - // iteration, either because it is not yet Running, or being Deleted, that - // prevents other creates/deletions. - blockingPet *pcb -} - -// Sync syncs the given pet. -func (p *petSyncer) Sync(pet *pcb) error { - if pet == nil { - return nil - } - realPet, exists, err := p.Get(pet) - if err != nil { - return err - } - // There is not constraint except quota on the number of pvcs created. - // This is done per pet so we get a working cluster ASAP, even if user - // runs out of quota. - if err := p.SyncPVCs(pet); err != nil { - return err - } - if exists { - if !p.isHealthy(realPet.pod) { - glog.Infof("PetSet %v waiting on unhealthy pet %v", pet.parent.Name, realPet.pod.Name) - } - return p.Update(realPet, pet) - } - if p.blockingPet != nil { - glog.Infof("Create of %v in PetSet %v blocked by unhealthy pet %v", pet.pod.Name, pet.parent.Name, p.blockingPet.pod.Name) - return nil - } - // This is counted as a create, even if it fails. We can't skip indices - // because some pets might allocate a special role to earlier indices. - // The returned error will force a requeue. - // TODO: What's the desired behavior if pet-0 is deleted while pet-1 is - // not yet healthy? currently pet-0 will wait till pet-1 is healthy, - // this feels safer, but might lead to deadlock. - p.blockingPet = pet - if err := p.Create(pet); err != nil { - return err - } - return nil -} - -// Delete deletes the given pet, if no other pet in the petset is blocking a -// scale event. -func (p *petSyncer) Delete(pet *pcb) error { - if pet == nil { - return nil - } - realPet, exists, err := p.Get(pet) - if err != nil { - return err - } - if !exists { - return nil - } - if p.blockingPet != nil { - glog.Infof("Delete of %v in PetSet %v blocked by unhealthy pet %v", realPet.pod.Name, pet.parent.Name, p.blockingPet.pod.Name) - return nil - } - // This is counted as a delete, even if it fails. - // The returned error will force a requeue. - p.blockingPet = realPet - if !p.isDying(realPet.pod) { - glog.Infof("PetSet %v deleting pet %v", pet.parent.Name, pet.pod.Name) - return p.petClient.Delete(pet) - } - glog.Infof("PetSet %v waiting on pet %v to die in %v", pet.parent.Name, realPet.pod.Name, realPet.pod.DeletionTimestamp) - return nil -} - -// petClient is a client for managing pets. -type petClient interface { - pvcClient - petHealthChecker - Delete(*pcb) error - Get(*pcb) (*pcb, bool, error) - Create(*pcb) error - Update(*pcb, *pcb) error -} - -// apiServerPetClient is a petset aware Kubernetes client. -type apiServerPetClient struct { - c *client.Client - recorder record.EventRecorder - petHealthChecker -} - -// Get gets the pet in the pcb from the apiserver. -func (p *apiServerPetClient) Get(pet *pcb) (*pcb, bool, error) { - found := true - ns := pet.parent.Namespace - pod, err := podClient(p.c, ns).Get(pet.pod.Name) - if errors.IsNotFound(err) { - found = false - err = nil - } - if err != nil || !found { - return nil, found, err - } - realPet := *pet - realPet.pod = pod - return &realPet, true, nil -} - -// Delete deletes the pet in the pcb from the apiserver. -func (p *apiServerPetClient) Delete(pet *pcb) error { - err := podClient(p.c, pet.parent.Namespace).Delete(pet.pod.Name, nil) - if errors.IsNotFound(err) { - err = nil - } - p.event(pet.parent, "Delete", fmt.Sprintf("pet: %v", pet.pod.Name), err) - return err -} - -// Create creates the pet in the pcb. -func (p *apiServerPetClient) Create(pet *pcb) error { - _, err := podClient(p.c, pet.parent.Namespace).Create(pet.pod) - p.event(pet.parent, "Create", fmt.Sprintf("pet: %v", pet.pod.Name), err) - return err -} - -// Update updates the pet in the 'pet' pcb to match the pet in the 'expectedPet' pcb. -func (p *apiServerPetClient) Update(pet *pcb, expectedPet *pcb) (updateErr error) { - var getErr error - pc := podClient(p.c, pet.parent.Namespace) - - pod, needsUpdate, err := copyPetID(pet, expectedPet) - if err != nil || !needsUpdate { - return err - } - glog.Infof("Resetting pet %v to match PetSet %v spec", pod.Name, pet.parent.Name) - for i, p := 0, &pod; ; i++ { - _, updateErr = pc.Update(p) - if updateErr == nil || i >= updateRetries { - return updateErr - } - if p, getErr = pc.Get(pod.Name); getErr != nil { - return getErr - } - } -} - -// DeletePVCs should delete PVCs, when implemented. -func (p *apiServerPetClient) DeletePVCs(pet *pcb) error { - // TODO: Implement this when we delete pvcs. - return nil -} - -func (p *apiServerPetClient) getPVC(pvcName, pvcNamespace string) (*api.PersistentVolumeClaim, bool, error) { - found := true - pvc, err := claimClient(p.c, pvcNamespace).Get(pvcName) - if errors.IsNotFound(err) { - found = false - } - if err != nil || !found { - return nil, found, err - } - return pvc, true, nil -} - -func (p *apiServerPetClient) createPVC(pvc *api.PersistentVolumeClaim) error { - _, err := claimClient(p.c, pvc.Namespace).Create(pvc) - return err -} - -// SyncPVCs syncs pvcs in the given pcb. -func (p *apiServerPetClient) SyncPVCs(pet *pcb) error { - errMsg := "" - // Create new claims. - for i, pvc := range pet.pvcs { - _, exists, err := p.getPVC(pvc.Name, pet.parent.Namespace) - if !exists { - if err := p.createPVC(&pet.pvcs[i]); err != nil { - errMsg += fmt.Sprintf("Failed to create %v: %v", pvc.Name, err) - } - p.event(pet.parent, "Create", fmt.Sprintf("pvc: %v", pvc.Name), err) - } else if err != nil { - errMsg += fmt.Sprintf("Error trying to get pvc %v, %v.", pvc.Name, err) - } - // TODO: Check resource requirements and accessmodes, update if necessary - } - if len(errMsg) != 0 { - return fmt.Errorf("%v", errMsg) - } - return nil -} - -// event formats an event for the given runtime object. -func (p *apiServerPetClient) event(obj runtime.Object, reason, msg string, err error) { - if err != nil { - p.recorder.Eventf(obj, api.EventTypeWarning, fmt.Sprintf("Failed%v", reason), fmt.Sprintf("%v, error: %v", msg, err)) - } else { - p.recorder.Eventf(obj, api.EventTypeNormal, fmt.Sprintf("Successful%v", reason), msg) - } -} - -// petHealthChecker is an interface to check pet health. It makes a boolean -// decision based on the given pod. -type petHealthChecker interface { - isHealthy(*api.Pod) bool - isDying(*api.Pod) bool -} - -// defaultPetHealthChecks does basic health checking. -// It doesn't update, probe or get the pod. -type defaultPetHealthChecker struct{} - -// isHealthy returns true if the pod is running and has the -// "pod.alpha.kubernetes.io/initialized" set to "true". -func (d *defaultPetHealthChecker) isHealthy(pod *api.Pod) bool { - if pod == nil || pod.Status.Phase != api.PodRunning { - return false - } - initialized, ok := pod.Annotations[PetSetInitAnnotation] - if !ok { - glog.Infof("PetSet pod %v in %v, waiting on annotation %v", api.PodRunning, pod.Name, PetSetInitAnnotation) - return false - } - b, err := strconv.ParseBool(initialized) - if err != nil { - return false - } - return b -} - -// isDying returns true if the pod has a non-nil deletion timestamp. Since the -// timestamp can only decrease, once this method returns true for a given pet, it -// will never return false. -func (d *defaultPetHealthChecker) isDying(pod *api.Pod) bool { - return pod != nil && pod.DeletionTimestamp != nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set.go deleted file mode 100644 index a34eb6d5c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set.go +++ /dev/null @@ -1,356 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - "reflect" - "sort" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/client/cache" - "k8s.io/kubernetes/pkg/client/record" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/runtime" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" - - "github.com/golang/glog" -) - -const ( - // Time to sleep before polling to see if the pod cache has synced. - PodStoreSyncedPollPeriod = 100 * time.Millisecond - // number of retries for a status update. - statusUpdateRetries = 2 - // period to relist petsets and verify pets - petSetResyncPeriod = 30 * time.Second -) - -// PetSetController controls petsets. -type PetSetController struct { - kubeClient *client.Client - - // newSyncer returns an interface capable of syncing a single pet. - // Abstracted out for testing. - newSyncer func(*pcb) *petSyncer - - // podStore is a cache of watched pods. - podStore cache.StoreToPodLister - - // podStoreSynced returns true if the pod store has synced at least once. - podStoreSynced func() bool - // Watches changes to all pods. - podController framework.ControllerInterface - - // A store of PetSets, populated by the psController. - psStore cache.StoreToPetSetLister - // Watches changes to all PetSets. - psController *framework.Controller - - // A store of the 1 unhealthy pet blocking progress for a given ps - blockingPetStore *unhealthyPetTracker - - // Controllers that need to be synced. - queue *workqueue.Type - - // syncHandler handles sync events for petsets. - // Abstracted as a func to allow injection for testing. - syncHandler func(psKey string) []error -} - -// NewPetSetController creates a new petset controller. -func NewPetSetController(podInformer framework.SharedIndexInformer, kubeClient *client.Client, resyncPeriod time.Duration) *PetSetController { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(kubeClient.Events("")) - recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "petset"}) - pc := &apiServerPetClient{kubeClient, recorder, &defaultPetHealthChecker{}} - - psc := &PetSetController{ - kubeClient: kubeClient, - blockingPetStore: newUnHealthyPetTracker(pc), - newSyncer: func(blockingPet *pcb) *petSyncer { - return &petSyncer{pc, blockingPet} - }, - queue: workqueue.New(), - } - - podInformer.AddEventHandler(framework.ResourceEventHandlerFuncs{ - // lookup the petset and enqueue - AddFunc: psc.addPod, - // lookup current and old petset if labels changed - UpdateFunc: psc.updatePod, - // lookup petset accounting for deletion tombstones - DeleteFunc: psc.deletePod, - }) - psc.podStore.Indexer = podInformer.GetIndexer() - psc.podController = podInformer.GetController() - - psc.psStore.Store, psc.psController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return psc.kubeClient.Apps().PetSets(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return psc.kubeClient.Apps().PetSets(api.NamespaceAll).Watch(options) - }, - }, - &apps.PetSet{}, - petSetResyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: psc.enqueuePetSet, - UpdateFunc: func(old, cur interface{}) { - oldPS := old.(*apps.PetSet) - curPS := cur.(*apps.PetSet) - if oldPS.Status.Replicas != curPS.Status.Replicas { - glog.V(4).Infof("Observed updated replica count for PetSet: %v, %d->%d", curPS.Name, oldPS.Status.Replicas, curPS.Status.Replicas) - } - psc.enqueuePetSet(cur) - }, - DeleteFunc: psc.enqueuePetSet, - }, - ) - // TODO: Watch volumes - psc.podStoreSynced = psc.podController.HasSynced - psc.syncHandler = psc.Sync - return psc -} - -// Run runs the petset controller. -func (psc *PetSetController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - glog.Infof("Starting petset controller") - go psc.podController.Run(stopCh) - go psc.psController.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(psc.worker, time.Second, stopCh) - } - <-stopCh - glog.Infof("Shutting down petset controller") - psc.queue.ShutDown() -} - -// addPod adds the petset for the pod to the sync queue -func (psc *PetSetController) addPod(obj interface{}) { - pod := obj.(*api.Pod) - glog.V(4).Infof("Pod %s created, labels: %+v", pod.Name, pod.Labels) - ps := psc.getPetSetForPod(pod) - if ps == nil { - return - } - psc.enqueuePetSet(ps) -} - -// updatePod adds the petset for the current and old pods to the sync queue. -// If the labels of the pod didn't change, this method enqueues a single petset. -func (psc *PetSetController) updatePod(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - return - } - curPod := cur.(*api.Pod) - oldPod := old.(*api.Pod) - ps := psc.getPetSetForPod(curPod) - if ps == nil { - return - } - psc.enqueuePetSet(ps) - if !reflect.DeepEqual(curPod.Labels, oldPod.Labels) { - if oldPS := psc.getPetSetForPod(oldPod); oldPS != nil { - psc.enqueuePetSet(oldPS) - } - } -} - -// deletePod enqueues the petset for the pod accounting for deletion tombstones. -func (psc *PetSetController) deletePod(obj interface{}) { - pod, ok := obj.(*api.Pod) - - // When a delete is dropped, the relist will notice a pod in the store not - // in the list, leading to the insertion of a tombstone object which contains - // the deleted key/value. Note that this value might be stale. If the pod - // changed labels the new PetSet will not be woken up till the periodic resync. - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("couldn't get object from tombstone %+v", obj) - return - } - pod, ok = tombstone.Obj.(*api.Pod) - if !ok { - glog.Errorf("tombstone contained object that is not a pod %+v", obj) - return - } - } - glog.V(4).Infof("Pod %s/%s deleted through %v.", pod.Namespace, pod.Name, utilruntime.GetCaller()) - if ps := psc.getPetSetForPod(pod); ps != nil { - psc.enqueuePetSet(ps) - } -} - -// getPodsForPetSets returns the pods that match the selectors of the given petset. -func (psc *PetSetController) getPodsForPetSet(ps *apps.PetSet) ([]*api.Pod, error) { - // TODO: Do we want the petset to fight with RCs? check parent petset annoation, or name prefix? - sel, err := unversioned.LabelSelectorAsSelector(ps.Spec.Selector) - if err != nil { - return []*api.Pod{}, err - } - petList, err := psc.podStore.Pods(ps.Namespace).List(sel) - if err != nil { - return []*api.Pod{}, err - } - pods := []*api.Pod{} - for _, p := range petList.Items { - pods = append(pods, &p) - } - return pods, nil -} - -// getPetSetForPod returns the pet set managing the given pod. -func (psc *PetSetController) getPetSetForPod(pod *api.Pod) *apps.PetSet { - ps, err := psc.psStore.GetPodPetSets(pod) - if err != nil { - glog.V(4).Infof("No PetSets found for pod %v, PetSet controller will avoid syncing", pod.Name) - return nil - } - // Resolve a overlapping petset tie by creation timestamp. - // Let's hope users don't create overlapping petsets. - if len(ps) > 1 { - glog.Errorf("user error! more than one PetSet is selecting pods with labels: %+v", pod.Labels) - sort.Sort(overlappingPetSets(ps)) - } - return &ps[0] -} - -// enqueuePetSet enqueues the given petset in the work queue. -func (psc *PetSetController) enqueuePetSet(obj interface{}) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Cound't get key for object %+v: %v", obj, err) - return - } - psc.queue.Add(key) -} - -// worker runs a worker thread that just dequeues items, processes them, and marks them done. -// It enforces that the syncHandler is never invoked concurrently with the same key. -func (psc *PetSetController) worker() { - for { - func() { - key, quit := psc.queue.Get() - if quit { - return - } - defer psc.queue.Done(key) - if errs := psc.syncHandler(key.(string)); len(errs) != 0 { - glog.Errorf("Error syncing PetSet %v, requeuing: %v", key.(string), errs) - psc.queue.Add(key) - } - }() - } -} - -// Sync syncs the given petset. -func (psc *PetSetController) Sync(key string) []error { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing pet set %q (%v)", key, time.Now().Sub(startTime)) - }() - - if !psc.podStoreSynced() { - // Sleep so we give the pod reflector goroutine a chance to run. - time.Sleep(PodStoreSyncedPollPeriod) - return []error{fmt.Errorf("waiting for pods controller to sync")} - } - - obj, exists, err := psc.psStore.Store.GetByKey(key) - if !exists { - if err = psc.blockingPetStore.store.Delete(key); err != nil { - return []error{err} - } - glog.Infof("PetSet has been deleted %v", key) - return []error{} - } - if err != nil { - glog.Errorf("Unable to retrieve PetSet %v from store: %v", key, err) - return []error{err} - } - - ps := *obj.(*apps.PetSet) - petList, err := psc.getPodsForPetSet(&ps) - if err != nil { - return []error{err} - } - - numPets, errs := psc.syncPetSet(&ps, petList) - if err := updatePetCount(psc.kubeClient, ps, numPets); err != nil { - glog.Infof("Failed to update replica count for petset %v/%v; requeuing; error: %v", ps.Namespace, ps.Name, err) - errs = append(errs, err) - } - - return errs -} - -// syncPetSet syncs a tuple of (petset, pets). -func (psc *PetSetController) syncPetSet(ps *apps.PetSet, pets []*api.Pod) (int, []error) { - glog.Infof("Syncing PetSet %v/%v with %d pets", ps.Namespace, ps.Name, len(pets)) - - it := NewPetSetIterator(ps, pets) - blockingPet, err := psc.blockingPetStore.Get(ps, pets) - if err != nil { - return 0, []error{err} - } - if blockingPet != nil { - glog.Infof("PetSet %v blocked from scaling on pet %v", ps.Name, blockingPet.pod.Name) - } - petManager := psc.newSyncer(blockingPet) - numPets := 0 - - for it.Next() { - pet := it.Value() - if pet == nil { - continue - } - switch pet.event { - case syncPet: - err = petManager.Sync(pet) - if err == nil { - numPets++ - } - case deletePet: - err = petManager.Delete(pet) - } - if err != nil { - it.errs = append(it.errs, err) - } - } - - if err := psc.blockingPetStore.Add(petManager.blockingPet); err != nil { - it.errs = append(it.errs, err) - } - // TODO: GC pvcs. We can't delete them per pet because of grace period, and - // in fact we *don't want to* till petset is stable to guarantee that bugs - // in the controller don't corrupt user data. - return numPets, it.errs -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set_test.go deleted file mode 100644 index 8498fce87..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set_test.go +++ /dev/null @@ -1,264 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - "math/rand" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/client/cache" - "k8s.io/kubernetes/pkg/controller" -) - -func newFakePetSetController() (*PetSetController, *fakePetClient) { - fpc := newFakePetClient() - return &PetSetController{ - kubeClient: nil, - blockingPetStore: newUnHealthyPetTracker(fpc), - podStoreSynced: func() bool { return true }, - psStore: cache.StoreToPetSetLister{Store: cache.NewStore(controller.KeyFunc)}, - podStore: cache.StoreToPodLister{Indexer: cache.NewIndexer(controller.KeyFunc, cache.Indexers{})}, - newSyncer: func(blockingPet *pcb) *petSyncer { - return &petSyncer{fpc, blockingPet} - }, - }, fpc -} - -func checkPets(ps *apps.PetSet, creates, deletes int, fc *fakePetClient, t *testing.T) { - if fc.petsCreated != creates || fc.petsDeleted != deletes { - t.Errorf("Found (creates: %d, deletes: %d), expected (creates: %d, deletes: %d)", fc.petsCreated, fc.petsDeleted, creates, deletes) - } - gotClaims := map[string]api.PersistentVolumeClaim{} - for _, pvc := range fc.claims { - gotClaims[pvc.Name] = pvc - } - for i := range fc.pets { - expectedPet, _ := newPCB(fmt.Sprintf("%v", i), ps) - if identityHash(ps, fc.pets[i].pod) != identityHash(ps, expectedPet.pod) { - t.Errorf("Unexpected pet at index %d", i) - } - for _, pvc := range expectedPet.pvcs { - gotPVC, ok := gotClaims[pvc.Name] - if !ok { - t.Errorf("PVC %v not created for pet %v", pvc.Name, expectedPet.pod.Name) - } - if !reflect.DeepEqual(gotPVC.Spec, pvc.Spec) { - t.Errorf("got PVC %v differs from created pvc", pvc.Name) - } - } - } -} - -func scalePetSet(t *testing.T, ps *apps.PetSet, psc *PetSetController, fc *fakePetClient, scale int) []error { - errs := []error{} - for i := 0; i < scale; i++ { - pl := fc.getPodList() - if len(pl) != i { - t.Errorf("Unexpected number of pets, expected %d found %d", i, len(fc.pets)) - } - _, syncErrs := psc.syncPetSet(ps, pl) - errs = append(errs, syncErrs...) - fc.setHealthy(i) - checkPets(ps, i+1, 0, fc, t) - } - return errs -} - -func saturatePetSet(t *testing.T, ps *apps.PetSet, psc *PetSetController, fc *fakePetClient) { - errs := scalePetSet(t, ps, psc, fc, ps.Spec.Replicas) - if len(errs) != 0 { - t.Errorf("%v", errs) - } -} - -func TestPetSetControllerCreates(t *testing.T) { - psc, fc := newFakePetSetController() - replicas := 3 - ps := newPetSet(replicas) - - saturatePetSet(t, ps, psc, fc) - - podList := fc.getPodList() - // Deleted pet gets recreated - fc.pets = fc.pets[:replicas-1] - if _, errs := psc.syncPetSet(ps, podList); len(errs) != 0 { - t.Errorf("%v", errs) - } - checkPets(ps, replicas+1, 0, fc, t) -} - -func TestPetSetControllerDeletes(t *testing.T) { - psc, fc := newFakePetSetController() - replicas := 4 - ps := newPetSet(replicas) - - saturatePetSet(t, ps, psc, fc) - - // Drain - errs := []error{} - ps.Spec.Replicas = 0 - knownPods := fc.getPodList() - for i := replicas - 1; i >= 0; i-- { - if len(fc.pets) != i+1 { - t.Errorf("Unexpected number of pets, expected %d found %d", i, len(fc.pets)) - } - _, syncErrs := psc.syncPetSet(ps, knownPods) - errs = append(errs, syncErrs...) - } - if len(errs) != 0 { - t.Errorf("%v", errs) - } - checkPets(ps, replicas, replicas, fc, t) -} - -func TestPetSetControllerRespectsTermination(t *testing.T) { - psc, fc := newFakePetSetController() - replicas := 4 - ps := newPetSet(replicas) - - saturatePetSet(t, ps, psc, fc) - - fc.setDeletionTimestamp(replicas - 1) - ps.Spec.Replicas = 2 - _, errs := psc.syncPetSet(ps, fc.getPodList()) - if len(errs) != 0 { - t.Errorf("%v", errs) - } - // Finding a pod with the deletion timestamp will pause all deletions. - knownPods := fc.getPodList() - if len(knownPods) != 4 { - t.Errorf("Pods deleted prematurely before deletion timestamp expired, len %d", len(knownPods)) - } - fc.pets = fc.pets[:replicas-1] - _, errs = psc.syncPetSet(ps, fc.getPodList()) - if len(errs) != 0 { - t.Errorf("%v", errs) - } - checkPets(ps, replicas, 1, fc, t) -} - -func TestPetSetControllerRespectsOrder(t *testing.T) { - psc, fc := newFakePetSetController() - replicas := 4 - ps := newPetSet(replicas) - - saturatePetSet(t, ps, psc, fc) - - errs := []error{} - ps.Spec.Replicas = 0 - // Shuffle known list and check that pets are deleted in reverse - knownPods := fc.getPodList() - for i := range knownPods { - j := rand.Intn(i + 1) - knownPods[i], knownPods[j] = knownPods[j], knownPods[i] - } - - for i := 0; i < replicas; i++ { - if len(fc.pets) != replicas-i { - t.Errorf("Unexpected number of pets, expected %d found %d", i, len(fc.pets)) - } - _, syncErrs := psc.syncPetSet(ps, knownPods) - errs = append(errs, syncErrs...) - checkPets(ps, replicas, i+1, fc, t) - } - if len(errs) != 0 { - t.Errorf("%v", errs) - } -} - -func TestPetSetControllerBlocksScaling(t *testing.T) { - psc, fc := newFakePetSetController() - replicas := 5 - ps := newPetSet(replicas) - scalePetSet(t, ps, psc, fc, 3) - - // Create 4th pet, then before flipping it to healthy, kill the first pet. - // There should only be 1 not-healty pet at a time. - pl := fc.getPodList() - if _, errs := psc.syncPetSet(ps, pl); len(errs) != 0 { - t.Errorf("%v", errs) - } - - deletedPod := pl[0] - fc.deletePetAtIndex(0) - pl = fc.getPodList() - if _, errs := psc.syncPetSet(ps, pl); len(errs) != 0 { - t.Errorf("%v", errs) - } - newPodList := fc.getPodList() - for _, p := range newPodList { - if p.Name == deletedPod.Name { - t.Errorf("Deleted pod was created while existing pod was unhealthy") - } - } - - fc.setHealthy(len(newPodList) - 1) - if _, errs := psc.syncPetSet(ps, pl); len(errs) != 0 { - t.Errorf("%v", errs) - } - - found := false - for _, p := range fc.getPodList() { - if p.Name == deletedPod.Name { - found = true - } - } - if !found { - t.Errorf("Deleted pod was not created after existing pods became healthy") - } -} - -func TestPetSetBlockingPetIsCleared(t *testing.T) { - psc, fc := newFakePetSetController() - ps := newPetSet(3) - scalePetSet(t, ps, psc, fc, 1) - - if blocking, err := psc.blockingPetStore.Get(ps, fc.getPodList()); err != nil || blocking != nil { - t.Errorf("Unexpected blocking pet %v, err %v", blocking, err) - } - - // 1 not yet healthy pet - psc.syncPetSet(ps, fc.getPodList()) - - if blocking, err := psc.blockingPetStore.Get(ps, fc.getPodList()); err != nil || blocking == nil { - t.Errorf("Expected blocking pet %v, err %v", blocking, err) - } - - // Deleting the petset should clear the blocking pet - if err := psc.psStore.Store.Delete(ps); err != nil { - t.Fatalf("Unable to delete pet %v from petset controller store.", ps.Name) - } - if errs := psc.Sync(fmt.Sprintf("%v/%v", ps.Namespace, ps.Name)); len(errs) != 0 { - t.Errorf("Error during sync of deleted petset %v", errs) - } - fc.pets = []*pcb{} - fc.petsCreated = 0 - if blocking, err := psc.blockingPetStore.Get(ps, fc.getPodList()); err != nil || blocking != nil { - t.Errorf("Unexpected blocking pet %v, err %v", blocking, err) - } - saturatePetSet(t, ps, psc, fc) - - // Make sure we don't leak the final blockin pet in the store - psc.syncPetSet(ps, fc.getPodList()) - if p, exists, err := psc.blockingPetStore.store.GetByKey(fmt.Sprintf("%v/%v", ps.Namespace, ps.Name)); err != nil || exists { - t.Errorf("Unexpected blocking pet, err %v: %+v", err, p) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set_utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set_utils.go deleted file mode 100644 index d6d373050..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/petset/pet_set_utils.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 petset - -import ( - "fmt" - "sync" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/apps" - "k8s.io/kubernetes/pkg/client/cache" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/controller" - - "github.com/golang/glog" -) - -// overlappingPetSets sorts a list of PetSets by creation timestamp, using their names as a tie breaker. -// Generally used to tie break between PetSets that have overlapping selectors. -type overlappingPetSets []apps.PetSet - -func (o overlappingPetSets) Len() int { return len(o) } -func (o overlappingPetSets) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o overlappingPetSets) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} - -// updatePetCount attempts to update the Status.Replicas of the given PetSet, with a single GET/PUT retry. -func updatePetCount(kubeClient *client.Client, ps apps.PetSet, numPets int) (updateErr error) { - if ps.Status.Replicas == numPets || kubeClient == nil { - return nil - } - psClient := kubeClient.Apps().PetSets(ps.Namespace) - var getErr error - for i, ps := 0, &ps; ; i++ { - glog.V(4).Infof(fmt.Sprintf("Updating replica count for PetSet: %s/%s, ", ps.Namespace, ps.Name) + - fmt.Sprintf("replicas %d->%d (need %d), ", ps.Status.Replicas, numPets, ps.Spec.Replicas)) - - ps.Status = apps.PetSetStatus{Replicas: numPets} - _, updateErr = psClient.UpdateStatus(ps) - if updateErr == nil || i >= statusUpdateRetries { - return updateErr - } - if ps, getErr = psClient.Get(ps.Name); getErr != nil { - return getErr - } - } -} - -// claimClient returns the pvcClient for the given kubeClient/ns. -func claimClient(kubeClient *client.Client, ns string) client.PersistentVolumeClaimInterface { - return kubeClient.PersistentVolumeClaims(ns) -} - -// podClient returns the given podClient for the given kubeClient/ns. -func podClient(kubeClient *client.Client, ns string) client.PodInterface { - return kubeClient.Pods(ns) -} - -// unhealthyPetTracker tracks unhealthy pets for petsets. -type unhealthyPetTracker struct { - pc petClient - store cache.Store - storeLock sync.Mutex -} - -// Get returns a previously recorded blocking pet for the given petset. -func (u *unhealthyPetTracker) Get(ps *apps.PetSet, knownPets []*api.Pod) (*pcb, error) { - u.storeLock.Lock() - defer u.storeLock.Unlock() - - // We "Get" by key but "Add" by object because the store interface doesn't - // allow us to Get/Add a related obj (eg petset: blocking pet). - key, err := controller.KeyFunc(ps) - if err != nil { - return nil, err - } - obj, exists, err := u.store.GetByKey(key) - if err != nil { - return nil, err - } - - hc := defaultPetHealthChecker{} - // There's no unhealthy pet blocking a scale event, but this might be - // a controller manager restart. If it is, knownPets can be trusted. - if !exists { - for _, p := range knownPets { - if hc.isHealthy(p) && !hc.isDying(p) { - glog.V(4).Infof("Ignoring healthy pet %v for PetSet %v", p.Name, ps.Name) - continue - } - glog.Infof("No recorded blocking pet, but found unhealty pet %v for PetSet %v", p.Name, ps.Name) - return &pcb{pod: p, parent: ps}, nil - } - return nil, nil - } - - // This is a pet that's blocking further creates/deletes of a petset. If it - // disappears, it's no longer blocking. If it exists, it continues to block - // till it turns healthy or disappears. - bp := obj.(*pcb) - blockingPet, exists, err := u.pc.Get(bp) - if err != nil { - return nil, err - } - if !exists { - glog.V(4).Infof("Clearing blocking pet %v for PetSet %v because it's been deleted", bp.pod.Name, ps.Name) - return nil, nil - } - blockingPetPod := blockingPet.pod - if hc.isHealthy(blockingPetPod) && !hc.isDying(blockingPetPod) { - glog.V(4).Infof("Clearing blocking pet %v for PetSet %v because it's healthy", bp.pod.Name, ps.Name) - u.store.Delete(blockingPet) - blockingPet = nil - } - return blockingPet, nil -} - -// Add records the given pet as a blocking pet. -func (u *unhealthyPetTracker) Add(blockingPet *pcb) error { - u.storeLock.Lock() - defer u.storeLock.Unlock() - - if blockingPet == nil { - return nil - } - glog.V(4).Infof("Adding blocking pet %v for PetSet %v", blockingPet.pod.Name, blockingPet.parent.Name) - return u.store.Add(blockingPet) -} - -// newUnHealthyPetTracker tracks unhealthy pets that block progress of petsets. -func newUnHealthyPetTracker(pc petClient) *unhealthyPetTracker { - return &unhealthyPetTracker{pc: pc, store: cache.NewStore(pcbKeyFunc)} -} - -// pcbKeyFunc computes the key for a given pcb. -// If it's given a key, it simply returns it. -func pcbKeyFunc(obj interface{}) (string, error) { - if key, ok := obj.(string); ok { - return key, nil - } - p, ok := obj.(*pcb) - if !ok { - return "", fmt.Errorf("not a valid pet control block %+v", p) - } - if p.parent == nil { - return "", fmt.Errorf("cannot compute pet control block key without parent pointer %+v", p) - } - return controller.KeyFunc(p.parent) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal_test.go deleted file mode 100644 index 97b61abf1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/podautoscaler/horizontal_test.go +++ /dev/null @@ -1,749 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 podautoscaler - -import ( - "encoding/json" - "fmt" - "io" - "sync" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/unversioned" - _ "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/watch" - - heapster "k8s.io/heapster/metrics/api/v1/types" - - "github.com/stretchr/testify/assert" -) - -func (w fakeResponseWrapper) DoRaw() ([]byte, error) { - return w.raw, nil -} - -func (w fakeResponseWrapper) Stream() (io.ReadCloser, error) { - return nil, nil -} - -func newFakeResponseWrapper(raw []byte) fakeResponseWrapper { - return fakeResponseWrapper{raw: raw} -} - -type fakeResponseWrapper struct { - raw []byte -} - -type fakeResource struct { - name string - apiVersion string - kind string -} - -type testCase struct { - sync.Mutex - minReplicas int32 - maxReplicas int32 - initialReplicas int32 - desiredReplicas int32 - - // CPU target utilization as a percentage of the requested resources. - CPUTarget int32 - CPUCurrent int32 - verifyCPUCurrent bool - reportedLevels []uint64 - reportedCPURequests []resource.Quantity - cmTarget *extensions.CustomMetricTargetList - scaleUpdated bool - statusUpdated bool - eventCreated bool - verifyEvents bool - // Channel with names of HPA objects which we have reconciled. - processed chan string - - // Target resource information. - resource *fakeResource -} - -// Needs to be called under a lock. -func (tc *testCase) computeCPUCurrent() { - if len(tc.reportedLevels) != len(tc.reportedCPURequests) || len(tc.reportedLevels) == 0 { - return - } - reported := 0 - for _, r := range tc.reportedLevels { - reported += int(r) - } - requested := 0 - for _, req := range tc.reportedCPURequests { - requested += int(req.MilliValue()) - } - tc.CPUCurrent = int32(100 * reported / requested) -} - -func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { - namespace := "test-namespace" - hpaName := "test-hpa" - podNamePrefix := "test-pod" - selector := &unversioned.LabelSelector{ - MatchLabels: map[string]string{"name": podNamePrefix}, - } - - tc.Lock() - - tc.scaleUpdated = false - tc.statusUpdated = false - tc.eventCreated = false - tc.processed = make(chan string, 100) - tc.computeCPUCurrent() - - // TODO(madhusudancs): HPA only supports resources in extensions/v1beta1 right now. Add - // tests for "v1" replicationcontrollers when HPA adds support for cross-group scale. - if tc.resource == nil { - tc.resource = &fakeResource{ - name: "test-rc", - apiVersion: "extensions/v1beta1", - kind: "replicationcontrollers", - } - } - tc.Unlock() - - fakeClient := &fake.Clientset{} - fakeClient.AddReactor("list", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := &extensions.HorizontalPodAutoscalerList{ - Items: []extensions.HorizontalPodAutoscaler{ - { - ObjectMeta: api.ObjectMeta{ - Name: hpaName, - Namespace: namespace, - SelfLink: "experimental/v1/namespaces/" + namespace + "/horizontalpodautoscalers/" + hpaName, - }, - Spec: extensions.HorizontalPodAutoscalerSpec{ - ScaleRef: extensions.SubresourceReference{ - Kind: tc.resource.kind, - Name: tc.resource.name, - APIVersion: tc.resource.apiVersion, - Subresource: "scale", - }, - MinReplicas: &tc.minReplicas, - MaxReplicas: tc.maxReplicas, - }, - Status: extensions.HorizontalPodAutoscalerStatus{ - CurrentReplicas: tc.initialReplicas, - DesiredReplicas: tc.initialReplicas, - }, - }, - }, - } - - if tc.CPUTarget > 0.0 { - obj.Items[0].Spec.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: tc.CPUTarget} - } - if tc.cmTarget != nil { - b, err := json.Marshal(tc.cmTarget) - if err != nil { - t.Fatalf("Failed to marshal cm: %v", err) - } - obj.Items[0].Annotations = make(map[string]string) - obj.Items[0].Annotations[HpaCustomMetricsTargetAnnotationName] = string(b) - } - return true, obj, nil - }) - - fakeClient.AddReactor("get", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := &extensions.Scale{ - ObjectMeta: api.ObjectMeta{ - Name: tc.resource.name, - Namespace: namespace, - }, - Spec: extensions.ScaleSpec{ - Replicas: tc.initialReplicas, - }, - Status: extensions.ScaleStatus{ - Replicas: tc.initialReplicas, - Selector: selector, - }, - } - return true, obj, nil - }) - - fakeClient.AddReactor("get", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := &extensions.Scale{ - ObjectMeta: api.ObjectMeta{ - Name: tc.resource.name, - Namespace: namespace, - }, - Spec: extensions.ScaleSpec{ - Replicas: tc.initialReplicas, - }, - Status: extensions.ScaleStatus{ - Replicas: tc.initialReplicas, - Selector: selector, - }, - } - return true, obj, nil - }) - - fakeClient.AddReactor("get", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := &extensions.Scale{ - ObjectMeta: api.ObjectMeta{ - Name: tc.resource.name, - Namespace: namespace, - }, - Spec: extensions.ScaleSpec{ - Replicas: tc.initialReplicas, - }, - Status: extensions.ScaleStatus{ - Replicas: tc.initialReplicas, - Selector: selector, - }, - } - return true, obj, nil - }) - - fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := &api.PodList{} - for i := 0; i < len(tc.reportedCPURequests); i++ { - podName := fmt.Sprintf("%s-%d", podNamePrefix, i) - pod := api.Pod{ - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - ObjectMeta: api.ObjectMeta{ - Name: podName, - Namespace: namespace, - Labels: map[string]string{ - "name": podNamePrefix, - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceCPU: tc.reportedCPURequests[i], - }, - }, - }, - }, - }, - } - obj.Items = append(obj.Items, pod) - } - return true, obj, nil - }) - - fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) { - tc.Lock() - defer tc.Unlock() - - timestamp := time.Now() - metrics := heapster.MetricResultList{} - for _, level := range tc.reportedLevels { - metric := heapster.MetricResult{ - Metrics: []heapster.MetricPoint{{timestamp, level, nil}}, - LatestTimestamp: timestamp, - } - metrics.Items = append(metrics.Items, metric) - } - heapsterRawMemResponse, _ := json.Marshal(&metrics) - return true, newFakeResponseWrapper(heapsterRawMemResponse), nil - }) - - fakeClient.AddReactor("update", "replicationcontrollers", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := action.(core.UpdateAction).GetObject().(*extensions.Scale) - replicas := action.(core.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas - assert.Equal(t, tc.desiredReplicas, replicas) - tc.scaleUpdated = true - return true, obj, nil - }) - - fakeClient.AddReactor("update", "deployments", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := action.(core.UpdateAction).GetObject().(*extensions.Scale) - replicas := action.(core.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas - assert.Equal(t, tc.desiredReplicas, replicas) - tc.scaleUpdated = true - return true, obj, nil - }) - - fakeClient.AddReactor("update", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := action.(core.UpdateAction).GetObject().(*extensions.Scale) - replicas := action.(core.UpdateAction).GetObject().(*extensions.Scale).Spec.Replicas - assert.Equal(t, tc.desiredReplicas, replicas) - tc.scaleUpdated = true - return true, obj, nil - }) - - fakeClient.AddReactor("update", "horizontalpodautoscalers", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := action.(core.UpdateAction).GetObject().(*extensions.HorizontalPodAutoscaler) - assert.Equal(t, namespace, obj.Namespace) - assert.Equal(t, hpaName, obj.Name) - assert.Equal(t, tc.desiredReplicas, obj.Status.DesiredReplicas) - if tc.verifyCPUCurrent { - assert.NotNil(t, obj.Status.CurrentCPUUtilizationPercentage) - assert.Equal(t, tc.CPUCurrent, *obj.Status.CurrentCPUUtilizationPercentage) - } - tc.statusUpdated = true - // Every time we reconcile HPA object we are updating status. - tc.processed <- obj.Name - return true, obj, nil - }) - - fakeClient.AddReactor("*", "events", func(action core.Action) (handled bool, ret runtime.Object, err error) { - tc.Lock() - defer tc.Unlock() - - obj := action.(core.CreateAction).GetObject().(*api.Event) - if tc.verifyEvents { - assert.Equal(t, "SuccessfulRescale", obj.Reason) - assert.Equal(t, fmt.Sprintf("New size: %d; reason: CPU utilization above target", tc.desiredReplicas), obj.Message) - } - tc.eventCreated = true - return true, obj, nil - }) - - fakeWatch := watch.NewFake() - fakeClient.AddWatchReactor("*", core.DefaultWatchReactor(fakeWatch, nil)) - - return fakeClient -} - -func (tc *testCase) verifyResults(t *testing.T) { - tc.Lock() - defer tc.Unlock() - - assert.Equal(t, tc.initialReplicas != tc.desiredReplicas, tc.scaleUpdated) - assert.True(t, tc.statusUpdated) - if tc.verifyEvents { - assert.Equal(t, tc.initialReplicas != tc.desiredReplicas, tc.eventCreated) - } -} - -func (tc *testCase) runTest(t *testing.T) { - testClient := tc.prepareTestClient(t) - metricsClient := metrics.NewHeapsterMetricsClient(testClient, metrics.DefaultHeapsterNamespace, metrics.DefaultHeapsterScheme, metrics.DefaultHeapsterService, metrics.DefaultHeapsterPort) - - broadcaster := record.NewBroadcasterForTests(0) - broadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: testClient.Core().Events("")}) - recorder := broadcaster.NewRecorder(api.EventSource{Component: "horizontal-pod-autoscaler"}) - - hpaController := &HorizontalController{ - metricsClient: metricsClient, - eventRecorder: recorder, - scaleNamespacer: testClient.Extensions(), - hpaNamespacer: testClient.Extensions(), - } - - store, frameworkController := newInformer(hpaController, time.Minute) - hpaController.store = store - hpaController.controller = frameworkController - - stop := make(chan struct{}) - defer close(stop) - go hpaController.Run(stop) - - tc.Lock() - if tc.verifyEvents { - tc.Unlock() - // We need to wait for events to be broadcasted (sleep for longer than record.sleepDuration). - time.Sleep(2 * time.Second) - } else { - tc.Unlock() - } - // Wait for HPA to be processed. - <-tc.processed - tc.verifyResults(t) -} - -func TestDefaultScaleUpRC(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 4, - desiredReplicas: 5, - verifyCPUCurrent: true, - reportedLevels: []uint64{900, 950, 950, 1000}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestDefaultScaleUpDeployment(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 4, - desiredReplicas: 5, - verifyCPUCurrent: true, - reportedLevels: []uint64{900, 950, 950, 1000}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - resource: &fakeResource{ - name: "test-dep", - apiVersion: "extensions/v1beta1", - kind: "deployments", - }, - } - tc.runTest(t) -} - -func TestDefaultScaleUpReplicaSet(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 4, - desiredReplicas: 5, - verifyCPUCurrent: true, - reportedLevels: []uint64{900, 950, 950, 1000}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - resource: &fakeResource{ - name: "test-replicaset", - apiVersion: "extensions/v1beta1", - kind: "replicasets", - }, - } - tc.runTest(t) -} - -func TestScaleUp(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 3, - desiredReplicas: 5, - CPUTarget: 30, - verifyCPUCurrent: true, - reportedLevels: []uint64{300, 500, 700}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestScaleUpDeployment(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 3, - desiredReplicas: 5, - CPUTarget: 30, - verifyCPUCurrent: true, - reportedLevels: []uint64{300, 500, 700}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - resource: &fakeResource{ - name: "test-dep", - apiVersion: "extensions/v1beta1", - kind: "deployments", - }, - } - tc.runTest(t) -} - -func TestScaleUpReplicaSet(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 3, - desiredReplicas: 5, - CPUTarget: 30, - verifyCPUCurrent: true, - reportedLevels: []uint64{300, 500, 700}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - resource: &fakeResource{ - name: "test-replicaset", - apiVersion: "extensions/v1beta1", - kind: "replicasets", - }, - } - tc.runTest(t) -} - -func TestScaleUpCM(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 3, - desiredReplicas: 4, - CPUTarget: 0, - cmTarget: &extensions.CustomMetricTargetList{ - Items: []extensions.CustomMetricTarget{{ - Name: "qps", - TargetValue: resource.MustParse("15.0"), - }}, - }, - reportedLevels: []uint64{20, 10, 30}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestDefaultScaleDown(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 5, - desiredReplicas: 4, - verifyCPUCurrent: true, - reportedLevels: []uint64{400, 500, 600, 700, 800}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestScaleDown(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 5, - desiredReplicas: 3, - CPUTarget: 50, - verifyCPUCurrent: true, - reportedLevels: []uint64{100, 300, 500, 250, 250}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestScaleDownCM(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 5, - desiredReplicas: 3, - CPUTarget: 0, - cmTarget: &extensions.CustomMetricTargetList{ - Items: []extensions.CustomMetricTarget{{ - Name: "qps", - TargetValue: resource.MustParse("20"), - }}}, - reportedLevels: []uint64{12, 12, 12, 12, 12}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestTolerance(t *testing.T) { - tc := testCase{ - minReplicas: 1, - maxReplicas: 5, - initialReplicas: 3, - desiredReplicas: 3, - CPUTarget: 100, - reportedLevels: []uint64{1010, 1030, 1020}, - reportedCPURequests: []resource.Quantity{resource.MustParse("0.9"), resource.MustParse("1.0"), resource.MustParse("1.1")}, - } - tc.runTest(t) -} - -func TestToleranceCM(t *testing.T) { - tc := testCase{ - minReplicas: 1, - maxReplicas: 5, - initialReplicas: 3, - desiredReplicas: 3, - cmTarget: &extensions.CustomMetricTargetList{ - Items: []extensions.CustomMetricTarget{{ - Name: "qps", - TargetValue: resource.MustParse("20"), - }}}, - reportedLevels: []uint64{20, 21, 21}, - reportedCPURequests: []resource.Quantity{resource.MustParse("0.9"), resource.MustParse("1.0"), resource.MustParse("1.1")}, - } - tc.runTest(t) -} - -func TestMinReplicas(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 5, - initialReplicas: 3, - desiredReplicas: 2, - CPUTarget: 90, - reportedLevels: []uint64{10, 95, 10}, - reportedCPURequests: []resource.Quantity{resource.MustParse("0.9"), resource.MustParse("1.0"), resource.MustParse("1.1")}, - } - tc.runTest(t) -} - -func TestZeroReplicas(t *testing.T) { - tc := testCase{ - minReplicas: 3, - maxReplicas: 5, - initialReplicas: 0, - desiredReplicas: 3, - CPUTarget: 90, - reportedLevels: []uint64{}, - reportedCPURequests: []resource.Quantity{}, - } - tc.runTest(t) -} - -func TestTooFewReplicas(t *testing.T) { - tc := testCase{ - minReplicas: 3, - maxReplicas: 5, - initialReplicas: 2, - desiredReplicas: 3, - CPUTarget: 90, - reportedLevels: []uint64{}, - reportedCPURequests: []resource.Quantity{}, - } - tc.runTest(t) -} - -func TestTooManyReplicas(t *testing.T) { - tc := testCase{ - minReplicas: 3, - maxReplicas: 5, - initialReplicas: 10, - desiredReplicas: 5, - CPUTarget: 90, - reportedLevels: []uint64{}, - reportedCPURequests: []resource.Quantity{}, - } - tc.runTest(t) -} - -func TestMaxReplicas(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 5, - initialReplicas: 3, - desiredReplicas: 5, - CPUTarget: 90, - reportedLevels: []uint64{8000, 9500, 1000}, - reportedCPURequests: []resource.Quantity{resource.MustParse("0.9"), resource.MustParse("1.0"), resource.MustParse("1.1")}, - } - tc.runTest(t) -} - -func TestSuperfluousMetrics(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 4, - desiredReplicas: 4, - CPUTarget: 100, - reportedLevels: []uint64{4000, 9500, 3000, 7000, 3200, 2000}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestMissingMetrics(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 4, - desiredReplicas: 4, - CPUTarget: 100, - reportedLevels: []uint64{400, 95}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestEmptyMetrics(t *testing.T) { - tc := testCase{ - minReplicas: 2, - maxReplicas: 6, - initialReplicas: 4, - desiredReplicas: 4, - CPUTarget: 100, - reportedLevels: []uint64{}, - reportedCPURequests: []resource.Quantity{resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0"), resource.MustParse("1.0")}, - } - tc.runTest(t) -} - -func TestEmptyCPURequest(t *testing.T) { - tc := testCase{ - minReplicas: 1, - maxReplicas: 5, - initialReplicas: 1, - desiredReplicas: 1, - CPUTarget: 100, - reportedLevels: []uint64{200}, - } - tc.runTest(t) -} - -func TestEventCreated(t *testing.T) { - tc := testCase{ - minReplicas: 1, - maxReplicas: 5, - initialReplicas: 1, - desiredReplicas: 2, - CPUTarget: 50, - reportedLevels: []uint64{200}, - reportedCPURequests: []resource.Quantity{resource.MustParse("0.2")}, - verifyEvents: true, - } - tc.runTest(t) -} - -func TestEventNotCreated(t *testing.T) { - tc := testCase{ - minReplicas: 1, - maxReplicas: 5, - initialReplicas: 2, - desiredReplicas: 2, - CPUTarget: 50, - reportedLevels: []uint64{200, 200}, - reportedCPURequests: []resource.Quantity{resource.MustParse("0.4"), resource.MustParse("0.4")}, - verifyEvents: true, - } - tc.runTest(t) -} - -// TODO: add more tests diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/metrics_client_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/metrics_client_test.go deleted file mode 100644 index a67a35aba..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/podautoscaler/metrics/metrics_client_test.go +++ /dev/null @@ -1,455 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 metrics - -import ( - "encoding/json" - "fmt" - "io" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - _ "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - - heapster "k8s.io/heapster/metrics/api/v1/types" - - "github.com/stretchr/testify/assert" -) - -var fixedTimestamp = time.Date(2015, time.November, 10, 12, 30, 0, 0, time.UTC) - -func (w fakeResponseWrapper) DoRaw() ([]byte, error) { - return w.raw, nil -} - -func (w fakeResponseWrapper) Stream() (io.ReadCloser, error) { - return nil, nil -} - -func newFakeResponseWrapper(raw []byte) fakeResponseWrapper { - return fakeResponseWrapper{raw: raw} -} - -type fakeResponseWrapper struct { - raw []byte -} - -// timestamp is used for establishing order on metricPoints -type metricPoint struct { - level uint64 - timestamp int -} - -type testCase struct { - replicas int - desiredValue float64 - desiredError error - targetResource string - targetTimestamp int - reportedMetricsPoints [][]metricPoint - namespace string - podListOverride *api.PodList - selector labels.Selector -} - -func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { - namespace := "test-namespace" - tc.namespace = namespace - podNamePrefix := "test-pod" - podLabels := map[string]string{"name": podNamePrefix} - tc.selector = labels.SelectorFromSet(podLabels) - - fakeClient := &fake.Clientset{} - - fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { - if tc.podListOverride != nil { - return true, tc.podListOverride, nil - } - obj := &api.PodList{} - for i := 0; i < tc.replicas; i++ { - podName := fmt.Sprintf("%s-%d", podNamePrefix, i) - pod := buildPod(namespace, podName, podLabels, api.PodRunning) - obj.Items = append(obj.Items, pod) - } - return true, obj, nil - }) - - fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) { - metrics := heapster.MetricResultList{} - var latestTimestamp time.Time - for _, reportedMetricPoints := range tc.reportedMetricsPoints { - var heapsterMetricPoints []heapster.MetricPoint - for _, reportedMetricPoint := range reportedMetricPoints { - timestamp := fixedTimestamp.Add(time.Duration(reportedMetricPoint.timestamp) * time.Minute) - if latestTimestamp.Before(timestamp) { - latestTimestamp = timestamp - } - heapsterMetricPoint := heapster.MetricPoint{Timestamp: timestamp, Value: reportedMetricPoint.level, FloatValue: nil} - heapsterMetricPoints = append(heapsterMetricPoints, heapsterMetricPoint) - } - metric := heapster.MetricResult{ - Metrics: heapsterMetricPoints, - LatestTimestamp: latestTimestamp, - } - metrics.Items = append(metrics.Items, metric) - } - heapsterRawMemResponse, _ := json.Marshal(&metrics) - return true, newFakeResponseWrapper(heapsterRawMemResponse), nil - }) - - return fakeClient -} - -func buildPod(namespace, podName string, podLabels map[string]string, phase api.PodPhase) api.Pod { - return api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: podName, - Namespace: namespace, - Labels: podLabels, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceCPU: resource.MustParse("10"), - }, - }, - }, - }, - }, - Status: api.PodStatus{ - Phase: phase, - }, - } -} - -func (tc *testCase) verifyResults(t *testing.T, val *float64, timestamp time.Time, err error) { - assert.Equal(t, tc.desiredError, err) - if tc.desiredError != nil { - return - } - assert.NotNil(t, val) - assert.True(t, tc.desiredValue-0.001 < *val) - assert.True(t, tc.desiredValue+0.001 > *val) - - targetTimestamp := fixedTimestamp.Add(time.Duration(tc.targetTimestamp) * time.Minute) - assert.Equal(t, targetTimestamp, timestamp) -} - -func (tc *testCase) runTest(t *testing.T) { - testClient := tc.prepareTestClient(t) - metricsClient := NewHeapsterMetricsClient(testClient, DefaultHeapsterNamespace, DefaultHeapsterScheme, DefaultHeapsterService, DefaultHeapsterPort) - if tc.targetResource == "cpu-usage" { - val, _, timestamp, err := metricsClient.GetCpuConsumptionAndRequestInMillis(tc.namespace, tc.selector) - fval := float64(val) - tc.verifyResults(t, &fval, timestamp, err) - } else { - val, timestamp, err := metricsClient.GetCustomMetric(tc.targetResource, tc.namespace, tc.selector) - tc.verifyResults(t, val, timestamp, err) - } -} - -func TestCPU(t *testing.T) { - tc := testCase{ - replicas: 3, - desiredValue: 5000, - targetResource: "cpu-usage", - targetTimestamp: 1, - reportedMetricsPoints: [][]metricPoint{{{5000, 1}}, {{5000, 1}}, {{5000, 1}}}, - } - tc.runTest(t) -} - -func TestCPUPending(t *testing.T) { - tc := testCase{ - replicas: 4, - desiredValue: 5000, - targetResource: "cpu-usage", - targetTimestamp: 1, - reportedMetricsPoints: [][]metricPoint{{{5000, 1}}, {{5000, 1}}, {{5000, 1}}}, - podListOverride: &api.PodList{}, - } - - namespace := "test-namespace" - podNamePrefix := "test-pod" - podLabels := map[string]string{"name": podNamePrefix} - for i := 0; i < tc.replicas; i++ { - podName := fmt.Sprintf("%s-%d", podNamePrefix, i) - pod := buildPod(namespace, podName, podLabels, api.PodRunning) - tc.podListOverride.Items = append(tc.podListOverride.Items, pod) - } - tc.podListOverride.Items[0].Status.Phase = api.PodPending - - tc.runTest(t) -} - -func TestCPUAllPending(t *testing.T) { - tc := testCase{ - replicas: 4, - targetResource: "cpu-usage", - targetTimestamp: 1, - reportedMetricsPoints: [][]metricPoint{}, - podListOverride: &api.PodList{}, - desiredError: fmt.Errorf("no running pods"), - } - - namespace := "test-namespace" - podNamePrefix := "test-pod" - podLabels := map[string]string{"name": podNamePrefix} - for i := 0; i < tc.replicas; i++ { - podName := fmt.Sprintf("%s-%d", podNamePrefix, i) - pod := buildPod(namespace, podName, podLabels, api.PodPending) - tc.podListOverride.Items = append(tc.podListOverride.Items, pod) - } - tc.runTest(t) -} - -func TestQPS(t *testing.T) { - tc := testCase{ - replicas: 3, - desiredValue: 13.33333, - targetResource: "qps", - targetTimestamp: 1, - reportedMetricsPoints: [][]metricPoint{{{10, 1}}, {{20, 1}}, {{10, 1}}}, - } - tc.runTest(t) -} - -func TestQPSPending(t *testing.T) { - tc := testCase{ - replicas: 4, - desiredValue: 13.33333, - targetResource: "qps", - targetTimestamp: 1, - reportedMetricsPoints: [][]metricPoint{{{10, 1}}, {{20, 1}}, {{10, 1}}}, - podListOverride: &api.PodList{}, - } - - namespace := "test-namespace" - podNamePrefix := "test-pod" - podLabels := map[string]string{"name": podNamePrefix} - for i := 0; i < tc.replicas; i++ { - podName := fmt.Sprintf("%s-%d", podNamePrefix, i) - pod := buildPod(namespace, podName, podLabels, api.PodRunning) - tc.podListOverride.Items = append(tc.podListOverride.Items, pod) - } - tc.podListOverride.Items[0].Status.Phase = api.PodPending - tc.runTest(t) -} - -func TestQPSAllPending(t *testing.T) { - tc := testCase{ - replicas: 4, - desiredError: fmt.Errorf("no running pods"), - targetResource: "qps", - targetTimestamp: 1, - reportedMetricsPoints: [][]metricPoint{}, - podListOverride: &api.PodList{}, - } - - namespace := "test-namespace" - podNamePrefix := "test-pod" - podLabels := map[string]string{"name": podNamePrefix} - for i := 0; i < tc.replicas; i++ { - podName := fmt.Sprintf("%s-%d", podNamePrefix, i) - pod := buildPod(namespace, podName, podLabels, api.PodPending) - tc.podListOverride.Items = append(tc.podListOverride.Items, pod) - } - tc.podListOverride.Items[0].Status.Phase = api.PodPending - tc.runTest(t) -} - -func TestCPUSumEqualZero(t *testing.T) { - tc := testCase{ - replicas: 3, - desiredValue: 0, - targetResource: "cpu-usage", - targetTimestamp: 0, - reportedMetricsPoints: [][]metricPoint{{{0, 0}}, {{0, 0}}, {{0, 0}}}, - } - tc.runTest(t) -} - -func TestQpsSumEqualZero(t *testing.T) { - tc := testCase{ - replicas: 3, - desiredValue: 0, - targetResource: "qps", - targetTimestamp: 0, - reportedMetricsPoints: [][]metricPoint{{{0, 0}}, {{0, 0}}, {{0, 0}}}, - } - tc.runTest(t) -} - -func TestCPUMoreMetrics(t *testing.T) { - tc := testCase{ - replicas: 5, - desiredValue: 5000, - targetResource: "cpu-usage", - targetTimestamp: 10, - reportedMetricsPoints: [][]metricPoint{ - {{0, 3}, {0, 6}, {5, 4}, {9000, 10}}, - {{5000, 2}, {10, 5}, {66, 1}, {0, 10}}, - {{5000, 3}, {80, 5}, {6000, 10}}, - {{5000, 3}, {40, 3}, {0, 9}, {200, 2}, {8000, 10}}, - {{5000, 2}, {20, 2}, {2000, 10}}}, - } - tc.runTest(t) -} - -func TestCPUResultIsFloat(t *testing.T) { - tc := testCase{ - replicas: 6, - desiredValue: 4783, - targetResource: "cpu-usage", - targetTimestamp: 4, - reportedMetricsPoints: [][]metricPoint{{{4000, 4}}, {{9500, 4}}, {{3000, 4}}, {{7000, 4}}, {{3200, 4}}, {{2000, 4}}}, - } - tc.runTest(t) -} - -func TestCPUSamplesWithRandomTimestamps(t *testing.T) { - tc := testCase{ - replicas: 3, - desiredValue: 3000, - targetResource: "cpu-usage", - targetTimestamp: 3, - reportedMetricsPoints: [][]metricPoint{ - {{1, 1}, {3000, 5}, {2, 2}}, - {{2, 2}, {1, 1}, {3000, 3}}, - {{3000, 4}, {1, 1}, {2, 2}}}, - } - tc.runTest(t) -} - -func TestCPUMissingMetrics(t *testing.T) { - tc := testCase{ - replicas: 3, - targetResource: "cpu-usage", - desiredError: fmt.Errorf("metrics obtained for 1/3 of pods"), - reportedMetricsPoints: [][]metricPoint{{{4000, 4}}}, - } - tc.runTest(t) -} - -func TestQpsMissingMetrics(t *testing.T) { - tc := testCase{ - replicas: 3, - targetResource: "qps", - desiredError: fmt.Errorf("metrics obtained for 1/3 of pods"), - reportedMetricsPoints: [][]metricPoint{{{4000, 4}}}, - } - tc.runTest(t) -} - -func TestCPUSuperfluousMetrics(t *testing.T) { - tc := testCase{ - replicas: 3, - targetResource: "cpu-usage", - desiredError: fmt.Errorf("metrics obtained for 6/3 of pods"), - reportedMetricsPoints: [][]metricPoint{{{1000, 1}}, {{2000, 4}}, {{2000, 1}}, {{4000, 5}}, {{2000, 1}}, {{4000, 4}}}, - } - tc.runTest(t) -} - -func TestQpsSuperfluousMetrics(t *testing.T) { - tc := testCase{ - replicas: 3, - targetResource: "qps", - desiredError: fmt.Errorf("metrics obtained for 6/3 of pods"), - reportedMetricsPoints: [][]metricPoint{{{1000, 1}}, {{2000, 4}}, {{2000, 1}}, {{4000, 5}}, {{2000, 1}}, {{4000, 4}}}, - } - tc.runTest(t) -} - -func TestCPUEmptyMetrics(t *testing.T) { - tc := testCase{ - replicas: 3, - targetResource: "cpu-usage", - desiredError: fmt.Errorf("metrics obtained for 0/3 of pods"), - reportedMetricsPoints: [][]metricPoint{}, - } - tc.runTest(t) -} - -func TestCPUZeroReplicas(t *testing.T) { - tc := testCase{ - replicas: 0, - targetResource: "cpu-usage", - desiredError: fmt.Errorf("some pods do not have request for cpu"), - reportedMetricsPoints: [][]metricPoint{}, - } - tc.runTest(t) -} - -func TestCPUEmptyMetricsForOnePod(t *testing.T) { - tc := testCase{ - replicas: 3, - targetResource: "cpu-usage", - desiredError: fmt.Errorf("metrics obtained for 2/3 of pods"), - reportedMetricsPoints: [][]metricPoint{{}, {{100, 1}}, {{400, 2}, {300, 3}}}, - } - tc.runTest(t) -} - -func TestAggregateSum(t *testing.T) { - //calculateSumFromTimeSample(metrics heapster.MetricResultList, duration time.Duration) (sum intAndFloat, count int, timestamp time.Time) { - now := time.Now() - result := heapster.MetricResultList{ - Items: []heapster.MetricResult{ - { - Metrics: []heapster.MetricPoint{ - {now, 50, nil}, - {now.Add(-15 * time.Second), 100, nil}, - {now.Add(-60 * time.Second), 100000, nil}}, - LatestTimestamp: now, - }, - }, - } - sum, cnt, _ := calculateSumFromTimeSample(result, time.Minute) - assert.Equal(t, int64(75), sum.intValue) - assert.InEpsilon(t, 75.0, sum.floatValue, 0.1) - assert.Equal(t, 1, cnt) -} - -func TestAggregateSumSingle(t *testing.T) { - now := time.Now() - result := heapster.MetricResultList{ - Items: []heapster.MetricResult{ - { - Metrics: []heapster.MetricPoint{ - {now, 50, nil}, - {now.Add(-65 * time.Second), 100000, nil}}, - LatestTimestamp: now, - }, - }, - } - sum, cnt, _ := calculateSumFromTimeSample(result, time.Minute) - assert.Equal(t, int64(50), sum.intValue) - assert.InEpsilon(t, 50.0, sum.floatValue, 0.1) - assert.Equal(t, 1, cnt) -} - -// TODO: add proper tests for request diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/doc.go deleted file mode 100644 index 9d42796d9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 replicaset contains logic for watching and synchronizing -// ReplicaSets. -package replicaset diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/options/options.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/options/options.go deleted file mode 100644 index 91951a549..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/options/options.go +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 options - -import ( - "github.com/spf13/pflag" -) - -type ReplicasetControllerOptions struct { - ConcurrentRSSyncs int -} - -func NewReplicasetControllerOptions() ReplicasetControllerOptions { - return ReplicasetControllerOptions{ - ConcurrentRSSyncs: 5, - } -} - -func (o *ReplicasetControllerOptions) AddFlags(fs *pflag.FlagSet) { - fs.IntVar(&o.ConcurrentRSSyncs, "concurrent-replicaset-syncs", o.ConcurrentRSSyncs, "The number of replicasets that are allowed to sync concurrently. Larger number = more reponsive replica management, but more CPU (and network) load") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go deleted file mode 100644 index e26ce810c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go +++ /dev/null @@ -1,577 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// If you make changes to this file, you should also make the corresponding change in ReplicationController. - -package replicaset - -import ( - "fmt" - "reflect" - "sort" - "sync" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" -) - -const ( - // We'll attempt to recompute the required replicas of all ReplicaSets - // that have fulfilled their expectations at least this often. This recomputation - // happens based on contents in local pod storage. - FullControllerResyncPeriod = 30 * time.Second - - // Realistic value of the burstReplica field for the replica set manager based off - // performance requirements for kubernetes 1.0. - BurstReplicas = 500 - - // We must avoid counting pods until the pod store has synced. If it hasn't synced, to - // avoid a hot loop, we'll wait this long between checks. - PodStoreSyncedPollPeriod = 100 * time.Millisecond - - // The number of times we retry updating a ReplicaSet's status. - statusUpdateRetries = 1 -) - -// ReplicaSetController is responsible for synchronizing ReplicaSet objects stored -// in the system with actual running pods. -type ReplicaSetController struct { - kubeClient clientset.Interface - podControl controller.PodControlInterface - - // A ReplicaSet is temporarily suspended after creating/deleting these many replicas. - // It resumes normal action after observing the watch events for them. - burstReplicas int - // To allow injection of syncReplicaSet for testing. - syncHandler func(rsKey string) error - - // A TTLCache of pod creates/deletes each rc expects to see. - expectations *controller.UIDTrackingControllerExpectations - - // A store of ReplicaSets, populated by the rsController - rsStore cache.StoreToReplicaSetLister - // Watches changes to all ReplicaSets - rsController *framework.Controller - // A store of pods, populated by the podController - podStore cache.StoreToPodLister - // Watches changes to all pods - podController *framework.Controller - // podStoreSynced returns true if the pod store has been synced at least once. - // Added as a member to the struct to allow injection for testing. - podStoreSynced func() bool - - lookupCache *controller.MatchingCache - - // Controllers that need to be synced - queue *workqueue.Type -} - -// NewReplicaSetController creates a new ReplicaSetController. -func NewReplicaSetController(kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, burstReplicas int, lookupCacheSize int) *ReplicaSetController { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) - - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("replicaset_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - - rsc := &ReplicaSetController{ - kubeClient: kubeClient, - podControl: controller.RealPodControl{ - KubeClient: kubeClient, - Recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "replicaset-controller"}), - }, - burstReplicas: burstReplicas, - expectations: controller.NewUIDTrackingControllerExpectations(controller.NewControllerExpectations()), - queue: workqueue.New(), - } - - rsc.rsStore.Store, rsc.rsController = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return rsc.kubeClient.Extensions().ReplicaSets(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return rsc.kubeClient.Extensions().ReplicaSets(api.NamespaceAll).Watch(options) - }, - }, - &extensions.ReplicaSet{}, - // TODO: Can we have much longer period here? - FullControllerResyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: rsc.enqueueReplicaSet, - UpdateFunc: func(old, cur interface{}) { - oldRS := old.(*extensions.ReplicaSet) - curRS := cur.(*extensions.ReplicaSet) - - // We should invalidate the whole lookup cache if a RS's selector has been updated. - // - // Imagine that you have two RSs: - // * old RS1 - // * new RS2 - // You also have a pod that is attached to RS2 (because it doesn't match RS1 selector). - // Now imagine that you are changing RS1 selector so that it is now matching that pod, - // in such case we must invalidate the whole cache so that pod could be adopted by RS1 - // - // This makes the lookup cache less helpful, but selector update does not happen often, - // so it's not a big problem - if !reflect.DeepEqual(oldRS.Spec.Selector, curRS.Spec.Selector) { - rsc.lookupCache.InvalidateAll() - } - - // You might imagine that we only really need to enqueue the - // replica set when Spec changes, but it is safer to sync any - // time this function is triggered. That way a full informer - // resync can requeue any replica set that don't yet have pods - // but whose last attempts at creating a pod have failed (since - // we don't block on creation of pods) instead of those - // replica sets stalling indefinitely. Enqueueing every time - // does result in some spurious syncs (like when Status.Replica - // is updated and the watch notification from it retriggers - // this function), but in general extra resyncs shouldn't be - // that bad as ReplicaSets that haven't met expectations yet won't - // sync, and all the listing is done using local stores. - if oldRS.Status.Replicas != curRS.Status.Replicas { - glog.V(4).Infof("Observed updated replica count for ReplicaSet: %v, %d->%d", curRS.Name, oldRS.Status.Replicas, curRS.Status.Replicas) - } - rsc.enqueueReplicaSet(cur) - }, - // This will enter the sync loop and no-op, because the replica set has been deleted from the store. - // Note that deleting a replica set immediately after scaling it to 0 will not work. The recommended - // way of achieving this is by performing a `stop` operation on the replica set. - DeleteFunc: rsc.enqueueReplicaSet, - }, - ) - - rsc.podStore.Indexer, rsc.podController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return rsc.kubeClient.Core().Pods(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return rsc.kubeClient.Core().Pods(api.NamespaceAll).Watch(options) - }, - }, - &api.Pod{}, - resyncPeriod(), - framework.ResourceEventHandlerFuncs{ - AddFunc: rsc.addPod, - // This invokes the ReplicaSet for every pod change, eg: host assignment. Though this might seem like - // overkill the most frequent pod update is status, and the associated ReplicaSet will only list from - // local storage, so it should be ok. - UpdateFunc: rsc.updatePod, - DeleteFunc: rsc.deletePod, - }, - cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, - ) - - rsc.syncHandler = rsc.syncReplicaSet - rsc.podStoreSynced = rsc.podController.HasSynced - rsc.lookupCache = controller.NewMatchingCache(lookupCacheSize) - return rsc -} - -// SetEventRecorder replaces the event recorder used by the ReplicaSetController -// with the given recorder. Only used for testing. -func (rsc *ReplicaSetController) SetEventRecorder(recorder record.EventRecorder) { - // TODO: Hack. We can't cleanly shutdown the event recorder, so benchmarks - // need to pass in a fake. - rsc.podControl = controller.RealPodControl{KubeClient: rsc.kubeClient, Recorder: recorder} -} - -// Run begins watching and syncing. -func (rsc *ReplicaSetController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - go rsc.rsController.Run(stopCh) - go rsc.podController.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(rsc.worker, time.Second, stopCh) - } - <-stopCh - glog.Infof("Shutting down ReplicaSet Controller") - rsc.queue.ShutDown() -} - -// getPodReplicaSet returns the replica set managing the given pod. -// TODO: Surface that we are ignoring multiple replica sets for a single pod. -func (rsc *ReplicaSetController) getPodReplicaSet(pod *api.Pod) *extensions.ReplicaSet { - // look up in the cache, if cached and the cache is valid, just return cached value - if obj, cached := rsc.lookupCache.GetMatchingObject(pod); cached { - rs, ok := obj.(*extensions.ReplicaSet) - if !ok { - // This should not happen - glog.Errorf("lookup cache does not retuen a ReplicaSet object") - return nil - } - if cached && rsc.isCacheValid(pod, rs) { - return rs - } - } - - // if not cached or cached value is invalid, search all the rs to find the matching one, and update cache - rss, err := rsc.rsStore.GetPodReplicaSets(pod) - if err != nil { - glog.V(4).Infof("No ReplicaSets found for pod %v, ReplicaSet controller will avoid syncing", pod.Name) - return nil - } - // In theory, overlapping ReplicaSets is user error. This sorting will not prevent - // oscillation of replicas in all cases, eg: - // rs1 (older rs): [(k1=v1)], replicas=1 rs2: [(k2=v2)], replicas=2 - // pod: [(k1:v1), (k2:v2)] will wake both rs1 and rs2, and we will sync rs1. - // pod: [(k2:v2)] will wake rs2 which creates a new replica. - if len(rss) > 1 { - // More than two items in this list indicates user error. If two replicasets - // overlap, sort by creation timestamp, subsort by name, then pick - // the first. - glog.Errorf("user error! more than one ReplicaSet is selecting pods with labels: %+v", pod.Labels) - sort.Sort(overlappingReplicaSets(rss)) - } - - // update lookup cache - rsc.lookupCache.Update(pod, &rss[0]) - - return &rss[0] -} - -// isCacheValid check if the cache is valid -func (rsc *ReplicaSetController) isCacheValid(pod *api.Pod, cachedRS *extensions.ReplicaSet) bool { - _, exists, err := rsc.rsStore.Get(cachedRS) - // rs has been deleted or updated, cache is invalid - if err != nil || !exists || !isReplicaSetMatch(pod, cachedRS) { - return false - } - return true -} - -// isReplicaSetMatch take a Pod and ReplicaSet, return whether the Pod and ReplicaSet are matching -// TODO(mqliang): This logic is a copy from GetPodReplicaSets(), remove the duplication -func isReplicaSetMatch(pod *api.Pod, rs *extensions.ReplicaSet) bool { - if rs.Namespace != pod.Namespace { - return false - } - selector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector) - if err != nil { - err = fmt.Errorf("invalid selector: %v", err) - return false - } - - // If a ReplicaSet with a nil or empty selector creeps in, it should match nothing, not everything. - if selector.Empty() || !selector.Matches(labels.Set(pod.Labels)) { - return false - } - return true -} - -// When a pod is created, enqueue the replica set that manages it and update it's expectations. -func (rsc *ReplicaSetController) addPod(obj interface{}) { - pod := obj.(*api.Pod) - glog.V(4).Infof("Pod %s created: %+v.", pod.Name, pod) - - rs := rsc.getPodReplicaSet(pod) - if rs == nil { - return - } - rsKey, err := controller.KeyFunc(rs) - if err != nil { - glog.Errorf("Couldn't get key for replica set %#v: %v", rs, err) - return - } - if pod.DeletionTimestamp != nil { - // on a restart of the controller manager, it's possible a new pod shows up in a state that - // is already pending deletion. Prevent the pod from being a creation observation. - rsc.deletePod(pod) - return - } - rsc.expectations.CreationObserved(rsKey) - rsc.enqueueReplicaSet(rs) -} - -// When a pod is updated, figure out what replica set/s manage it and wake them -// up. If the labels of the pod have changed we need to awaken both the old -// and new replica set. old and cur must be *api.Pod types. -func (rsc *ReplicaSetController) updatePod(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - // A periodic relist will send update events for all known pods. - return - } - curPod := cur.(*api.Pod) - oldPod := old.(*api.Pod) - glog.V(4).Infof("Pod %s updated %+v -> %+v.", curPod.Name, oldPod, curPod) - rs := rsc.getPodReplicaSet(curPod) - if rs == nil { - return - } - - if curPod.DeletionTimestamp != nil { - // when a pod is deleted gracefully it's deletion timestamp is first modified to reflect a grace period, - // and after such time has passed, the kubelet actually deletes it from the store. We receive an update - // for modification of the deletion timestamp and expect an rs to create more replicas asap, not wait - // until the kubelet actually deletes the pod. This is different from the Phase of a pod changing, because - // an rs never initiates a phase change, and so is never asleep waiting for the same. - rsc.deletePod(curPod) - return - } - - rsc.enqueueReplicaSet(rs) - if !reflect.DeepEqual(curPod.Labels, oldPod.Labels) { - // If the old and new ReplicaSet are the same, the first one that syncs - // will set expectations preventing any damage from the second. - if oldRS := rsc.getPodReplicaSet(oldPod); oldRS != nil { - rsc.enqueueReplicaSet(oldRS) - } - } -} - -// When a pod is deleted, enqueue the replica set that manages the pod and update its expectations. -// obj could be an *api.Pod, or a DeletionFinalStateUnknown marker item. -func (rsc *ReplicaSetController) deletePod(obj interface{}) { - pod, ok := obj.(*api.Pod) - - // When a delete is dropped, the relist will notice a pod in the store not - // in the list, leading to the insertion of a tombstone object which contains - // the deleted key/value. Note that this value might be stale. If the pod - // changed labels the new ReplicaSet will not be woken up till the periodic resync. - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("Couldn't get object from tombstone %+v", obj) - return - } - pod, ok = tombstone.Obj.(*api.Pod) - if !ok { - glog.Errorf("Tombstone contained object that is not a pod %+v", obj) - return - } - } - glog.V(4).Infof("Pod %s/%s deleted through %v, timestamp %+v: %+v.", pod.Namespace, pod.Name, utilruntime.GetCaller(), pod.DeletionTimestamp, pod) - if rs := rsc.getPodReplicaSet(pod); rs != nil { - rsKey, err := controller.KeyFunc(rs) - if err != nil { - glog.Errorf("Couldn't get key for ReplicaSet %#v: %v", rs, err) - return - } - rsc.expectations.DeletionObserved(rsKey, controller.PodKey(pod)) - rsc.enqueueReplicaSet(rs) - } -} - -// obj could be an *extensions.ReplicaSet, or a DeletionFinalStateUnknown marker item. -func (rsc *ReplicaSetController) enqueueReplicaSet(obj interface{}) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - return - } - - // TODO: Handle overlapping replica sets better. Either disallow them at admission time or - // deterministically avoid syncing replica sets that fight over pods. Currently, we only - // ensure that the same replica set is synced for a given pod. When we periodically relist - // all replica sets there will still be some replica instability. One way to handle this is - // by querying the store for all replica sets that this replica set overlaps, as well as all - // replica sets that overlap this ReplicaSet, and sorting them. - rsc.queue.Add(key) -} - -// worker runs a worker thread that just dequeues items, processes them, and marks them done. -// It enforces that the syncHandler is never invoked concurrently with the same key. -func (rsc *ReplicaSetController) worker() { - for { - func() { - key, quit := rsc.queue.Get() - if quit { - return - } - defer rsc.queue.Done(key) - err := rsc.syncHandler(key.(string)) - if err != nil { - glog.Errorf("Error syncing ReplicaSet: %v", err) - } - }() - } -} - -// manageReplicas checks and updates replicas for the given ReplicaSet. -func (rsc *ReplicaSetController) manageReplicas(filteredPods []*api.Pod, rs *extensions.ReplicaSet) { - diff := len(filteredPods) - int(rs.Spec.Replicas) - rsKey, err := controller.KeyFunc(rs) - if err != nil { - glog.Errorf("Couldn't get key for ReplicaSet %#v: %v", rs, err) - return - } - if diff < 0 { - diff *= -1 - if diff > rsc.burstReplicas { - diff = rsc.burstReplicas - } - // TODO: Track UIDs of creates just like deletes. The problem currently - // is we'd need to wait on the result of a create to record the pod's - // UID, which would require locking *across* the create, which will turn - // into a performance bottleneck. We should generate a UID for the pod - // beforehand and store it via ExpectCreations. - rsc.expectations.ExpectCreations(rsKey, diff) - wait := sync.WaitGroup{} - wait.Add(diff) - glog.V(2).Infof("Too few %q/%q replicas, need %d, creating %d", rs.Namespace, rs.Name, rs.Spec.Replicas, diff) - for i := 0; i < diff; i++ { - go func() { - defer wait.Done() - if err := rsc.podControl.CreatePods(rs.Namespace, &rs.Spec.Template, rs); err != nil { - // Decrement the expected number of creates because the informer won't observe this pod - glog.V(2).Infof("Failed creation, decrementing expectations for replica set %q/%q", rs.Namespace, rs.Name) - rsc.expectations.CreationObserved(rsKey) - utilruntime.HandleError(err) - } - }() - } - wait.Wait() - } else if diff > 0 { - if diff > rsc.burstReplicas { - diff = rsc.burstReplicas - } - glog.V(2).Infof("Too many %q/%q replicas, need %d, deleting %d", rs.Namespace, rs.Name, rs.Spec.Replicas, diff) - // No need to sort pods if we are about to delete all of them - if rs.Spec.Replicas != 0 { - // Sort the pods in the order such that not-ready < ready, unscheduled - // < scheduled, and pending < running. This ensures that we delete pods - // in the earlier stages whenever possible. - sort.Sort(controller.ActivePods(filteredPods)) - } - // Snapshot the UIDs (ns/name) of the pods we're expecting to see - // deleted, so we know to record their expectations exactly once either - // when we see it as an update of the deletion timestamp, or as a delete. - // Note that if the labels on a pod/rs change in a way that the pod gets - // orphaned, the rs will only wake up after the expectations have - // expired even if other pods are deleted. - deletedPodKeys := []string{} - for i := 0; i < diff; i++ { - deletedPodKeys = append(deletedPodKeys, controller.PodKey(filteredPods[i])) - } - rsc.expectations.ExpectDeletions(rsKey, deletedPodKeys) - wait := sync.WaitGroup{} - wait.Add(diff) - for i := 0; i < diff; i++ { - go func(ix int) { - defer wait.Done() - if err := rsc.podControl.DeletePod(rs.Namespace, filteredPods[ix].Name, rs); err != nil { - // Decrement the expected number of deletes because the informer won't observe this deletion - podKey := controller.PodKey(filteredPods[ix]) - glog.V(2).Infof("Failed to delete %v, decrementing expectations for controller %q/%q", podKey, rs.Namespace, rs.Name) - rsc.expectations.DeletionObserved(rsKey, podKey) - utilruntime.HandleError(err) - } - }(i) - } - wait.Wait() - } -} - -// syncReplicaSet will sync the ReplicaSet with the given key if it has had its expectations fulfilled, -// meaning it did not expect to see any more of its pods created or deleted. This function is not meant to be -// invoked concurrently with the same key. -func (rsc *ReplicaSetController) syncReplicaSet(key string) error { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing replica set %q (%v)", key, time.Now().Sub(startTime)) - }() - - if !rsc.podStoreSynced() { - // Sleep so we give the pod reflector goroutine a chance to run. - time.Sleep(PodStoreSyncedPollPeriod) - glog.Infof("Waiting for pods controller to sync, requeuing ReplicaSet %v", key) - rsc.queue.Add(key) - return nil - } - - obj, exists, err := rsc.rsStore.Store.GetByKey(key) - if !exists { - glog.Infof("ReplicaSet has been deleted %v", key) - rsc.expectations.DeleteExpectations(key) - return nil - } - if err != nil { - glog.Infof("Unable to retrieve ReplicaSet %v from store: %v", key, err) - rsc.queue.Add(key) - return err - } - rs := *obj.(*extensions.ReplicaSet) - - // Check the expectations of the ReplicaSet before counting active pods, otherwise a new pod can sneak - // in and update the expectations after we've retrieved active pods from the store. If a new pod enters - // the store after we've checked the expectation, the ReplicaSet sync is just deferred till the next - // relist. - rsKey, err := controller.KeyFunc(&rs) - if err != nil { - glog.Errorf("Couldn't get key for ReplicaSet %#v: %v", rs, err) - return err - } - rsNeedsSync := rsc.expectations.SatisfiedExpectations(rsKey) - selector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector) - if err != nil { - glog.Errorf("Error converting pod selector to selector: %v", err) - return err - } - podList, err := rsc.podStore.Pods(rs.Namespace).List(selector) - if err != nil { - glog.Errorf("Error getting pods for ReplicaSet %q: %v", key, err) - rsc.queue.Add(key) - return err - } - - // TODO: Do this in a single pass, or use an index. - filteredPods := controller.FilterActivePods(podList.Items) - if rsNeedsSync { - rsc.manageReplicas(filteredPods, &rs) - } - - // Count the number of pods that have labels matching the labels of the pod - // template of the replicaSet, the matching pods may have more labels than - // are in the template. Because the label of podTemplateSpec is a superset - // of the selector of the replicaset, so the possible matching pods must be - // part of the filteredPods. - fullyLabeledReplicasCount := 0 - templateLabel := labels.Set(rs.Spec.Template.Labels).AsSelector() - for _, pod := range filteredPods { - if templateLabel.Matches(labels.Set(pod.Labels)) { - fullyLabeledReplicasCount++ - } - } - - // Always updates status as pods come up or die. - if err := updateReplicaCount(rsc.kubeClient.Extensions().ReplicaSets(rs.Namespace), rs, len(filteredPods), fullyLabeledReplicasCount); err != nil { - // Multiple things could lead to this update failing. Requeuing the replica set ensures - // we retry with some fairness. - glog.V(2).Infof("Failed to update replica count for controller %v/%v; requeuing; error: %v", rs.Namespace, rs.Name, err) - rsc.enqueueReplicaSet(&rs) - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go deleted file mode 100644 index d8324ebb0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_test.go +++ /dev/null @@ -1,1036 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// If you make changes to this file, you should also make the corresponding change in ReplicationController. - -package replicaset - -import ( - "fmt" - "math/rand" - "net/http/httptest" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/securitycontext" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/sets" - utiltesting "k8s.io/kubernetes/pkg/util/testing" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" -) - -var alwaysReady = func() bool { return true } - -func getKey(rs *extensions.ReplicaSet, t *testing.T) string { - if key, err := controller.KeyFunc(rs); err != nil { - t.Errorf("Unexpected error getting key for ReplicaSet %v: %v", rs.Name, err) - return "" - } else { - return key - } -} - -func newReplicaSet(replicas int, selectorMap map[string]string) *extensions.ReplicaSet { - rs := &extensions.ReplicaSet{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Default.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - UID: util.NewUUID(), - Name: "foobar", - Namespace: api.NamespaceDefault, - ResourceVersion: "18", - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: int32(replicas), - Selector: &unversioned.LabelSelector{MatchLabels: selectorMap}, - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "name": "foo", - "type": "production", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo/bar", - TerminationMessagePath: api.TerminationMessagePathDefault, - ImagePullPolicy: api.PullIfNotPresent, - SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), - }, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSDefault, - NodeSelector: map[string]string{ - "baz": "blah", - }, - }, - }, - }, - } - return rs -} - -// create count pods with the given phase for the given ReplicaSet (same selectors and namespace), and add them to the store. -func newPodList(store cache.Store, count int, status api.PodPhase, labelMap map[string]string, rs *extensions.ReplicaSet, name string) *api.PodList { - pods := []api.Pod{} - for i := 0; i < count; i++ { - newPod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s%d", name, i), - Labels: labelMap, - Namespace: rs.Namespace, - }, - Status: api.PodStatus{Phase: status}, - } - if store != nil { - store.Add(&newPod) - } - pods = append(pods, newPod) - } - return &api.PodList{ - Items: pods, - } -} - -func validateSyncReplicaSet(t *testing.T, fakePodControl *controller.FakePodControl, expectedCreates, expectedDeletes int) { - if len(fakePodControl.Templates) != expectedCreates { - t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", expectedCreates, len(fakePodControl.Templates)) - } - if len(fakePodControl.DeletePodName) != expectedDeletes { - t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", expectedDeletes, len(fakePodControl.DeletePodName)) - } -} - -func replicaSetResourceName() string { - return "replicasets" -} - -type serverResponse struct { - statusCode int - obj interface{} -} - -func TestSyncReplicaSetDoesNothing(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // 2 running pods, a controller with 2 replicas, sync is a no-op - labelMap := map[string]string{"foo": "bar"} - rsSpec := newReplicaSet(2, labelMap) - manager.rsStore.Store.Add(rsSpec) - newPodList(manager.podStore.Indexer, 2, api.PodRunning, labelMap, rsSpec, "pod") - - manager.podControl = &fakePodControl - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 0, 0) -} - -func TestSyncReplicaSetDeletes(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - // 2 running pods and a controller with 1 replica, one pod delete expected - labelMap := map[string]string{"foo": "bar"} - rsSpec := newReplicaSet(1, labelMap) - manager.rsStore.Store.Add(rsSpec) - newPodList(manager.podStore.Indexer, 2, api.PodRunning, labelMap, rsSpec, "pod") - - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 0, 1) -} - -func TestDeleteFinalStateUnknown(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - received := make(chan string) - manager.syncHandler = func(key string) error { - received <- key - return nil - } - - // The DeletedFinalStateUnknown object should cause the ReplicaSet manager to insert - // the controller matching the selectors of the deleted pod into the work queue. - labelMap := map[string]string{"foo": "bar"} - rsSpec := newReplicaSet(1, labelMap) - manager.rsStore.Store.Add(rsSpec) - pods := newPodList(nil, 1, api.PodRunning, labelMap, rsSpec, "pod") - manager.deletePod(cache.DeletedFinalStateUnknown{Key: "foo", Obj: &pods.Items[0]}) - - go manager.worker() - - expected := getKey(rsSpec, t) - select { - case key := <-received: - if key != expected { - t.Errorf("Unexpected sync all for ReplicaSet %v, expected %v", key, expected) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Processing DeleteFinalStateUnknown took longer than expected") - } -} - -func TestSyncReplicaSetCreates(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // A controller with 2 replicas and no pods in the store, 2 creates expected - labelMap := map[string]string{"foo": "bar"} - rs := newReplicaSet(2, labelMap) - manager.rsStore.Store.Add(rs) - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.syncReplicaSet(getKey(rs, t)) - validateSyncReplicaSet(t, &fakePodControl, 2, 0) -} - -func TestStatusUpdatesWithoutReplicasChange(t *testing.T) { - // Setup a fake server to listen for requests, and run the ReplicaSet controller in steady state - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: "{}", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // Steady state for the ReplicaSet, no Status.Replicas updates expected - activePods := 5 - labelMap := map[string]string{"foo": "bar"} - rs := newReplicaSet(activePods, labelMap) - manager.rsStore.Store.Add(rs) - rs.Status = extensions.ReplicaSetStatus{Replicas: int32(activePods)} - newPodList(manager.podStore.Indexer, activePods, api.PodRunning, labelMap, rs, "pod") - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.syncReplicaSet(getKey(rs, t)) - - validateSyncReplicaSet(t, &fakePodControl, 0, 0) - if fakeHandler.RequestReceived != nil { - t.Errorf("Unexpected update when pods and ReplicaSets are in a steady state") - } - - // This response body is just so we don't err out decoding the http response, all - // we care about is the request body sent below. - response := runtime.EncodeOrDie(testapi.Extensions.Codec(), &extensions.ReplicaSet{}) - fakeHandler.ResponseBody = response - - rs.Generation = rs.Generation + 1 - manager.syncReplicaSet(getKey(rs, t)) - - rs.Status.ObservedGeneration = rs.Generation - updatedRc := runtime.EncodeOrDie(testapi.Extensions.Codec(), rs) - fakeHandler.ValidateRequest(t, testapi.Extensions.ResourcePath(replicaSetResourceName(), rs.Namespace, rs.Name)+"/status", "PUT", &updatedRc) -} - -func TestControllerUpdateReplicas(t *testing.T) { - // This is a happy server just to record the PUT request we expect for status.Replicas - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: "{}", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // Insufficient number of pods in the system, and Status.Replicas is wrong; - // Status.Replica should update to match number of pods in system, 1 new pod should be created. - labelMap := map[string]string{"foo": "bar"} - extraLabelMap := map[string]string{"foo": "bar", "extraKey": "extraValue"} - rs := newReplicaSet(5, labelMap) - rs.Spec.Template.Labels = extraLabelMap - manager.rsStore.Store.Add(rs) - rs.Status = extensions.ReplicaSetStatus{Replicas: 2, FullyLabeledReplicas: 6, ObservedGeneration: 0} - rs.Generation = 1 - newPodList(manager.podStore.Indexer, 2, api.PodRunning, labelMap, rs, "pod") - newPodList(manager.podStore.Indexer, 2, api.PodRunning, extraLabelMap, rs, "podWithExtraLabel") - - // This response body is just so we don't err out decoding the http response - response := runtime.EncodeOrDie(testapi.Extensions.Codec(), &extensions.ReplicaSet{}) - fakeHandler.ResponseBody = response - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - - manager.syncReplicaSet(getKey(rs, t)) - - // 1. Status.Replicas should go up from 2->4 even though we created 5-4=1 pod. - // 2. Status.FullyLabeledReplicas should equal to the number of pods that - // has the extra labels, i.e., 2. - // 3. Every update to the status should include the Generation of the spec. - rs.Status = extensions.ReplicaSetStatus{Replicas: 4, FullyLabeledReplicas: 2, ObservedGeneration: 1} - - decRc := runtime.EncodeOrDie(testapi.Extensions.Codec(), rs) - fakeHandler.ValidateRequest(t, testapi.Extensions.ResourcePath(replicaSetResourceName(), rs.Namespace, rs.Name)+"/status", "PUT", &decRc) - validateSyncReplicaSet(t, &fakePodControl, 1, 0) -} - -func TestSyncReplicaSetDormancy(t *testing.T) { - // Setup a test server so we can lie about the current state of pods - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: "{}", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - - fakePodControl := controller.FakePodControl{} - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - labelMap := map[string]string{"foo": "bar"} - rsSpec := newReplicaSet(2, labelMap) - manager.rsStore.Store.Add(rsSpec) - newPodList(manager.podStore.Indexer, 1, api.PodRunning, labelMap, rsSpec, "pod") - - // Creates a replica and sets expectations - rsSpec.Status.Replicas = 1 - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 1, 0) - - // Expectations prevents replicas but not an update on status - rsSpec.Status.Replicas = 0 - fakePodControl.Clear() - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 0, 0) - - // Get the key for the controller - rsKey, err := controller.KeyFunc(rsSpec) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", rsSpec, err) - } - - // Lowering expectations should lead to a sync that creates a replica, however the - // fakePodControl error will prevent this, leaving expectations at 0, 0 - manager.expectations.CreationObserved(rsKey) - rsSpec.Status.Replicas = 1 - fakePodControl.Clear() - fakePodControl.Err = fmt.Errorf("Fake Error") - - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 0, 0) - - // This replica should not need a Lowering of expectations, since the previous create failed - fakePodControl.Err = nil - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 1, 0) - - // 1 PUT for the ReplicaSet status during dormancy window. - // Note that the pod creates go through pod control so they're not recorded. - fakeHandler.ValidateRequestCount(t, 1) -} - -func TestPodControllerLookup(t *testing.T) { - manager := NewReplicaSetController(clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}), controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - testCases := []struct { - inRSs []*extensions.ReplicaSet - pod *api.Pod - outRSName string - }{ - // pods without labels don't match any ReplicaSets - { - inRSs: []*extensions.ReplicaSet{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}}, - pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo1", Namespace: api.NamespaceAll}}, - outRSName: "", - }, - // Matching labels, not namespace - { - inRSs: []*extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - }, - pod: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo2", Namespace: "ns", Labels: map[string]string{"foo": "bar"}}}, - outRSName: "", - }, - // Matching ns and labels returns the key to the ReplicaSet, not the ReplicaSet name - { - inRSs: []*extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, - }, - }, - }, - pod: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo3", Namespace: "ns", Labels: map[string]string{"foo": "bar"}}}, - outRSName: "bar", - }, - } - for _, c := range testCases { - for _, r := range c.inRSs { - manager.rsStore.Add(r) - } - if rs := manager.getPodReplicaSet(c.pod); rs != nil { - if c.outRSName != rs.Name { - t.Errorf("Got replica set %+v expected %+v", rs.Name, c.outRSName) - } - } else if c.outRSName != "" { - t.Errorf("Expected a replica set %v pod %v, found none", c.outRSName, c.pod.Name) - } - } -} - -type FakeWatcher struct { - w *watch.FakeWatcher - *fake.Clientset -} - -func TestWatchControllers(t *testing.T) { - fakeWatch := watch.NewFake() - client := &fake.Clientset{} - client.AddWatchReactor("*", core.DefaultWatchReactor(fakeWatch, nil)) - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - var testRSSpec extensions.ReplicaSet - received := make(chan string) - - // The update sent through the fakeWatcher should make its way into the workqueue, - // and eventually into the syncHandler. The handler validates the received controller - // and closes the received channel to indicate that the test can finish. - manager.syncHandler = func(key string) error { - - obj, exists, err := manager.rsStore.Store.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find replica set under key %v", key) - } - rsSpec := *obj.(*extensions.ReplicaSet) - if !api.Semantic.DeepDerivative(rsSpec, testRSSpec) { - t.Errorf("Expected %#v, but got %#v", testRSSpec, rsSpec) - } - close(received) - return nil - } - // Start only the ReplicaSet watcher and the workqueue, send a watch event, - // and make sure it hits the sync method. - stopCh := make(chan struct{}) - defer close(stopCh) - go manager.rsController.Run(stopCh) - go wait.Until(manager.worker, 10*time.Millisecond, stopCh) - - testRSSpec.Name = "foo" - fakeWatch.Add(&testRSSpec) - - select { - case <-received: - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Expected 1 call but got 0") - } -} - -func TestWatchPods(t *testing.T) { - fakeWatch := watch.NewFake() - client := &fake.Clientset{} - client.AddWatchReactor("*", core.DefaultWatchReactor(fakeWatch, nil)) - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // Put one ReplicaSet and one pod into the controller's stores - labelMap := map[string]string{"foo": "bar"} - testRSSpec := newReplicaSet(1, labelMap) - manager.rsStore.Store.Add(testRSSpec) - received := make(chan string) - // The pod update sent through the fakeWatcher should figure out the managing ReplicaSet and - // send it into the syncHandler. - manager.syncHandler = func(key string) error { - - obj, exists, err := manager.rsStore.Store.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find replica set under key %v", key) - } - rsSpec := obj.(*extensions.ReplicaSet) - if !api.Semantic.DeepDerivative(rsSpec, testRSSpec) { - t.Errorf("\nExpected %#v,\nbut got %#v", testRSSpec, rsSpec) - } - close(received) - return nil - } - // Start only the pod watcher and the workqueue, send a watch event, - // and make sure it hits the sync method for the right ReplicaSet. - stopCh := make(chan struct{}) - defer close(stopCh) - go manager.podController.Run(stopCh) - go wait.Until(manager.worker, 10*time.Millisecond, stopCh) - - pods := newPodList(nil, 1, api.PodRunning, labelMap, testRSSpec, "pod") - testPod := pods.Items[0] - testPod.Status.Phase = api.PodFailed - fakeWatch.Add(&testPod) - - select { - case <-received: - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Expected 1 call but got 0") - } -} - -func TestUpdatePods(t *testing.T) { - manager := NewReplicaSetController(fake.NewSimpleClientset(), controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - received := make(chan string) - - manager.syncHandler = func(key string) error { - obj, exists, err := manager.rsStore.Store.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find replica set under key %v", key) - } - received <- obj.(*extensions.ReplicaSet).Name - return nil - } - - stopCh := make(chan struct{}) - defer close(stopCh) - go wait.Until(manager.worker, 10*time.Millisecond, stopCh) - - // Put 2 ReplicaSets and one pod into the controller's stores - labelMap1 := map[string]string{"foo": "bar"} - testRSSpec1 := newReplicaSet(1, labelMap1) - manager.rsStore.Store.Add(testRSSpec1) - testRSSpec2 := *testRSSpec1 - labelMap2 := map[string]string{"bar": "foo"} - testRSSpec2.Spec.Selector = &unversioned.LabelSelector{MatchLabels: labelMap2} - testRSSpec2.Name = "barfoo" - manager.rsStore.Store.Add(&testRSSpec2) - - // Put one pod in the podStore - pod1 := newPodList(manager.podStore.Indexer, 1, api.PodRunning, labelMap1, testRSSpec1, "pod").Items[0] - pod2 := pod1 - pod2.Labels = labelMap2 - - // Send an update of the same pod with modified labels, and confirm we get a sync request for - // both controllers - manager.updatePod(&pod1, &pod2) - - expected := sets.NewString(testRSSpec1.Name, testRSSpec2.Name) - for _, name := range expected.List() { - t.Logf("Expecting update for %+v", name) - select { - case got := <-received: - if !expected.Has(got) { - t.Errorf("Expected keys %#v got %v", expected, got) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Expected update notifications for replica sets within 100ms each") - } - } -} - -func TestControllerUpdateRequeue(t *testing.T) { - // This server should force a requeue of the controller because it fails to update status.Replicas. - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 500, - ResponseBody: "{}", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - - client := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - labelMap := map[string]string{"foo": "bar"} - rs := newReplicaSet(1, labelMap) - manager.rsStore.Store.Add(rs) - rs.Status = extensions.ReplicaSetStatus{Replicas: 2} - newPodList(manager.podStore.Indexer, 1, api.PodRunning, labelMap, rs, "pod") - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - - manager.syncReplicaSet(getKey(rs, t)) - - ch := make(chan interface{}) - go func() { - item, _ := manager.queue.Get() - ch <- item - }() - select { - case key := <-ch: - expectedKey := getKey(rs, t) - if key != expectedKey { - t.Errorf("Expected requeue of replica set with key %s got %s", expectedKey, key) - } - case <-time.After(wait.ForeverTestTimeout): - manager.queue.ShutDown() - t.Errorf("Expected to find a ReplicaSet in the queue, found none.") - } - // 1 Update and 1 GET, both of which fail - fakeHandler.ValidateRequestCount(t, 2) -} - -func TestControllerUpdateStatusWithFailure(t *testing.T) { - rs := newReplicaSet(1, map[string]string{"foo": "bar"}) - fakeClient := &fake.Clientset{} - fakeClient.AddReactor("get", "replicasets", func(action core.Action) (bool, runtime.Object, error) { return true, rs, nil }) - fakeClient.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { - return true, &extensions.ReplicaSet{}, fmt.Errorf("Fake error") - }) - fakeRSClient := fakeClient.Extensions().ReplicaSets("default") - numReplicas := 10 - updateReplicaCount(fakeRSClient, *rs, numReplicas, 0) - updates, gets := 0, 0 - for _, a := range fakeClient.Actions() { - if a.GetResource().Resource != "replicasets" { - t.Errorf("Unexpected action %+v", a) - continue - } - - switch action := a.(type) { - case core.GetAction: - gets++ - // Make sure the get is for the right ReplicaSet even though the update failed. - if action.GetName() != rs.Name { - t.Errorf("Expected get for ReplicaSet %v, got %+v instead", rs.Name, action.GetName()) - } - case core.UpdateAction: - updates++ - // Confirm that the update has the right status.Replicas even though the Get - // returned a ReplicaSet with replicas=1. - if c, ok := action.GetObject().(*extensions.ReplicaSet); !ok { - t.Errorf("Expected a ReplicaSet as the argument to update, got %T", c) - } else if int(c.Status.Replicas) != numReplicas { - t.Errorf("Expected update for ReplicaSet to contain replicas %v, got %v instead", - numReplicas, c.Status.Replicas) - } - default: - t.Errorf("Unexpected action %+v", a) - break - } - } - if gets != 1 || updates != 2 { - t.Errorf("Expected 1 get and 2 updates, got %d gets %d updates", gets, updates) - } -} - -// TODO: This test is too hairy for a unittest. It should be moved to an E2E suite. -func doTestControllerBurstReplicas(t *testing.T, burstReplicas, numReplicas int) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, burstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - labelMap := map[string]string{"foo": "bar"} - rsSpec := newReplicaSet(numReplicas, labelMap) - manager.rsStore.Store.Add(rsSpec) - - expectedPods := int32(0) - pods := newPodList(nil, numReplicas, api.PodPending, labelMap, rsSpec, "pod") - - rsKey, err := controller.KeyFunc(rsSpec) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", rsSpec, err) - } - - // Size up the controller, then size it down, and confirm the expected create/delete pattern - for _, replicas := range []int32{int32(numReplicas), 0} { - - rsSpec.Spec.Replicas = replicas - manager.rsStore.Store.Add(rsSpec) - - for i := 0; i < numReplicas; i += burstReplicas { - manager.syncReplicaSet(getKey(rsSpec, t)) - - // The store accrues active pods. It's also used by the ReplicaSet to determine how many - // replicas to create. - activePods := int32(len(manager.podStore.Indexer.List())) - if replicas != 0 { - // This is the number of pods currently "in flight". They were created by the - // ReplicaSet controller above, which then puts the ReplicaSet to sleep till - // all of them have been observed. - expectedPods = replicas - activePods - if expectedPods > int32(burstReplicas) { - expectedPods = int32(burstReplicas) - } - // This validates the ReplicaSet manager sync actually created pods - validateSyncReplicaSet(t, &fakePodControl, int(expectedPods), 0) - - // This simulates the watch events for all but 1 of the expected pods. - // None of these should wake the controller because it has expectations==BurstReplicas. - for i := int32(0); i < expectedPods-1; i++ { - manager.podStore.Indexer.Add(&pods.Items[i]) - manager.addPod(&pods.Items[i]) - } - - podExp, exists, err := manager.expectations.GetExpectations(rsKey) - if !exists || err != nil { - t.Fatalf("Did not find expectations for rc.") - } - if add, _ := podExp.GetExpectations(); add != 1 { - t.Fatalf("Expectations are wrong %v", podExp) - } - } else { - expectedPods = (replicas - activePods) * -1 - if expectedPods > int32(burstReplicas) { - expectedPods = int32(burstReplicas) - } - validateSyncReplicaSet(t, &fakePodControl, 0, int(expectedPods)) - - // To accurately simulate a watch we must delete the exact pods - // the rs is waiting for. - expectedDels := manager.expectations.GetUIDs(getKey(rsSpec, t)) - podsToDelete := []*api.Pod{} - for _, key := range expectedDels.List() { - nsName := strings.Split(key, "/") - podsToDelete = append(podsToDelete, &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: nsName[1], - Namespace: nsName[0], - Labels: rsSpec.Spec.Selector.MatchLabels, - }, - }) - } - // Don't delete all pods because we confirm that the last pod - // has exactly one expectation at the end, to verify that we - // don't double delete. - for i := range podsToDelete[1:] { - manager.podStore.Delete(podsToDelete[i]) - manager.deletePod(podsToDelete[i]) - } - podExp, exists, err := manager.expectations.GetExpectations(rsKey) - if !exists || err != nil { - t.Fatalf("Did not find expectations for ReplicaSet.") - } - if _, del := podExp.GetExpectations(); del != 1 { - t.Fatalf("Expectations are wrong %v", podExp) - } - } - - // Check that the ReplicaSet didn't take any action for all the above pods - fakePodControl.Clear() - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 0, 0) - - // Create/Delete the last pod - // The last add pod will decrease the expectation of the ReplicaSet to 0, - // which will cause it to create/delete the remaining replicas up to burstReplicas. - if replicas != 0 { - manager.podStore.Indexer.Add(&pods.Items[expectedPods-1]) - manager.addPod(&pods.Items[expectedPods-1]) - } else { - expectedDel := manager.expectations.GetUIDs(getKey(rsSpec, t)) - if expectedDel.Len() != 1 { - t.Fatalf("Waiting on unexpected number of deletes.") - } - nsName := strings.Split(expectedDel.List()[0], "/") - lastPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: nsName[1], - Namespace: nsName[0], - Labels: rsSpec.Spec.Selector.MatchLabels, - }, - } - manager.podStore.Indexer.Delete(lastPod) - manager.deletePod(lastPod) - } - pods.Items = pods.Items[expectedPods:] - } - - // Confirm that we've created the right number of replicas - activePods := int32(len(manager.podStore.Indexer.List())) - if activePods != rsSpec.Spec.Replicas { - t.Fatalf("Unexpected number of active pods, expected %d, got %d", rsSpec.Spec.Replicas, activePods) - } - // Replenish the pod list, since we cut it down sizing up - pods = newPodList(nil, int(replicas), api.PodRunning, labelMap, rsSpec, "pod") - } -} - -func TestControllerBurstReplicas(t *testing.T) { - doTestControllerBurstReplicas(t, 5, 30) - doTestControllerBurstReplicas(t, 5, 12) - doTestControllerBurstReplicas(t, 3, 2) -} - -type FakeRSExpectations struct { - *controller.ControllerExpectations - satisfied bool - expSatisfied func() -} - -func (fe FakeRSExpectations) SatisfiedExpectations(controllerKey string) bool { - fe.expSatisfied() - return fe.satisfied -} - -// TestRSSyncExpectations tests that a pod cannot sneak in between counting active pods -// and checking expectations. -func TestRSSyncExpectations(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, 2, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - labelMap := map[string]string{"foo": "bar"} - rsSpec := newReplicaSet(2, labelMap) - manager.rsStore.Store.Add(rsSpec) - pods := newPodList(nil, 2, api.PodPending, labelMap, rsSpec, "pod") - manager.podStore.Indexer.Add(&pods.Items[0]) - postExpectationsPod := pods.Items[1] - - manager.expectations = controller.NewUIDTrackingControllerExpectations(FakeRSExpectations{ - controller.NewControllerExpectations(), true, func() { - // If we check active pods before checking expectataions, the - // ReplicaSet will create a new replica because it doesn't see - // this pod, but has fulfilled its expectations. - manager.podStore.Indexer.Add(&postExpectationsPod) - }, - }) - manager.syncReplicaSet(getKey(rsSpec, t)) - validateSyncReplicaSet(t, &fakePodControl, 0, 0) -} - -func TestDeleteControllerAndExpectations(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, 10, 0) - manager.podStoreSynced = alwaysReady - - rs := newReplicaSet(1, map[string]string{"foo": "bar"}) - manager.rsStore.Store.Add(rs) - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - - // This should set expectations for the ReplicaSet - manager.syncReplicaSet(getKey(rs, t)) - validateSyncReplicaSet(t, &fakePodControl, 1, 0) - fakePodControl.Clear() - - // Get the ReplicaSet key - rsKey, err := controller.KeyFunc(rs) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", rs, err) - } - - // This is to simulate a concurrent addPod, that has a handle on the expectations - // as the controller deletes it. - podExp, exists, err := manager.expectations.GetExpectations(rsKey) - if !exists || err != nil { - t.Errorf("No expectations found for ReplicaSet") - } - manager.rsStore.Delete(rs) - manager.syncReplicaSet(getKey(rs, t)) - - if _, exists, err = manager.expectations.GetExpectations(rsKey); exists { - t.Errorf("Found expectaions, expected none since the ReplicaSet has been deleted.") - } - - // This should have no effect, since we've deleted the ReplicaSet. - podExp.Add(-1, 0) - manager.podStore.Indexer.Replace(make([]interface{}, 0), "0") - manager.syncReplicaSet(getKey(rs, t)) - validateSyncReplicaSet(t, &fakePodControl, 0, 0) -} - -func TestRSManagerNotReady(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, 2, 0) - manager.podControl = &fakePodControl - manager.podStoreSynced = func() bool { return false } - - // Simulates the ReplicaSet reflector running before the pod reflector. We don't - // want to end up creating replicas in this case until the pod reflector - // has synced, so the ReplicaSet controller should just requeue the ReplicaSet. - rsSpec := newReplicaSet(1, map[string]string{"foo": "bar"}) - manager.rsStore.Store.Add(rsSpec) - - rsKey := getKey(rsSpec, t) - manager.syncReplicaSet(rsKey) - validateSyncReplicaSet(t, &fakePodControl, 0, 0) - queueRS, _ := manager.queue.Get() - if queueRS != rsKey { - t.Fatalf("Expected to find key %v in queue, found %v", rsKey, queueRS) - } - - manager.podStoreSynced = alwaysReady - manager.syncReplicaSet(rsKey) - validateSyncReplicaSet(t, &fakePodControl, 1, 0) -} - -// shuffle returns a new shuffled list of container controllers. -func shuffle(controllers []*extensions.ReplicaSet) []*extensions.ReplicaSet { - numControllers := len(controllers) - randIndexes := rand.Perm(numControllers) - shuffled := make([]*extensions.ReplicaSet, numControllers) - for i := 0; i < numControllers; i++ { - shuffled[i] = controllers[randIndexes[i]] - } - return shuffled -} - -func TestOverlappingRSs(t *testing.T) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - labelMap := map[string]string{"foo": "bar"} - - for i := 0; i < 5; i++ { - manager := NewReplicaSetController(client, controller.NoResyncPeriodFunc, 10, 0) - manager.podStoreSynced = alwaysReady - - // Create 10 ReplicaSets, shuffled them randomly and insert them into the ReplicaSet controller's store - var controllers []*extensions.ReplicaSet - for j := 1; j < 10; j++ { - rsSpec := newReplicaSet(1, labelMap) - rsSpec.CreationTimestamp = unversioned.Date(2014, time.December, j, 0, 0, 0, 0, time.Local) - rsSpec.Name = string(util.NewUUID()) - controllers = append(controllers, rsSpec) - } - shuffledControllers := shuffle(controllers) - for j := range shuffledControllers { - manager.rsStore.Store.Add(shuffledControllers[j]) - } - // Add a pod and make sure only the oldest ReplicaSet is synced - pods := newPodList(nil, 1, api.PodPending, labelMap, controllers[0], "pod") - rsKey := getKey(controllers[0], t) - - manager.addPod(&pods.Items[0]) - queueRS, _ := manager.queue.Get() - if queueRS != rsKey { - t.Fatalf("Expected to find key %v in queue, found %v", rsKey, queueRS) - } - } -} - -func TestDeletionTimestamp(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - labelMap := map[string]string{"foo": "bar"} - manager := NewReplicaSetController(c, controller.NoResyncPeriodFunc, 10, 0) - manager.podStoreSynced = alwaysReady - - rs := newReplicaSet(1, labelMap) - manager.rsStore.Store.Add(rs) - rsKey, err := controller.KeyFunc(rs) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", rs, err) - } - pod := newPodList(nil, 1, api.PodPending, labelMap, rs, "pod").Items[0] - pod.DeletionTimestamp = &unversioned.Time{Time: time.Now()} - manager.expectations.ExpectDeletions(rsKey, []string{controller.PodKey(&pod)}) - - // A pod added with a deletion timestamp should decrement deletions, not creations. - manager.addPod(&pod) - - queueRC, _ := manager.queue.Get() - if queueRC != rsKey { - t.Fatalf("Expected to find key %v in queue, found %v", rsKey, queueRC) - } - manager.queue.Done(rsKey) - - podExp, exists, err := manager.expectations.GetExpectations(rsKey) - if !exists || err != nil || !podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // An update from no deletion timestamp to having one should be treated - // as a deletion. - oldPod := newPodList(nil, 1, api.PodPending, labelMap, rs, "pod").Items[0] - manager.expectations.ExpectDeletions(rsKey, []string{controller.PodKey(&pod)}) - manager.updatePod(&oldPod, &pod) - - queueRC, _ = manager.queue.Get() - if queueRC != rsKey { - t.Fatalf("Expected to find key %v in queue, found %v", rsKey, queueRC) - } - manager.queue.Done(rsKey) - - podExp, exists, err = manager.expectations.GetExpectations(rsKey) - if !exists || err != nil || !podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // An update to the pod (including an update to the deletion timestamp) - // should not be counted as a second delete. - secondPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: pod.Namespace, - Name: "secondPod", - Labels: pod.Labels, - }, - } - manager.expectations.ExpectDeletions(rsKey, []string{controller.PodKey(secondPod)}) - oldPod.DeletionTimestamp = &unversioned.Time{Time: time.Now()} - manager.updatePod(&oldPod, &pod) - - podExp, exists, err = manager.expectations.GetExpectations(rsKey) - if !exists || err != nil || podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // A pod with a non-nil deletion timestamp should also be ignored by the - // delete handler, because it's already been counted in the update. - manager.deletePod(&pod) - podExp, exists, err = manager.expectations.GetExpectations(rsKey) - if !exists || err != nil || podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // Deleting the second pod should clear expectations. - manager.deletePod(secondPod) - - queueRC, _ = manager.queue.Get() - if queueRC != rsKey { - t.Fatalf("Expected to find key %v in queue, found %v", rsKey, queueRC) - } - manager.queue.Done(rsKey) - - podExp, exists, err = manager.expectations.GetExpectations(rsKey) - if !exists || err != nil || !podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils.go deleted file mode 100644 index fd8bd7062..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replicaset/replica_set_utils.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// If you make changes to this file, you should also make the corresponding change in ReplicationController. - -package replicaset - -import ( - "fmt" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/apis/extensions" - client "k8s.io/kubernetes/pkg/client/unversioned" -) - -// updateReplicaCount attempts to update the Status.Replicas of the given ReplicaSet, with a single GET/PUT retry. -func updateReplicaCount(rsClient client.ReplicaSetInterface, rs extensions.ReplicaSet, numReplicas, numFullyLabeledReplicas int) (updateErr error) { - // This is the steady state. It happens when the ReplicaSet doesn't have any expectations, since - // we do a periodic relist every 30s. If the generations differ but the replicas are - // the same, a caller might've resized to the same replica count. - if int(rs.Status.Replicas) == numReplicas && - int(rs.Status.FullyLabeledReplicas) == numFullyLabeledReplicas && - rs.Generation == rs.Status.ObservedGeneration { - return nil - } - // Save the generation number we acted on, otherwise we might wrongfully indicate - // that we've seen a spec update when we retry. - // TODO: This can clobber an update if we allow multiple agents to write to the - // same status. - generation := rs.Generation - - var getErr error - for i, rs := 0, &rs; ; i++ { - glog.V(4).Infof(fmt.Sprintf("Updating replica count for ReplicaSet: %s/%s, ", rs.Namespace, rs.Name) + - fmt.Sprintf("replicas %d->%d (need %d), ", rs.Status.Replicas, numReplicas, rs.Spec.Replicas) + - fmt.Sprintf("fullyLabeledReplicas %d->%d, ", rs.Status.FullyLabeledReplicas, numFullyLabeledReplicas) + - fmt.Sprintf("sequence No: %v->%v", rs.Status.ObservedGeneration, generation)) - - rs.Status = extensions.ReplicaSetStatus{Replicas: int32(numReplicas), FullyLabeledReplicas: int32(numFullyLabeledReplicas), ObservedGeneration: generation} - _, updateErr = rsClient.UpdateStatus(rs) - if updateErr == nil || i >= statusUpdateRetries { - return updateErr - } - // Update the ReplicaSet with the latest resource version for the next poll - if rs, getErr = rsClient.Get(rs.Name); getErr != nil { - // If the GET fails we can't trust status.Replicas anymore. This error - // is bound to be more interesting than the update failure. - return getErr - } - } -} - -// overlappingReplicaSets sorts a list of ReplicaSets by creation timestamp, using their names as a tie breaker. -type overlappingReplicaSets []extensions.ReplicaSet - -func (o overlappingReplicaSets) Len() int { return len(o) } -func (o overlappingReplicaSets) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o overlappingReplicaSets) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/doc.go deleted file mode 100644 index b60e1d99c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 replication contains logic for watching and synchronizing -// replication controllers. -package replication diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller.go deleted file mode 100644 index 8fc0f16fd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller.go +++ /dev/null @@ -1,582 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// If you make changes to this file, you should also make the corresponding change in ReplicaSet. - -package replication - -import ( - "reflect" - "sort" - "sync" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/controller/framework/informers" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" -) - -const ( - // We'll attempt to recompute the required replicas of all replication controllers - // that have fulfilled their expectations at least this often. This recomputation - // happens based on contents in local pod storage. - FullControllerResyncPeriod = 30 * time.Second - - // Realistic value of the burstReplica field for the replication manager based off - // performance requirements for kubernetes 1.0. - BurstReplicas = 500 - - // We must avoid counting pods until the pod store has synced. If it hasn't synced, to - // avoid a hot loop, we'll wait this long between checks. - PodStoreSyncedPollPeriod = 100 * time.Millisecond - - // The number of times we retry updating a replication controller's status. - statusUpdateRetries = 1 -) - -// ReplicationManager is responsible for synchronizing ReplicationController objects stored -// in the system with actual running pods. -// TODO: this really should be called ReplicationController. The only reason why it's a Manager -// is to distinguish this type from API object "ReplicationController". We should fix this. -type ReplicationManager struct { - kubeClient clientset.Interface - podControl controller.PodControlInterface - - // internalPodInformer is used to hold a personal informer. If we're using - // a normal shared informer, then the informer will be started for us. If - // we have a personal informer, we must start it ourselves. If you start - // the controller using NewReplicationManager(passing SharedInformer), this - // will be null - internalPodInformer framework.SharedIndexInformer - - // An rc is temporarily suspended after creating/deleting these many replicas. - // It resumes normal action after observing the watch events for them. - burstReplicas int - // To allow injection of syncReplicationController for testing. - syncHandler func(rcKey string) error - - // A TTLCache of pod creates/deletes each rc expects to see. - expectations *controller.UIDTrackingControllerExpectations - - // A store of replication controllers, populated by the rcController - rcStore cache.StoreToReplicationControllerLister - // Watches changes to all replication controllers - rcController *framework.Controller - // A store of pods, populated by the podController - podStore cache.StoreToPodLister - // Watches changes to all pods - podController framework.ControllerInterface - // podStoreSynced returns true if the pod store has been synced at least once. - // Added as a member to the struct to allow injection for testing. - podStoreSynced func() bool - - lookupCache *controller.MatchingCache - - // Controllers that need to be synced - queue *workqueue.Type -} - -func NewReplicationManager(podInformer framework.SharedIndexInformer, kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, burstReplicas int, lookupCacheSize int) *ReplicationManager { - eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(glog.Infof) - eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kubeClient.Core().Events("")}) - - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("replication_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - - rm := &ReplicationManager{ - kubeClient: kubeClient, - podControl: controller.RealPodControl{ - KubeClient: kubeClient, - Recorder: eventBroadcaster.NewRecorder(api.EventSource{Component: "replication-controller"}), - }, - burstReplicas: burstReplicas, - expectations: controller.NewUIDTrackingControllerExpectations(controller.NewControllerExpectations()), - queue: workqueue.New(), - } - - rm.rcStore.Indexer, rm.rcController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return rm.kubeClient.Core().ReplicationControllers(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return rm.kubeClient.Core().ReplicationControllers(api.NamespaceAll).Watch(options) - }, - }, - &api.ReplicationController{}, - // TODO: Can we have much longer period here? - FullControllerResyncPeriod, - framework.ResourceEventHandlerFuncs{ - AddFunc: rm.enqueueController, - UpdateFunc: func(old, cur interface{}) { - oldRC := old.(*api.ReplicationController) - curRC := cur.(*api.ReplicationController) - - // We should invalidate the whole lookup cache if a RC's selector has been updated. - // - // Imagine that you have two RCs: - // * old RC1 - // * new RC2 - // You also have a pod that is attached to RC2 (because it doesn't match RC1 selector). - // Now imagine that you are changing RC1 selector so that it is now matching that pod, - // in such case, we must invalidate the whole cache so that pod could be adopted by RC1 - // - // This makes the lookup cache less helpful, but selector update does not happen often, - // so it's not a big problem - if !reflect.DeepEqual(oldRC.Spec.Selector, curRC.Spec.Selector) { - rm.lookupCache.InvalidateAll() - } - - // You might imagine that we only really need to enqueue the - // controller when Spec changes, but it is safer to sync any - // time this function is triggered. That way a full informer - // resync can requeue any controllers that don't yet have pods - // but whose last attempts at creating a pod have failed (since - // we don't block on creation of pods) instead of those - // controllers stalling indefinitely. Enqueueing every time - // does result in some spurious syncs (like when Status.Replica - // is updated and the watch notification from it retriggers - // this function), but in general extra resyncs shouldn't be - // that bad as rcs that haven't met expectations yet won't - // sync, and all the listing is done using local stores. - if oldRC.Status.Replicas != curRC.Status.Replicas { - glog.V(4).Infof("Observed updated replica count for rc: %v, %d->%d", curRC.Name, oldRC.Status.Replicas, curRC.Status.Replicas) - } - rm.enqueueController(cur) - }, - // This will enter the sync loop and no-op, because the controller has been deleted from the store. - // Note that deleting a controller immediately after scaling it to 0 will not work. The recommended - // way of achieving this is by performing a `stop` operation on the controller. - DeleteFunc: rm.enqueueController, - }, - cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, - ) - - podInformer.AddEventHandler(framework.ResourceEventHandlerFuncs{ - AddFunc: rm.addPod, - // This invokes the rc for every pod change, eg: host assignment. Though this might seem like overkill - // the most frequent pod update is status, and the associated rc will only list from local storage, so - // it should be ok. - UpdateFunc: rm.updatePod, - DeleteFunc: rm.deletePod, - }) - rm.podStore.Indexer = podInformer.GetIndexer() - rm.podController = podInformer.GetController() - - rm.syncHandler = rm.syncReplicationController - rm.podStoreSynced = rm.podController.HasSynced - rm.lookupCache = controller.NewMatchingCache(lookupCacheSize) - return rm - -} - -// NewReplicationManagerFromClient creates a new ReplicationManager that runs its own informer. -func NewReplicationManagerFromClient(kubeClient clientset.Interface, resyncPeriod controller.ResyncPeriodFunc, burstReplicas int, lookupCacheSize int) *ReplicationManager { - podInformer := informers.CreateSharedPodIndexInformer(kubeClient, resyncPeriod()) - rm := NewReplicationManager(podInformer, kubeClient, resyncPeriod, burstReplicas, lookupCacheSize) - rm.internalPodInformer = podInformer - - return rm -} - -// SetEventRecorder replaces the event recorder used by the replication manager -// with the given recorder. Only used for testing. -func (rm *ReplicationManager) SetEventRecorder(recorder record.EventRecorder) { - // TODO: Hack. We can't cleanly shutdown the event recorder, so benchmarks - // need to pass in a fake. - rm.podControl = controller.RealPodControl{KubeClient: rm.kubeClient, Recorder: recorder} -} - -// Run begins watching and syncing. -func (rm *ReplicationManager) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - glog.Infof("Starting RC Manager") - go rm.rcController.Run(stopCh) - go rm.podController.Run(stopCh) - for i := 0; i < workers; i++ { - go wait.Until(rm.worker, time.Second, stopCh) - } - - if rm.internalPodInformer != nil { - go rm.internalPodInformer.Run(stopCh) - } - - <-stopCh - glog.Infof("Shutting down RC Manager") - rm.queue.ShutDown() -} - -// getPodController returns the controller managing the given pod. -// TODO: Surface that we are ignoring multiple controllers for a single pod. -func (rm *ReplicationManager) getPodController(pod *api.Pod) *api.ReplicationController { - // look up in the cache, if cached and the cache is valid, just return cached value - if obj, cached := rm.lookupCache.GetMatchingObject(pod); cached { - controller, ok := obj.(*api.ReplicationController) - if !ok { - // This should not happen - glog.Errorf("lookup cache does not retuen a ReplicationController object") - return nil - } - if cached && rm.isCacheValid(pod, controller) { - return controller - } - } - - // if not cached or cached value is invalid, search all the rc to find the matching one, and update cache - controllers, err := rm.rcStore.GetPodControllers(pod) - if err != nil { - glog.V(4).Infof("No controllers found for pod %v, replication manager will avoid syncing", pod.Name) - return nil - } - // In theory, overlapping controllers is user error. This sorting will not prevent - // oscillation of replicas in all cases, eg: - // rc1 (older rc): [(k1=v1)], replicas=1 rc2: [(k2=v2)], replicas=2 - // pod: [(k1:v1), (k2:v2)] will wake both rc1 and rc2, and we will sync rc1. - // pod: [(k2:v2)] will wake rc2 which creates a new replica. - if len(controllers) > 1 { - // More than two items in this list indicates user error. If two replication-controller - // overlap, sort by creation timestamp, subsort by name, then pick - // the first. - glog.Errorf("user error! more than one replication controller is selecting pods with labels: %+v", pod.Labels) - sort.Sort(OverlappingControllers(controllers)) - } - - // update lookup cache - rm.lookupCache.Update(pod, &controllers[0]) - - return &controllers[0] -} - -// isCacheValid check if the cache is valid -func (rm *ReplicationManager) isCacheValid(pod *api.Pod, cachedRC *api.ReplicationController) bool { - exists, err := rm.rcStore.Exists(cachedRC) - // rc has been deleted or updated, cache is invalid - if err != nil || !exists || !isControllerMatch(pod, cachedRC) { - return false - } - return true -} - -// isControllerMatch take a Pod and ReplicationController, return whether the Pod and ReplicationController are matching -// TODO(mqliang): This logic is a copy from GetPodControllers(), remove the duplication -func isControllerMatch(pod *api.Pod, rc *api.ReplicationController) bool { - if rc.Namespace != pod.Namespace { - return false - } - labelSet := labels.Set(rc.Spec.Selector) - selector := labels.Set(rc.Spec.Selector).AsSelector() - - // If an rc with a nil or empty selector creeps in, it should match nothing, not everything. - if labelSet.AsSelector().Empty() || !selector.Matches(labels.Set(pod.Labels)) { - return false - } - return true -} - -// When a pod is created, enqueue the controller that manages it and update it's expectations. -func (rm *ReplicationManager) addPod(obj interface{}) { - pod := obj.(*api.Pod) - - rc := rm.getPodController(pod) - if rc == nil { - return - } - rcKey, err := controller.KeyFunc(rc) - if err != nil { - glog.Errorf("Couldn't get key for replication controller %#v: %v", rc, err) - return - } - - if pod.DeletionTimestamp != nil { - // on a restart of the controller manager, it's possible a new pod shows up in a state that - // is already pending deletion. Prevent the pod from being a creation observation. - rm.deletePod(pod) - return - } - rm.expectations.CreationObserved(rcKey) - rm.enqueueController(rc) -} - -// When a pod is updated, figure out what controller/s manage it and wake them -// up. If the labels of the pod have changed we need to awaken both the old -// and new controller. old and cur must be *api.Pod types. -func (rm *ReplicationManager) updatePod(old, cur interface{}) { - if api.Semantic.DeepEqual(old, cur) { - // A periodic relist will send update events for all known pods. - return - } - curPod := cur.(*api.Pod) - rc := rm.getPodController(curPod) - if rc == nil { - return - } - oldPod := old.(*api.Pod) - - if curPod.DeletionTimestamp != nil { - // when a pod is deleted gracefully it's deletion timestamp is first modified to reflect a grace period, - // and after such time has passed, the kubelet actually deletes it from the store. We receive an update - // for modification of the deletion timestamp and expect an rc to create more replicas asap, not wait - // until the kubelet actually deletes the pod. This is different from the Phase of a pod changing, because - // an rc never initiates a phase change, and so is never asleep waiting for the same. - rm.deletePod(curPod) - return - } - rm.enqueueController(rc) - // Only need to get the old controller if the labels changed. - if !reflect.DeepEqual(curPod.Labels, oldPod.Labels) { - // If the old and new rc are the same, the first one that syncs - // will set expectations preventing any damage from the second. - if oldRC := rm.getPodController(oldPod); oldRC != nil { - rm.enqueueController(oldRC) - } - } -} - -// When a pod is deleted, enqueue the controller that manages the pod and update its expectations. -// obj could be an *api.Pod, or a DeletionFinalStateUnknown marker item. -func (rm *ReplicationManager) deletePod(obj interface{}) { - pod, ok := obj.(*api.Pod) - - // When a delete is dropped, the relist will notice a pod in the store not - // in the list, leading to the insertion of a tombstone object which contains - // the deleted key/value. Note that this value might be stale. If the pod - // changed labels the new rc will not be woken up till the periodic resync. - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("Couldn't get object from tombstone %+v", obj) - return - } - pod, ok = tombstone.Obj.(*api.Pod) - if !ok { - glog.Errorf("Tombstone contained object that is not a pod %+v", obj) - return - } - } - glog.V(4).Infof("Pod %s/%s deleted through %v, timestamp %+v, labels %+v.", pod.Namespace, pod.Name, utilruntime.GetCaller(), pod.DeletionTimestamp, pod.Labels) - if rc := rm.getPodController(pod); rc != nil { - rcKey, err := controller.KeyFunc(rc) - if err != nil { - glog.Errorf("Couldn't get key for replication controller %#v: %v", rc, err) - return - } - rm.expectations.DeletionObserved(rcKey, controller.PodKey(pod)) - rm.enqueueController(rc) - } -} - -// obj could be an *api.ReplicationController, or a DeletionFinalStateUnknown marker item. -func (rm *ReplicationManager) enqueueController(obj interface{}) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - return - } - - // TODO: Handle overlapping controllers better. Either disallow them at admission time or - // deterministically avoid syncing controllers that fight over pods. Currently, we only - // ensure that the same controller is synced for a given pod. When we periodically relist - // all controllers there will still be some replica instability. One way to handle this is - // by querying the store for all controllers that this rc overlaps, as well as all - // controllers that overlap this rc, and sorting them. - rm.queue.Add(key) -} - -// worker runs a worker thread that just dequeues items, processes them, and marks them done. -// It enforces that the syncHandler is never invoked concurrently with the same key. -func (rm *ReplicationManager) worker() { - for { - func() { - key, quit := rm.queue.Get() - if quit { - return - } - defer rm.queue.Done(key) - err := rm.syncHandler(key.(string)) - if err != nil { - glog.Errorf("Error syncing replication controller: %v", err) - } - }() - } -} - -// manageReplicas checks and updates replicas for the given replication controller. -func (rm *ReplicationManager) manageReplicas(filteredPods []*api.Pod, rc *api.ReplicationController) { - diff := len(filteredPods) - int(rc.Spec.Replicas) - rcKey, err := controller.KeyFunc(rc) - if err != nil { - glog.Errorf("Couldn't get key for replication controller %#v: %v", rc, err) - return - } - if diff < 0 { - diff *= -1 - if diff > rm.burstReplicas { - diff = rm.burstReplicas - } - // TODO: Track UIDs of creates just like deletes. The problem currently - // is we'd need to wait on the result of a create to record the pod's - // UID, which would require locking *across* the create, which will turn - // into a performance bottleneck. We should generate a UID for the pod - // beforehand and store it via ExpectCreations. - rm.expectations.ExpectCreations(rcKey, diff) - wait := sync.WaitGroup{} - wait.Add(diff) - glog.V(2).Infof("Too few %q/%q replicas, need %d, creating %d", rc.Namespace, rc.Name, rc.Spec.Replicas, diff) - for i := 0; i < diff; i++ { - go func() { - defer wait.Done() - if err := rm.podControl.CreatePods(rc.Namespace, rc.Spec.Template, rc); err != nil { - // Decrement the expected number of creates because the informer won't observe this pod - glog.V(2).Infof("Failed creation, decrementing expectations for controller %q/%q", rc.Namespace, rc.Name) - rm.expectations.CreationObserved(rcKey) - utilruntime.HandleError(err) - } - }() - } - wait.Wait() - } else if diff > 0 { - if diff > rm.burstReplicas { - diff = rm.burstReplicas - } - glog.V(2).Infof("Too many %q/%q replicas, need %d, deleting %d", rc.Namespace, rc.Name, rc.Spec.Replicas, diff) - // No need to sort pods if we are about to delete all of them - if rc.Spec.Replicas != 0 { - // Sort the pods in the order such that not-ready < ready, unscheduled - // < scheduled, and pending < running. This ensures that we delete pods - // in the earlier stages whenever possible. - sort.Sort(controller.ActivePods(filteredPods)) - } - // Snapshot the UIDs (ns/name) of the pods we're expecting to see - // deleted, so we know to record their expectations exactly once either - // when we see it as an update of the deletion timestamp, or as a delete. - // Note that if the labels on a pod/rc change in a way that the pod gets - // orphaned, the rs will only wake up after the expectations have - // expired even if other pods are deleted. - deletedPodKeys := []string{} - for i := 0; i < diff; i++ { - deletedPodKeys = append(deletedPodKeys, controller.PodKey(filteredPods[i])) - } - // We use pod namespace/name as a UID to wait for deletions, so if the - // labels on a pod/rc change in a way that the pod gets orphaned, the - // rc will only wake up after the expectation has expired. - rm.expectations.ExpectDeletions(rcKey, deletedPodKeys) - wait := sync.WaitGroup{} - wait.Add(diff) - for i := 0; i < diff; i++ { - go func(ix int) { - defer wait.Done() - if err := rm.podControl.DeletePod(rc.Namespace, filteredPods[ix].Name, rc); err != nil { - // Decrement the expected number of deletes because the informer won't observe this deletion - podKey := controller.PodKey(filteredPods[ix]) - glog.V(2).Infof("Failed to delete %v due to %v, decrementing expectations for controller %q/%q", podKey, err, rc.Namespace, rc.Name) - rm.expectations.DeletionObserved(rcKey, podKey) - utilruntime.HandleError(err) - } - }(i) - } - wait.Wait() - } -} - -// syncReplicationController will sync the rc with the given key if it has had its expectations fulfilled, meaning -// it did not expect to see any more of its pods created or deleted. This function is not meant to be invoked -// concurrently with the same key. -func (rm *ReplicationManager) syncReplicationController(key string) error { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing controller %q (%v)", key, time.Now().Sub(startTime)) - }() - - if !rm.podStoreSynced() { - // Sleep so we give the pod reflector goroutine a chance to run. - time.Sleep(PodStoreSyncedPollPeriod) - glog.Infof("Waiting for pods controller to sync, requeuing rc %v", key) - rm.queue.Add(key) - return nil - } - - obj, exists, err := rm.rcStore.Indexer.GetByKey(key) - if !exists { - glog.Infof("Replication Controller has been deleted %v", key) - rm.expectations.DeleteExpectations(key) - return nil - } - if err != nil { - glog.Infof("Unable to retrieve rc %v from store: %v", key, err) - rm.queue.Add(key) - return err - } - rc := *obj.(*api.ReplicationController) - - // Check the expectations of the rc before counting active pods, otherwise a new pod can sneak in - // and update the expectations after we've retrieved active pods from the store. If a new pod enters - // the store after we've checked the expectation, the rc sync is just deferred till the next relist. - rcKey, err := controller.KeyFunc(&rc) - if err != nil { - glog.Errorf("Couldn't get key for replication controller %#v: %v", rc, err) - return err - } - rcNeedsSync := rm.expectations.SatisfiedExpectations(rcKey) - podList, err := rm.podStore.Pods(rc.Namespace).List(labels.Set(rc.Spec.Selector).AsSelector()) - if err != nil { - glog.Errorf("Error getting pods for rc %q: %v", key, err) - rm.queue.Add(key) - return err - } - - // TODO: Do this in a single pass, or use an index. - filteredPods := controller.FilterActivePods(podList.Items) - if rcNeedsSync { - rm.manageReplicas(filteredPods, &rc) - } - - // Count the number of pods that have labels matching the labels of the pod - // template of the replication controller, the matching pods may have more - // labels than are in the template. Because the label of podTemplateSpec is - // a superset of the selector of the replication controller, so the possible - // matching pods must be part of the filteredPods. - fullyLabeledReplicasCount := 0 - templateLabel := labels.Set(rc.Spec.Template.Labels).AsSelector() - for _, pod := range filteredPods { - if templateLabel.Matches(labels.Set(pod.Labels)) { - fullyLabeledReplicasCount++ - } - } - - // Always updates status as pods come up or die. - if err := updateReplicaCount(rm.kubeClient.Core().ReplicationControllers(rc.Namespace), rc, len(filteredPods), fullyLabeledReplicasCount); err != nil { - // Multiple things could lead to this update failing. Requeuing the controller ensures - // we retry with some fairness. - glog.V(2).Infof("Failed to update replica count for controller %v/%v; requeuing; error: %v", rc.Namespace, rc.Name, err) - rm.enqueueController(&rc) - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller_test.go deleted file mode 100644 index 376e5a4b9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller_test.go +++ /dev/null @@ -1,1102 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// If you make changes to this file, you should also make the corresponding change in ReplicaSet. - -package replication - -import ( - "fmt" - "math/rand" - "net/http/httptest" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/securitycontext" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/sets" - utiltesting "k8s.io/kubernetes/pkg/util/testing" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" -) - -var alwaysReady = func() bool { return true } - -func getKey(rc *api.ReplicationController, t *testing.T) string { - if key, err := controller.KeyFunc(rc); err != nil { - t.Errorf("Unexpected error getting key for rc %v: %v", rc.Name, err) - return "" - } else { - return key - } -} - -func newReplicationController(replicas int) *api.ReplicationController { - rc := &api.ReplicationController{ - TypeMeta: unversioned.TypeMeta{APIVersion: testapi.Default.GroupVersion().String()}, - ObjectMeta: api.ObjectMeta{ - UID: util.NewUUID(), - Name: "foobar", - Namespace: api.NamespaceDefault, - ResourceVersion: "18", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: int32(replicas), - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "name": "foo", - "type": "production", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo/bar", - TerminationMessagePath: api.TerminationMessagePathDefault, - ImagePullPolicy: api.PullIfNotPresent, - SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), - }, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSDefault, - NodeSelector: map[string]string{ - "baz": "blah", - }, - }, - }, - }, - } - return rc -} - -// create count pods with the given phase for the given rc (same selectors and namespace), and add them to the store. -func newPodList(store cache.Store, count int, status api.PodPhase, rc *api.ReplicationController, name string) *api.PodList { - pods := []api.Pod{} - for i := 0; i < count; i++ { - newPod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("%s%d", name, i), - Labels: rc.Spec.Selector, - Namespace: rc.Namespace, - }, - Status: api.PodStatus{Phase: status}, - } - if store != nil { - store.Add(&newPod) - } - pods = append(pods, newPod) - } - return &api.PodList{ - Items: pods, - } -} - -func validateSyncReplication(t *testing.T, fakePodControl *controller.FakePodControl, expectedCreates, expectedDeletes int) { - if len(fakePodControl.Templates) != expectedCreates { - t.Errorf("Unexpected number of creates. Expected %d, saw %d\n", expectedCreates, len(fakePodControl.Templates)) - } - if len(fakePodControl.DeletePodName) != expectedDeletes { - t.Errorf("Unexpected number of deletes. Expected %d, saw %d\n", expectedDeletes, len(fakePodControl.DeletePodName)) - } -} - -func replicationControllerResourceName() string { - return "replicationcontrollers" -} - -type serverResponse struct { - statusCode int - obj interface{} -} - -func TestSyncReplicationControllerDoesNothing(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // 2 running pods, a controller with 2 replicas, sync is a no-op - controllerSpec := newReplicationController(2) - manager.rcStore.Indexer.Add(controllerSpec) - newPodList(manager.podStore.Indexer, 2, api.PodRunning, controllerSpec, "pod") - - manager.podControl = &fakePodControl - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 0, 0) -} - -func TestSyncReplicationControllerDeletes(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - // 2 running pods and a controller with 1 replica, one pod delete expected - controllerSpec := newReplicationController(1) - manager.rcStore.Indexer.Add(controllerSpec) - newPodList(manager.podStore.Indexer, 2, api.PodRunning, controllerSpec, "pod") - - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 0, 1) -} - -func TestDeleteFinalStateUnknown(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - received := make(chan string) - manager.syncHandler = func(key string) error { - received <- key - return nil - } - - // The DeletedFinalStateUnknown object should cause the rc manager to insert - // the controller matching the selectors of the deleted pod into the work queue. - controllerSpec := newReplicationController(1) - manager.rcStore.Indexer.Add(controllerSpec) - pods := newPodList(nil, 1, api.PodRunning, controllerSpec, "pod") - manager.deletePod(cache.DeletedFinalStateUnknown{Key: "foo", Obj: &pods.Items[0]}) - - go manager.worker() - - expected := getKey(controllerSpec, t) - select { - case key := <-received: - if key != expected { - t.Errorf("Unexpected sync all for rc %v, expected %v", key, expected) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Processing DeleteFinalStateUnknown took longer than expected") - } -} - -func TestSyncReplicationControllerCreates(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // A controller with 2 replicas and no pods in the store, 2 creates expected - rc := newReplicationController(2) - manager.rcStore.Indexer.Add(rc) - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.syncReplicationController(getKey(rc, t)) - validateSyncReplication(t, &fakePodControl, 2, 0) -} - -func TestStatusUpdatesWithoutReplicasChange(t *testing.T) { - // Setup a fake server to listen for requests, and run the rc manager in steady state - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: "", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // Steady state for the replication controller, no Status.Replicas updates expected - activePods := 5 - rc := newReplicationController(activePods) - manager.rcStore.Indexer.Add(rc) - rc.Status = api.ReplicationControllerStatus{Replicas: int32(activePods)} - newPodList(manager.podStore.Indexer, activePods, api.PodRunning, rc, "pod") - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - manager.syncReplicationController(getKey(rc, t)) - - validateSyncReplication(t, &fakePodControl, 0, 0) - if fakeHandler.RequestReceived != nil { - t.Errorf("Unexpected update when pods and rcs are in a steady state") - } - - // This response body is just so we don't err out decoding the http response, all - // we care about is the request body sent below. - response := runtime.EncodeOrDie(testapi.Default.Codec(), &api.ReplicationController{}) - fakeHandler.ResponseBody = response - - rc.Generation = rc.Generation + 1 - manager.syncReplicationController(getKey(rc, t)) - - rc.Status.ObservedGeneration = rc.Generation - updatedRc := runtime.EncodeOrDie(testapi.Default.Codec(), rc) - fakeHandler.ValidateRequest(t, testapi.Default.ResourcePath(replicationControllerResourceName(), rc.Namespace, rc.Name)+"/status", "PUT", &updatedRc) -} - -func TestControllerUpdateReplicas(t *testing.T) { - // This is a happy server just to record the PUT request we expect for status.Replicas - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: "", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // Insufficient number of pods in the system, and Status.Replicas is wrong; - // Status.Replica should update to match number of pods in system, 1 new pod should be created. - rc := newReplicationController(5) - manager.rcStore.Indexer.Add(rc) - rc.Status = api.ReplicationControllerStatus{Replicas: 2, FullyLabeledReplicas: 6, ObservedGeneration: 0} - rc.Generation = 1 - newPodList(manager.podStore.Indexer, 2, api.PodRunning, rc, "pod") - rcCopy := *rc - extraLabelMap := map[string]string{"foo": "bar", "extraKey": "extraValue"} - rcCopy.Spec.Selector = extraLabelMap - newPodList(manager.podStore.Indexer, 2, api.PodRunning, &rcCopy, "podWithExtraLabel") - - // This response body is just so we don't err out decoding the http response - response := runtime.EncodeOrDie(testapi.Default.Codec(), &api.ReplicationController{}) - fakeHandler.ResponseBody = response - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - - manager.syncReplicationController(getKey(rc, t)) - - // 1. Status.Replicas should go up from 2->4 even though we created 5-4=1 pod. - // 2. Status.FullyLabeledReplicas should equal to the number of pods that - // has the extra labels, i.e., 2. - // 3. Every update to the status should include the Generation of the spec. - rc.Status = api.ReplicationControllerStatus{Replicas: 4, ObservedGeneration: 1} - - decRc := runtime.EncodeOrDie(testapi.Default.Codec(), rc) - fakeHandler.ValidateRequest(t, testapi.Default.ResourcePath(replicationControllerResourceName(), rc.Namespace, rc.Name)+"/status", "PUT", &decRc) - validateSyncReplication(t, &fakePodControl, 1, 0) -} - -func TestSyncReplicationControllerDormancy(t *testing.T) { - // Setup a test server so we can lie about the current state of pods - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 200, - ResponseBody: "{}", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - c := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - controllerSpec := newReplicationController(2) - manager.rcStore.Indexer.Add(controllerSpec) - newPodList(manager.podStore.Indexer, 1, api.PodRunning, controllerSpec, "pod") - - // Creates a replica and sets expectations - controllerSpec.Status.Replicas = 1 - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 1, 0) - - // Expectations prevents replicas but not an update on status - controllerSpec.Status.Replicas = 0 - fakePodControl.Clear() - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 0, 0) - - // Get the key for the controller - rcKey, err := controller.KeyFunc(controllerSpec) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", controllerSpec, err) - } - - // Lowering expectations should lead to a sync that creates a replica, however the - // fakePodControl error will prevent this, leaving expectations at 0, 0 - manager.expectations.CreationObserved(rcKey) - controllerSpec.Status.Replicas = 1 - fakePodControl.Clear() - fakePodControl.Err = fmt.Errorf("Fake Error") - - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 0, 0) - - // This replica should not need a Lowering of expectations, since the previous create failed - fakePodControl.Err = nil - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 1, 0) - - // 1 PUT for the rc status during dormancy window. - // Note that the pod creates go through pod control so they're not recorded. - fakeHandler.ValidateRequestCount(t, 1) -} - -func TestPodControllerLookup(t *testing.T) { - manager := NewReplicationManagerFromClient(clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}), controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - testCases := []struct { - inRCs []*api.ReplicationController - pod *api.Pod - outRCName string - }{ - // pods without labels don't match any rcs - { - inRCs: []*api.ReplicationController{ - {ObjectMeta: api.ObjectMeta{Name: "basic"}}}, - pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo1", Namespace: api.NamespaceAll}}, - outRCName: "", - }, - // Matching labels, not namespace - { - inRCs: []*api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"foo": "bar"}, - }, - }, - }, - pod: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo2", Namespace: "ns", Labels: map[string]string{"foo": "bar"}}}, - outRCName: "", - }, - // Matching ns and labels returns the key to the rc, not the rc name - { - inRCs: []*api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"foo": "bar"}, - }, - }, - }, - pod: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo3", Namespace: "ns", Labels: map[string]string{"foo": "bar"}}}, - outRCName: "bar", - }, - } - for _, c := range testCases { - for _, r := range c.inRCs { - manager.rcStore.Indexer.Add(r) - } - if rc := manager.getPodController(c.pod); rc != nil { - if c.outRCName != rc.Name { - t.Errorf("Got controller %+v expected %+v", rc.Name, c.outRCName) - } - } else if c.outRCName != "" { - t.Errorf("Expected a controller %v pod %v, found none", c.outRCName, c.pod.Name) - } - } -} - -func TestWatchControllers(t *testing.T) { - fakeWatch := watch.NewFake() - c := &fake.Clientset{} - c.AddWatchReactor("*", core.DefaultWatchReactor(fakeWatch, nil)) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - var testControllerSpec api.ReplicationController - received := make(chan string) - - // The update sent through the fakeWatcher should make its way into the workqueue, - // and eventually into the syncHandler. The handler validates the received controller - // and closes the received channel to indicate that the test can finish. - manager.syncHandler = func(key string) error { - - obj, exists, err := manager.rcStore.Indexer.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find controller under key %v", key) - } - controllerSpec := *obj.(*api.ReplicationController) - if !api.Semantic.DeepDerivative(controllerSpec, testControllerSpec) { - t.Errorf("Expected %#v, but got %#v", testControllerSpec, controllerSpec) - } - close(received) - return nil - } - // Start only the rc watcher and the workqueue, send a watch event, - // and make sure it hits the sync method. - stopCh := make(chan struct{}) - defer close(stopCh) - go manager.rcController.Run(stopCh) - go wait.Until(manager.worker, 10*time.Millisecond, stopCh) - - testControllerSpec.Name = "foo" - fakeWatch.Add(&testControllerSpec) - - select { - case <-received: - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Expected 1 call but got 0") - } -} - -func TestWatchPods(t *testing.T) { - fakeWatch := watch.NewFake() - c := &fake.Clientset{} - c.AddWatchReactor("*", core.DefaultWatchReactor(fakeWatch, nil)) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - // Put one rc and one pod into the controller's stores - testControllerSpec := newReplicationController(1) - manager.rcStore.Indexer.Add(testControllerSpec) - received := make(chan string) - // The pod update sent through the fakeWatcher should figure out the managing rc and - // send it into the syncHandler. - manager.syncHandler = func(key string) error { - - obj, exists, err := manager.rcStore.Indexer.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find controller under key %v", key) - } - controllerSpec := obj.(*api.ReplicationController) - if !api.Semantic.DeepDerivative(controllerSpec, testControllerSpec) { - t.Errorf("\nExpected %#v,\nbut got %#v", testControllerSpec, controllerSpec) - } - close(received) - return nil - } - // Start only the pod watcher and the workqueue, send a watch event, - // and make sure it hits the sync method for the right rc. - stopCh := make(chan struct{}) - defer close(stopCh) - go manager.podController.Run(stopCh) - go manager.internalPodInformer.Run(stopCh) - go wait.Until(manager.worker, 10*time.Millisecond, stopCh) - - pods := newPodList(nil, 1, api.PodRunning, testControllerSpec, "pod") - testPod := pods.Items[0] - testPod.Status.Phase = api.PodFailed - fakeWatch.Add(&testPod) - - select { - case <-received: - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Expected 1 call but got 0") - } -} - -func TestUpdatePods(t *testing.T) { - manager := NewReplicationManagerFromClient(fake.NewSimpleClientset(), controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - received := make(chan string) - - manager.syncHandler = func(key string) error { - obj, exists, err := manager.rcStore.Indexer.GetByKey(key) - if !exists || err != nil { - t.Errorf("Expected to find controller under key %v", key) - } - received <- obj.(*api.ReplicationController).Name - return nil - } - - stopCh := make(chan struct{}) - defer close(stopCh) - go wait.Until(manager.worker, 10*time.Millisecond, stopCh) - - // Put 2 rcs and one pod into the controller's stores - testControllerSpec1 := newReplicationController(1) - manager.rcStore.Indexer.Add(testControllerSpec1) - testControllerSpec2 := *testControllerSpec1 - testControllerSpec2.Spec.Selector = map[string]string{"bar": "foo"} - testControllerSpec2.Name = "barfoo" - manager.rcStore.Indexer.Add(&testControllerSpec2) - - // Put one pod in the podStore - pod1 := newPodList(manager.podStore.Indexer, 1, api.PodRunning, testControllerSpec1, "pod").Items[0] - pod2 := pod1 - pod2.Labels = testControllerSpec2.Spec.Selector - - // Send an update of the same pod with modified labels, and confirm we get a sync request for - // both controllers - manager.updatePod(&pod1, &pod2) - - expected := sets.NewString(testControllerSpec1.Name, testControllerSpec2.Name) - for _, name := range expected.List() { - t.Logf("Expecting update for %+v", name) - select { - case got := <-received: - if !expected.Has(got) { - t.Errorf("Expected keys %#v got %v", expected, got) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("Expected update notifications for controllers within 100ms each") - } - } -} - -func TestControllerUpdateRequeue(t *testing.T) { - // This server should force a requeue of the controller because it fails to update status.Replicas. - fakeHandler := utiltesting.FakeHandler{ - StatusCode: 500, - ResponseBody: "", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - - c := clientset.NewForConfigOrDie(&restclient.Config{Host: testServer.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, BurstReplicas, 0) - manager.podStoreSynced = alwaysReady - - rc := newReplicationController(1) - manager.rcStore.Indexer.Add(rc) - rc.Status = api.ReplicationControllerStatus{Replicas: 2} - newPodList(manager.podStore.Indexer, 1, api.PodRunning, rc, "pod") - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - - manager.syncReplicationController(getKey(rc, t)) - - ch := make(chan interface{}) - go func() { - item, _ := manager.queue.Get() - ch <- item - }() - select { - case key := <-ch: - expectedKey := getKey(rc, t) - if key != expectedKey { - t.Errorf("Expected requeue of controller with key %s got %s", expectedKey, key) - } - case <-time.After(wait.ForeverTestTimeout): - manager.queue.ShutDown() - t.Errorf("Expected to find an rc in the queue, found none.") - } - // 1 Update and 1 GET, both of which fail - fakeHandler.ValidateRequestCount(t, 2) -} - -func TestControllerUpdateStatusWithFailure(t *testing.T) { - rc := newReplicationController(1) - c := &fake.Clientset{} - c.AddReactor("get", "replicationcontrollers", func(action core.Action) (bool, runtime.Object, error) { - return true, rc, nil - }) - c.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { - return true, &api.ReplicationController{}, fmt.Errorf("Fake error") - }) - fakeRCClient := c.Core().ReplicationControllers("default") - numReplicas := 10 - updateReplicaCount(fakeRCClient, *rc, numReplicas, 0) - updates, gets := 0, 0 - for _, a := range c.Actions() { - if a.GetResource().Resource != "replicationcontrollers" { - t.Errorf("Unexpected action %+v", a) - continue - } - - switch action := a.(type) { - case core.GetAction: - gets++ - // Make sure the get is for the right rc even though the update failed. - if action.GetName() != rc.Name { - t.Errorf("Expected get for rc %v, got %+v instead", rc.Name, action.GetName()) - } - case core.UpdateAction: - updates++ - // Confirm that the update has the right status.Replicas even though the Get - // returned an rc with replicas=1. - if c, ok := action.GetObject().(*api.ReplicationController); !ok { - t.Errorf("Expected an rc as the argument to update, got %T", c) - } else if c.Status.Replicas != int32(numReplicas) { - t.Errorf("Expected update for rc to contain replicas %v, got %v instead", - numReplicas, c.Status.Replicas) - } - default: - t.Errorf("Unexpected action %+v", a) - break - } - } - if gets != 1 || updates != 2 { - t.Errorf("Expected 1 get and 2 updates, got %d gets %d updates", gets, updates) - } -} - -// TODO: This test is too hairy for a unittest. It should be moved to an E2E suite. -func doTestControllerBurstReplicas(t *testing.T, burstReplicas, numReplicas int) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, burstReplicas, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - controllerSpec := newReplicationController(numReplicas) - manager.rcStore.Indexer.Add(controllerSpec) - - expectedPods := 0 - pods := newPodList(nil, numReplicas, api.PodPending, controllerSpec, "pod") - - rcKey, err := controller.KeyFunc(controllerSpec) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", controllerSpec, err) - } - - // Size up the controller, then size it down, and confirm the expected create/delete pattern - for _, replicas := range []int{numReplicas, 0} { - - controllerSpec.Spec.Replicas = int32(replicas) - manager.rcStore.Indexer.Add(controllerSpec) - - for i := 0; i < numReplicas; i += burstReplicas { - manager.syncReplicationController(getKey(controllerSpec, t)) - - // The store accrues active pods. It's also used by the rc to determine how many - // replicas to create. - activePods := len(manager.podStore.Indexer.List()) - if replicas != 0 { - // This is the number of pods currently "in flight". They were created by the rc manager above, - // which then puts the rc to sleep till all of them have been observed. - expectedPods = replicas - activePods - if expectedPods > burstReplicas { - expectedPods = burstReplicas - } - // This validates the rc manager sync actually created pods - validateSyncReplication(t, &fakePodControl, expectedPods, 0) - - // This simulates the watch events for all but 1 of the expected pods. - // None of these should wake the controller because it has expectations==BurstReplicas. - for i := 0; i < expectedPods-1; i++ { - manager.podStore.Indexer.Add(&pods.Items[i]) - manager.addPod(&pods.Items[i]) - } - - podExp, exists, err := manager.expectations.GetExpectations(rcKey) - if !exists || err != nil { - t.Fatalf("Did not find expectations for rc.") - } - if add, _ := podExp.GetExpectations(); add != 1 { - t.Fatalf("Expectations are wrong %v", podExp) - } - } else { - expectedPods = (replicas - activePods) * -1 - if expectedPods > burstReplicas { - expectedPods = burstReplicas - } - validateSyncReplication(t, &fakePodControl, 0, expectedPods) - - // To accurately simulate a watch we must delete the exact pods - // the rc is waiting for. - expectedDels := manager.expectations.GetUIDs(getKey(controllerSpec, t)) - podsToDelete := []*api.Pod{} - for _, key := range expectedDels.List() { - nsName := strings.Split(key, "/") - podsToDelete = append(podsToDelete, &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: nsName[1], - Namespace: nsName[0], - Labels: controllerSpec.Spec.Selector, - }, - }) - } - // Don't delete all pods because we confirm that the last pod - // has exactly one expectation at the end, to verify that we - // don't double delete. - for i := range podsToDelete[1:] { - manager.podStore.Indexer.Delete(podsToDelete[i]) - manager.deletePod(podsToDelete[i]) - } - podExp, exists, err := manager.expectations.GetExpectations(rcKey) - if !exists || err != nil { - t.Fatalf("Did not find expectations for rc.") - } - if _, del := podExp.GetExpectations(); del != 1 { - t.Fatalf("Expectations are wrong %v", podExp) - } - } - - // Check that the rc didn't take any action for all the above pods - fakePodControl.Clear() - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 0, 0) - - // Create/Delete the last pod - // The last add pod will decrease the expectation of the rc to 0, - // which will cause it to create/delete the remaining replicas up to burstReplicas. - if replicas != 0 { - manager.podStore.Indexer.Add(&pods.Items[expectedPods-1]) - manager.addPod(&pods.Items[expectedPods-1]) - } else { - expectedDel := manager.expectations.GetUIDs(getKey(controllerSpec, t)) - if expectedDel.Len() != 1 { - t.Fatalf("Waiting on unexpected number of deletes.") - } - nsName := strings.Split(expectedDel.List()[0], "/") - lastPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: nsName[1], - Namespace: nsName[0], - Labels: controllerSpec.Spec.Selector, - }, - } - manager.podStore.Indexer.Delete(lastPod) - manager.deletePod(lastPod) - } - pods.Items = pods.Items[expectedPods:] - } - - // Confirm that we've created the right number of replicas - activePods := int32(len(manager.podStore.Indexer.List())) - if activePods != controllerSpec.Spec.Replicas { - t.Fatalf("Unexpected number of active pods, expected %d, got %d", controllerSpec.Spec.Replicas, activePods) - } - // Replenish the pod list, since we cut it down sizing up - pods = newPodList(nil, replicas, api.PodRunning, controllerSpec, "pod") - } -} - -func TestControllerBurstReplicas(t *testing.T) { - doTestControllerBurstReplicas(t, 5, 30) - doTestControllerBurstReplicas(t, 5, 12) - doTestControllerBurstReplicas(t, 3, 2) -} - -type FakeRCExpectations struct { - *controller.ControllerExpectations - satisfied bool - expSatisfied func() -} - -func (fe FakeRCExpectations) SatisfiedExpectations(controllerKey string) bool { - fe.expSatisfied() - return fe.satisfied -} - -// TestRCSyncExpectations tests that a pod cannot sneak in between counting active pods -// and checking expectations. -func TestRCSyncExpectations(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, 2, 0) - manager.podStoreSynced = alwaysReady - manager.podControl = &fakePodControl - - controllerSpec := newReplicationController(2) - manager.rcStore.Indexer.Add(controllerSpec) - pods := newPodList(nil, 2, api.PodPending, controllerSpec, "pod") - manager.podStore.Indexer.Add(&pods.Items[0]) - postExpectationsPod := pods.Items[1] - - manager.expectations = controller.NewUIDTrackingControllerExpectations(FakeRCExpectations{ - controller.NewControllerExpectations(), true, func() { - // If we check active pods before checking expectataions, the rc - // will create a new replica because it doesn't see this pod, but - // has fulfilled its expectations. - manager.podStore.Indexer.Add(&postExpectationsPod) - }, - }) - manager.syncReplicationController(getKey(controllerSpec, t)) - validateSyncReplication(t, &fakePodControl, 0, 0) -} - -func TestDeleteControllerAndExpectations(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, 10, 0) - manager.podStoreSynced = alwaysReady - - rc := newReplicationController(1) - manager.rcStore.Indexer.Add(rc) - - fakePodControl := controller.FakePodControl{} - manager.podControl = &fakePodControl - - // This should set expectations for the rc - manager.syncReplicationController(getKey(rc, t)) - validateSyncReplication(t, &fakePodControl, 1, 0) - fakePodControl.Clear() - - // Get the RC key - rcKey, err := controller.KeyFunc(rc) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", rc, err) - } - - // This is to simulate a concurrent addPod, that has a handle on the expectations - // as the controller deletes it. - podExp, exists, err := manager.expectations.GetExpectations(rcKey) - if !exists || err != nil { - t.Errorf("No expectations found for rc") - } - manager.rcStore.Indexer.Delete(rc) - manager.syncReplicationController(getKey(rc, t)) - - if _, exists, err = manager.expectations.GetExpectations(rcKey); exists { - t.Errorf("Found expectaions, expected none since the rc has been deleted.") - } - - // This should have no effect, since we've deleted the rc. - podExp.Add(-1, 0) - manager.podStore.Indexer.Replace(make([]interface{}, 0), "0") - manager.syncReplicationController(getKey(rc, t)) - validateSyncReplication(t, &fakePodControl, 0, 0) -} - -func TestRCManagerNotReady(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - fakePodControl := controller.FakePodControl{} - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, 2, 0) - manager.podControl = &fakePodControl - manager.podStoreSynced = func() bool { return false } - - // Simulates the rc reflector running before the pod reflector. We don't - // want to end up creating replicas in this case until the pod reflector - // has synced, so the rc manager should just requeue the rc. - controllerSpec := newReplicationController(1) - manager.rcStore.Indexer.Add(controllerSpec) - - rcKey := getKey(controllerSpec, t) - manager.syncReplicationController(rcKey) - validateSyncReplication(t, &fakePodControl, 0, 0) - queueRC, _ := manager.queue.Get() - if queueRC != rcKey { - t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) - } - - manager.podStoreSynced = alwaysReady - manager.syncReplicationController(rcKey) - validateSyncReplication(t, &fakePodControl, 1, 0) -} - -// shuffle returns a new shuffled list of container controllers. -func shuffle(controllers []*api.ReplicationController) []*api.ReplicationController { - numControllers := len(controllers) - randIndexes := rand.Perm(numControllers) - shuffled := make([]*api.ReplicationController, numControllers) - for i := 0; i < numControllers; i++ { - shuffled[i] = controllers[randIndexes[i]] - } - return shuffled -} - -func TestOverlappingRCs(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - - for i := 0; i < 5; i++ { - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, 10, 0) - manager.podStoreSynced = alwaysReady - - // Create 10 rcs, shuffled them randomly and insert them into the rc manager's store - var controllers []*api.ReplicationController - for j := 1; j < 10; j++ { - controllerSpec := newReplicationController(1) - controllerSpec.CreationTimestamp = unversioned.Date(2014, time.December, j, 0, 0, 0, 0, time.Local) - controllerSpec.Name = string(util.NewUUID()) - controllers = append(controllers, controllerSpec) - } - shuffledControllers := shuffle(controllers) - for j := range shuffledControllers { - manager.rcStore.Indexer.Add(shuffledControllers[j]) - } - // Add a pod and make sure only the oldest rc is synced - pods := newPodList(nil, 1, api.PodPending, controllers[0], "pod") - rcKey := getKey(controllers[0], t) - - manager.addPod(&pods.Items[0]) - queueRC, _ := manager.queue.Get() - if queueRC != rcKey { - t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) - } - } -} - -func TestDeletionTimestamp(t *testing.T) { - c := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(c, controller.NoResyncPeriodFunc, 10, 0) - manager.podStoreSynced = alwaysReady - - controllerSpec := newReplicationController(1) - manager.rcStore.Indexer.Add(controllerSpec) - rcKey, err := controller.KeyFunc(controllerSpec) - if err != nil { - t.Errorf("Couldn't get key for object %+v: %v", controllerSpec, err) - } - pod := newPodList(nil, 1, api.PodPending, controllerSpec, "pod").Items[0] - pod.DeletionTimestamp = &unversioned.Time{Time: time.Now()} - manager.expectations.ExpectDeletions(rcKey, []string{controller.PodKey(&pod)}) - - // A pod added with a deletion timestamp should decrement deletions, not creations. - manager.addPod(&pod) - - queueRC, _ := manager.queue.Get() - if queueRC != rcKey { - t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) - } - manager.queue.Done(rcKey) - - podExp, exists, err := manager.expectations.GetExpectations(rcKey) - if !exists || err != nil || !podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // An update from no deletion timestamp to having one should be treated - // as a deletion. - oldPod := newPodList(nil, 1, api.PodPending, controllerSpec, "pod").Items[0] - manager.expectations.ExpectDeletions(rcKey, []string{controller.PodKey(&pod)}) - manager.updatePod(&oldPod, &pod) - - queueRC, _ = manager.queue.Get() - if queueRC != rcKey { - t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) - } - manager.queue.Done(rcKey) - - podExp, exists, err = manager.expectations.GetExpectations(rcKey) - if !exists || err != nil || !podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // An update to the pod (including an update to the deletion timestamp) - // should not be counted as a second delete. - secondPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: pod.Namespace, - Name: "secondPod", - Labels: pod.Labels, - }, - } - manager.expectations.ExpectDeletions(rcKey, []string{controller.PodKey(secondPod)}) - oldPod.DeletionTimestamp = &unversioned.Time{Time: time.Now()} - manager.updatePod(&oldPod, &pod) - - podExp, exists, err = manager.expectations.GetExpectations(rcKey) - if !exists || err != nil || podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // A pod with a non-nil deletion timestamp should also be ignored by the - // delete handler, because it's already been counted in the update. - manager.deletePod(&pod) - podExp, exists, err = manager.expectations.GetExpectations(rcKey) - if !exists || err != nil || podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } - - // Deleting the second pod should clear expectations. - manager.deletePod(secondPod) - - queueRC, _ = manager.queue.Get() - if queueRC != rcKey { - t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) - } - manager.queue.Done(rcKey) - - podExp, exists, err = manager.expectations.GetExpectations(rcKey) - if !exists || err != nil || !podExp.Fulfilled() { - t.Fatalf("Wrong expectations %+v", podExp) - } -} - -func BenchmarkGetPodControllerMultiNS(b *testing.B) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - - const nsNum = 1000 - - pods := []api.Pod{} - for i := 0; i < nsNum; i++ { - ns := fmt.Sprintf("ns-%d", i) - for j := 0; j < 10; j++ { - rcName := fmt.Sprintf("rc-%d", j) - for k := 0; k < 10; k++ { - podName := fmt.Sprintf("pod-%d-%d", j, k) - pods = append(pods, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: podName, - Namespace: ns, - Labels: map[string]string{"rcName": rcName}, - }, - }) - } - } - } - - for i := 0; i < nsNum; i++ { - ns := fmt.Sprintf("ns-%d", i) - for j := 0; j < 10; j++ { - rcName := fmt.Sprintf("rc-%d", j) - manager.rcStore.Indexer.Add(&api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: rcName, Namespace: ns}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"rcName": rcName}, - }, - }) - } - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - for _, pod := range pods { - manager.getPodController(&pod) - } - } -} - -func BenchmarkGetPodControllerSingleNS(b *testing.B) { - client := clientset.NewForConfigOrDie(&restclient.Config{Host: "", ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) - manager := NewReplicationManagerFromClient(client, controller.NoResyncPeriodFunc, BurstReplicas, 0) - - const rcNum = 1000 - const replicaNum = 3 - - pods := []api.Pod{} - for i := 0; i < rcNum; i++ { - rcName := fmt.Sprintf("rc-%d", i) - for j := 0; j < replicaNum; j++ { - podName := fmt.Sprintf("pod-%d-%d", i, j) - pods = append(pods, api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: podName, - Namespace: "foo", - Labels: map[string]string{"rcName": rcName}, - }, - }) - } - } - - for i := 0; i < rcNum; i++ { - rcName := fmt.Sprintf("rc-%d", i) - manager.rcStore.Indexer.Add(&api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: rcName, Namespace: "foo"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{"rcName": rcName}, - }, - }) - } - b.ResetTimer() - - for i := 0; i < b.N; i++ { - for _, pod := range pods { - manager.getPodController(&pod) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller_utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller_utils.go deleted file mode 100644 index 0383fa946..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/replication/replication_controller_utils.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// If you make changes to this file, you should also make the corresponding change in ReplicaSet. - -package replication - -import ( - "fmt" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - unversionedcore "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" -) - -// updateReplicaCount attempts to update the Status.Replicas of the given controller, with a single GET/PUT retry. -func updateReplicaCount(rcClient unversionedcore.ReplicationControllerInterface, controller api.ReplicationController, numReplicas, numFullyLabeledReplicas int) (updateErr error) { - // This is the steady state. It happens when the rc doesn't have any expectations, since - // we do a periodic relist every 30s. If the generations differ but the replicas are - // the same, a caller might've resized to the same replica count. - if int(controller.Status.Replicas) == numReplicas && - int(controller.Status.FullyLabeledReplicas) == numFullyLabeledReplicas && - controller.Generation == controller.Status.ObservedGeneration { - return nil - } - // Save the generation number we acted on, otherwise we might wrongfully indicate - // that we've seen a spec update when we retry. - // TODO: This can clobber an update if we allow multiple agents to write to the - // same status. - generation := controller.Generation - - var getErr error - for i, rc := 0, &controller; ; i++ { - glog.V(4).Infof(fmt.Sprintf("Updating replica count for rc: %s/%s, ", controller.Namespace, controller.Name) + - fmt.Sprintf("replicas %d->%d (need %d), ", controller.Status.Replicas, numReplicas, controller.Spec.Replicas) + - fmt.Sprintf("fullyLabeledReplicas %d->%d, ", controller.Status.FullyLabeledReplicas, numFullyLabeledReplicas) + - fmt.Sprintf("sequence No: %v->%v", controller.Status.ObservedGeneration, generation)) - - rc.Status = api.ReplicationControllerStatus{Replicas: int32(numReplicas), FullyLabeledReplicas: int32(numFullyLabeledReplicas), ObservedGeneration: generation} - _, updateErr = rcClient.UpdateStatus(rc) - if updateErr == nil || i >= statusUpdateRetries { - return updateErr - } - // Update the controller with the latest resource version for the next poll - if rc, getErr = rcClient.Get(controller.Name); getErr != nil { - // If the GET fails we can't trust status.Replicas anymore. This error - // is bound to be more interesting than the update failure. - return getErr - } - } -} - -// OverlappingControllers sorts a list of controllers by creation timestamp, using their names as a tie breaker. -type OverlappingControllers []api.ReplicationController - -func (o OverlappingControllers) Len() int { return len(o) } -func (o OverlappingControllers) Swap(i, j int) { o[i], o[j] = o[j], o[i] } - -func (o OverlappingControllers) Less(i, j int) bool { - if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) { - return o[i].Name < o[j].Name - } - return o[i].CreationTimestamp.Before(o[j].CreationTimestamp) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/doc.go deleted file mode 100644 index a83ad10dd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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. -*/ - -// resourcequota contains a controller that makes resource quota usage observations -package resourcequota diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/replenishment_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/replenishment_controller.go deleted file mode 100644 index a344bec87..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/replenishment_controller.go +++ /dev/null @@ -1,231 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 resourcequota - -import ( - "fmt" - - "github.com/golang/glog" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/controller/framework/informers" - "k8s.io/kubernetes/pkg/quota/evaluator/core" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/watch" -) - -// ReplenishmentFunc is a function that is invoked when controller sees a change -// that may require a quota to be replenished (i.e. object deletion, or object moved to terminal state) -type ReplenishmentFunc func(groupKind unversioned.GroupKind, namespace string, object runtime.Object) - -// ReplenishmentControllerOptions is an options struct that tells a factory -// how to configure a controller that can inform the quota system it should -// replenish quota -type ReplenishmentControllerOptions struct { - // The kind monitored for replenishment - GroupKind unversioned.GroupKind - // The period that should be used to re-sync the monitored resource - ResyncPeriod controller.ResyncPeriodFunc - // The function to invoke when a change is observed that should trigger - // replenishment - ReplenishmentFunc ReplenishmentFunc -} - -// PodReplenishmentUpdateFunc will replenish if the old pod was quota tracked but the new is not -func PodReplenishmentUpdateFunc(options *ReplenishmentControllerOptions) func(oldObj, newObj interface{}) { - return func(oldObj, newObj interface{}) { - oldPod := oldObj.(*api.Pod) - newPod := newObj.(*api.Pod) - if core.QuotaPod(oldPod) && !core.QuotaPod(newPod) { - options.ReplenishmentFunc(options.GroupKind, newPod.Namespace, newPod) - } - } -} - -// ObjectReplenenishmentDeleteFunc will replenish on every delete -func ObjectReplenishmentDeleteFunc(options *ReplenishmentControllerOptions) func(obj interface{}) { - return func(obj interface{}) { - metaObject, err := meta.Accessor(obj) - if err != nil { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.Errorf("replenishment controller could not get object from tombstone %+v, could take up to %v before quota is replenished", obj, options.ResyncPeriod()) - utilruntime.HandleError(err) - return - } - metaObject, err = meta.Accessor(tombstone.Obj) - if err != nil { - glog.Errorf("replenishment controller tombstone contained object that is not a meta %+v, could take up to %v before quota is replenished", tombstone.Obj, options.ResyncPeriod()) - utilruntime.HandleError(err) - return - } - } - options.ReplenishmentFunc(options.GroupKind, metaObject.GetNamespace(), nil) - } -} - -// ReplenishmentControllerFactory knows how to build replenishment controllers -type ReplenishmentControllerFactory interface { - // NewController returns a controller configured with the specified options. - // This method is NOT thread-safe. - NewController(options *ReplenishmentControllerOptions) (framework.ControllerInterface, error) -} - -// replenishmentControllerFactory implements ReplenishmentControllerFactory -type replenishmentControllerFactory struct { - kubeClient clientset.Interface - podInformer framework.SharedInformer -} - -// NewReplenishmentControllerFactory returns a factory that knows how to build controllers -// to replenish resources when updated or deleted -func NewReplenishmentControllerFactory(podInformer framework.SharedInformer, kubeClient clientset.Interface) ReplenishmentControllerFactory { - return &replenishmentControllerFactory{ - kubeClient: kubeClient, - podInformer: podInformer, - } -} - -func NewReplenishmentControllerFactoryFromClient(kubeClient clientset.Interface) ReplenishmentControllerFactory { - return NewReplenishmentControllerFactory(nil, kubeClient) -} - -func (r *replenishmentControllerFactory) NewController(options *ReplenishmentControllerOptions) (framework.ControllerInterface, error) { - var result framework.ControllerInterface - if r.kubeClient != nil && r.kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("replenishment_controller", r.kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - - switch options.GroupKind { - case api.Kind("Pod"): - if r.podInformer != nil { - r.podInformer.AddEventHandler(framework.ResourceEventHandlerFuncs{ - UpdateFunc: PodReplenishmentUpdateFunc(options), - DeleteFunc: ObjectReplenishmentDeleteFunc(options), - }) - result = r.podInformer.GetController() - break - } - - r.podInformer = informers.CreateSharedPodInformer(r.kubeClient, options.ResyncPeriod()) - result = r.podInformer - - case api.Kind("Service"): - _, result = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return r.kubeClient.Core().Services(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return r.kubeClient.Core().Services(api.NamespaceAll).Watch(options) - }, - }, - &api.Service{}, - options.ResyncPeriod(), - framework.ResourceEventHandlerFuncs{ - UpdateFunc: ServiceReplenishmentUpdateFunc(options), - DeleteFunc: ObjectReplenishmentDeleteFunc(options), - }, - ) - case api.Kind("ReplicationController"): - _, result = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return r.kubeClient.Core().ReplicationControllers(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return r.kubeClient.Core().ReplicationControllers(api.NamespaceAll).Watch(options) - }, - }, - &api.ReplicationController{}, - options.ResyncPeriod(), - framework.ResourceEventHandlerFuncs{ - DeleteFunc: ObjectReplenishmentDeleteFunc(options), - }, - ) - case api.Kind("PersistentVolumeClaim"): - _, result = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return r.kubeClient.Core().PersistentVolumeClaims(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return r.kubeClient.Core().PersistentVolumeClaims(api.NamespaceAll).Watch(options) - }, - }, - &api.PersistentVolumeClaim{}, - options.ResyncPeriod(), - framework.ResourceEventHandlerFuncs{ - DeleteFunc: ObjectReplenishmentDeleteFunc(options), - }, - ) - case api.Kind("Secret"): - _, result = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return r.kubeClient.Core().Secrets(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return r.kubeClient.Core().Secrets(api.NamespaceAll).Watch(options) - }, - }, - &api.Secret{}, - options.ResyncPeriod(), - framework.ResourceEventHandlerFuncs{ - DeleteFunc: ObjectReplenishmentDeleteFunc(options), - }, - ) - case api.Kind("ConfigMap"): - _, result = framework.NewInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return r.kubeClient.Core().ConfigMaps(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return r.kubeClient.Core().ConfigMaps(api.NamespaceAll).Watch(options) - }, - }, - &api.ConfigMap{}, - options.ResyncPeriod(), - framework.ResourceEventHandlerFuncs{ - DeleteFunc: ObjectReplenishmentDeleteFunc(options), - }, - ) - default: - return nil, fmt.Errorf("no replenishment controller available for %s", options.GroupKind) - } - return result, nil -} - -// ServiceReplenishmentUpdateFunc will replenish if the old service was quota tracked but the new is not -func ServiceReplenishmentUpdateFunc(options *ReplenishmentControllerOptions) func(oldObj, newObj interface{}) { - return func(oldObj, newObj interface{}) { - oldService := oldObj.(*api.Service) - newService := newObj.(*api.Service) - if core.QuotaServiceType(oldService) || core.QuotaServiceType(newService) { - options.ReplenishmentFunc(options.GroupKind, newService.Namespace, newService) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/replenishment_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/replenishment_controller_test.go deleted file mode 100644 index b7bb66502..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/replenishment_controller_test.go +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 resourcequota - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/intstr" -) - -// testReplenishment lets us test replenishment functions are invoked -type testReplenishment struct { - groupKind unversioned.GroupKind - namespace string -} - -// mock function that holds onto the last kind that was replenished -func (t *testReplenishment) Replenish(groupKind unversioned.GroupKind, namespace string, object runtime.Object) { - t.groupKind = groupKind - t.namespace = namespace -} - -func TestPodReplenishmentUpdateFunc(t *testing.T) { - mockReplenish := &testReplenishment{} - options := ReplenishmentControllerOptions{ - GroupKind: api.Kind("Pod"), - ReplenishmentFunc: mockReplenish.Replenish, - ResyncPeriod: controller.NoResyncPeriodFunc, - } - oldPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "pod"}, - Status: api.PodStatus{Phase: api.PodRunning}, - } - newPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "pod"}, - Status: api.PodStatus{Phase: api.PodFailed}, - } - updateFunc := PodReplenishmentUpdateFunc(&options) - updateFunc(oldPod, newPod) - if mockReplenish.groupKind != api.Kind("Pod") { - t.Errorf("Unexpected group kind %v", mockReplenish.groupKind) - } - if mockReplenish.namespace != oldPod.Namespace { - t.Errorf("Unexpected namespace %v", mockReplenish.namespace) - } -} - -func TestObjectReplenishmentDeleteFunc(t *testing.T) { - mockReplenish := &testReplenishment{} - options := ReplenishmentControllerOptions{ - GroupKind: api.Kind("Pod"), - ReplenishmentFunc: mockReplenish.Replenish, - ResyncPeriod: controller.NoResyncPeriodFunc, - } - oldPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "pod"}, - Status: api.PodStatus{Phase: api.PodRunning}, - } - deleteFunc := ObjectReplenishmentDeleteFunc(&options) - deleteFunc(oldPod) - if mockReplenish.groupKind != api.Kind("Pod") { - t.Errorf("Unexpected group kind %v", mockReplenish.groupKind) - } - if mockReplenish.namespace != oldPod.Namespace { - t.Errorf("Unexpected namespace %v", mockReplenish.namespace) - } -} - -func TestServiceReplenishmentUpdateFunc(t *testing.T) { - mockReplenish := &testReplenishment{} - options := ReplenishmentControllerOptions{ - GroupKind: api.Kind("Service"), - ReplenishmentFunc: mockReplenish.Replenish, - ResyncPeriod: controller.NoResyncPeriodFunc, - } - oldService := &api.Service{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "mysvc"}, - Spec: api.ServiceSpec{ - Type: api.ServiceTypeNodePort, - Ports: []api.ServicePort{{ - Port: 80, - TargetPort: intstr.FromInt(80), - }}, - }, - } - newService := &api.Service{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "mysvc"}, - Spec: api.ServiceSpec{ - Type: api.ServiceTypeClusterIP, - Ports: []api.ServicePort{{ - Port: 80, - TargetPort: intstr.FromInt(80), - }}}, - } - updateFunc := ServiceReplenishmentUpdateFunc(&options) - updateFunc(oldService, newService) - if mockReplenish.groupKind != api.Kind("Service") { - t.Errorf("Unexpected group kind %v", mockReplenish.groupKind) - } - if mockReplenish.namespace != oldService.Namespace { - t.Errorf("Unexpected namespace %v", mockReplenish.namespace) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller.go deleted file mode 100644 index cb965ef7e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller.go +++ /dev/null @@ -1,321 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 resourcequota - -import ( - "time" - - "github.com/golang/glog" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/quota" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/util/workqueue" - "k8s.io/kubernetes/pkg/watch" -) - -// ResourceQuotaControllerOptions holds options for creating a quota controller -type ResourceQuotaControllerOptions struct { - // Must have authority to list all quotas, and update quota status - KubeClient clientset.Interface - // Controls full recalculation of quota usage - ResyncPeriod controller.ResyncPeriodFunc - // Knows how to calculate usage - Registry quota.Registry - // Knows how to build controllers that notify replenishment events - ControllerFactory ReplenishmentControllerFactory - // Controls full resync of objects monitored for replenihsment. - ReplenishmentResyncPeriod controller.ResyncPeriodFunc - // List of GroupKind objects that should be monitored for replenishment at - // a faster frequency than the quota controller recalculation interval - GroupKindsToReplenish []unversioned.GroupKind -} - -// ResourceQuotaController is responsible for tracking quota usage status in the system -type ResourceQuotaController struct { - // Must have authority to list all resources in the system, and update quota status - kubeClient clientset.Interface - // An index of resource quota objects by namespace - rqIndexer cache.Indexer - // Watches changes to all resource quota - rqController *framework.Controller - // ResourceQuota objects that need to be synchronized - queue *workqueue.Type - // To allow injection of syncUsage for testing. - syncHandler func(key string) error - // function that controls full recalculation of quota usage - resyncPeriod controller.ResyncPeriodFunc - // knows how to calculate usage - registry quota.Registry - // controllers monitoring to notify for replenishment - replenishmentControllers []framework.ControllerInterface -} - -func NewResourceQuotaController(options *ResourceQuotaControllerOptions) *ResourceQuotaController { - // build the resource quota controller - rq := &ResourceQuotaController{ - kubeClient: options.KubeClient, - queue: workqueue.New(), - resyncPeriod: options.ResyncPeriod, - registry: options.Registry, - replenishmentControllers: []framework.ControllerInterface{}, - } - if options.KubeClient != nil && options.KubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("resource_quota_controller", options.KubeClient.Core().GetRESTClient().GetRateLimiter()) - } - // set the synchronization handler - rq.syncHandler = rq.syncResourceQuotaFromKey - - // build the controller that observes quota - rq.rqIndexer, rq.rqController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return rq.kubeClient.Core().ResourceQuotas(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return rq.kubeClient.Core().ResourceQuotas(api.NamespaceAll).Watch(options) - }, - }, - &api.ResourceQuota{}, - rq.resyncPeriod(), - framework.ResourceEventHandlerFuncs{ - AddFunc: rq.enqueueResourceQuota, - UpdateFunc: func(old, cur interface{}) { - // We are only interested in observing updates to quota.spec to drive updates to quota.status. - // We ignore all updates to quota.Status because they are all driven by this controller. - // IMPORTANT: - // We do not use this function to queue up a full quota recalculation. To do so, would require - // us to enqueue all quota.Status updates, and since quota.Status updates involve additional queries - // that cannot be backed by a cache and result in a full query of a namespace's content, we do not - // want to pay the price on spurious status updates. As a result, we have a separate routine that is - // responsible for enqueue of all resource quotas when doing a full resync (enqueueAll) - oldResourceQuota := old.(*api.ResourceQuota) - curResourceQuota := cur.(*api.ResourceQuota) - if quota.Equals(curResourceQuota.Spec.Hard, oldResourceQuota.Spec.Hard) { - return - } - rq.enqueueResourceQuota(curResourceQuota) - }, - // This will enter the sync loop and no-op, because the controller has been deleted from the store. - // Note that deleting a controller immediately after scaling it to 0 will not work. The recommended - // way of achieving this is by performing a `stop` operation on the controller. - DeleteFunc: rq.enqueueResourceQuota, - }, - cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, - ) - - for _, groupKindToReplenish := range options.GroupKindsToReplenish { - controllerOptions := &ReplenishmentControllerOptions{ - GroupKind: groupKindToReplenish, - ResyncPeriod: options.ReplenishmentResyncPeriod, - ReplenishmentFunc: rq.replenishQuota, - } - replenishmentController, err := options.ControllerFactory.NewController(controllerOptions) - if err != nil { - glog.Warningf("quota controller unable to replenish %s due to %v, changes only accounted during full resync", groupKindToReplenish, err) - } else { - rq.replenishmentControllers = append(rq.replenishmentControllers, replenishmentController) - } - } - return rq -} - -// enqueueAll is called at the fullResyncPeriod interval to force a full recalculation of quota usage statistics -func (rq *ResourceQuotaController) enqueueAll() { - defer glog.V(4).Infof("Resource quota controller queued all resource quota for full calculation of usage") - for _, k := range rq.rqIndexer.ListKeys() { - rq.queue.Add(k) - } -} - -// obj could be an *api.ResourceQuota, or a DeletionFinalStateUnknown marker item. -func (rq *ResourceQuotaController) enqueueResourceQuota(obj interface{}) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - return - } - rq.queue.Add(key) -} - -// worker runs a worker thread that just dequeues items, processes them, and marks them done. -// It enforces that the syncHandler is never invoked concurrently with the same key. -func (rq *ResourceQuotaController) worker() { - for { - func() { - key, quit := rq.queue.Get() - if quit { - return - } - defer rq.queue.Done(key) - err := rq.syncHandler(key.(string)) - if err != nil { - utilruntime.HandleError(err) - rq.queue.Add(key) - } - }() - } -} - -// Run begins quota controller using the specified number of workers -func (rq *ResourceQuotaController) Run(workers int, stopCh <-chan struct{}) { - defer utilruntime.HandleCrash() - go rq.rqController.Run(stopCh) - // the controllers that replenish other resources to respond rapidly to state changes - for _, replenishmentController := range rq.replenishmentControllers { - go replenishmentController.Run(stopCh) - } - // the workers that chug through the quota calculation backlog - for i := 0; i < workers; i++ { - go wait.Until(rq.worker, time.Second, stopCh) - } - // the timer for how often we do a full recalculation across all quotas - go wait.Until(func() { rq.enqueueAll() }, rq.resyncPeriod(), stopCh) - <-stopCh - glog.Infof("Shutting down ResourceQuotaController") - rq.queue.ShutDown() -} - -// syncResourceQuotaFromKey syncs a quota key -func (rq *ResourceQuotaController) syncResourceQuotaFromKey(key string) (err error) { - startTime := time.Now() - defer func() { - glog.V(4).Infof("Finished syncing resource quota %q (%v)", key, time.Now().Sub(startTime)) - }() - - obj, exists, err := rq.rqIndexer.GetByKey(key) - if !exists { - glog.Infof("Resource quota has been deleted %v", key) - return nil - } - if err != nil { - glog.Infof("Unable to retrieve resource quota %v from store: %v", key, err) - rq.queue.Add(key) - return err - } - quota := *obj.(*api.ResourceQuota) - return rq.syncResourceQuota(quota) -} - -// syncResourceQuota runs a complete sync of resource quota status across all known kinds -func (rq *ResourceQuotaController) syncResourceQuota(resourceQuota api.ResourceQuota) (err error) { - // quota is dirty if any part of spec hard limits differs from the status hard limits - dirty := !api.Semantic.DeepEqual(resourceQuota.Spec.Hard, resourceQuota.Status.Hard) - - // dirty tracks if the usage status differs from the previous sync, - // if so, we send a new usage with latest status - // if this is our first sync, it will be dirty by default, since we need track usage - dirty = dirty || (resourceQuota.Status.Hard == nil || resourceQuota.Status.Used == nil) - - // Create a usage object that is based on the quota resource version that will handle updates - // by default, we preserve the past usage observation, and set hard to the current spec - previousUsed := api.ResourceList{} - if resourceQuota.Status.Used != nil { - previousUsed = quota.Add(api.ResourceList{}, resourceQuota.Status.Used) - } - usage := api.ResourceQuota{ - ObjectMeta: api.ObjectMeta{ - Name: resourceQuota.Name, - Namespace: resourceQuota.Namespace, - ResourceVersion: resourceQuota.ResourceVersion, - Labels: resourceQuota.Labels, - Annotations: resourceQuota.Annotations}, - Status: api.ResourceQuotaStatus{ - Hard: quota.Add(api.ResourceList{}, resourceQuota.Spec.Hard), - Used: previousUsed, - }, - } - - // find the intersection between the hard resources on the quota - // and the resources this controller can track to know what we can - // look to measure updated usage stats for - hardResources := quota.ResourceNames(usage.Status.Hard) - potentialResources := []api.ResourceName{} - evaluators := rq.registry.Evaluators() - for _, evaluator := range evaluators { - potentialResources = append(potentialResources, evaluator.MatchesResources()...) - } - matchedResources := quota.Intersection(hardResources, potentialResources) - - // sum the observed usage from each evaluator - newUsage := api.ResourceList{} - usageStatsOptions := quota.UsageStatsOptions{Namespace: resourceQuota.Namespace, Scopes: resourceQuota.Spec.Scopes} - for _, evaluator := range evaluators { - stats, err := evaluator.UsageStats(usageStatsOptions) - if err != nil { - return err - } - newUsage = quota.Add(newUsage, stats.Used) - } - - // mask the observed usage to only the set of resources tracked by this quota - // merge our observed usage with the quota usage status - // if the new usage is different than the last usage, we will need to do an update - newUsage = quota.Mask(newUsage, matchedResources) - for key, value := range newUsage { - usage.Status.Used[key] = value - } - - dirty = dirty || !quota.Equals(usage.Status.Used, resourceQuota.Status.Used) - - // there was a change observed by this controller that requires we update quota - if dirty { - _, err = rq.kubeClient.Core().ResourceQuotas(usage.Namespace).UpdateStatus(&usage) - return err - } - return nil -} - -// replenishQuota is a replenishment function invoked by a controller to notify that a quota should be recalculated -func (rq *ResourceQuotaController) replenishQuota(groupKind unversioned.GroupKind, namespace string, object runtime.Object) { - // check if the quota controller can evaluate this kind, if not, ignore it altogether... - evaluators := rq.registry.Evaluators() - evaluator, found := evaluators[groupKind] - if !found { - return - } - - // check if this namespace even has a quota... - indexKey := &api.ResourceQuota{} - indexKey.Namespace = namespace - resourceQuotas, err := rq.rqIndexer.Index("namespace", indexKey) - if err != nil { - glog.Errorf("quota controller could not find ResourceQuota associated with namespace: %s, could take up to %v before a quota replenishes", namespace, rq.resyncPeriod()) - } - if len(resourceQuotas) == 0 { - return - } - - // only queue those quotas that are tracking a resource associated with this kind. - matchedResources := evaluator.MatchesResources() - for i := range resourceQuotas { - resourceQuota := resourceQuotas[i].(*api.ResourceQuota) - resourceQuotaResources := quota.ResourceNames(resourceQuota.Status.Hard) - if len(quota.Intersection(matchedResources, resourceQuotaResources)) > 0 { - // TODO: make this support targeted replenishment to a specific kind, right now it does a full recalc on that quota. - rq.enqueueResourceQuota(resourceQuota) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller_test.go deleted file mode 100644 index 71ef5df79..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/resourcequota/resource_quota_controller_test.go +++ /dev/null @@ -1,302 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 resourcequota - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/quota/install" - "k8s.io/kubernetes/pkg/util/sets" -) - -func getResourceList(cpu, memory string) api.ResourceList { - res := api.ResourceList{} - if cpu != "" { - res[api.ResourceCPU] = resource.MustParse(cpu) - } - if memory != "" { - res[api.ResourceMemory] = resource.MustParse(memory) - } - return res -} - -func getResourceRequirements(requests, limits api.ResourceList) api.ResourceRequirements { - res := api.ResourceRequirements{} - res.Requests = requests - res.Limits = limits - return res -} - -func TestSyncResourceQuota(t *testing.T) { - podList := api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{Name: "pod-running", Namespace: "testing"}, - Status: api.PodStatus{Phase: api.PodRunning}, - Spec: api.PodSpec{ - Volumes: []api.Volume{{Name: "vol"}}, - Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", ""))}}, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "pod-running-2", Namespace: "testing"}, - Status: api.PodStatus{Phase: api.PodRunning}, - Spec: api.PodSpec{ - Volumes: []api.Volume{{Name: "vol"}}, - Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", ""))}}, - }, - }, - { - ObjectMeta: api.ObjectMeta{Name: "pod-failed", Namespace: "testing"}, - Status: api.PodStatus{Phase: api.PodFailed}, - Spec: api.PodSpec{ - Volumes: []api.Volume{{Name: "vol"}}, - Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements(getResourceList("100m", "1Gi"), getResourceList("", ""))}}, - }, - }, - }, - } - resourceQuota := api.ResourceQuota{ - ObjectMeta: api.ObjectMeta{Name: "quota", Namespace: "testing"}, - Spec: api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("3"), - api.ResourceMemory: resource.MustParse("100Gi"), - api.ResourcePods: resource.MustParse("5"), - }, - }, - } - expectedUsage := api.ResourceQuota{ - Status: api.ResourceQuotaStatus{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("3"), - api.ResourceMemory: resource.MustParse("100Gi"), - api.ResourcePods: resource.MustParse("5"), - }, - Used: api.ResourceList{ - api.ResourceCPU: resource.MustParse("200m"), - api.ResourceMemory: resource.MustParse("2Gi"), - api.ResourcePods: resource.MustParse("2"), - }, - }, - } - - kubeClient := fake.NewSimpleClientset(&podList, &resourceQuota) - resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ - KubeClient: kubeClient, - ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), - GroupKindsToReplenish: []unversioned.GroupKind{ - api.Kind("Pod"), - api.Kind("Service"), - api.Kind("ReplicationController"), - api.Kind("PersistentVolumeClaim"), - }, - ControllerFactory: NewReplenishmentControllerFactoryFromClient(kubeClient), - ReplenishmentResyncPeriod: controller.NoResyncPeriodFunc, - } - quotaController := NewResourceQuotaController(resourceQuotaControllerOptions) - err := quotaController.syncResourceQuota(resourceQuota) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - expectedActionSet := sets.NewString( - strings.Join([]string{"list", "replicationcontrollers", ""}, "-"), - strings.Join([]string{"list", "services", ""}, "-"), - strings.Join([]string{"list", "pods", ""}, "-"), - strings.Join([]string{"list", "resourcequotas", ""}, "-"), - strings.Join([]string{"list", "secrets", ""}, "-"), - strings.Join([]string{"list", "persistentvolumeclaims", ""}, "-"), - strings.Join([]string{"update", "resourcequotas", "status"}, "-"), - ) - actionSet := sets.NewString() - for _, action := range kubeClient.Actions() { - actionSet.Insert(strings.Join([]string{action.GetVerb(), action.GetResource().Resource, action.GetSubresource()}, "-")) - } - if !actionSet.HasAll(expectedActionSet.List()...) { - t.Errorf("Expected actions:\n%v\n but got:\n%v\nDifference:\n%v", expectedActionSet, actionSet, expectedActionSet.Difference(actionSet)) - } - - lastActionIndex := len(kubeClient.Actions()) - 1 - usage := kubeClient.Actions()[lastActionIndex].(core.UpdateAction).GetObject().(*api.ResourceQuota) - - // ensure hard and used limits are what we expected - for k, v := range expectedUsage.Status.Hard { - actual := usage.Status.Hard[k] - actualValue := actual.String() - expectedValue := v.String() - if expectedValue != actualValue { - t.Errorf("Usage Hard: Key: %v, Expected: %v, Actual: %v", k, expectedValue, actualValue) - } - } - for k, v := range expectedUsage.Status.Used { - actual := usage.Status.Used[k] - actualValue := actual.String() - expectedValue := v.String() - if expectedValue != actualValue { - t.Errorf("Usage Used: Key: %v, Expected: %v, Actual: %v", k, expectedValue, actualValue) - } - } -} - -func TestSyncResourceQuotaSpecChange(t *testing.T) { - resourceQuota := api.ResourceQuota{ - Spec: api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("4"), - }, - }, - Status: api.ResourceQuotaStatus{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("3"), - }, - Used: api.ResourceList{ - api.ResourceCPU: resource.MustParse("0"), - }, - }, - } - - expectedUsage := api.ResourceQuota{ - Status: api.ResourceQuotaStatus{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("4"), - }, - Used: api.ResourceList{ - api.ResourceCPU: resource.MustParse("0"), - }, - }, - } - - kubeClient := fake.NewSimpleClientset(&resourceQuota) - resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ - KubeClient: kubeClient, - ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), - GroupKindsToReplenish: []unversioned.GroupKind{ - api.Kind("Pod"), - api.Kind("Service"), - api.Kind("ReplicationController"), - api.Kind("PersistentVolumeClaim"), - }, - ControllerFactory: NewReplenishmentControllerFactoryFromClient(kubeClient), - ReplenishmentResyncPeriod: controller.NoResyncPeriodFunc, - } - quotaController := NewResourceQuotaController(resourceQuotaControllerOptions) - err := quotaController.syncResourceQuota(resourceQuota) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - - expectedActionSet := sets.NewString( - strings.Join([]string{"list", "replicationcontrollers", ""}, "-"), - strings.Join([]string{"list", "services", ""}, "-"), - strings.Join([]string{"list", "pods", ""}, "-"), - strings.Join([]string{"list", "resourcequotas", ""}, "-"), - strings.Join([]string{"list", "secrets", ""}, "-"), - strings.Join([]string{"list", "persistentvolumeclaims", ""}, "-"), - strings.Join([]string{"update", "resourcequotas", "status"}, "-"), - ) - actionSet := sets.NewString() - for _, action := range kubeClient.Actions() { - actionSet.Insert(strings.Join([]string{action.GetVerb(), action.GetResource().Resource, action.GetSubresource()}, "-")) - } - if !actionSet.HasAll(expectedActionSet.List()...) { - t.Errorf("Expected actions:\n%v\n but got:\n%v\nDifference:\n%v", expectedActionSet, actionSet, expectedActionSet.Difference(actionSet)) - } - - lastActionIndex := len(kubeClient.Actions()) - 1 - usage := kubeClient.Actions()[lastActionIndex].(core.UpdateAction).GetObject().(*api.ResourceQuota) - - // ensure hard and used limits are what we expected - for k, v := range expectedUsage.Status.Hard { - actual := usage.Status.Hard[k] - actualValue := actual.String() - expectedValue := v.String() - if expectedValue != actualValue { - t.Errorf("Usage Hard: Key: %v, Expected: %v, Actual: %v", k, expectedValue, actualValue) - } - } - for k, v := range expectedUsage.Status.Used { - actual := usage.Status.Used[k] - actualValue := actual.String() - expectedValue := v.String() - if expectedValue != actualValue { - t.Errorf("Usage Used: Key: %v, Expected: %v, Actual: %v", k, expectedValue, actualValue) - } - } - -} - -func TestSyncResourceQuotaNoChange(t *testing.T) { - resourceQuota := api.ResourceQuota{ - Spec: api.ResourceQuotaSpec{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("4"), - }, - }, - Status: api.ResourceQuotaStatus{ - Hard: api.ResourceList{ - api.ResourceCPU: resource.MustParse("4"), - }, - Used: api.ResourceList{ - api.ResourceCPU: resource.MustParse("0"), - }, - }, - } - - kubeClient := fake.NewSimpleClientset(&api.PodList{}, &resourceQuota) - resourceQuotaControllerOptions := &ResourceQuotaControllerOptions{ - KubeClient: kubeClient, - ResyncPeriod: controller.NoResyncPeriodFunc, - Registry: install.NewRegistry(kubeClient), - GroupKindsToReplenish: []unversioned.GroupKind{ - api.Kind("Pod"), - api.Kind("Service"), - api.Kind("ReplicationController"), - api.Kind("PersistentVolumeClaim"), - }, - ControllerFactory: NewReplenishmentControllerFactoryFromClient(kubeClient), - ReplenishmentResyncPeriod: controller.NoResyncPeriodFunc, - } - quotaController := NewResourceQuotaController(resourceQuotaControllerOptions) - err := quotaController.syncResourceQuota(resourceQuota) - if err != nil { - t.Fatalf("Unexpected error %v", err) - } - expectedActionSet := sets.NewString( - strings.Join([]string{"list", "replicationcontrollers", ""}, "-"), - strings.Join([]string{"list", "services", ""}, "-"), - strings.Join([]string{"list", "pods", ""}, "-"), - strings.Join([]string{"list", "resourcequotas", ""}, "-"), - strings.Join([]string{"list", "secrets", ""}, "-"), - strings.Join([]string{"list", "persistentvolumeclaims", ""}, "-"), - ) - actionSet := sets.NewString() - for _, action := range kubeClient.Actions() { - actionSet.Insert(strings.Join([]string{action.GetVerb(), action.GetResource().Resource, action.GetSubresource()}, "-")) - } - if !actionSet.HasAll(expectedActionSet.List()...) { - t.Errorf("Expected actions:\n%v\n but got:\n%v\nDifference:\n%v", expectedActionSet, actionSet, expectedActionSet.Difference(actionSet)) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/doc.go deleted file mode 100644 index bc4ae60a2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 route contains code for syncing cloud routing rules with -// the list of registered nodes. -package route diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/routecontroller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/routecontroller.go deleted file mode 100644 index 206a5c79f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/routecontroller.go +++ /dev/null @@ -1,148 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 route - -import ( - "fmt" - "net" - "sync" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/util/metrics" - "k8s.io/kubernetes/pkg/util/wait" -) - -type RouteController struct { - routes cloudprovider.Routes - kubeClient clientset.Interface - clusterName string - clusterCIDR *net.IPNet -} - -func New(routes cloudprovider.Routes, kubeClient clientset.Interface, clusterName string, clusterCIDR *net.IPNet) *RouteController { - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("route_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - return &RouteController{ - routes: routes, - kubeClient: kubeClient, - clusterName: clusterName, - clusterCIDR: clusterCIDR, - } -} - -func (rc *RouteController) Run(syncPeriod time.Duration) { - go wait.Until(func() { - if err := rc.reconcileNodeRoutes(); err != nil { - glog.Errorf("Couldn't reconcile node routes: %v", err) - } - }, syncPeriod, wait.NeverStop) -} - -func (rc *RouteController) reconcileNodeRoutes() error { - routeList, err := rc.routes.ListRoutes(rc.clusterName) - if err != nil { - return fmt.Errorf("error listing routes: %v", err) - } - // TODO (cjcullen): use pkg/controller/framework.NewInformer to watch this - // and reduce the number of lists needed. - nodeList, err := rc.kubeClient.Core().Nodes().List(api.ListOptions{}) - if err != nil { - return fmt.Errorf("error listing nodes: %v", err) - } - return rc.reconcile(nodeList.Items, routeList) -} - -func (rc *RouteController) reconcile(nodes []api.Node, routes []*cloudprovider.Route) error { - // nodeCIDRs maps nodeName->nodeCIDR - nodeCIDRs := make(map[string]string) - // routeMap maps routeTargetInstance->route - routeMap := make(map[string]*cloudprovider.Route) - for _, route := range routes { - routeMap[route.TargetInstance] = route - } - wg := sync.WaitGroup{} - for _, node := range nodes { - // Skip if the node hasn't been assigned a CIDR yet. - if node.Spec.PodCIDR == "" { - continue - } - // Check if we have a route for this node w/ the correct CIDR. - r := routeMap[node.Name] - if r == nil || r.DestinationCIDR != node.Spec.PodCIDR { - // If not, create the route. - route := &cloudprovider.Route{ - TargetInstance: node.Name, - DestinationCIDR: node.Spec.PodCIDR, - } - nameHint := string(node.UID) - wg.Add(1) - glog.Infof("Creating route for node %s %s with hint %s", node.Name, route.DestinationCIDR, nameHint) - go func(nodeName string, nameHint string, route *cloudprovider.Route, startTime time.Time) { - if err := rc.routes.CreateRoute(rc.clusterName, nameHint, route); err != nil { - glog.Errorf("Could not create route %s %s for node %s after %v: %v", nameHint, route.DestinationCIDR, nodeName, time.Now().Sub(startTime), err) - } else { - glog.Infof("Created route for node %s %s with hint %s after %v", nodeName, route.DestinationCIDR, nameHint, time.Now().Sub(startTime)) - } - wg.Done() - }(node.Name, nameHint, route, time.Now()) - } - nodeCIDRs[node.Name] = node.Spec.PodCIDR - } - for _, route := range routes { - if rc.isResponsibleForRoute(route) { - // Check if this route applies to a node we know about & has correct CIDR. - if nodeCIDRs[route.TargetInstance] != route.DestinationCIDR { - wg.Add(1) - // Delete the route. - glog.Infof("Deleting route %s %s", route.Name, route.DestinationCIDR) - go func(route *cloudprovider.Route, startTime time.Time) { - if err := rc.routes.DeleteRoute(rc.clusterName, route); err != nil { - glog.Errorf("Could not delete route %s %s after %v: %v", route.Name, route.DestinationCIDR, time.Now().Sub(startTime), err) - } else { - glog.Infof("Deleted route %s %s after %v", route.Name, route.DestinationCIDR, time.Now().Sub(startTime)) - } - wg.Done() - - }(route, time.Now()) - } - } - } - wg.Wait() - return nil -} - -func (rc *RouteController) isResponsibleForRoute(route *cloudprovider.Route) bool { - _, cidr, err := net.ParseCIDR(route.DestinationCIDR) - if err != nil { - glog.Errorf("Ignoring route %s, unparsable CIDR: %v", route.Name, err) - return false - } - // Not responsible if this route's CIDR is not within our clusterCIDR - lastIP := make([]byte, len(cidr.IP)) - for i := range lastIP { - lastIP[i] = cidr.IP[i] | ^cidr.Mask[i] - } - if !rc.clusterCIDR.Contains(cidr.IP) || !rc.clusterCIDR.Contains(lastIP) { - return false - } - return true -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/routecontroller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/routecontroller_test.go deleted file mode 100644 index 3db2079f5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/route/routecontroller_test.go +++ /dev/null @@ -1,219 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 route - -import ( - "net" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/cloudprovider" - fakecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" -) - -func TestIsResponsibleForRoute(t *testing.T) { - myClusterName := "my-awesome-cluster" - myClusterRoute := "my-awesome-cluster-12345678-90ab-cdef-1234-567890abcdef" - testCases := []struct { - clusterCIDR string - routeName string - routeCIDR string - expectedResponsible bool - }{ - // Routes that belong to this cluster - {"10.244.0.0/16", myClusterRoute, "10.244.0.0/24", true}, - {"10.244.0.0/16", myClusterRoute, "10.244.10.0/24", true}, - {"10.244.0.0/16", myClusterRoute, "10.244.255.0/24", true}, - {"10.244.0.0/14", myClusterRoute, "10.244.0.0/24", true}, - {"10.244.0.0/14", myClusterRoute, "10.247.255.0/24", true}, - // Routes that match our naming/tagging scheme, but are outside our cidr - {"10.244.0.0/16", myClusterRoute, "10.224.0.0/24", false}, - {"10.244.0.0/16", myClusterRoute, "10.0.10.0/24", false}, - {"10.244.0.0/16", myClusterRoute, "10.255.255.0/24", false}, - {"10.244.0.0/14", myClusterRoute, "10.248.0.0/24", false}, - {"10.244.0.0/14", myClusterRoute, "10.243.255.0/24", false}, - } - for i, testCase := range testCases { - _, cidr, err := net.ParseCIDR(testCase.clusterCIDR) - if err != nil { - t.Errorf("%d. Error in test case: unparsable cidr %q", i, testCase.clusterCIDR) - } - rc := New(nil, nil, myClusterName, cidr) - route := &cloudprovider.Route{ - Name: testCase.routeName, - TargetInstance: "doesnt-matter-for-this-test", - DestinationCIDR: testCase.routeCIDR, - } - if resp := rc.isResponsibleForRoute(route); resp != testCase.expectedResponsible { - t.Errorf("%d. isResponsibleForRoute() = %t; want %t", i, resp, testCase.expectedResponsible) - } - } -} - -func TestReconcile(t *testing.T) { - cluster := "my-k8s" - testCases := []struct { - nodes []api.Node - initialRoutes []*cloudprovider.Route - expectedRoutes []*cloudprovider.Route - }{ - // 2 nodes, routes already there - { - nodes: []api.Node{ - {ObjectMeta: api.ObjectMeta{Name: "node-1", UID: "01"}, Spec: api.NodeSpec{PodCIDR: "10.120.0.0/24"}}, - {ObjectMeta: api.ObjectMeta{Name: "node-2", UID: "02"}, Spec: api.NodeSpec{PodCIDR: "10.120.1.0/24"}}, - }, - initialRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-02", "node-2", "10.120.1.0/24"}, - }, - expectedRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-02", "node-2", "10.120.1.0/24"}, - }, - }, - // 2 nodes, one route already there - { - nodes: []api.Node{ - {ObjectMeta: api.ObjectMeta{Name: "node-1", UID: "01"}, Spec: api.NodeSpec{PodCIDR: "10.120.0.0/24"}}, - {ObjectMeta: api.ObjectMeta{Name: "node-2", UID: "02"}, Spec: api.NodeSpec{PodCIDR: "10.120.1.0/24"}}, - }, - initialRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - }, - expectedRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-02", "node-2", "10.120.1.0/24"}, - }, - }, - // 2 nodes, no routes yet - { - nodes: []api.Node{ - {ObjectMeta: api.ObjectMeta{Name: "node-1", UID: "01"}, Spec: api.NodeSpec{PodCIDR: "10.120.0.0/24"}}, - {ObjectMeta: api.ObjectMeta{Name: "node-2", UID: "02"}, Spec: api.NodeSpec{PodCIDR: "10.120.1.0/24"}}, - }, - initialRoutes: []*cloudprovider.Route{}, - expectedRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-02", "node-2", "10.120.1.0/24"}, - }, - }, - // 2 nodes, a few too many routes - { - nodes: []api.Node{ - {ObjectMeta: api.ObjectMeta{Name: "node-1", UID: "01"}, Spec: api.NodeSpec{PodCIDR: "10.120.0.0/24"}}, - {ObjectMeta: api.ObjectMeta{Name: "node-2", UID: "02"}, Spec: api.NodeSpec{PodCIDR: "10.120.1.0/24"}}, - }, - initialRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-02", "node-2", "10.120.1.0/24"}, - {cluster + "-03", "node-3", "10.120.2.0/24"}, - {cluster + "-04", "node-4", "10.120.3.0/24"}, - }, - expectedRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-02", "node-2", "10.120.1.0/24"}, - }, - }, - // 2 nodes, 2 routes, but only 1 is right - { - nodes: []api.Node{ - {ObjectMeta: api.ObjectMeta{Name: "node-1", UID: "01"}, Spec: api.NodeSpec{PodCIDR: "10.120.0.0/24"}}, - {ObjectMeta: api.ObjectMeta{Name: "node-2", UID: "02"}, Spec: api.NodeSpec{PodCIDR: "10.120.1.0/24"}}, - }, - initialRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-03", "node-3", "10.120.2.0/24"}, - }, - expectedRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - {cluster + "-02", "node-2", "10.120.1.0/24"}, - }, - }, - // 2 nodes, one node without CIDR assigned. - { - nodes: []api.Node{ - {ObjectMeta: api.ObjectMeta{Name: "node-1", UID: "01"}, Spec: api.NodeSpec{PodCIDR: "10.120.0.0/24"}}, - {ObjectMeta: api.ObjectMeta{Name: "node-2", UID: "02"}, Spec: api.NodeSpec{PodCIDR: ""}}, - }, - initialRoutes: []*cloudprovider.Route{}, - expectedRoutes: []*cloudprovider.Route{ - {cluster + "-01", "node-1", "10.120.0.0/24"}, - }, - }, - } - for i, testCase := range testCases { - cloud := &fakecloud.FakeCloud{RouteMap: make(map[string]*fakecloud.FakeRoute)} - for _, route := range testCase.initialRoutes { - fakeRoute := &fakecloud.FakeRoute{} - fakeRoute.ClusterName = cluster - fakeRoute.Route = *route - cloud.RouteMap[route.Name] = fakeRoute - } - routes, ok := cloud.Routes() - if !ok { - t.Error("Error in test: fakecloud doesn't support Routes()") - } - _, cidr, _ := net.ParseCIDR("10.120.0.0/16") - rc := New(routes, nil, cluster, cidr) - if err := rc.reconcile(testCase.nodes, testCase.initialRoutes); err != nil { - t.Errorf("%d. Error from rc.reconcile(): %v", i, err) - } - var finalRoutes []*cloudprovider.Route - var err error - timeoutChan := time.After(200 * time.Millisecond) - tick := time.NewTicker(10 * time.Millisecond) - defer tick.Stop() - poll: - for { - select { - case <-tick.C: - if finalRoutes, err = routes.ListRoutes(cluster); err == nil && routeListEqual(finalRoutes, testCase.expectedRoutes) { - break poll - } - case <-timeoutChan: - t.Errorf("%d. rc.reconcile() = %v, routes:\n%v\nexpected: nil, routes:\n%v\n", i, err, flatten(finalRoutes), flatten(testCase.expectedRoutes)) - break poll - } - } - } -} - -func routeListEqual(list1, list2 []*cloudprovider.Route) bool { - if len(list1) != len(list2) { - return false - } - routeMap1 := make(map[string]*cloudprovider.Route) - for _, route1 := range list1 { - routeMap1[route1.Name] = route1 - } - for _, route2 := range list2 { - if route1, exists := routeMap1[route2.Name]; !exists || *route1 != *route2 { - return false - } - } - return true -} - -func flatten(list []*cloudprovider.Route) []cloudprovider.Route { - var structList []cloudprovider.Route - for _, route := range list { - structList = append(structList, *route) - } - return structList -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/controller-test/ct b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/controller-test/ct deleted file mode 100644 index 9072db6ec..000000000 Binary files a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/controller-test/ct and /dev/null differ diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/doc.go deleted file mode 100644 index 78c20eb96..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 service contains code for syncing cloud load balancers -// with the service registry. -package service diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/servicecontroller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/servicecontroller.go deleted file mode 100644 index 6803d8c89..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/servicecontroller.go +++ /dev/null @@ -1,769 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 service - -import ( - "fmt" - "sort" - "sync" - "time" - - "reflect" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - unversioned_core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/unversioned" - "k8s.io/kubernetes/pkg/client/record" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/types" - "k8s.io/kubernetes/pkg/util/metrics" - "k8s.io/kubernetes/pkg/util/runtime" -) - -const ( - workerGoroutines = 10 - - // How long to wait before retrying the processing of a service change. - // If this changes, the sleep in hack/jenkins/e2e.sh before downing a cluster - // should be changed appropriately. - minRetryDelay = 5 * time.Second - maxRetryDelay = 300 * time.Second - - clientRetryCount = 5 - clientRetryInterval = 5 * time.Second - - retryable = true - notRetryable = false - - doNotRetry = time.Duration(0) -) - -type cachedService struct { - // The last-known state of the service - lastState *api.Service - // The state as successfully applied to the load balancer - appliedState *api.Service - - // Ensures only one goroutine can operate on this service at any given time. - mu sync.Mutex - - // Controls error back-off - lastRetryDelay time.Duration -} - -type serviceCache struct { - mu sync.Mutex // protects serviceMap - serviceMap map[string]*cachedService -} - -type ServiceController struct { - cloud cloudprovider.Interface - kubeClient clientset.Interface - clusterName string - balancer cloudprovider.LoadBalancer - zone cloudprovider.Zone - cache *serviceCache - eventBroadcaster record.EventBroadcaster - eventRecorder record.EventRecorder - nodeLister cache.StoreToNodeLister -} - -// New returns a new service controller to keep cloud provider service resources -// (like load balancers) in sync with the registry. -func New(cloud cloudprovider.Interface, kubeClient clientset.Interface, clusterName string) *ServiceController { - broadcaster := record.NewBroadcaster() - broadcaster.StartRecordingToSink(&unversioned_core.EventSinkImpl{Interface: kubeClient.Core().Events("")}) - recorder := broadcaster.NewRecorder(api.EventSource{Component: "service-controller"}) - - if kubeClient != nil && kubeClient.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("service_controller", kubeClient.Core().GetRESTClient().GetRateLimiter()) - } - - return &ServiceController{ - cloud: cloud, - kubeClient: kubeClient, - clusterName: clusterName, - cache: &serviceCache{serviceMap: make(map[string]*cachedService)}, - eventBroadcaster: broadcaster, - eventRecorder: recorder, - nodeLister: cache.StoreToNodeLister{ - Store: cache.NewStore(cache.MetaNamespaceKeyFunc), - }, - } -} - -// Run starts a background goroutine that watches for changes to services that -// have (or had) LoadBalancers=true and ensures that they have -// load balancers created and deleted appropriately. -// serviceSyncPeriod controls how often we check the cluster's services to -// ensure that the correct load balancers exist. -// nodeSyncPeriod controls how often we check the cluster's nodes to determine -// if load balancers need to be updated to point to a new set. -// -// It's an error to call Run() more than once for a given ServiceController -// object. -func (s *ServiceController) Run(serviceSyncPeriod, nodeSyncPeriod time.Duration) error { - if err := s.init(); err != nil { - return err - } - - // We have to make this check beecause the ListWatch that we use in - // WatchServices requires Client functions that aren't in the interface - // for some reason. - if _, ok := s.kubeClient.(*clientset.Clientset); !ok { - return fmt.Errorf("ServiceController only works with real Client objects, but was passed something else satisfying the clientset.Interface.") - } - - // Get the currently existing set of services and then all future creates - // and updates of services. - // A delta compressor is needed for the DeltaFIFO queue because we only ever - // care about the most recent state. - serviceQueue := cache.NewDeltaFIFO( - cache.MetaNamespaceKeyFunc, - cache.DeltaCompressorFunc(func(d cache.Deltas) cache.Deltas { - if len(d) == 0 { - return d - } - return cache.Deltas{*d.Newest()} - }), - s.cache, - ) - lw := cache.NewListWatchFromClient(s.kubeClient.(*clientset.Clientset).CoreClient, "services", api.NamespaceAll, fields.Everything()) - cache.NewReflector(lw, &api.Service{}, serviceQueue, serviceSyncPeriod).Run() - for i := 0; i < workerGoroutines; i++ { - go s.watchServices(serviceQueue) - } - - nodeLW := cache.NewListWatchFromClient(s.kubeClient.(*clientset.Clientset).CoreClient, "nodes", api.NamespaceAll, fields.Everything()) - cache.NewReflector(nodeLW, &api.Node{}, s.nodeLister.Store, 0).Run() - go s.nodeSyncLoop(nodeSyncPeriod) - return nil -} - -func (s *ServiceController) init() error { - if s.cloud == nil { - return fmt.Errorf("ServiceController should not be run without a cloudprovider.") - } - - balancer, ok := s.cloud.LoadBalancer() - if !ok { - return fmt.Errorf("the cloud provider does not support external load balancers.") - } - s.balancer = balancer - - zones, ok := s.cloud.Zones() - if !ok { - return fmt.Errorf("the cloud provider does not support zone enumeration, which is required for creating load balancers.") - } - zone, err := zones.GetZone() - if err != nil { - return fmt.Errorf("failed to get zone from cloud provider, will not be able to create load balancers: %v", err) - } - s.zone = zone - return nil -} - -// Loop infinitely, processing all service updates provided by the queue. -func (s *ServiceController) watchServices(serviceQueue *cache.DeltaFIFO) { - for { - newItem := serviceQueue.Pop() - deltas, ok := newItem.(cache.Deltas) - if !ok { - glog.Errorf("Received object from service watcher that wasn't Deltas: %+v", newItem) - } - delta := deltas.Newest() - if delta == nil { - glog.Errorf("Received nil delta from watcher queue.") - continue - } - err, retryDelay := s.processDelta(delta) - if retryDelay != 0 { - // Add the failed service back to the queue so we'll retry it. - glog.Errorf("Failed to process service delta. Retrying in %s: %v", retryDelay, err) - go func(deltas cache.Deltas, delay time.Duration) { - time.Sleep(delay) - if err := serviceQueue.AddIfNotPresent(deltas); err != nil { - glog.Errorf("Error requeuing service delta - will not retry: %v", err) - } - }(deltas, retryDelay) - } else if err != nil { - runtime.HandleError(fmt.Errorf("Failed to process service delta. Not retrying: %v", err)) - } - } -} - -// Returns an error if processing the delta failed, along with a time.Duration -// indicating whether processing should be retried; zero means no-retry; otherwise -// we should retry in that Duration. -func (s *ServiceController) processDelta(delta *cache.Delta) (error, time.Duration) { - deltaService, ok := delta.Object.(*api.Service) - var namespacedName types.NamespacedName - var cachedService *cachedService - if !ok { - // If the DeltaFIFO saw a key in our cache that it didn't know about, it - // can send a deletion with an unknown state. Grab the service from our - // cache for deleting. - key, ok := delta.Object.(cache.DeletedFinalStateUnknown) - if !ok { - return fmt.Errorf("Delta contained object that wasn't a service or a deleted key: %+v", delta), doNotRetry - } - cachedService, ok = s.cache.get(key.Key) - if !ok { - return fmt.Errorf("Service %s not in cache even though the watcher thought it was. Ignoring the deletion.", key), doNotRetry - } - deltaService = cachedService.lastState - delta.Object = deltaService - namespacedName = types.NamespacedName{Namespace: deltaService.Namespace, Name: deltaService.Name} - } else { - namespacedName.Namespace = deltaService.Namespace - namespacedName.Name = deltaService.Name - cachedService = s.cache.getOrCreate(namespacedName.String()) - } - glog.V(2).Infof("Got new %s delta for service: %v", delta.Type, namespacedName) - - // Ensure that no other goroutine will interfere with our processing of the - // service. - cachedService.mu.Lock() - defer cachedService.mu.Unlock() - - // Get the most recent state of the service from the API directly rather than - // trusting the body of the delta. This avoids update re-ordering problems. - // TODO: Handle sync delta types differently rather than doing a get on every - // service every time we sync? - service, err := s.kubeClient.Core().Services(namespacedName.Namespace).Get(namespacedName.Name) - if err != nil && !errors.IsNotFound(err) { - glog.Warningf("Failed to get most recent state of service %v from API (will retry): %v", namespacedName, err) - return err, cachedService.nextRetryDelay() - } else if errors.IsNotFound(err) { - glog.V(2).Infof("Service %v not found, ensuring load balancer is deleted", namespacedName) - s.eventRecorder.Event(deltaService, api.EventTypeNormal, "DeletingLoadBalancer", "Deleting load balancer") - err := s.balancer.EnsureLoadBalancerDeleted(deltaService) - if err != nil { - message := "Error deleting load balancer (will retry): " + err.Error() - s.eventRecorder.Event(deltaService, api.EventTypeWarning, "DeletingLoadBalancerFailed", message) - return err, cachedService.nextRetryDelay() - } - s.eventRecorder.Event(deltaService, api.EventTypeNormal, "DeletedLoadBalancer", "Deleted load balancer") - s.cache.delete(namespacedName.String()) - - cachedService.resetRetryDelay() - return nil, doNotRetry - } - - // Update the cached service (used above for populating synthetic deletes) - cachedService.lastState = service - - err, retry := s.createLoadBalancerIfNeeded(namespacedName, service, cachedService.appliedState) - if err != nil { - message := "Error creating load balancer" - if retry { - message += " (will retry): " - } else { - message += " (will not retry): " - } - message += err.Error() - s.eventRecorder.Event(service, api.EventTypeWarning, "CreatingLoadBalancerFailed", message) - - return err, cachedService.nextRetryDelay() - } - // Always update the cache upon success. - // NOTE: Since we update the cached service if and only if we successfully - // processed it, a cached service being nil implies that it hasn't yet - // been successfully processed. - cachedService.appliedState = service - s.cache.set(namespacedName.String(), cachedService) - - cachedService.resetRetryDelay() - return nil, doNotRetry -} - -// Returns whatever error occurred along with a boolean indicator of whether it -// should be retried. -func (s *ServiceController) createLoadBalancerIfNeeded(namespacedName types.NamespacedName, service, appliedState *api.Service) (error, bool) { - if appliedState != nil && !s.needsUpdate(appliedState, service) { - glog.Infof("LB doesn't need update for service %s", namespacedName) - return nil, notRetryable - } - - // Note: It is safe to just call EnsureLoadBalancer. But, on some clouds that requires a delete & create, - // which may involve service interruption. Also, we would like user-friendly events. - - // Save the state so we can avoid a write if it doesn't change - previousState := api.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer) - - if !wantsLoadBalancer(service) { - needDelete := true - if appliedState != nil { - if !wantsLoadBalancer(appliedState) { - needDelete = false - } - } else { - // If we don't have any cached memory of the load balancer, we have to ask - // the cloud provider for what it knows about it. - // Technically EnsureLoadBalancerDeleted can cope, but we want to post meaningful events - _, exists, err := s.balancer.GetLoadBalancer(service) - if err != nil { - return fmt.Errorf("Error getting LB for service %s: %v", namespacedName, err), retryable - } - if !exists { - needDelete = false - } - } - - if needDelete { - glog.Infof("Deleting existing load balancer for service %s that no longer needs a load balancer.", namespacedName) - s.eventRecorder.Event(service, api.EventTypeNormal, "DeletingLoadBalancer", "Deleting load balancer") - if err := s.balancer.EnsureLoadBalancerDeleted(service); err != nil { - return err, retryable - } - s.eventRecorder.Event(service, api.EventTypeNormal, "DeletedLoadBalancer", "Deleted load balancer") - } - - service.Status.LoadBalancer = api.LoadBalancerStatus{} - } else { - glog.V(2).Infof("Ensuring LB for service %s", namespacedName) - - // TODO: We could do a dry-run here if wanted to avoid the spurious cloud-calls & events when we restart - - // The load balancer doesn't exist yet, so create it. - s.eventRecorder.Event(service, api.EventTypeNormal, "CreatingLoadBalancer", "Creating load balancer") - err := s.createLoadBalancer(service) - if err != nil { - return fmt.Errorf("Failed to create load balancer for service %s: %v", namespacedName, err), retryable - } - s.eventRecorder.Event(service, api.EventTypeNormal, "CreatedLoadBalancer", "Created load balancer") - } - - // Write the state if changed - // TODO: Be careful here ... what if there were other changes to the service? - if !api.LoadBalancerStatusEqual(previousState, &service.Status.LoadBalancer) { - if err := s.persistUpdate(service); err != nil { - return fmt.Errorf("Failed to persist updated status to apiserver, even after retries. Giving up: %v", err), notRetryable - } - } else { - glog.V(2).Infof("Not persisting unchanged LoadBalancerStatus to registry.") - } - - return nil, notRetryable -} - -func (s *ServiceController) persistUpdate(service *api.Service) error { - var err error - for i := 0; i < clientRetryCount; i++ { - _, err = s.kubeClient.Core().Services(service.Namespace).UpdateStatus(service) - if err == nil { - return nil - } - // If the object no longer exists, we don't want to recreate it. Just bail - // out so that we can process the delete, which we should soon be receiving - // if we haven't already. - if errors.IsNotFound(err) { - glog.Infof("Not persisting update to service '%s/%s' that no longer exists: %v", - service.Namespace, service.Name, err) - return nil - } - // TODO: Try to resolve the conflict if the change was unrelated to load - // balancer status. For now, just rely on the fact that we'll - // also process the update that caused the resource version to change. - if errors.IsConflict(err) { - glog.V(4).Infof("Not persisting update to service '%s/%s' that has been changed since we received it: %v", - service.Namespace, service.Name, err) - return nil - } - glog.Warningf("Failed to persist updated LoadBalancerStatus to service '%s/%s' after creating its load balancer: %v", - service.Namespace, service.Name, err) - time.Sleep(clientRetryInterval) - } - return err -} - -func (s *ServiceController) createLoadBalancer(service *api.Service) error { - nodes, err := s.nodeLister.List() - if err != nil { - return err - } - - // - Only one protocol supported per service - // - Not all cloud providers support all protocols and the next step is expected to return - // an error for unsupported protocols - status, err := s.balancer.EnsureLoadBalancer(service, hostsFromNodeList(&nodes), service.ObjectMeta.Annotations) - if err != nil { - return err - } else { - service.Status.LoadBalancer = *status - } - - return nil -} - -// ListKeys implements the interface required by DeltaFIFO to list the keys we -// already know about. -func (s *serviceCache) ListKeys() []string { - s.mu.Lock() - defer s.mu.Unlock() - keys := make([]string, 0, len(s.serviceMap)) - for k := range s.serviceMap { - keys = append(keys, k) - } - return keys -} - -// GetByKey returns the value stored in the serviceMap under the given key -func (s *serviceCache) GetByKey(key string) (interface{}, bool, error) { - s.mu.Lock() - defer s.mu.Unlock() - if v, ok := s.serviceMap[key]; ok { - return v, true, nil - } - return nil, false, nil -} - -// ListKeys implements the interface required by DeltaFIFO to list the keys we -// already know about. -func (s *serviceCache) allServices() []*cachedService { - s.mu.Lock() - defer s.mu.Unlock() - services := make([]*cachedService, 0, len(s.serviceMap)) - for _, v := range s.serviceMap { - services = append(services, v) - } - return services -} - -func (s *serviceCache) get(serviceName string) (*cachedService, bool) { - s.mu.Lock() - defer s.mu.Unlock() - service, ok := s.serviceMap[serviceName] - return service, ok -} - -func (s *serviceCache) getOrCreate(serviceName string) *cachedService { - s.mu.Lock() - defer s.mu.Unlock() - service, ok := s.serviceMap[serviceName] - if !ok { - service = &cachedService{} - s.serviceMap[serviceName] = service - } - return service -} - -func (s *serviceCache) set(serviceName string, service *cachedService) { - s.mu.Lock() - defer s.mu.Unlock() - s.serviceMap[serviceName] = service -} - -func (s *serviceCache) delete(serviceName string) { - s.mu.Lock() - defer s.mu.Unlock() - delete(s.serviceMap, serviceName) -} - -func (s *ServiceController) needsUpdate(oldService *api.Service, newService *api.Service) bool { - if !wantsLoadBalancer(oldService) && !wantsLoadBalancer(newService) { - return false - } - if wantsLoadBalancer(oldService) != wantsLoadBalancer(newService) { - s.eventRecorder.Eventf(newService, api.EventTypeNormal, "Type", "%v -> %v", - oldService.Spec.Type, newService.Spec.Type) - return true - } - if !portsEqualForLB(oldService, newService) || oldService.Spec.SessionAffinity != newService.Spec.SessionAffinity { - return true - } - if !loadBalancerIPsAreEqual(oldService, newService) { - s.eventRecorder.Eventf(newService, api.EventTypeNormal, "LoadbalancerIP", "%v -> %v", - oldService.Spec.LoadBalancerIP, newService.Spec.LoadBalancerIP) - return true - } - if len(oldService.Spec.ExternalIPs) != len(newService.Spec.ExternalIPs) { - s.eventRecorder.Eventf(newService, api.EventTypeNormal, "ExternalIP", "Count: %v -> %v", - len(oldService.Spec.ExternalIPs), len(newService.Spec.ExternalIPs)) - return true - } - for i := range oldService.Spec.ExternalIPs { - if oldService.Spec.ExternalIPs[i] != newService.Spec.ExternalIPs[i] { - s.eventRecorder.Eventf(newService, api.EventTypeNormal, "ExternalIP", "Added: %v", - newService.Spec.ExternalIPs[i]) - return true - } - } - if !reflect.DeepEqual(oldService.Annotations, newService.Annotations) { - return true - } - if oldService.UID != newService.UID { - s.eventRecorder.Eventf(newService, api.EventTypeNormal, "UID", "%v -> %v", - oldService.UID, newService.UID) - return true - } - - return false -} - -func (s *ServiceController) loadBalancerName(service *api.Service) string { - return cloudprovider.GetLoadBalancerName(service) -} - -func getPortsForLB(service *api.Service) ([]*api.ServicePort, error) { - var protocol api.Protocol - - ports := []*api.ServicePort{} - for i := range service.Spec.Ports { - sp := &service.Spec.Ports[i] - // The check on protocol was removed here. The cloud provider itself is now responsible for all protocol validation - ports = append(ports, sp) - if protocol == "" { - protocol = sp.Protocol - } else if protocol != sp.Protocol && wantsLoadBalancer(service) { - // TODO: Convert error messages to use event recorder - return nil, fmt.Errorf("mixed protocol external load balancers are not supported.") - } - } - return ports, nil -} - -func portsEqualForLB(x, y *api.Service) bool { - xPorts, err := getPortsForLB(x) - if err != nil { - return false - } - yPorts, err := getPortsForLB(y) - if err != nil { - return false - } - return portSlicesEqualForLB(xPorts, yPorts) -} - -func portSlicesEqualForLB(x, y []*api.ServicePort) bool { - if len(x) != len(y) { - return false - } - - for i := range x { - if !portEqualForLB(x[i], y[i]) { - return false - } - } - return true -} - -func portEqualForLB(x, y *api.ServicePort) bool { - // TODO: Should we check name? (In theory, an LB could expose it) - if x.Name != y.Name { - return false - } - - if x.Protocol != y.Protocol { - return false - } - - if x.Port != y.Port { - return false - } - - if x.NodePort != y.NodePort { - return false - } - - // We don't check TargetPort; that is not relevant for load balancing - // TODO: Should we blank it out? Or just check it anyway? - - return true -} - -func intSlicesEqual(x, y []int) bool { - if len(x) != len(y) { - return false - } - if !sort.IntsAreSorted(x) { - sort.Ints(x) - } - if !sort.IntsAreSorted(y) { - sort.Ints(y) - } - for i := range x { - if x[i] != y[i] { - return false - } - } - return true -} - -func stringSlicesEqual(x, y []string) bool { - if len(x) != len(y) { - return false - } - if !sort.StringsAreSorted(x) { - sort.Strings(x) - } - if !sort.StringsAreSorted(y) { - sort.Strings(y) - } - for i := range x { - if x[i] != y[i] { - return false - } - } - return true -} - -func hostsFromNodeList(list *api.NodeList) []string { - result := []string{} - for ix := range list.Items { - if list.Items[ix].Spec.Unschedulable { - continue - } - result = append(result, list.Items[ix].Name) - } - return result -} - -func getNodeConditionPredicate() cache.NodeConditionPredicate { - return func(node api.Node) bool { - // We add the master to the node list, but its unschedulable. So we use this to filter - // the master. - // TODO: Use a node annotation to indicate the master - if node.Spec.Unschedulable { - return false - } - // If we have no info, don't accept - if len(node.Status.Conditions) == 0 { - return false - } - for _, cond := range node.Status.Conditions { - // We consider the node for load balancing only when its NodeReady condition status - // is ConditionTrue - if cond.Type == api.NodeReady && cond.Status != api.ConditionTrue { - glog.V(4).Infof("Ignoring node %v with %v condition status %v", node.Name, cond.Type, cond.Status) - return false - } - } - return true - } -} - -// nodeSyncLoop handles updating the hosts pointed to by all load -// balancers whenever the set of nodes in the cluster changes. -func (s *ServiceController) nodeSyncLoop(period time.Duration) { - var prevHosts []string - var servicesToUpdate []*cachedService - for range time.Tick(period) { - nodes, err := s.nodeLister.NodeCondition(getNodeConditionPredicate()).List() - if err != nil { - glog.Errorf("Failed to retrieve current set of nodes from node lister: %v", err) - continue - } - newHosts := hostsFromNodeList(&nodes) - if stringSlicesEqual(newHosts, prevHosts) { - // The set of nodes in the cluster hasn't changed, but we can retry - // updating any services that we failed to update last time around. - servicesToUpdate = s.updateLoadBalancerHosts(servicesToUpdate, newHosts) - continue - } - glog.Infof("Detected change in list of current cluster nodes. New node set: %v", newHosts) - - // Try updating all services, and save the ones that fail to try again next - // round. - servicesToUpdate = s.cache.allServices() - numServices := len(servicesToUpdate) - servicesToUpdate = s.updateLoadBalancerHosts(servicesToUpdate, newHosts) - glog.Infof("Successfully updated %d out of %d load balancers to direct traffic to the updated set of nodes", - numServices-len(servicesToUpdate), numServices) - - prevHosts = newHosts - } -} - -// updateLoadBalancerHosts updates all existing load balancers so that -// they will match the list of hosts provided. -// Returns the list of services that couldn't be updated. -func (s *ServiceController) updateLoadBalancerHosts(services []*cachedService, hosts []string) (servicesToRetry []*cachedService) { - for _, service := range services { - func() { - service.mu.Lock() - defer service.mu.Unlock() - // If the applied state is nil, that means it hasn't yet been successfully dealt - // with by the load balancer reconciler. We can trust the load balancer - // reconciler to ensure the service's load balancer is created to target - // the correct nodes. - if service.appliedState == nil { - return - } - if err := s.lockedUpdateLoadBalancerHosts(service.appliedState, hosts); err != nil { - glog.Errorf("External error while updating load balancer: %v.", err) - servicesToRetry = append(servicesToRetry, service) - } - }() - } - return servicesToRetry -} - -// Updates the load balancer of a service, assuming we hold the mutex -// associated with the service. -func (s *ServiceController) lockedUpdateLoadBalancerHosts(service *api.Service, hosts []string) error { - if !wantsLoadBalancer(service) { - return nil - } - - // This operation doesn't normally take very long (and happens pretty often), so we only record the final event - err := s.balancer.UpdateLoadBalancer(service, hosts) - if err == nil { - s.eventRecorder.Event(service, api.EventTypeNormal, "UpdatedLoadBalancer", "Updated load balancer with new hosts") - return nil - } - - // It's only an actual error if the load balancer still exists. - if _, exists, err := s.balancer.GetLoadBalancer(service); err != nil { - glog.Errorf("External error while checking if load balancer %q exists: name, %v", cloudprovider.GetLoadBalancerName(service), err) - } else if !exists { - return nil - } - - s.eventRecorder.Eventf(service, api.EventTypeWarning, "LoadBalancerUpdateFailed", "Error updating load balancer with new hosts %v: %v", hosts, err) - return err -} - -func wantsLoadBalancer(service *api.Service) bool { - return service.Spec.Type == api.ServiceTypeLoadBalancer -} - -func loadBalancerIPsAreEqual(oldService, newService *api.Service) bool { - return oldService.Spec.LoadBalancerIP == newService.Spec.LoadBalancerIP -} - -// Computes the next retry, using exponential backoff -// mutex must be held. -func (s *cachedService) nextRetryDelay() time.Duration { - s.lastRetryDelay = s.lastRetryDelay * 2 - if s.lastRetryDelay < minRetryDelay { - s.lastRetryDelay = minRetryDelay - } - if s.lastRetryDelay > maxRetryDelay { - s.lastRetryDelay = maxRetryDelay - } - return s.lastRetryDelay -} - -// Resets the retry exponential backoff. mutex must be held. -func (s *cachedService) resetRetryDelay() { - s.lastRetryDelay = time.Duration(0) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/servicecontroller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/servicecontroller_test.go deleted file mode 100644 index 8f58de10a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/service/servicecontroller_test.go +++ /dev/null @@ -1,329 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 service - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - fakecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/fake" - "k8s.io/kubernetes/pkg/types" -) - -const region = "us-central" - -func newService(name string, uid types.UID, serviceType api.ServiceType) *api.Service { - return &api.Service{ObjectMeta: api.ObjectMeta{Name: name, Namespace: "namespace", UID: uid}, Spec: api.ServiceSpec{Type: serviceType}} -} - -func TestCreateExternalLoadBalancer(t *testing.T) { - table := []struct { - service *api.Service - expectErr bool - expectCreateAttempt bool - }{ - { - service: &api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "no-external-balancer", - Namespace: "default", - }, - Spec: api.ServiceSpec{ - Type: api.ServiceTypeClusterIP, - }, - }, - expectErr: false, - expectCreateAttempt: false, - }, - { - service: &api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "udp-service", - Namespace: "default", - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{{ - Port: 80, - Protocol: api.ProtocolUDP, - }}, - Type: api.ServiceTypeLoadBalancer, - }, - }, - expectErr: false, - expectCreateAttempt: true, - }, - { - service: &api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "basic-service1", - Namespace: "default", - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{{ - Port: 80, - Protocol: api.ProtocolTCP, - }}, - Type: api.ServiceTypeLoadBalancer, - }, - }, - expectErr: false, - expectCreateAttempt: true, - }, - } - - for _, item := range table { - cloud := &fakecloud.FakeCloud{} - cloud.Region = region - client := &fake.Clientset{} - controller := New(cloud, client, "test-cluster") - controller.init() - cloud.Calls = nil // ignore any cloud calls made in init() - client.ClearActions() // ignore any client calls made in init() - err, _ := controller.createLoadBalancerIfNeeded(types.NamespacedName{Namespace: "foo", Name: "bar"}, item.service, nil) - if !item.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } else if item.expectErr && err == nil { - t.Errorf("expected error creating %v, got nil", item.service) - } - actions := client.Actions() - if !item.expectCreateAttempt { - if len(cloud.Calls) > 0 { - t.Errorf("unexpected cloud provider calls: %v", cloud.Calls) - } - if len(actions) > 0 { - t.Errorf("unexpected client actions: %v", actions) - } - } else { - var balancer *fakecloud.FakeBalancer - for k := range cloud.Balancers { - if balancer == nil { - b := cloud.Balancers[k] - balancer = &b - } else { - t.Errorf("expected one load balancer to be created, got %v", cloud.Balancers) - break - } - } - if balancer == nil { - t.Errorf("expected one load balancer to be created, got none") - } else if balancer.Name != controller.loadBalancerName(item.service) || - balancer.Region != region || - balancer.Ports[0].Port != item.service.Spec.Ports[0].Port { - t.Errorf("created load balancer has incorrect parameters: %v", balancer) - } - actionFound := false - for _, action := range actions { - if action.GetVerb() == "update" && action.GetResource().Resource == "services" { - actionFound = true - } - } - if !actionFound { - t.Errorf("expected updated service to be sent to client, got these actions instead: %v", actions) - } - } - } -} - -// TODO: Finish converting and update comments -func TestUpdateNodesInExternalLoadBalancer(t *testing.T) { - hosts := []string{"node0", "node1", "node73"} - table := []struct { - services []*api.Service - expectedUpdateCalls []fakecloud.FakeUpdateBalancerCall - }{ - { - // No services present: no calls should be made. - services: []*api.Service{}, - expectedUpdateCalls: nil, - }, - { - // Services do not have external load balancers: no calls should be made. - services: []*api.Service{ - newService("s0", "111", api.ServiceTypeClusterIP), - newService("s1", "222", api.ServiceTypeNodePort), - }, - expectedUpdateCalls: nil, - }, - { - // Services does have an external load balancer: one call should be made. - services: []*api.Service{ - newService("s0", "333", api.ServiceTypeLoadBalancer), - }, - expectedUpdateCalls: []fakecloud.FakeUpdateBalancerCall{ - {newService("s0", "333", api.ServiceTypeLoadBalancer), hosts}, - }, - }, - { - // Three services have an external load balancer: three calls. - services: []*api.Service{ - newService("s0", "444", api.ServiceTypeLoadBalancer), - newService("s1", "555", api.ServiceTypeLoadBalancer), - newService("s2", "666", api.ServiceTypeLoadBalancer), - }, - expectedUpdateCalls: []fakecloud.FakeUpdateBalancerCall{ - {newService("s0", "444", api.ServiceTypeLoadBalancer), hosts}, - {newService("s1", "555", api.ServiceTypeLoadBalancer), hosts}, - {newService("s2", "666", api.ServiceTypeLoadBalancer), hosts}, - }, - }, - { - // Two services have an external load balancer and two don't: two calls. - services: []*api.Service{ - newService("s0", "777", api.ServiceTypeNodePort), - newService("s1", "888", api.ServiceTypeLoadBalancer), - newService("s3", "999", api.ServiceTypeLoadBalancer), - newService("s4", "123", api.ServiceTypeClusterIP), - }, - expectedUpdateCalls: []fakecloud.FakeUpdateBalancerCall{ - {newService("s1", "888", api.ServiceTypeLoadBalancer), hosts}, - {newService("s3", "999", api.ServiceTypeLoadBalancer), hosts}, - }, - }, - { - // One service has an external load balancer and one is nil: one call. - services: []*api.Service{ - newService("s0", "234", api.ServiceTypeLoadBalancer), - nil, - }, - expectedUpdateCalls: []fakecloud.FakeUpdateBalancerCall{ - {newService("s0", "234", api.ServiceTypeLoadBalancer), hosts}, - }, - }, - } - for _, item := range table { - cloud := &fakecloud.FakeCloud{} - - cloud.Region = region - client := &fake.Clientset{} - controller := New(cloud, client, "test-cluster2") - controller.init() - cloud.Calls = nil // ignore any cloud calls made in init() - - var services []*cachedService - for _, service := range item.services { - services = append(services, &cachedService{lastState: service, appliedState: service}) - } - if err := controller.updateLoadBalancerHosts(services, hosts); err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(item.expectedUpdateCalls, cloud.UpdateCalls) { - t.Errorf("expected update calls mismatch, expected %+v, got %+v", item.expectedUpdateCalls, cloud.UpdateCalls) - } - } -} - -func TestHostsFromNodeList(t *testing.T) { - tests := []struct { - nodes *api.NodeList - expectedHosts []string - }{ - { - nodes: &api.NodeList{}, - expectedHosts: []string{}, - }, - { - nodes: &api.NodeList{ - Items: []api.Node{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Status: api.NodeStatus{Phase: api.NodeRunning}, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar"}, - Status: api.NodeStatus{Phase: api.NodeRunning}, - }, - }, - }, - expectedHosts: []string{"foo", "bar"}, - }, - { - nodes: &api.NodeList{ - Items: []api.Node{ - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Status: api.NodeStatus{Phase: api.NodeRunning}, - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar"}, - Status: api.NodeStatus{Phase: api.NodeRunning}, - }, - { - ObjectMeta: api.ObjectMeta{Name: "unschedulable"}, - Spec: api.NodeSpec{Unschedulable: true}, - Status: api.NodeStatus{Phase: api.NodeRunning}, - }, - }, - }, - expectedHosts: []string{"foo", "bar"}, - }, - } - - for _, test := range tests { - hosts := hostsFromNodeList(test.nodes) - if !reflect.DeepEqual(hosts, test.expectedHosts) { - t.Errorf("expected: %v, saw: %v", test.expectedHosts, hosts) - } - } -} - -func TestGetNodeConditionPredicate(t *testing.T) { - tests := []struct { - node api.Node - expectAccept bool - name string - }{ - { - node: api.Node{}, - expectAccept: false, - name: "empty", - }, - { - node: api.Node{ - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - {Type: api.NodeReady, Status: api.ConditionTrue}, - }, - }, - }, - expectAccept: true, - name: "basic", - }, - { - node: api.Node{ - Spec: api.NodeSpec{Unschedulable: true}, - Status: api.NodeStatus{ - Conditions: []api.NodeCondition{ - {Type: api.NodeReady, Status: api.ConditionTrue}, - }, - }, - }, - expectAccept: false, - name: "unschedulable", - }, - } - pred := getNodeConditionPredicate() - for _, test := range tests { - accept := pred(test.node) - if accept != test.expectAccept { - t.Errorf("Test failed for %s, expected %v, saw %v", test.name, test.expectAccept, accept) - } - } -} - -// TODO(a-robinson): Add tests for update/sync/delete. diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/doc.go deleted file mode 100644 index b69d1a121..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 serviceaccount provides implementations -// to manage service accounts and service account tokens -package serviceaccount diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller.go deleted file mode 100644 index 084ddae50..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller.go +++ /dev/null @@ -1,259 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 serviceaccount - -import ( - "fmt" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - apierrs "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/metrics" - "k8s.io/kubernetes/pkg/watch" -) - -// nameIndexFunc is an index function that indexes based on an object's name -func nameIndexFunc(obj interface{}) ([]string, error) { - meta, err := meta.Accessor(obj) - if err != nil { - return []string{""}, fmt.Errorf("object has no meta: %v", err) - } - return []string{meta.GetName()}, nil -} - -// ServiceAccountsControllerOptions contains options for running a ServiceAccountsController -type ServiceAccountsControllerOptions struct { - // ServiceAccounts is the list of service accounts to ensure exist in every namespace - ServiceAccounts []api.ServiceAccount - - // ServiceAccountResync is the interval between full resyncs of ServiceAccounts. - // If non-zero, all service accounts will be re-listed this often. - // Otherwise, re-list will be delayed as long as possible (until the watch is closed or times out). - ServiceAccountResync time.Duration - - // NamespaceResync is the interval between full resyncs of Namespaces. - // If non-zero, all namespaces will be re-listed this often. - // Otherwise, re-list will be delayed as long as possible (until the watch is closed or times out). - NamespaceResync time.Duration -} - -func DefaultServiceAccountsControllerOptions() ServiceAccountsControllerOptions { - return ServiceAccountsControllerOptions{ - ServiceAccounts: []api.ServiceAccount{ - {ObjectMeta: api.ObjectMeta{Name: "default"}}, - }, - } -} - -// NewServiceAccountsController returns a new *ServiceAccountsController. -func NewServiceAccountsController(cl clientset.Interface, options ServiceAccountsControllerOptions) *ServiceAccountsController { - e := &ServiceAccountsController{ - client: cl, - serviceAccountsToEnsure: options.ServiceAccounts, - } - if cl != nil && cl.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.Core().GetRESTClient().GetRateLimiter()) - } - accountSelector := fields.Everything() - if len(options.ServiceAccounts) == 1 { - // If we're maintaining a single account, we can scope the accounts we watch to just that name - accountSelector = fields.SelectorFromSet(map[string]string{api.ObjectNameField: options.ServiceAccounts[0].Name}) - } - e.serviceAccounts, e.serviceAccountController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - options.FieldSelector = accountSelector - return e.client.Core().ServiceAccounts(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - options.FieldSelector = accountSelector - return e.client.Core().ServiceAccounts(api.NamespaceAll).Watch(options) - }, - }, - &api.ServiceAccount{}, - options.ServiceAccountResync, - framework.ResourceEventHandlerFuncs{ - DeleteFunc: e.serviceAccountDeleted, - }, - cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, - ) - - e.namespaces, e.namespaceController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return e.client.Core().Namespaces().List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return e.client.Core().Namespaces().Watch(options) - }, - }, - &api.Namespace{}, - options.NamespaceResync, - framework.ResourceEventHandlerFuncs{ - AddFunc: e.namespaceAdded, - UpdateFunc: e.namespaceUpdated, - }, - cache.Indexers{"name": nameIndexFunc}, - ) - - return e -} - -// ServiceAccountsController manages ServiceAccount objects inside Namespaces -type ServiceAccountsController struct { - stopChan chan struct{} - - client clientset.Interface - serviceAccountsToEnsure []api.ServiceAccount - - serviceAccounts cache.Indexer - namespaces cache.Indexer - - // Since we join two objects, we'll watch both of them with controllers. - serviceAccountController *framework.Controller - namespaceController *framework.Controller -} - -// Runs controller loops and returns immediately -func (e *ServiceAccountsController) Run() { - if e.stopChan == nil { - e.stopChan = make(chan struct{}) - go e.serviceAccountController.Run(e.stopChan) - go e.namespaceController.Run(e.stopChan) - } -} - -// Stop gracefully shuts down this controller -func (e *ServiceAccountsController) Stop() { - if e.stopChan != nil { - close(e.stopChan) - e.stopChan = nil - } -} - -// serviceAccountDeleted reacts to a ServiceAccount deletion by recreating a default ServiceAccount in the namespace if needed -func (e *ServiceAccountsController) serviceAccountDeleted(obj interface{}) { - serviceAccount, ok := obj.(*api.ServiceAccount) - if !ok { - // Unknown type. If we missed a ServiceAccount deletion, the - // corresponding secrets will be cleaned up during the Secret re-list - return - } - // If the deleted service account is one we're maintaining, recreate it - for _, sa := range e.serviceAccountsToEnsure { - if sa.Name == serviceAccount.Name { - e.createServiceAccountIfNeeded(sa, serviceAccount.Namespace) - } - } -} - -// namespaceAdded reacts to a Namespace creation by creating a default ServiceAccount object -func (e *ServiceAccountsController) namespaceAdded(obj interface{}) { - namespace := obj.(*api.Namespace) - for _, sa := range e.serviceAccountsToEnsure { - e.createServiceAccountIfNeeded(sa, namespace.Name) - } -} - -// namespaceUpdated reacts to a Namespace update (or re-list) by creating a default ServiceAccount in the namespace if needed -func (e *ServiceAccountsController) namespaceUpdated(oldObj interface{}, newObj interface{}) { - newNamespace := newObj.(*api.Namespace) - for _, sa := range e.serviceAccountsToEnsure { - e.createServiceAccountIfNeeded(sa, newNamespace.Name) - } -} - -// createServiceAccountIfNeeded creates a ServiceAccount with the given name in the given namespace if: -// * the named ServiceAccount does not already exist -// * the specified namespace exists -// * the specified namespace is in the ACTIVE phase -func (e *ServiceAccountsController) createServiceAccountIfNeeded(sa api.ServiceAccount, namespace string) { - existingServiceAccount, err := e.getServiceAccount(sa.Name, namespace) - if err != nil { - glog.Error(err) - return - } - if existingServiceAccount != nil { - // If service account already exists, it doesn't need to be created - return - } - - namespaceObj, err := e.getNamespace(namespace) - if err != nil { - glog.Error(err) - return - } - if namespaceObj == nil { - // If namespace does not exist, no service account is needed - return - } - if namespaceObj.Status.Phase != api.NamespaceActive { - // If namespace is not active, we shouldn't try to create anything - return - } - - e.createServiceAccount(sa, namespace) -} - -// createDefaultServiceAccount creates a default ServiceAccount in the specified namespace -func (e *ServiceAccountsController) createServiceAccount(sa api.ServiceAccount, namespace string) { - sa.Namespace = namespace - if _, err := e.client.Core().ServiceAccounts(namespace).Create(&sa); err != nil && !apierrs.IsAlreadyExists(err) { - glog.Error(err) - } -} - -// getServiceAccount returns the ServiceAccount with the given name for the given namespace -func (e *ServiceAccountsController) getServiceAccount(name, namespace string) (*api.ServiceAccount, error) { - key := &api.ServiceAccount{ObjectMeta: api.ObjectMeta{Namespace: namespace}} - accounts, err := e.serviceAccounts.Index("namespace", key) - if err != nil { - return nil, err - } - - for _, obj := range accounts { - serviceAccount := obj.(*api.ServiceAccount) - if name == serviceAccount.Name { - return serviceAccount, nil - } - } - return nil, nil -} - -// getNamespace returns the Namespace with the given name -func (e *ServiceAccountsController) getNamespace(name string) (*api.Namespace, error) { - key := &api.Namespace{ObjectMeta: api.ObjectMeta{Name: name}} - namespaces, err := e.namespaces.Index("name", key) - if err != nil { - return nil, err - } - - if len(namespaces) == 0 { - return nil, nil - } - if len(namespaces) == 1 { - return namespaces[0].(*api.Namespace), nil - } - return nil, fmt.Errorf("%d namespaces with the name %s indexed", len(namespaces), name) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller_test.go deleted file mode 100644 index e55ffeb51..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/serviceaccounts_controller_test.go +++ /dev/null @@ -1,197 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 serviceaccount - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/util/sets" -) - -type serverResponse struct { - statusCode int - obj interface{} -} - -func TestServiceAccountCreation(t *testing.T) { - ns := api.NamespaceDefault - - defaultName := "default" - managedName := "managed" - - activeNS := &api.Namespace{ - ObjectMeta: api.ObjectMeta{Name: ns}, - Status: api.NamespaceStatus{ - Phase: api.NamespaceActive, - }, - } - terminatingNS := &api.Namespace{ - ObjectMeta: api.ObjectMeta{Name: ns}, - Status: api.NamespaceStatus{ - Phase: api.NamespaceTerminating, - }, - } - defaultServiceAccount := &api.ServiceAccount{ - ObjectMeta: api.ObjectMeta{ - Name: defaultName, - Namespace: ns, - ResourceVersion: "1", - }, - } - managedServiceAccount := &api.ServiceAccount{ - ObjectMeta: api.ObjectMeta{ - Name: managedName, - Namespace: ns, - ResourceVersion: "1", - }, - } - unmanagedServiceAccount := &api.ServiceAccount{ - ObjectMeta: api.ObjectMeta{ - Name: "other-unmanaged", - Namespace: ns, - ResourceVersion: "1", - }, - } - - testcases := map[string]struct { - ExistingNamespace *api.Namespace - ExistingServiceAccounts []*api.ServiceAccount - - AddedNamespace *api.Namespace - UpdatedNamespace *api.Namespace - DeletedServiceAccount *api.ServiceAccount - - ExpectCreatedServiceAccounts []string - }{ - "new active namespace missing serviceaccounts": { - ExistingServiceAccounts: []*api.ServiceAccount{}, - AddedNamespace: activeNS, - ExpectCreatedServiceAccounts: sets.NewString(defaultName, managedName).List(), - }, - "new active namespace missing serviceaccount": { - ExistingServiceAccounts: []*api.ServiceAccount{managedServiceAccount}, - AddedNamespace: activeNS, - ExpectCreatedServiceAccounts: []string{defaultName}, - }, - "new active namespace with serviceaccounts": { - ExistingServiceAccounts: []*api.ServiceAccount{defaultServiceAccount, managedServiceAccount}, - AddedNamespace: activeNS, - ExpectCreatedServiceAccounts: []string{}, - }, - - "new terminating namespace": { - ExistingServiceAccounts: []*api.ServiceAccount{}, - AddedNamespace: terminatingNS, - ExpectCreatedServiceAccounts: []string{}, - }, - - "updated active namespace missing serviceaccounts": { - ExistingServiceAccounts: []*api.ServiceAccount{}, - UpdatedNamespace: activeNS, - ExpectCreatedServiceAccounts: sets.NewString(defaultName, managedName).List(), - }, - "updated active namespace missing serviceaccount": { - ExistingServiceAccounts: []*api.ServiceAccount{defaultServiceAccount}, - UpdatedNamespace: activeNS, - ExpectCreatedServiceAccounts: []string{managedName}, - }, - "updated active namespace with serviceaccounts": { - ExistingServiceAccounts: []*api.ServiceAccount{defaultServiceAccount, managedServiceAccount}, - UpdatedNamespace: activeNS, - ExpectCreatedServiceAccounts: []string{}, - }, - "updated terminating namespace": { - ExistingServiceAccounts: []*api.ServiceAccount{}, - UpdatedNamespace: terminatingNS, - ExpectCreatedServiceAccounts: []string{}, - }, - - "deleted serviceaccount without namespace": { - DeletedServiceAccount: defaultServiceAccount, - ExpectCreatedServiceAccounts: []string{}, - }, - "deleted serviceaccount with active namespace": { - ExistingNamespace: activeNS, - DeletedServiceAccount: defaultServiceAccount, - ExpectCreatedServiceAccounts: []string{defaultName}, - }, - "deleted serviceaccount with terminating namespace": { - ExistingNamespace: terminatingNS, - DeletedServiceAccount: defaultServiceAccount, - ExpectCreatedServiceAccounts: []string{}, - }, - "deleted unmanaged serviceaccount with active namespace": { - ExistingNamespace: activeNS, - DeletedServiceAccount: unmanagedServiceAccount, - ExpectCreatedServiceAccounts: []string{}, - }, - "deleted unmanaged serviceaccount with terminating namespace": { - ExistingNamespace: terminatingNS, - DeletedServiceAccount: unmanagedServiceAccount, - ExpectCreatedServiceAccounts: []string{}, - }, - } - - for k, tc := range testcases { - client := fake.NewSimpleClientset(defaultServiceAccount, managedServiceAccount) - options := DefaultServiceAccountsControllerOptions() - options.ServiceAccounts = []api.ServiceAccount{ - {ObjectMeta: api.ObjectMeta{Name: defaultName}}, - {ObjectMeta: api.ObjectMeta{Name: managedName}}, - } - controller := NewServiceAccountsController(client, options) - - if tc.ExistingNamespace != nil { - controller.namespaces.Add(tc.ExistingNamespace) - } - for _, s := range tc.ExistingServiceAccounts { - controller.serviceAccounts.Add(s) - } - - if tc.AddedNamespace != nil { - controller.namespaces.Add(tc.AddedNamespace) - controller.namespaceAdded(tc.AddedNamespace) - } - if tc.UpdatedNamespace != nil { - controller.namespaces.Add(tc.UpdatedNamespace) - controller.namespaceUpdated(nil, tc.UpdatedNamespace) - } - if tc.DeletedServiceAccount != nil { - controller.serviceAccountDeleted(tc.DeletedServiceAccount) - } - - actions := client.Actions() - if len(tc.ExpectCreatedServiceAccounts) != len(actions) { - t.Errorf("%s: Expected to create accounts %#v. Actual actions were: %#v", k, tc.ExpectCreatedServiceAccounts, actions) - continue - } - for i, expectedName := range tc.ExpectCreatedServiceAccounts { - action := actions[i] - if !action.Matches("create", "serviceaccounts") { - t.Errorf("%s: Unexpected action %s", k, action) - break - } - createdAccount := action.(core.CreateAction).GetObject().(*api.ServiceAccount) - if createdAccount.Name != expectedName { - t.Errorf("%s: Expected %s to be created, got %s", k, expectedName, createdAccount.Name) - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokengetter.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokengetter.go deleted file mode 100644 index bd7fc827b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokengetter.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 serviceaccount - -import ( - "k8s.io/kubernetes/pkg/api" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/registry/secret" - secretetcd "k8s.io/kubernetes/pkg/registry/secret/etcd" - serviceaccountregistry "k8s.io/kubernetes/pkg/registry/serviceaccount" - serviceaccountetcd "k8s.io/kubernetes/pkg/registry/serviceaccount/etcd" - "k8s.io/kubernetes/pkg/serviceaccount" - "k8s.io/kubernetes/pkg/storage" -) - -// clientGetter implements ServiceAccountTokenGetter using a clientset.Interface -type clientGetter struct { - client clientset.Interface -} - -// NewGetterFromClient returns a ServiceAccountTokenGetter that -// uses the specified client to retrieve service accounts and secrets. -// The client should NOT authenticate using a service account token -// the returned getter will be used to retrieve, or recursion will result. -func NewGetterFromClient(c clientset.Interface) serviceaccount.ServiceAccountTokenGetter { - return clientGetter{c} -} -func (c clientGetter) GetServiceAccount(namespace, name string) (*api.ServiceAccount, error) { - return c.client.Core().ServiceAccounts(namespace).Get(name) -} -func (c clientGetter) GetSecret(namespace, name string) (*api.Secret, error) { - return c.client.Core().Secrets(namespace).Get(name) -} - -// registryGetter implements ServiceAccountTokenGetter using a service account and secret registry -type registryGetter struct { - serviceAccounts serviceaccountregistry.Registry - secrets secret.Registry -} - -// NewGetterFromRegistries returns a ServiceAccountTokenGetter that -// uses the specified registries to retrieve service accounts and secrets. -func NewGetterFromRegistries(serviceAccounts serviceaccountregistry.Registry, secrets secret.Registry) serviceaccount.ServiceAccountTokenGetter { - return ®istryGetter{serviceAccounts, secrets} -} -func (r *registryGetter) GetServiceAccount(namespace, name string) (*api.ServiceAccount, error) { - ctx := api.WithNamespace(api.NewContext(), namespace) - return r.serviceAccounts.GetServiceAccount(ctx, name) -} -func (r *registryGetter) GetSecret(namespace, name string) (*api.Secret, error) { - ctx := api.WithNamespace(api.NewContext(), namespace) - return r.secrets.GetSecret(ctx, name) -} - -// NewGetterFromStorageInterface returns a ServiceAccountTokenGetter that -// uses the specified storage to retrieve service accounts and secrets. -func NewGetterFromStorageInterface(s storage.Interface) serviceaccount.ServiceAccountTokenGetter { - return NewGetterFromRegistries( - serviceaccountregistry.NewRegistry(serviceaccountetcd.NewREST(generic.RESTOptions{Storage: s, Decorator: generic.UndecoratedStorage})), - secret.NewRegistry(secretetcd.NewREST(generic.RESTOptions{Storage: s, Decorator: generic.UndecoratedStorage})), - ) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller.go deleted file mode 100644 index b660afc96..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller.go +++ /dev/null @@ -1,525 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 serviceaccount - -import ( - "bytes" - "fmt" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" - apierrors "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/client/cache" - clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/controller/framework" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/registry/secret" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/serviceaccount" - "k8s.io/kubernetes/pkg/util/metrics" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" -) - -// RemoveTokenBackoff is the recommended (empirical) retry interval for removing -// a secret reference from a service account when the secret is deleted. It is -// exported for use by custom secret controllers. -var RemoveTokenBackoff = wait.Backoff{ - Steps: 10, - Duration: 100 * time.Millisecond, - Jitter: 1.0, -} - -// TokensControllerOptions contains options for the TokensController -type TokensControllerOptions struct { - // TokenGenerator is the generator to use to create new tokens - TokenGenerator serviceaccount.TokenGenerator - // ServiceAccountResync is the time.Duration at which to fully re-list service accounts. - // If zero, re-list will be delayed as long as possible - ServiceAccountResync time.Duration - // SecretResync is the time.Duration at which to fully re-list secrets. - // If zero, re-list will be delayed as long as possible - SecretResync time.Duration - // This CA will be added in the secretes of service accounts - RootCA []byte -} - -// NewTokensController returns a new *TokensController. -func NewTokensController(cl clientset.Interface, options TokensControllerOptions) *TokensController { - e := &TokensController{ - client: cl, - token: options.TokenGenerator, - rootCA: options.RootCA, - } - if cl != nil && cl.Core().GetRESTClient().GetRateLimiter() != nil { - metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.Core().GetRESTClient().GetRateLimiter()) - } - e.serviceAccounts, e.serviceAccountController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return e.client.Core().ServiceAccounts(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - return e.client.Core().ServiceAccounts(api.NamespaceAll).Watch(options) - }, - }, - &api.ServiceAccount{}, - options.ServiceAccountResync, - framework.ResourceEventHandlerFuncs{ - AddFunc: e.serviceAccountAdded, - UpdateFunc: e.serviceAccountUpdated, - DeleteFunc: e.serviceAccountDeleted, - }, - cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, - ) - - tokenSelector := fields.SelectorFromSet(map[string]string{api.SecretTypeField: string(api.SecretTypeServiceAccountToken)}) - e.secrets, e.secretController = framework.NewIndexerInformer( - &cache.ListWatch{ - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - options.FieldSelector = tokenSelector - return e.client.Core().Secrets(api.NamespaceAll).List(options) - }, - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - options.FieldSelector = tokenSelector - return e.client.Core().Secrets(api.NamespaceAll).Watch(options) - }, - }, - &api.Secret{}, - options.SecretResync, - framework.ResourceEventHandlerFuncs{ - AddFunc: e.secretAdded, - UpdateFunc: e.secretUpdated, - DeleteFunc: e.secretDeleted, - }, - cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}, - ) - - e.serviceAccountsSynced = e.serviceAccountController.HasSynced - e.secretsSynced = e.secretController.HasSynced - - return e -} - -// TokensController manages ServiceAccountToken secrets for ServiceAccount objects -type TokensController struct { - stopChan chan struct{} - - client clientset.Interface - token serviceaccount.TokenGenerator - - rootCA []byte - - serviceAccounts cache.Indexer - secrets cache.Indexer - - // Since we join two objects, we'll watch both of them with controllers. - serviceAccountController *framework.Controller - secretController *framework.Controller - - // These are here so tests can inject a 'return true'. - serviceAccountsSynced func() bool - secretsSynced func() bool -} - -// Runs controller loops and returns immediately -func (e *TokensController) Run() { - if e.stopChan == nil { - e.stopChan = make(chan struct{}) - go e.serviceAccountController.Run(e.stopChan) - go e.secretController.Run(e.stopChan) - } -} - -// Stop gracefully shuts down this controller -func (e *TokensController) Stop() { - if e.stopChan != nil { - close(e.stopChan) - e.stopChan = nil - } -} - -// serviceAccountAdded reacts to a ServiceAccount creation by creating a corresponding ServiceAccountToken Secret -func (e *TokensController) serviceAccountAdded(obj interface{}) { - serviceAccount := obj.(*api.ServiceAccount) - err := e.createSecretIfNeeded(serviceAccount) - if err != nil { - glog.Error(err) - } -} - -// serviceAccountUpdated reacts to a ServiceAccount update (or re-list) by ensuring a corresponding ServiceAccountToken Secret exists -func (e *TokensController) serviceAccountUpdated(oldObj interface{}, newObj interface{}) { - newServiceAccount := newObj.(*api.ServiceAccount) - err := e.createSecretIfNeeded(newServiceAccount) - if err != nil { - glog.Error(err) - } -} - -// serviceAccountDeleted reacts to a ServiceAccount deletion by deleting all corresponding ServiceAccountToken Secrets -func (e *TokensController) serviceAccountDeleted(obj interface{}) { - serviceAccount, ok := obj.(*api.ServiceAccount) - if !ok { - // Unknown type. If we missed a ServiceAccount deletion, the - // corresponding secrets will be cleaned up during the Secret re-list - return - } - secrets, err := e.listTokenSecrets(serviceAccount) - if err != nil { - glog.Error(err) - return - } - for _, secret := range secrets { - glog.V(4).Infof("Deleting secret %s/%s because service account %s was deleted", secret.Namespace, secret.Name, serviceAccount.Name) - if err := e.deleteSecret(secret); err != nil { - glog.Errorf("Error deleting secret %s/%s: %v", secret.Namespace, secret.Name, err) - } - } -} - -// secretAdded reacts to a Secret create by ensuring the referenced ServiceAccount exists, and by adding a token to the secret if needed -func (e *TokensController) secretAdded(obj interface{}) { - secret := obj.(*api.Secret) - serviceAccount, err := e.getServiceAccount(secret, true) - if err != nil { - glog.Error(err) - return - } - if serviceAccount == nil { - glog.V(2).Infof( - "Deleting new secret %s/%s because service account %s (uid=%s) was not found", - secret.Namespace, secret.Name, - secret.Annotations[api.ServiceAccountNameKey], secret.Annotations[api.ServiceAccountUIDKey]) - if err := e.deleteSecret(secret); err != nil { - glog.Errorf("Error deleting secret %s/%s: %v", secret.Namespace, secret.Name, err) - } - } else { - e.generateTokenIfNeeded(serviceAccount, secret) - } -} - -// secretUpdated reacts to a Secret update (or re-list) by deleting the secret (if the referenced ServiceAccount does not exist) -func (e *TokensController) secretUpdated(oldObj interface{}, newObj interface{}) { - newSecret := newObj.(*api.Secret) - newServiceAccount, err := e.getServiceAccount(newSecret, true) - if err != nil { - glog.Error(err) - return - } - if newServiceAccount == nil { - glog.V(2).Infof( - "Deleting updated secret %s/%s because service account %s (uid=%s) was not found", - newSecret.Namespace, newSecret.Name, - newSecret.Annotations[api.ServiceAccountNameKey], newSecret.Annotations[api.ServiceAccountUIDKey]) - if err := e.deleteSecret(newSecret); err != nil { - glog.Errorf("Error deleting secret %s/%s: %v", newSecret.Namespace, newSecret.Name, err) - } - } else { - e.generateTokenIfNeeded(newServiceAccount, newSecret) - } -} - -// secretDeleted reacts to a Secret being deleted by removing a reference from the corresponding ServiceAccount if needed -func (e *TokensController) secretDeleted(obj interface{}) { - secret, ok := obj.(*api.Secret) - if !ok { - // Unknown type. If we missed a Secret deletion, the corresponding ServiceAccount (if it exists) - // will get a secret recreated (if needed) during the ServiceAccount re-list - return - } - - serviceAccount, err := e.getServiceAccount(secret, false) - if err != nil { - glog.Error(err) - return - } - if serviceAccount == nil { - return - } - - if err := client.RetryOnConflict(RemoveTokenBackoff, func() error { - return e.removeSecretReferenceIfNeeded(serviceAccount, secret.Name) - }); err != nil { - utilruntime.HandleError(err) - } -} - -// createSecretIfNeeded makes sure at least one ServiceAccountToken secret exists, and is included in the serviceAccount's Secrets list -func (e *TokensController) createSecretIfNeeded(serviceAccount *api.ServiceAccount) error { - // If the service account references no secrets, short-circuit and create a new one - if len(serviceAccount.Secrets) == 0 { - return e.createSecret(serviceAccount) - } - - // We shouldn't try to validate secret references until the secrets store is synced - if !e.secretsSynced() { - return nil - } - - // If any existing token secrets are referenced by the service account, return - allSecrets, err := e.listTokenSecrets(serviceAccount) - if err != nil { - return err - } - referencedSecrets := getSecretReferences(serviceAccount) - for _, secret := range allSecrets { - if referencedSecrets.Has(secret.Name) { - return nil - } - } - - // Otherwise create a new token secret - return e.createSecret(serviceAccount) -} - -// createSecret creates a secret of type ServiceAccountToken for the given ServiceAccount -func (e *TokensController) createSecret(serviceAccount *api.ServiceAccount) error { - // We don't want to update the cache's copy of the service account - // so add the secret to a freshly retrieved copy of the service account - serviceAccounts := e.client.Core().ServiceAccounts(serviceAccount.Namespace) - liveServiceAccount, err := serviceAccounts.Get(serviceAccount.Name) - if err != nil { - return err - } - if liveServiceAccount.ResourceVersion != serviceAccount.ResourceVersion { - // our view of the service account is not up to date - // we'll get notified of an update event later and get to try again - // this only prevent interactions between successive runs of this controller's event handlers, but that is useful - glog.V(2).Infof("View of ServiceAccount %s/%s is not up to date, skipping token creation", serviceAccount.Namespace, serviceAccount.Name) - return nil - } - - // Build the secret - secret := &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: secret.Strategy.GenerateName(fmt.Sprintf("%s-token-", serviceAccount.Name)), - Namespace: serviceAccount.Namespace, - Annotations: map[string]string{ - api.ServiceAccountNameKey: serviceAccount.Name, - api.ServiceAccountUIDKey: string(serviceAccount.UID), - }, - }, - Type: api.SecretTypeServiceAccountToken, - Data: map[string][]byte{}, - } - - // Generate the token - token, err := e.token.GenerateToken(*serviceAccount, *secret) - if err != nil { - return err - } - secret.Data[api.ServiceAccountTokenKey] = []byte(token) - secret.Data[api.ServiceAccountNamespaceKey] = []byte(serviceAccount.Namespace) - if e.rootCA != nil && len(e.rootCA) > 0 { - secret.Data[api.ServiceAccountRootCAKey] = e.rootCA - } - - // Save the secret - if createdToken, err := e.client.Core().Secrets(serviceAccount.Namespace).Create(secret); err != nil { - return err - } else { - // Manually add the new token to the cache store. - // This prevents the service account update (below) triggering another token creation, if the referenced token couldn't be found in the store - e.secrets.Add(createdToken) - } - - liveServiceAccount.Secrets = append(liveServiceAccount.Secrets, api.ObjectReference{Name: secret.Name}) - - _, err = serviceAccounts.Update(liveServiceAccount) - if err != nil { - // we weren't able to use the token, try to clean it up. - glog.V(2).Infof("Deleting secret %s/%s because reference couldn't be added (%v)", secret.Namespace, secret.Name, err) - if err := e.client.Core().Secrets(secret.Namespace).Delete(secret.Name, nil); err != nil { - glog.Error(err) // if we fail, just log it - } - } - if apierrors.IsConflict(err) { - // nothing to do. We got a conflict, that means that the service account was updated. We simply need to return because we'll get an update notification later - return nil - } - - return err -} - -// generateTokenIfNeeded populates the token data for the given Secret if not already set -func (e *TokensController) generateTokenIfNeeded(serviceAccount *api.ServiceAccount, secret *api.Secret) error { - if secret.Annotations == nil { - secret.Annotations = map[string]string{} - } - if secret.Data == nil { - secret.Data = map[string][]byte{} - } - - caData := secret.Data[api.ServiceAccountRootCAKey] - needsCA := len(e.rootCA) > 0 && bytes.Compare(caData, e.rootCA) != 0 - - needsNamespace := len(secret.Data[api.ServiceAccountNamespaceKey]) == 0 - - tokenData := secret.Data[api.ServiceAccountTokenKey] - needsToken := len(tokenData) == 0 - - if !needsCA && !needsToken && !needsNamespace { - return nil - } - - // Set the CA - if needsCA { - secret.Data[api.ServiceAccountRootCAKey] = e.rootCA - } - // Set the namespace - if needsNamespace { - secret.Data[api.ServiceAccountNamespaceKey] = []byte(secret.Namespace) - } - - // Generate the token - if needsToken { - token, err := e.token.GenerateToken(*serviceAccount, *secret) - if err != nil { - return err - } - secret.Data[api.ServiceAccountTokenKey] = []byte(token) - } - - // Set annotations - secret.Annotations[api.ServiceAccountNameKey] = serviceAccount.Name - secret.Annotations[api.ServiceAccountUIDKey] = string(serviceAccount.UID) - - // Save the secret - if _, err := e.client.Core().Secrets(secret.Namespace).Update(secret); err != nil { - return err - } - return nil -} - -// deleteSecret deletes the given secret -func (e *TokensController) deleteSecret(secret *api.Secret) error { - return e.client.Core().Secrets(secret.Namespace).Delete(secret.Name, nil) -} - -// removeSecretReferenceIfNeeded updates the given ServiceAccount to remove a reference to the given secretName if needed. -// Returns whether an update was performed, and any error that occurred -func (e *TokensController) removeSecretReferenceIfNeeded(serviceAccount *api.ServiceAccount, secretName string) error { - // We don't want to update the cache's copy of the service account - // so remove the secret from a freshly retrieved copy of the service account - serviceAccounts := e.client.Core().ServiceAccounts(serviceAccount.Namespace) - serviceAccount, err := serviceAccounts.Get(serviceAccount.Name) - if err != nil { - return err - } - - // Double-check to see if the account still references the secret - if !getSecretReferences(serviceAccount).Has(secretName) { - return nil - } - - secrets := []api.ObjectReference{} - for _, s := range serviceAccount.Secrets { - if s.Name != secretName { - secrets = append(secrets, s) - } - } - serviceAccount.Secrets = secrets - - _, err = serviceAccounts.Update(serviceAccount) - if err != nil { - return err - } - - return nil -} - -// getServiceAccount returns the ServiceAccount referenced by the given secret. If the secret is not -// of type ServiceAccountToken, or if the referenced ServiceAccount does not exist, nil is returned -func (e *TokensController) getServiceAccount(secret *api.Secret, fetchOnCacheMiss bool) (*api.ServiceAccount, error) { - name, _ := serviceAccountNameAndUID(secret) - if len(name) == 0 { - return nil, nil - } - - key := &api.ServiceAccount{ObjectMeta: api.ObjectMeta{Namespace: secret.Namespace}} - namespaceAccounts, err := e.serviceAccounts.Index("namespace", key) - if err != nil { - return nil, err - } - - for _, obj := range namespaceAccounts { - serviceAccount := obj.(*api.ServiceAccount) - - if serviceaccount.IsServiceAccountToken(secret, serviceAccount) { - return serviceAccount, nil - } - } - - if fetchOnCacheMiss { - serviceAccount, err := e.client.Core().ServiceAccounts(secret.Namespace).Get(name) - if apierrors.IsNotFound(err) { - return nil, nil - } - if err != nil { - return nil, err - } - - if serviceaccount.IsServiceAccountToken(secret, serviceAccount) { - return serviceAccount, nil - } - } - - return nil, nil -} - -// listTokenSecrets returns a list of all of the ServiceAccountToken secrets that -// reference the given service account's name and uid -func (e *TokensController) listTokenSecrets(serviceAccount *api.ServiceAccount) ([]*api.Secret, error) { - key := &api.Secret{ObjectMeta: api.ObjectMeta{Namespace: serviceAccount.Namespace}} - namespaceSecrets, err := e.secrets.Index("namespace", key) - if err != nil { - return nil, err - } - - items := []*api.Secret{} - for _, obj := range namespaceSecrets { - secret := obj.(*api.Secret) - - if serviceaccount.IsServiceAccountToken(secret, serviceAccount) { - items = append(items, secret) - } - } - return items, nil -} - -// serviceAccountNameAndUID is a helper method to get the ServiceAccount Name and UID from the given secret -// Returns "","" if the secret is not a ServiceAccountToken secret -// If the name or uid annotation is missing, "" is returned instead -func serviceAccountNameAndUID(secret *api.Secret) (string, string) { - if secret.Type != api.SecretTypeServiceAccountToken { - return "", "" - } - return secret.Annotations[api.ServiceAccountNameKey], secret.Annotations[api.ServiceAccountUIDKey] -} - -func getSecretReferences(serviceAccount *api.ServiceAccount) sets.String { - references := sets.NewString() - for _, secret := range serviceAccount.Secrets { - references.Insert(secret.Name) - } - return references -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller_test.go deleted file mode 100644 index 4f2ff6fb5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/controller/serviceaccount/tokens_controller_test.go +++ /dev/null @@ -1,562 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 serviceaccount - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/runtime" - utilrand "k8s.io/kubernetes/pkg/util/rand" -) - -type testGenerator struct { - GeneratedServiceAccounts []api.ServiceAccount - GeneratedSecrets []api.Secret - Token string - Err error -} - -func (t *testGenerator) GenerateToken(serviceAccount api.ServiceAccount, secret api.Secret) (string, error) { - t.GeneratedSecrets = append(t.GeneratedSecrets, secret) - t.GeneratedServiceAccounts = append(t.GeneratedServiceAccounts, serviceAccount) - return t.Token, t.Err -} - -// emptySecretReferences is used by a service account without any secrets -func emptySecretReferences() []api.ObjectReference { - return []api.ObjectReference{} -} - -// missingSecretReferences is used by a service account that references secrets which do no exist -func missingSecretReferences() []api.ObjectReference { - return []api.ObjectReference{{Name: "missing-secret-1"}} -} - -// regularSecretReferences is used by a service account that references secrets which are not ServiceAccountTokens -func regularSecretReferences() []api.ObjectReference { - return []api.ObjectReference{{Name: "regular-secret-1"}} -} - -// tokenSecretReferences is used by a service account that references a ServiceAccountToken secret -func tokenSecretReferences() []api.ObjectReference { - return []api.ObjectReference{{Name: "token-secret-1"}} -} - -// addTokenSecretReference adds a reference to the ServiceAccountToken that will be created -func addTokenSecretReference(refs []api.ObjectReference) []api.ObjectReference { - return append(refs, api.ObjectReference{Name: "default-token-fplln"}) -} - -// serviceAccount returns a service account with the given secret refs -func serviceAccount(secretRefs []api.ObjectReference) *api.ServiceAccount { - return &api.ServiceAccount{ - ObjectMeta: api.ObjectMeta{ - Name: "default", - UID: "12345", - Namespace: "default", - ResourceVersion: "1", - }, - Secrets: secretRefs, - } -} - -// updatedServiceAccount returns a service account with the resource version modified -func updatedServiceAccount(secretRefs []api.ObjectReference) *api.ServiceAccount { - sa := serviceAccount(secretRefs) - sa.ResourceVersion = "2" - return sa -} - -// opaqueSecret returns a persisted non-ServiceAccountToken secret named "regular-secret-1" -func opaqueSecret() *api.Secret { - return &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "regular-secret-1", - Namespace: "default", - UID: "23456", - ResourceVersion: "1", - }, - Type: "Opaque", - Data: map[string][]byte{ - "mykey": []byte("mydata"), - }, - } -} - -// createdTokenSecret returns the ServiceAccountToken secret posted when creating a new token secret. -// Named "default-token-fplln", since that is the first generated name after rand.Seed(1) -func createdTokenSecret() *api.Secret { - return &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "default-token-fplln", - Namespace: "default", - Annotations: map[string]string{ - api.ServiceAccountNameKey: "default", - api.ServiceAccountUIDKey: "12345", - }, - }, - Type: api.SecretTypeServiceAccountToken, - Data: map[string][]byte{ - "token": []byte("ABC"), - "ca.crt": []byte("CA Data"), - "namespace": []byte("default"), - }, - } -} - -// serviceAccountTokenSecret returns an existing ServiceAccountToken secret named "token-secret-1" -func serviceAccountTokenSecret() *api.Secret { - return &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "token-secret-1", - Namespace: "default", - UID: "23456", - ResourceVersion: "1", - Annotations: map[string]string{ - api.ServiceAccountNameKey: "default", - api.ServiceAccountUIDKey: "12345", - }, - }, - Type: api.SecretTypeServiceAccountToken, - Data: map[string][]byte{ - "token": []byte("ABC"), - "ca.crt": []byte("CA Data"), - "namespace": []byte("default"), - }, - } -} - -// serviceAccountTokenSecretWithoutTokenData returns an existing ServiceAccountToken secret that lacks token data -func serviceAccountTokenSecretWithoutTokenData() *api.Secret { - secret := serviceAccountTokenSecret() - delete(secret.Data, api.ServiceAccountTokenKey) - return secret -} - -// serviceAccountTokenSecretWithoutCAData returns an existing ServiceAccountToken secret that lacks ca data -func serviceAccountTokenSecretWithoutCAData() *api.Secret { - secret := serviceAccountTokenSecret() - delete(secret.Data, api.ServiceAccountRootCAKey) - return secret -} - -// serviceAccountTokenSecretWithCAData returns an existing ServiceAccountToken secret with the specified ca data -func serviceAccountTokenSecretWithCAData(data []byte) *api.Secret { - secret := serviceAccountTokenSecret() - secret.Data[api.ServiceAccountRootCAKey] = data - return secret -} - -// serviceAccountTokenSecretWithoutNamespaceData returns an existing ServiceAccountToken secret that lacks namespace data -func serviceAccountTokenSecretWithoutNamespaceData() *api.Secret { - secret := serviceAccountTokenSecret() - delete(secret.Data, api.ServiceAccountNamespaceKey) - return secret -} - -// serviceAccountTokenSecretWithNamespaceData returns an existing ServiceAccountToken secret with the specified namespace data -func serviceAccountTokenSecretWithNamespaceData(data []byte) *api.Secret { - secret := serviceAccountTokenSecret() - secret.Data[api.ServiceAccountNamespaceKey] = data - return secret -} - -func TestTokenCreation(t *testing.T) { - testcases := map[string]struct { - ClientObjects []runtime.Object - - SecretsSyncPending bool - ServiceAccountsSyncPending bool - - ExistingServiceAccount *api.ServiceAccount - ExistingSecrets []*api.Secret - - AddedServiceAccount *api.ServiceAccount - UpdatedServiceAccount *api.ServiceAccount - DeletedServiceAccount *api.ServiceAccount - AddedSecret *api.Secret - UpdatedSecret *api.Secret - DeletedSecret *api.Secret - - ExpectedActions []core.Action - }{ - "new serviceaccount with no secrets": { - ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, - - AddedServiceAccount: serviceAccount(emptySecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), - }, - }, - "new serviceaccount with no secrets with unsynced secret store": { - ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, - - SecretsSyncPending: true, - - AddedServiceAccount: serviceAccount(emptySecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), - }, - }, - "new serviceaccount with missing secrets": { - ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, - - AddedServiceAccount: serviceAccount(missingSecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(missingSecretReferences()))), - }, - }, - "new serviceaccount with missing secrets with unsynced secret store": { - ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, - - SecretsSyncPending: true, - - AddedServiceAccount: serviceAccount(missingSecretReferences()), - ExpectedActions: []core.Action{}, - }, - "new serviceaccount with non-token secrets": { - ClientObjects: []runtime.Object{serviceAccount(regularSecretReferences()), createdTokenSecret(), opaqueSecret()}, - - AddedServiceAccount: serviceAccount(regularSecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(regularSecretReferences()))), - }, - }, - "new serviceaccount with token secrets": { - ClientObjects: []runtime.Object{serviceAccount(tokenSecretReferences()), serviceAccountTokenSecret()}, - ExistingSecrets: []*api.Secret{serviceAccountTokenSecret()}, - - AddedServiceAccount: serviceAccount(tokenSecretReferences()), - ExpectedActions: []core.Action{}, - }, - "new serviceaccount with no secrets with resource conflict": { - ClientObjects: []runtime.Object{updatedServiceAccount(emptySecretReferences()), createdTokenSecret()}, - - AddedServiceAccount: serviceAccount(emptySecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - }, - }, - - "updated serviceaccount with no secrets": { - ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, - - UpdatedServiceAccount: serviceAccount(emptySecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), - }, - }, - "updated serviceaccount with no secrets with unsynced secret store": { - ClientObjects: []runtime.Object{serviceAccount(emptySecretReferences()), createdTokenSecret()}, - - SecretsSyncPending: true, - - UpdatedServiceAccount: serviceAccount(emptySecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(emptySecretReferences()))), - }, - }, - "updated serviceaccount with missing secrets": { - ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, - - UpdatedServiceAccount: serviceAccount(missingSecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(missingSecretReferences()))), - }, - }, - "updated serviceaccount with missing secrets with unsynced secret store": { - ClientObjects: []runtime.Object{serviceAccount(missingSecretReferences()), createdTokenSecret()}, - - SecretsSyncPending: true, - - UpdatedServiceAccount: serviceAccount(missingSecretReferences()), - ExpectedActions: []core.Action{}, - }, - "updated serviceaccount with non-token secrets": { - ClientObjects: []runtime.Object{serviceAccount(regularSecretReferences()), createdTokenSecret(), opaqueSecret()}, - - UpdatedServiceAccount: serviceAccount(regularSecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewCreateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, createdTokenSecret()), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(addTokenSecretReference(regularSecretReferences()))), - }, - }, - "updated serviceaccount with token secrets": { - ExistingSecrets: []*api.Secret{serviceAccountTokenSecret()}, - - UpdatedServiceAccount: serviceAccount(tokenSecretReferences()), - ExpectedActions: []core.Action{}, - }, - "updated serviceaccount with no secrets with resource conflict": { - ClientObjects: []runtime.Object{updatedServiceAccount(emptySecretReferences()), createdTokenSecret()}, - - UpdatedServiceAccount: serviceAccount(emptySecretReferences()), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - }, - }, - - "deleted serviceaccount with no secrets": { - DeletedServiceAccount: serviceAccount(emptySecretReferences()), - ExpectedActions: []core.Action{}, - }, - "deleted serviceaccount with missing secrets": { - DeletedServiceAccount: serviceAccount(missingSecretReferences()), - ExpectedActions: []core.Action{}, - }, - "deleted serviceaccount with non-token secrets": { - ClientObjects: []runtime.Object{opaqueSecret()}, - - DeletedServiceAccount: serviceAccount(regularSecretReferences()), - ExpectedActions: []core.Action{}, - }, - "deleted serviceaccount with token secrets": { - ClientObjects: []runtime.Object{serviceAccountTokenSecret()}, - ExistingSecrets: []*api.Secret{serviceAccountTokenSecret()}, - - DeletedServiceAccount: serviceAccount(tokenSecretReferences()), - ExpectedActions: []core.Action{ - core.NewDeleteAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, "token-secret-1"), - }, - }, - - "added secret without serviceaccount": { - ClientObjects: []runtime.Object{serviceAccountTokenSecret()}, - - AddedSecret: serviceAccountTokenSecret(), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewDeleteAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, "token-secret-1"), - }, - }, - "added secret with serviceaccount": { - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - AddedSecret: serviceAccountTokenSecret(), - ExpectedActions: []core.Action{}, - }, - "added token secret without token data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutTokenData()}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - AddedSecret: serviceAccountTokenSecretWithoutTokenData(), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "added token secret without ca data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutCAData()}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - AddedSecret: serviceAccountTokenSecretWithoutCAData(), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "added token secret with mismatched ca data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithCAData([]byte("mismatched"))}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - AddedSecret: serviceAccountTokenSecretWithCAData([]byte("mismatched")), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "added token secret without namespace data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutNamespaceData()}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - AddedSecret: serviceAccountTokenSecretWithoutNamespaceData(), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "added token secret with custom namespace data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithNamespaceData([]byte("custom"))}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - AddedSecret: serviceAccountTokenSecretWithNamespaceData([]byte("custom")), - ExpectedActions: []core.Action{ - // no update is performed... the custom namespace is preserved - }, - }, - - "updated secret without serviceaccount": { - ClientObjects: []runtime.Object{serviceAccountTokenSecret()}, - - UpdatedSecret: serviceAccountTokenSecret(), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewDeleteAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, "token-secret-1"), - }, - }, - "updated secret with serviceaccount": { - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - UpdatedSecret: serviceAccountTokenSecret(), - ExpectedActions: []core.Action{}, - }, - "updated token secret without token data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutTokenData()}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - UpdatedSecret: serviceAccountTokenSecretWithoutTokenData(), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "updated token secret without ca data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutCAData()}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - UpdatedSecret: serviceAccountTokenSecretWithoutCAData(), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "updated token secret with mismatched ca data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithCAData([]byte("mismatched"))}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - UpdatedSecret: serviceAccountTokenSecretWithCAData([]byte("mismatched")), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "updated token secret without namespace data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithoutNamespaceData()}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - UpdatedSecret: serviceAccountTokenSecretWithoutNamespaceData(), - ExpectedActions: []core.Action{ - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "secrets"}, api.NamespaceDefault, serviceAccountTokenSecret()), - }, - }, - "updated token secret with custom namespace data": { - ClientObjects: []runtime.Object{serviceAccountTokenSecretWithNamespaceData([]byte("custom"))}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - UpdatedSecret: serviceAccountTokenSecretWithNamespaceData([]byte("custom")), - ExpectedActions: []core.Action{ - // no update is performed... the custom namespace is preserved - }, - }, - - "deleted secret without serviceaccount": { - DeletedSecret: serviceAccountTokenSecret(), - ExpectedActions: []core.Action{}, - }, - "deleted secret with serviceaccount with reference": { - ClientObjects: []runtime.Object{serviceAccount(tokenSecretReferences())}, - ExistingServiceAccount: serviceAccount(tokenSecretReferences()), - - DeletedSecret: serviceAccountTokenSecret(), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - core.NewUpdateAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, serviceAccount(emptySecretReferences())), - }, - }, - "deleted secret with serviceaccount without reference": { - ExistingServiceAccount: serviceAccount(emptySecretReferences()), - - DeletedSecret: serviceAccountTokenSecret(), - ExpectedActions: []core.Action{ - core.NewGetAction(unversioned.GroupVersionResource{Resource: "serviceaccounts"}, api.NamespaceDefault, "default"), - }, - }, - } - - for k, tc := range testcases { - - // Re-seed to reset name generation - utilrand.Seed(1) - - generator := &testGenerator{Token: "ABC"} - - client := fake.NewSimpleClientset(tc.ClientObjects...) - - controller := NewTokensController(client, TokensControllerOptions{TokenGenerator: generator, RootCA: []byte("CA Data")}) - - // Tell the token controller whether its stores have been synced - controller.serviceAccountsSynced = func() bool { return !tc.ServiceAccountsSyncPending } - controller.secretsSynced = func() bool { return !tc.SecretsSyncPending } - - if tc.ExistingServiceAccount != nil { - controller.serviceAccounts.Add(tc.ExistingServiceAccount) - } - for _, s := range tc.ExistingSecrets { - controller.secrets.Add(s) - } - - if tc.AddedServiceAccount != nil { - controller.serviceAccountAdded(tc.AddedServiceAccount) - } - if tc.UpdatedServiceAccount != nil { - controller.serviceAccountUpdated(nil, tc.UpdatedServiceAccount) - } - if tc.DeletedServiceAccount != nil { - controller.serviceAccountDeleted(tc.DeletedServiceAccount) - } - if tc.AddedSecret != nil { - controller.secretAdded(tc.AddedSecret) - } - if tc.UpdatedSecret != nil { - controller.secretUpdated(nil, tc.UpdatedSecret) - } - if tc.DeletedSecret != nil { - controller.secretDeleted(tc.DeletedSecret) - } - - actions := client.Actions() - for i, action := range actions { - if len(tc.ExpectedActions) < i+1 { - t.Errorf("%s: %d unexpected actions: %+v", k, len(actions)-len(tc.ExpectedActions), actions[i:]) - break - } - - expectedAction := tc.ExpectedActions[i] - if !reflect.DeepEqual(expectedAction, action) { - t.Errorf("%s: Expected\n\t%#v\ngot\n\t%#v", k, expectedAction, action) - continue - } - } - - if len(tc.ExpectedActions) > len(actions) { - t.Errorf("%s: %d additional expected actions:%+v", k, len(tc.ExpectedActions)-len(actions), tc.ExpectedActions[len(actions):]) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/converter_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/converter_test.go deleted file mode 100644 index 6dde9af96..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/converter_test.go +++ /dev/null @@ -1,847 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 conversion - -import ( - "encoding/json" - "fmt" - "reflect" - "strconv" - "strings" - "testing" - - "github.com/google/gofuzz" - flag "github.com/spf13/pflag" - - "k8s.io/kubernetes/pkg/util/diff" -) - -var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.") - -// Test a weird version/kind embedding format. -type MyWeirdCustomEmbeddedVersionKindField struct { - ID string `json:"ID,omitempty"` - APIVersion string `json:"myVersionKey,omitempty"` - ObjectKind string `json:"myKindKey,omitempty"` - Z string `json:"Z,omitempty"` - Y uint64 `json:"Y,omitempty"` -} - -type TestType1 struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` - C int8 `json:"C,omitempty"` - D int16 `json:"D,omitempty"` - E int32 `json:"E,omitempty"` - F int64 `json:"F,omitempty"` - G uint `json:"G,omitempty"` - H uint8 `json:"H,omitempty"` - I uint16 `json:"I,omitempty"` - J uint32 `json:"J,omitempty"` - K uint64 `json:"K,omitempty"` - L bool `json:"L,omitempty"` - M map[string]int `json:"M,omitempty"` - N map[string]TestType2 `json:"N,omitempty"` - O *TestType2 `json:"O,omitempty"` - P []TestType2 `json:"Q,omitempty"` -} - -type TestType2 struct { - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` -} - -type ExternalTestType2 struct { - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` -} -type ExternalTestType1 struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` - C int8 `json:"C,omitempty"` - D int16 `json:"D,omitempty"` - E int32 `json:"E,omitempty"` - F int64 `json:"F,omitempty"` - G uint `json:"G,omitempty"` - H uint8 `json:"H,omitempty"` - I uint16 `json:"I,omitempty"` - J uint32 `json:"J,omitempty"` - K uint64 `json:"K,omitempty"` - L bool `json:"L,omitempty"` - M map[string]int `json:"M,omitempty"` - N map[string]ExternalTestType2 `json:"N,omitempty"` - O *ExternalTestType2 `json:"O,omitempty"` - P []ExternalTestType2 `json:"Q,omitempty"` -} - -func testLogger(t *testing.T) DebugLogger { - // We don't set logger to eliminate rubbish logs in tests. - // If you want to switch it, simply switch it to: "return t" - return nil -} - -func TestConverter_byteSlice(t *testing.T) { - c := NewConverter(DefaultNameFunc) - src := []byte{1, 2, 3} - dest := []byte{} - err := c.Convert(&src, &dest, 0, nil) - if err != nil { - t.Fatalf("expected no error") - } - if e, a := src, dest; !reflect.DeepEqual(e, a) { - t.Errorf("expected %#v, got %#v", e, a) - } -} - -func TestConverter_MismatchedTypes(t *testing.T) { - c := NewConverter(DefaultNameFunc) - - err := c.RegisterConversionFunc( - func(in *[]string, out *int, s Scope) error { - if str, err := strconv.Atoi((*in)[0]); err != nil { - return err - } else { - *out = str - return nil - } - }, - ) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - src := []string{"5"} - var dest *int - err = c.Convert(&src, &dest, 0, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if e, a := 5, *dest; e != a { - t.Errorf("expected %#v, got %#v", e, a) - } -} - -func TestConverter_DefaultConvert(t *testing.T) { - type A struct { - Foo string - Baz int - } - type B struct { - Bar string - Baz int - } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - c.nameFunc = func(t reflect.Type) string { return "MyType" } - - // Ensure conversion funcs can call DefaultConvert to get default behavior, - // then fixup remaining fields manually - err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { - if err := s.DefaultConvert(in, out, IgnoreMissingFields); err != nil { - return err - } - out.Bar = in.Foo - return nil - }) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - - x := A{"hello, intrepid test reader!", 3} - y := B{} - - err = c.Convert(&x, &y, 0, nil) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - if e, a := x.Foo, y.Bar; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := x.Baz, y.Baz; e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - -func TestConverter_DeepCopy(t *testing.T) { - type A struct { - Foo *string - Bar []string - Baz interface{} - Qux map[string]string - } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - - foo, baz := "foo", "baz" - x := A{ - Foo: &foo, - Bar: []string{"bar"}, - Baz: &baz, - Qux: map[string]string{"qux": "qux"}, - } - y := A{} - - if err := c.Convert(&x, &y, 0, nil); err != nil { - t.Fatalf("unexpected error %v", err) - } - *x.Foo = "foo2" - x.Bar[0] = "bar2" - *x.Baz.(*string) = "baz2" - x.Qux["qux"] = "qux2" - if e, a := *x.Foo, *y.Foo; e == a { - t.Errorf("expected difference between %v and %v", e, a) - } - if e, a := x.Bar, y.Bar; reflect.DeepEqual(e, a) { - t.Errorf("expected difference between %v and %v", e, a) - } - if e, a := *x.Baz.(*string), *y.Baz.(*string); e == a { - t.Errorf("expected difference between %v and %v", e, a) - } - if e, a := x.Qux, y.Qux; reflect.DeepEqual(e, a) { - t.Errorf("expected difference between %v and %v", e, a) - } -} - -func TestConverter_CallsRegisteredFunctions(t *testing.T) { - type A struct { - Foo string - Baz int - } - type B struct { - Bar string - Baz int - } - type C struct{} - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { - out.Bar = in.Foo - return s.Convert(&in.Baz, &out.Baz, 0) - }) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - err = c.RegisterConversionFunc(func(in *B, out *A, s Scope) error { - out.Foo = in.Bar - return s.Convert(&in.Baz, &out.Baz, 0) - }) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - - x := A{"hello, intrepid test reader!", 3} - y := B{} - - err = c.Convert(&x, &y, 0, nil) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - if e, a := x.Foo, y.Bar; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := x.Baz, y.Baz; e != a { - t.Errorf("expected %v, got %v", e, a) - } - - z := B{"all your test are belong to us", 42} - w := A{} - - err = c.Convert(&z, &w, 0, nil) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - if e, a := z.Bar, w.Foo; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := z.Baz, w.Baz; e != a { - t.Errorf("expected %v, got %v", e, a) - } - - err = c.RegisterConversionFunc(func(in *A, out *C, s Scope) error { - return fmt.Errorf("C can't store an A, silly") - }) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - err = c.Convert(&A{}, &C{}, 0, nil) - if err == nil { - t.Errorf("unexpected non-error") - } -} - -func TestConverter_IgnoredConversion(t *testing.T) { - type A struct{} - type B struct{} - - count := 0 - c := NewConverter(DefaultNameFunc) - if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { - count++ - return nil - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - if err := c.RegisterIgnoredConversion(&A{}, &B{}); err != nil { - t.Fatal(err) - } - a := A{} - b := B{} - if err := c.Convert(&a, &b, 0, nil); err != nil { - t.Errorf("%v", err) - } - if count != 0 { - t.Errorf("unexpected number of conversion invocations") - } -} - -func TestConverter_IgnoredConversionNested(t *testing.T) { - type C string - type A struct { - C C - } - type B struct { - C C - } - - c := NewConverter(DefaultNameFunc) - typed := C("") - if err := c.RegisterIgnoredConversion(&typed, &typed); err != nil { - t.Fatal(err) - } - a := A{C: C("test")} - b := B{C: C("other")} - if err := c.Convert(&a, &b, AllowDifferentFieldTypeNames, nil); err != nil { - t.Errorf("%v", err) - } - if b.C != C("other") { - t.Errorf("expected no conversion of field C: %#v", b) - } -} - -func TestConverter_GeneratedConversionOverriden(t *testing.T) { - type A struct{} - type B struct{} - c := NewConverter(DefaultNameFunc) - if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { - return nil - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error { - return fmt.Errorf("generated function should be overriden") - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - - a := A{} - b := B{} - if err := c.Convert(&a, &b, 0, nil); err != nil { - t.Errorf("%v", err) - } -} - -func TestConverter_WithConversionOverriden(t *testing.T) { - type A struct{} - type B struct{} - c := NewConverter(DefaultNameFunc) - if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { - return fmt.Errorf("conversion function should be overriden") - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error { - return fmt.Errorf("generated function should be overriden") - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - - ext := NewConversionFuncs() - ext.Add(func(in *A, out *B, s Scope) error { - return nil - }) - newc := c.WithConversions(ext) - - a := A{} - b := B{} - if err := c.Convert(&a, &b, 0, nil); err == nil || err.Error() != "conversion function should be overriden" { - t.Errorf("unexpected error: %v", err) - } - if err := newc.Convert(&a, &b, 0, nil); err != nil { - t.Errorf("%v", err) - } -} - -func TestConverter_MapsStringArrays(t *testing.T) { - type A struct { - Foo string - Baz int - Other string - } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error { - if len(*input) == 0 { - *out = "" - } - *out = (*input)[0] - return nil - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - - x := map[string][]string{ - "Foo": {"bar"}, - "Baz": {"1"}, - "Other": {"", "test"}, - "other": {"wrong"}, - } - y := A{"test", 2, "something"} - - if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames, nil); err == nil { - t.Error("unexpected non-error") - } - - if err := c.RegisterConversionFunc(func(input *[]string, out *int, s Scope) error { - if len(*input) == 0 { - *out = 0 - } - str := (*input)[0] - i, err := strconv.Atoi(str) - if err != nil { - return err - } - *out = i - return nil - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - - if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames, nil); err != nil { - t.Fatalf("unexpected error %v", err) - } - if !reflect.DeepEqual(y, A{"bar", 1, ""}) { - t.Errorf("unexpected result: %#v", y) - } -} - -func TestConverter_MapsStringArraysWithMappingKey(t *testing.T) { - type A struct { - Foo string `json:"test"` - Baz int - Other string - } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error { - if len(*input) == 0 { - *out = "" - } - *out = (*input)[0] - return nil - }); err != nil { - t.Fatalf("unexpected error %v", err) - } - - x := map[string][]string{ - "Foo": {"bar"}, - "test": {"baz"}, - } - y := A{"", 0, ""} - - if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames|IgnoreMissingFields, &Meta{}); err != nil { - t.Fatalf("unexpected error %v", err) - } - if !reflect.DeepEqual(y, A{"bar", 0, ""}) { - t.Errorf("unexpected result: %#v", y) - } - - mapping := func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string) { - if s := destTag.Get("json"); len(s) > 0 { - return strings.SplitN(s, ",", 2)[0], key - } - return key, key - } - - if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames|IgnoreMissingFields, &Meta{KeyNameMapping: mapping}); err != nil { - t.Fatalf("unexpected error %v", err) - } - if !reflect.DeepEqual(y, A{"baz", 0, ""}) { - t.Errorf("unexpected result: %#v", y) - } -} - -func TestConverter_fuzz(t *testing.T) { - // Use the same types from the scheme test. - table := []struct { - from, to, check interface{} - }{ - {&TestType1{}, &ExternalTestType1{}, &TestType1{}}, - {&ExternalTestType1{}, &TestType1{}, &ExternalTestType1{}}, - } - - f := fuzz.New().NilChance(.5).NumElements(0, 100) - c := NewConverter(DefaultNameFunc) - c.nameFunc = func(t reflect.Type) string { - // Hide the fact that we don't have separate packages for these things. - return map[reflect.Type]string{ - reflect.TypeOf(TestType1{}): "TestType1", - reflect.TypeOf(ExternalTestType1{}): "TestType1", - reflect.TypeOf(TestType2{}): "TestType2", - reflect.TypeOf(ExternalTestType2{}): "TestType2", - }[t] - } - c.Debug = testLogger(t) - - for i, item := range table { - for j := 0; j < *fuzzIters; j++ { - f.Fuzz(item.from) - err := c.Convert(item.from, item.to, 0, nil) - if err != nil { - t.Errorf("(%v, %v): unexpected error: %v", i, j, err) - continue - } - err = c.Convert(item.to, item.check, 0, nil) - if err != nil { - t.Errorf("(%v, %v): unexpected error: %v", i, j, err) - continue - } - if e, a := item.from, item.check; !reflect.DeepEqual(e, a) { - t.Errorf("(%v, %v): unexpected diff: %v", i, j, objDiff(e, a)) - } - } - } -} - -func TestConverter_MapElemAddr(t *testing.T) { - type Foo struct { - A map[int]int - } - type Bar struct { - A map[string]string - } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - err := c.RegisterConversionFunc( - func(in *int, out *string, s Scope) error { - *out = fmt.Sprintf("%v", *in) - return nil - }, - ) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - err = c.RegisterConversionFunc( - func(in *string, out *int, s Scope) error { - if str, err := strconv.Atoi(*in); err != nil { - return err - } else { - *out = str - return nil - } - }, - ) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - f := fuzz.New().NilChance(0).NumElements(3, 3) - first := Foo{} - second := Bar{} - f.Fuzz(&first) - err = c.Convert(&first, &second, AllowDifferentFieldTypeNames, nil) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - third := Foo{} - err = c.Convert(&second, &third, AllowDifferentFieldTypeNames, nil) - if e, a := first, third; !reflect.DeepEqual(e, a) { - t.Errorf("Unexpected diff: %v", objDiff(e, a)) - } -} - -func TestConverter_tags(t *testing.T) { - type Foo struct { - A string `test:"foo"` - } - type Bar struct { - A string `test:"bar"` - } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - err := c.RegisterConversionFunc( - func(in *string, out *string, s Scope) error { - if e, a := "foo", s.SrcTag().Get("test"); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "bar", s.DestTag().Get("test"); e != a { - t.Errorf("expected %v, got %v", e, a) - } - return nil - }, - ) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - err = c.Convert(&Foo{}, &Bar{}, AllowDifferentFieldTypeNames, nil) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } -} - -func TestConverter_meta(t *testing.T) { - type Foo struct{ A string } - type Bar struct{ A string } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - checks := 0 - err := c.RegisterConversionFunc( - func(in *Foo, out *Bar, s Scope) error { - if s.Meta() == nil || s.Meta().SrcVersion != "test" || s.Meta().DestVersion != "passes" { - t.Errorf("Meta did not get passed!") - } - checks++ - s.Convert(&in.A, &out.A, 0) - return nil - }, - ) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - err = c.RegisterConversionFunc( - func(in *string, out *string, s Scope) error { - if s.Meta() == nil || s.Meta().SrcVersion != "test" || s.Meta().DestVersion != "passes" { - t.Errorf("Meta did not get passed a second time!") - } - checks++ - return nil - }, - ) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - err = c.Convert(&Foo{}, &Bar{}, 0, &Meta{SrcVersion: "test", DestVersion: "passes"}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if checks != 2 { - t.Errorf("Registered functions did not get called.") - } -} - -func TestConverter_flags(t *testing.T) { - type Foo struct{ A string } - type Bar struct{ A string } - table := []struct { - from, to interface{} - flags FieldMatchingFlags - shouldSucceed bool - }{ - // Check that DestFromSource allows extra fields only in source. - { - from: &struct{ A string }{}, - to: &struct{ A, B string }{}, - flags: DestFromSource, - shouldSucceed: false, - }, { - from: &struct{ A, B string }{}, - to: &struct{ A string }{}, - flags: DestFromSource, - shouldSucceed: true, - }, - - // Check that SourceToDest allows for extra fields only in dest. - { - from: &struct{ A string }{}, - to: &struct{ A, B string }{}, - flags: SourceToDest, - shouldSucceed: true, - }, { - from: &struct{ A, B string }{}, - to: &struct{ A string }{}, - flags: SourceToDest, - shouldSucceed: false, - }, - - // Check that IgnoreMissingFields makes the above failure cases pass. - { - from: &struct{ A string }{}, - to: &struct{ A, B string }{}, - flags: DestFromSource | IgnoreMissingFields, - shouldSucceed: true, - }, { - from: &struct{ A, B string }{}, - to: &struct{ A string }{}, - flags: SourceToDest | IgnoreMissingFields, - shouldSucceed: true, - }, - - // Check that the field type name must match unless - // AllowDifferentFieldTypeNames is specified. - { - from: &struct{ A, B Foo }{}, - to: &struct{ A Bar }{}, - flags: DestFromSource, - shouldSucceed: false, - }, { - from: &struct{ A Foo }{}, - to: &struct{ A, B Bar }{}, - flags: SourceToDest, - shouldSucceed: false, - }, { - from: &struct{ A, B Foo }{}, - to: &struct{ A Bar }{}, - flags: DestFromSource | AllowDifferentFieldTypeNames, - shouldSucceed: true, - }, { - from: &struct{ A Foo }{}, - to: &struct{ A, B Bar }{}, - flags: SourceToDest | AllowDifferentFieldTypeNames, - shouldSucceed: true, - }, - } - f := fuzz.New().NilChance(.5).NumElements(0, 100) - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - - for i, item := range table { - for j := 0; j < *fuzzIters; j++ { - f.Fuzz(item.from) - err := c.Convert(item.from, item.to, item.flags, nil) - if item.shouldSucceed && err != nil { - t.Errorf("(%v, %v): unexpected error: %v", i, j, err) - continue - } - if !item.shouldSucceed && err == nil { - t.Errorf("(%v, %v): unexpected non-error", i, j) - continue - } - } - } -} - -func TestConverter_FieldRename(t *testing.T) { - type WeirdMeta struct { - Name string - Type string - } - type NameMeta struct { - Name string - } - type TypeMeta struct { - Type string - } - type A struct { - WeirdMeta - } - type B struct { - TypeMeta - NameMeta - } - - c := NewConverter(DefaultNameFunc) - err := c.SetStructFieldCopy(WeirdMeta{}, "WeirdMeta", TypeMeta{}, "TypeMeta") - if err != nil { - t.Fatalf("unexpected error %v", err) - } - err = c.SetStructFieldCopy(WeirdMeta{}, "WeirdMeta", NameMeta{}, "NameMeta") - if err != nil { - t.Fatalf("unexpected error %v", err) - } - err = c.SetStructFieldCopy(TypeMeta{}, "TypeMeta", WeirdMeta{}, "WeirdMeta") - if err != nil { - t.Fatalf("unexpected error %v", err) - } - err = c.SetStructFieldCopy(NameMeta{}, "NameMeta", WeirdMeta{}, "WeirdMeta") - if err != nil { - t.Fatalf("unexpected error %v", err) - } - c.Debug = testLogger(t) - - aVal := &A{ - WeirdMeta: WeirdMeta{ - Name: "Foo", - Type: "Bar", - }, - } - - bVal := &B{ - TypeMeta: TypeMeta{"Bar"}, - NameMeta: NameMeta{"Foo"}, - } - - table := map[string]struct { - from, to, expect interface{} - flags FieldMatchingFlags - }{ - "to": { - aVal, - &B{}, - bVal, - AllowDifferentFieldTypeNames | SourceToDest | IgnoreMissingFields, - }, - "from": { - bVal, - &A{}, - aVal, - AllowDifferentFieldTypeNames | SourceToDest, - }, - "toDestFirst": { - aVal, - &B{}, - bVal, - AllowDifferentFieldTypeNames, - }, - "fromDestFirst": { - bVal, - &A{}, - aVal, - AllowDifferentFieldTypeNames | IgnoreMissingFields, - }, - } - - for name, item := range table { - err := c.Convert(item.from, item.to, item.flags, nil) - if err != nil { - t.Errorf("%v: unexpected error: %v", name, err) - continue - } - if e, a := item.expect, item.to; !reflect.DeepEqual(e, a) { - t.Errorf("%v: unexpected diff: %v", name, objDiff(e, a)) - } - } -} - -func objDiff(a, b interface{}) string { - ab, err := json.Marshal(a) - if err != nil { - panic("a") - } - bb, err := json.Marshal(b) - if err != nil { - panic("b") - } - return diff.StringDiff(string(ab), string(bb)) - - // An alternate diff attempt, in case json isn't showing you - // the difference. (reflect.DeepEqual makes a distinction between - // nil and empty slices, for example.) - //return diff.StringDiff( - // fmt.Sprintf("%#v", a), - // fmt.Sprintf("%#v", b), - //) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/deep_copy_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/deep_copy_test.go deleted file mode 100644 index a1cd65308..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/deep_copy_test.go +++ /dev/null @@ -1,161 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 conversion - -import ( - "math/rand" - "reflect" - "testing" - - "github.com/google/gofuzz" -) - -func TestDeepCopy(t *testing.T) { - semantic := EqualitiesOrDie() - f := fuzz.New().NilChance(.5).NumElements(0, 100) - table := []interface{}{ - map[string]string{}, - int(5), - "hello world", - struct { - A, B, C struct { - D map[string]int - } - X []int - Y []byte - }{}, - } - for _, obj := range table { - obj2, err := NewCloner().DeepCopy(obj) - if err != nil { - t.Errorf("Error: couldn't copy %#v", obj) - continue - } - if e, a := obj, obj2; !semantic.DeepEqual(e, a) { - t.Errorf("expected %#v\ngot %#v", e, a) - } - - obj3 := reflect.New(reflect.TypeOf(obj)).Interface() - f.Fuzz(obj3) - obj4, err := NewCloner().DeepCopy(obj3) - if err != nil { - t.Errorf("Error: couldn't copy %#v", obj) - continue - } - if e, a := obj3, obj4; !semantic.DeepEqual(e, a) { - t.Errorf("expected %#v\ngot %#v", e, a) - } - f.Fuzz(obj3) - } -} - -func copyOrDie(t *testing.T, in interface{}) interface{} { - out, err := NewCloner().DeepCopy(in) - if err != nil { - t.Fatalf("DeepCopy failed: %#q: %v", in, err) - } - return out -} - -func TestDeepCopySliceSeparate(t *testing.T) { - x := []int{5} - y := copyOrDie(t, x).([]int) - x[0] = 3 - if y[0] == 3 { - t.Errorf("deep copy wasn't deep: %#q %#q", x, y) - } -} - -func TestDeepCopyArraySeparate(t *testing.T) { - x := [1]int{5} - y := copyOrDie(t, x).([1]int) - x[0] = 3 - if y[0] == 3 { - t.Errorf("deep copy wasn't deep: %#q %#q", x, y) - } -} - -func TestDeepCopyMapSeparate(t *testing.T) { - x := map[string]int{"foo": 5} - y := copyOrDie(t, x).(map[string]int) - x["foo"] = 3 - if y["foo"] == 3 { - t.Errorf("deep copy wasn't deep: %#q %#q", x, y) - } -} - -func TestDeepCopyPointerSeparate(t *testing.T) { - z := 5 - x := &z - y := copyOrDie(t, x).(*int) - *x = 3 - if *y == 3 { - t.Errorf("deep copy wasn't deep: %#q %#q", x, y) - } -} - -func TestDeepCopyStruct(t *testing.T) { - type Foo struct { - A int - } - type Bar struct { - Foo - F *Foo - } - a := &Bar{Foo{1}, &Foo{2}} - b := copyOrDie(t, a).(*Bar) - a.A = 3 - a.F.A = 4 - - if b.A != 1 || b.F.A != 2 { - t.Errorf("deep copy wasn't deep: %#v, %#v", a, b) - } -} - -var result interface{} - -func BenchmarkDeepCopy(b *testing.B) { - table := []interface{}{ - map[string]string{}, - int(5), - "hello world", - struct { - A, B, C struct { - D map[string]int - } - X []int - Y []byte - }{}, - } - - f := fuzz.New().RandSource(rand.NewSource(1)).NilChance(.5).NumElements(0, 100) - for i := range table { - out := table[i] - obj := reflect.New(reflect.TypeOf(out)).Interface() - f.Fuzz(obj) - table[i] = obj - } - - b.ResetTimer() - var r interface{} - for i := 0; i < b.N; i++ { - for j := range table { - r, _ = NewCloner().DeepCopy(table[j]) - } - } - result = r -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/helper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/helper_test.go deleted file mode 100644 index 69fef3334..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/helper_test.go +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 conversion - -import "testing" - -func TestInvalidPtrValueKind(t *testing.T) { - var simple interface{} - switch obj := simple.(type) { - default: - _, err := EnforcePtr(obj) - if err == nil { - t.Errorf("Expected error on invalid kind") - } - } -} - -func TestEnforceNilPtr(t *testing.T) { - var nilPtr *struct{} - _, err := EnforcePtr(nilPtr) - if err == nil { - t.Errorf("Expected error on nil pointer") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/queryparams/convert_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/queryparams/convert_test.go deleted file mode 100644 index cbeeeca73..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/queryparams/convert_test.go +++ /dev/null @@ -1,211 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 queryparams_test - -import ( - "net/url" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/conversion/queryparams" -) - -type namedString string -type namedBool bool - -type bar struct { - Float1 float32 `json:"float1"` - Float2 float64 `json:"float2"` - Int1 int64 `json:"int1,omitempty"` - Int2 int32 `json:"int2,omitempty"` - Int3 int16 `json:"int3,omitempty"` - Str1 string `json:"str1,omitempty"` - Ignored int - Ignored2 string -} - -func (obj *bar) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -type foo struct { - Str string `json:"str"` - Integer int `json:"integer,omitempty"` - Slice []string `json:"slice,omitempty"` - Boolean bool `json:"boolean,omitempty"` - NamedStr namedString `json:"namedStr,omitempty"` - NamedBool namedBool `json:"namedBool,omitempty"` - Foobar bar `json:"foobar,omitempty"` - Testmap map[string]string `json:"testmap,omitempty"` -} - -func (obj *foo) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -type baz struct { - Ptr *int `json:"ptr"` - Bptr *bool `json:"bptr,omitempty"` -} - -func (obj *baz) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -// childStructs tests some of the types we serialize to query params for log API calls -// notably, the nested time struct -type childStructs struct { - Container string `json:"container,omitempty"` - Follow bool `json:"follow,omitempty"` - Previous bool `json:"previous,omitempty"` - SinceSeconds *int64 `json:"sinceSeconds,omitempty"` - SinceTime *unversioned.Time `json:"sinceTime,omitempty"` - EmptyTime *unversioned.Time `json:"emptyTime"` -} - -func (obj *childStructs) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -func validateResult(t *testing.T, input interface{}, actual, expected url.Values) { - local := url.Values{} - for k, v := range expected { - local[k] = v - } - for k, v := range actual { - if ev, ok := local[k]; !ok || !reflect.DeepEqual(ev, v) { - if !ok { - t.Errorf("%#v: actual value key %s not found in expected map", input, k) - } else { - t.Errorf("%#v: values don't match: actual: %#v, expected: %#v", input, v, ev) - } - } - delete(local, k) - } - if len(local) > 0 { - t.Errorf("%#v: expected map has keys that were not found in actual map: %#v", input, local) - } -} - -func TestConvert(t *testing.T) { - sinceSeconds := int64(123) - sinceTime := unversioned.Date(2000, 1, 1, 12, 34, 56, 0, time.UTC) - - tests := []struct { - input interface{} - expected url.Values - }{ - { - input: &foo{ - Str: "hello", - }, - expected: url.Values{"str": {"hello"}}, - }, - { - input: &foo{ - Str: "test string", - Slice: []string{"one", "two", "three"}, - Integer: 234, - Boolean: true, - }, - expected: url.Values{"str": {"test string"}, "slice": {"one", "two", "three"}, "integer": {"234"}, "boolean": {"true"}}, - }, - { - input: &foo{ - Str: "named types", - NamedStr: "value1", - NamedBool: true, - }, - expected: url.Values{"str": {"named types"}, "namedStr": {"value1"}, "namedBool": {"true"}}, - }, - { - input: &foo{ - Str: "don't ignore embedded struct", - Foobar: bar{ - Float1: 5.0, - }, - }, - expected: url.Values{"str": {"don't ignore embedded struct"}, "float1": {"5"}, "float2": {"0"}}, - }, - { - // Ignore untagged fields - input: &bar{ - Float1: 23.5, - Float2: 100.7, - Int1: 1, - Int2: 2, - Int3: 3, - Ignored: 1, - Ignored2: "ignored", - }, - expected: url.Values{"float1": {"23.5"}, "float2": {"100.7"}, "int1": {"1"}, "int2": {"2"}, "int3": {"3"}}, - }, - { - // include fields that are not tagged omitempty - input: &foo{ - NamedStr: "named str", - }, - expected: url.Values{"str": {""}, "namedStr": {"named str"}}, - }, - { - input: &baz{ - Ptr: intp(5), - Bptr: boolp(true), - }, - expected: url.Values{"ptr": {"5"}, "bptr": {"true"}}, - }, - { - input: &baz{ - Bptr: boolp(true), - }, - expected: url.Values{"ptr": {""}, "bptr": {"true"}}, - }, - { - input: &baz{ - Ptr: intp(5), - }, - expected: url.Values{"ptr": {"5"}}, - }, - { - input: &childStructs{ - Container: "mycontainer", - Follow: true, - Previous: true, - SinceSeconds: &sinceSeconds, - SinceTime: &sinceTime, // test a custom marshaller - EmptyTime: nil, // test a nil custom marshaller without omitempty - }, - expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "sinceTime": {"2000-01-01T12:34:56Z"}, "emptyTime": {""}}, - }, - { - input: &childStructs{ - Container: "mycontainer", - Follow: true, - Previous: true, - SinceSeconds: &sinceSeconds, - SinceTime: nil, // test a nil custom marshaller with omitempty - }, - expected: url.Values{"container": {"mycontainer"}, "follow": {"true"}, "previous": {"true"}, "sinceSeconds": {"123"}, "emptyTime": {""}}, - }, - } - - for _, test := range tests { - result, err := queryparams.Convert(test.input) - if err != nil { - t.Errorf("Unexpected error while converting %#v: %v", test.input, err) - } - validateResult(t, test.input, result, test.expected) - } -} - -func intp(n int) *int { return &n } - -func boolp(b bool) *bool { return &b } diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/aws/aws_credentials.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/aws/aws_credentials.go deleted file mode 100644 index aeb7316b3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/aws/aws_credentials.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws_credentials - -import ( - "encoding/base64" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/request" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ecr" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/cloudprovider" - "k8s.io/kubernetes/pkg/credentialprovider" -) - -var registryUrls = []string{"*.dkr.ecr.*.amazonaws.com"} - -// awsHandlerLogger is a handler that logs all AWS SDK requests -// Copied from cloudprovider/aws/log_handler.go -func awsHandlerLogger(req *request.Request) { - service := req.ClientInfo.ServiceName - - name := "?" - if req.Operation != nil { - name = req.Operation.Name - } - - glog.V(4).Infof("AWS request: %s %s", service, name) -} - -// An interface for testing purposes. -type tokenGetter interface { - GetAuthorizationToken(input *ecr.GetAuthorizationTokenInput) (*ecr.GetAuthorizationTokenOutput, error) -} - -// The canonical implementation -type ecrTokenGetter struct { - svc *ecr.ECR -} - -func (p *ecrTokenGetter) GetAuthorizationToken(input *ecr.GetAuthorizationTokenInput) (*ecr.GetAuthorizationTokenOutput, error) { - return p.svc.GetAuthorizationToken(input) -} - -// ecrProvider is a DockerConfigProvider that gets and refreshes 12-hour tokens -// from AWS to access ECR. -type ecrProvider struct { - getter tokenGetter -} - -// Not using the package init() function: this module should be initialized only -// if using the AWS cloud provider. This way, we avoid timeouts waiting for a -// non-existent provider. -func Init() { - credentialprovider.RegisterCredentialProvider("aws-ecr-key", - &credentialprovider.CachingDockerConfigProvider{ - Provider: &ecrProvider{}, - // Refresh credentials a little earlier before they expire - Lifetime: 11*time.Hour + 55*time.Minute, - }) -} - -// Enabled implements DockerConfigProvider.Enabled for the AWS token-based implementation. -// For now, it gets activated only if AWS was chosen as the cloud provider. -// TODO: figure how to enable it manually for deployments that are not on AWS but still -// use ECR somehow? -func (p *ecrProvider) Enabled() bool { - provider, err := cloudprovider.GetCloudProvider("aws", nil) - if err != nil { - glog.Errorf("while initializing AWS cloud provider %v", err) - return false - } - if provider == nil { - return false - } - - zones, ok := provider.Zones() - if !ok { - glog.Errorf("couldn't get Zones() interface") - return false - } - zone, err := zones.GetZone() - if err != nil { - glog.Errorf("while getting zone %v", err) - return false - } - if zone.Region == "" { - glog.Errorf("Region information is empty") - return false - } - - getter := &ecrTokenGetter{svc: ecr.New(session.New(&aws.Config{ - Credentials: nil, - Region: &zone.Region, - }))} - getter.svc.Handlers.Sign.PushFrontNamed(request.NamedHandler{ - Name: "k8s/logger", - Fn: awsHandlerLogger, - }) - p.getter = getter - - return true -} - -// LazyProvide implements DockerConfigProvider.LazyProvide. Should never be called. -func (p *ecrProvider) LazyProvide() *credentialprovider.DockerConfigEntry { - return nil -} - -// Provide implements DockerConfigProvider.Provide, refreshing ECR tokens on demand -func (p *ecrProvider) Provide() credentialprovider.DockerConfig { - cfg := credentialprovider.DockerConfig{} - - // TODO: fill in RegistryIds? - params := &ecr.GetAuthorizationTokenInput{} - output, err := p.getter.GetAuthorizationToken(params) - if err != nil { - glog.Errorf("while requesting ECR authorization token %v", err) - return cfg - } - if output == nil { - glog.Errorf("Got back no ECR token") - return cfg - } - - for _, data := range output.AuthorizationData { - if data.ProxyEndpoint != nil && - data.AuthorizationToken != nil { - decodedToken, err := base64.StdEncoding.DecodeString(aws.StringValue(data.AuthorizationToken)) - if err != nil { - glog.Errorf("while decoding token for endpoint %v %v", data.ProxyEndpoint, err) - return cfg - } - parts := strings.SplitN(string(decodedToken), ":", 2) - user := parts[0] - password := parts[1] - entry := credentialprovider.DockerConfigEntry{ - Username: user, - Password: password, - // ECR doesn't care and Docker is about to obsolete it - Email: "not@val.id", - } - - // Add our entry for each of the supported container registry URLs - for _, k := range registryUrls { - cfg[k] = entry - } - } - } - return cfg -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/aws/aws_credentials_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/aws/aws_credentials_test.go deleted file mode 100644 index a07493993..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/aws/aws_credentials_test.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 aws_credentials - -import ( - "encoding/base64" - "fmt" - "path" - "testing" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/ecr" - - "k8s.io/kubernetes/pkg/credentialprovider" -) - -const user = "foo" -const password = "1234567890abcdef" -const email = "not@val.id" - -// Mock implementation -type testTokenGetter struct { - user string - password string - endpoint string -} - -func (p *testTokenGetter) GetAuthorizationToken(input *ecr.GetAuthorizationTokenInput) (*ecr.GetAuthorizationTokenOutput, error) { - - expiration := time.Now().Add(1 * time.Hour) - creds := []byte(fmt.Sprintf("%s:%s", p.user, p.password)) - data := &ecr.AuthorizationData{ - AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString(creds)), - ExpiresAt: &expiration, - ProxyEndpoint: aws.String(p.endpoint), - } - output := &ecr.GetAuthorizationTokenOutput{ - AuthorizationData: []*ecr.AuthorizationData{data}, - } - - return output, nil //p.svc.GetAuthorizationToken(input) -} - -func TestEcrProvide(t *testing.T) { - registry := "123456789012.dkr.ecr.lala-land-1.amazonaws.com" - otherRegistries := []string{"private.registry.com", - "gcr.io", - } - image := "foo/bar" - - provider := &ecrProvider{ - getter: &testTokenGetter{ - user: user, - password: password, - endpoint: registry}, - } - - keyring := &credentialprovider.BasicDockerKeyring{} - keyring.Add(provider.Provide()) - - // Verify that we get the expected username/password combo for - // an ECR image name. - fullImage := path.Join(registry, image) - creds, ok := keyring.Lookup(fullImage) - if !ok { - t.Errorf("Didn't find expected URL: %s", fullImage) - return - } - if len(creds) > 1 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if user != val.Username { - t.Errorf("Unexpected username value, want: _token, got: %s", val.Username) - } - if password != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } - - // Verify that we get an error for other images. - for _, otherRegistry := range otherRegistries { - fullImage = path.Join(otherRegistry, image) - creds, ok = keyring.Lookup(fullImage) - if ok { - t.Errorf("Unexpectedly found image: %s", fullImage) - return - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/config_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/config_test.go deleted file mode 100644 index 587879fe9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/config_test.go +++ /dev/null @@ -1,225 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 credentialprovider - -import ( - "encoding/json" - "reflect" - "testing" -) - -func TestDockerConfigJsonJSONDecode(t *testing.T) { - input := []byte(`{"auths": {"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"}}}`) - - expect := DockerConfigJson{ - Auths: DockerConfig(map[string]DockerConfigEntry{ - "http://foo.example.com": { - Username: "foo", - Password: "bar", - Email: "foo@example.com", - }, - "http://bar.example.com": { - Username: "bar", - Password: "baz", - Email: "bar@example.com", - }, - }), - } - - var output DockerConfigJson - err := json.Unmarshal(input, &output) - if err != nil { - t.Errorf("Received unexpected error: %v", err) - } - - if !reflect.DeepEqual(expect, output) { - t.Errorf("Received unexpected output. Expected %#v, got %#v", expect, output) - } -} - -func TestDockerConfigJSONDecode(t *testing.T) { - input := []byte(`{"http://foo.example.com":{"username": "foo", "password": "bar", "email": "foo@example.com"}, "http://bar.example.com":{"username": "bar", "password": "baz", "email": "bar@example.com"}}`) - - expect := DockerConfig(map[string]DockerConfigEntry{ - "http://foo.example.com": { - Username: "foo", - Password: "bar", - Email: "foo@example.com", - }, - "http://bar.example.com": { - Username: "bar", - Password: "baz", - Email: "bar@example.com", - }, - }) - - var output DockerConfig - err := json.Unmarshal(input, &output) - if err != nil { - t.Errorf("Received unexpected error: %v", err) - } - - if !reflect.DeepEqual(expect, output) { - t.Errorf("Received unexpected output. Expected %#v, got %#v", expect, output) - } -} - -func TestDockerConfigEntryJSONDecode(t *testing.T) { - tests := []struct { - input []byte - expect DockerConfigEntry - fail bool - }{ - // simple case, just decode the fields - { - input: []byte(`{"username": "foo", "password": "bar", "email": "foo@example.com"}`), - expect: DockerConfigEntry{ - Username: "foo", - Password: "bar", - Email: "foo@example.com", - }, - fail: false, - }, - - // auth field decodes to username & password - { - input: []byte(`{"auth": "Zm9vOmJhcg==", "email": "foo@example.com"}`), - expect: DockerConfigEntry{ - Username: "foo", - Password: "bar", - Email: "foo@example.com", - }, - fail: false, - }, - - // auth field overrides username & password - { - input: []byte(`{"username": "foo", "password": "bar", "auth": "cGluZzpwb25n", "email": "foo@example.com"}`), - expect: DockerConfigEntry{ - Username: "ping", - Password: "pong", - Email: "foo@example.com", - }, - fail: false, - }, - - // poorly-formatted auth causes failure - { - input: []byte(`{"auth": "pants", "email": "foo@example.com"}`), - expect: DockerConfigEntry{ - Username: "", - Password: "", - Email: "foo@example.com", - }, - fail: true, - }, - - // invalid JSON causes failure - { - input: []byte(`{"email": false}`), - expect: DockerConfigEntry{ - Username: "", - Password: "", - Email: "", - }, - fail: true, - }, - } - - for i, tt := range tests { - var output DockerConfigEntry - err := json.Unmarshal(tt.input, &output) - if (err != nil) != tt.fail { - t.Errorf("case %d: expected fail=%t, got err=%v", i, tt.fail, err) - } - - if !reflect.DeepEqual(tt.expect, output) { - t.Errorf("case %d: expected output %#v, got %#v", i, tt.expect, output) - } - } -} - -func TestDecodeDockerConfigFieldAuth(t *testing.T) { - tests := []struct { - input string - username string - password string - fail bool - }{ - // auth field decodes to username & password - { - input: "Zm9vOmJhcg==", - username: "foo", - password: "bar", - }, - - // good base64 data, but no colon separating username & password - { - input: "cGFudHM=", - fail: true, - }, - - // bad base64 data - { - input: "pants", - fail: true, - }, - } - - for i, tt := range tests { - username, password, err := decodeDockerConfigFieldAuth(tt.input) - if (err != nil) != tt.fail { - t.Errorf("case %d: expected fail=%t, got err=%v", i, tt.fail, err) - } - - if tt.username != username { - t.Errorf("case %d: expected username %q, got %q", i, tt.username, username) - } - - if tt.password != password { - t.Errorf("case %d: expected password %q, got %q", i, tt.password, password) - } - } -} - -func TestDockerConfigEntryJSONCompatibleEncode(t *testing.T) { - tests := []struct { - input DockerConfigEntry - expect []byte - }{ - // simple case, just decode the fields - { - expect: []byte(`{"username":"foo","password":"bar","email":"foo@example.com","auth":"Zm9vOmJhcg=="}`), - input: DockerConfigEntry{ - Username: "foo", - Password: "bar", - Email: "foo@example.com", - }, - }, - } - - for i, tt := range tests { - actual, err := json.Marshal(tt.input) - if err != nil { - t.Errorf("case %d: unexpected error: %v", i, err) - } - - if string(tt.expect) != string(actual) { - t.Errorf("case %d: expected %v, got %v", i, string(tt.expect), string(actual)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/doc.go deleted file mode 100644 index e6f2beba8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 gcp_credentials contains implementations of DockerConfigProvider -// for Google Cloud Platform. -package gcp_credentials diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt.go deleted file mode 100644 index e4c16afa8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt.go +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 gcp_credentials - -import ( - "io/ioutil" - "time" - - "github.com/golang/glog" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - "golang.org/x/oauth2/jwt" - "k8s.io/kubernetes/pkg/credentialprovider" - - "github.com/spf13/pflag" -) - -const ( - storageReadOnlyScope = "https://www.googleapis.com/auth/devstorage.read_only" -) - -var ( - flagJwtFile = pflag.String("google-json-key", "", - "The Google Cloud Platform Service Account JSON Key to use for authentication.") -) - -// A DockerConfigProvider that reads its configuration from Google -// Compute Engine metadata. -type jwtProvider struct { - path *string - config *jwt.Config - tokenUrl string -} - -// init registers the various means by which credentials may -// be resolved on GCP. -func init() { - credentialprovider.RegisterCredentialProvider("google-jwt-key", - &credentialprovider.CachingDockerConfigProvider{ - Provider: &jwtProvider{ - path: flagJwtFile, - }, - Lifetime: 30 * time.Minute, - }) -} - -// Enabled implements DockerConfigProvider for the JSON Key based implementation. -func (j *jwtProvider) Enabled() bool { - if *j.path == "" { - return false - } - - data, err := ioutil.ReadFile(*j.path) - if err != nil { - glog.Errorf("while reading file %s got %v", *j.path, err) - return false - } - config, err := google.JWTConfigFromJSON(data, storageReadOnlyScope) - if err != nil { - glog.Errorf("while parsing %s data got %v", *j.path, err) - return false - } - - j.config = config - if j.tokenUrl != "" { - j.config.TokenURL = j.tokenUrl - } - return true -} - -// LazyProvide implements DockerConfigProvider. Should never be called. -func (j *jwtProvider) LazyProvide() *credentialprovider.DockerConfigEntry { - return nil -} - -// Provide implements DockerConfigProvider -func (j *jwtProvider) Provide() credentialprovider.DockerConfig { - cfg := credentialprovider.DockerConfig{} - - ts := j.config.TokenSource(oauth2.NoContext) - token, err := ts.Token() - if err != nil { - glog.Errorf("while exchanging json key %s for access token %v", *j.path, err) - return cfg - } - if !token.Valid() { - glog.Errorf("Got back invalid token: %v", token) - return cfg - } - - entry := credentialprovider.DockerConfigEntry{ - Username: "_token", - Password: token.AccessToken, - Email: j.config.Email, - } - - // Add our entry for each of the supported container registry URLs - for _, k := range containerRegistryUrls { - cfg[k] = entry - } - return cfg -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt_test.go deleted file mode 100644 index 4066d02af..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/jwt_test.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 gcp_credentials - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/credentialprovider" -) - -const email = "foo@bar.com" - -// From oauth2/jwt_test.go -var ( - dummyPrivateKey = `-----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAx4fm7dngEmOULNmAs1IGZ9Apfzh+BkaQ1dzkmbUgpcoghucE -DZRnAGd2aPyB6skGMXUytWQvNYav0WTR00wFtX1ohWTfv68HGXJ8QXCpyoSKSSFY -fuP9X36wBSkSX9J5DVgiuzD5VBdzUISSmapjKm+DcbRALjz6OUIPEWi1Tjl6p5RK -1w41qdbmt7E5/kGhKLDuT7+M83g4VWhgIvaAXtnhklDAggilPPa8ZJ1IFe31lNlr -k4DRk38nc6sEutdf3RL7QoH7FBusI7uXV03DC6dwN1kP4GE7bjJhcRb/7jYt7CQ9 -/E9Exz3c0yAp0yrTg0Fwh+qxfH9dKwN52S7SBwIDAQABAoIBAQCaCs26K07WY5Jt -3a2Cw3y2gPrIgTCqX6hJs7O5ByEhXZ8nBwsWANBUe4vrGaajQHdLj5OKfsIDrOvn -2NI1MqflqeAbu/kR32q3tq8/Rl+PPiwUsW3E6Pcf1orGMSNCXxeducF2iySySzh3 -nSIhCG5uwJDWI7a4+9KiieFgK1pt/Iv30q1SQS8IEntTfXYwANQrfKUVMmVF9aIK -6/WZE2yd5+q3wVVIJ6jsmTzoDCX6QQkkJICIYwCkglmVy5AeTckOVwcXL0jqw5Kf -5/soZJQwLEyBoQq7Kbpa26QHq+CJONetPP8Ssy8MJJXBT+u/bSseMb3Zsr5cr43e -DJOhwsThAoGBAPY6rPKl2NT/K7XfRCGm1sbWjUQyDShscwuWJ5+kD0yudnT/ZEJ1 -M3+KS/iOOAoHDdEDi9crRvMl0UfNa8MAcDKHflzxg2jg/QI+fTBjPP5GOX0lkZ9g -z6VePoVoQw2gpPFVNPPTxKfk27tEzbaffvOLGBEih0Kb7HTINkW8rIlzAoGBAM9y -1yr+jvfS1cGFtNU+Gotoihw2eMKtIqR03Yn3n0PK1nVCDKqwdUqCypz4+ml6cxRK -J8+Pfdh7D+ZJd4LEG6Y4QRDLuv5OA700tUoSHxMSNn3q9As4+T3MUyYxWKvTeu3U -f2NWP9ePU0lV8ttk7YlpVRaPQmc1qwooBA/z/8AdAoGAW9x0HWqmRICWTBnpjyxx -QGlW9rQ9mHEtUotIaRSJ6K/F3cxSGUEkX1a3FRnp6kPLcckC6NlqdNgNBd6rb2rA -cPl/uSkZP42Als+9YMoFPU/xrrDPbUhu72EDrj3Bllnyb168jKLa4VBOccUvggxr -Dm08I1hgYgdN5huzs7y6GeUCgYEAj+AZJSOJ6o1aXS6rfV3mMRve9bQ9yt8jcKXw -5HhOCEmMtaSKfnOF1Ziih34Sxsb7O2428DiX0mV/YHtBnPsAJidL0SdLWIapBzeg -KHArByIRkwE6IvJvwpGMdaex1PIGhx5i/3VZL9qiq/ElT05PhIb+UXgoWMabCp84 -OgxDK20CgYAeaFo8BdQ7FmVX2+EEejF+8xSge6WVLtkaon8bqcn6P0O8lLypoOhd -mJAYH8WU+UAy9pecUnDZj14LAGNVmYcse8HFX71MoshnvCTFEPVo4rZxIAGwMpeJ -5jgQ3slYLpqrGlcbLgUXBUgzEO684Wk/UV9DFPlHALVqCfXQ9dpJPg== ------END RSA PRIVATE KEY-----` - - jsonKey = fmt.Sprintf(`{"private_key":"%[1]s", "client_email":"%[2]s"}`, - strings.Replace(dummyPrivateKey, "\n", "\\n", -1), email) -) - -func TestJwtProvider(t *testing.T) { - token := "asdhflkjsdfkjhsdf" - - // Modeled after oauth2/jwt_test.go - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(fmt.Sprintf(`{ - "access_token": "%[1]s", - "scope": "user", - "token_type": "bearer", - "expires_in": 3600 - }`, token))) - })) - defer ts.Close() - - file, err := ioutil.TempFile(os.TempDir(), "temp") - if err != nil { - t.Fatalf("Error creating temp file: %v", err) - } - - filename := file.Name() - _, err = file.WriteString(jsonKey) - if err != nil { - t.Fatalf("Error writing temp file: %v", err) - } - - provider := &jwtProvider{ - path: &filename, - tokenUrl: ts.URL, - } - if !provider.Enabled() { - t.Fatalf("Provider is unexpectedly disabled") - } - - keyring := &credentialprovider.BasicDockerKeyring{} - keyring.Add(provider.Provide()) - - // Verify that we get the expected username/password combo for - // a gcr.io image name. - registryUrl := "gcr.io/foo/bar" - creds, ok := keyring.Lookup(registryUrl) - if !ok { - t.Errorf("Didn't find expected URL: %s", registryUrl) - return - } - if len(creds) > 1 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if "_token" != val.Username { - t.Errorf("Unexpected username value, want: _token, got: %s", val.Username) - } - if token != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", token, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata.go deleted file mode 100644 index fb89b38c0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata.go +++ /dev/null @@ -1,217 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 gcp_credentials - -import ( - "encoding/json" - "net/http" - "strings" - "time" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/credentialprovider" -) - -const ( - metadataUrl = "http://metadata.google.internal./computeMetadata/v1/" - metadataAttributes = metadataUrl + "instance/attributes/" - dockerConfigKey = metadataAttributes + "google-dockercfg" - dockerConfigUrlKey = metadataAttributes + "google-dockercfg-url" - metadataScopes = metadataUrl + "instance/service-accounts/default/scopes" - metadataToken = metadataUrl + "instance/service-accounts/default/token" - metadataEmail = metadataUrl + "instance/service-accounts/default/email" - storageScopePrefix = "https://www.googleapis.com/auth/devstorage" - cloudPlatformScopePrefix = "https://www.googleapis.com/auth/cloud-platform" -) - -// For these urls, the parts of the host name can be glob, for example '*.gcr.io" will match -// "foo.gcr.io" and "bar.gcr.io". -var containerRegistryUrls = []string{"container.cloud.google.com", "gcr.io", "*.gcr.io"} - -var metadataHeader = &http.Header{ - "Metadata-Flavor": []string{"Google"}, -} - -// A DockerConfigProvider that reads its configuration from Google -// Compute Engine metadata. -type metadataProvider struct { - Client *http.Client -} - -// A DockerConfigProvider that reads its configuration from a specific -// Google Compute Engine metadata key: 'google-dockercfg'. -type dockerConfigKeyProvider struct { - metadataProvider -} - -// A DockerConfigProvider that reads its configuration from a URL read from -// a specific Google Compute Engine metadata key: 'google-dockercfg-url'. -type dockerConfigUrlKeyProvider struct { - metadataProvider -} - -// A DockerConfigProvider that provides a dockercfg with: -// Username: "_token" -// Password: "{access token from metadata}" -type containerRegistryProvider struct { - metadataProvider -} - -// init registers the various means by which credentials may -// be resolved on GCP. -func init() { - credentialprovider.RegisterCredentialProvider("google-dockercfg", - &credentialprovider.CachingDockerConfigProvider{ - Provider: &dockerConfigKeyProvider{ - metadataProvider{Client: http.DefaultClient}, - }, - Lifetime: 60 * time.Second, - }) - - credentialprovider.RegisterCredentialProvider("google-dockercfg-url", - &credentialprovider.CachingDockerConfigProvider{ - Provider: &dockerConfigUrlKeyProvider{ - metadataProvider{Client: http.DefaultClient}, - }, - Lifetime: 60 * time.Second, - }) - - credentialprovider.RegisterCredentialProvider("google-container-registry", - // Never cache this. The access token is already - // cached by the metadata service. - &containerRegistryProvider{ - metadataProvider{Client: http.DefaultClient}, - }) -} - -// Enabled implements DockerConfigProvider for all of the Google implementations. -func (g *metadataProvider) Enabled() bool { - _, err := credentialprovider.ReadUrl(metadataUrl, g.Client, metadataHeader) - return err == nil -} - -// LazyProvide implements DockerConfigProvider. Should never be called. -func (g *dockerConfigKeyProvider) LazyProvide() *credentialprovider.DockerConfigEntry { - return nil -} - -// Provide implements DockerConfigProvider -func (g *dockerConfigKeyProvider) Provide() credentialprovider.DockerConfig { - // Read the contents of the google-dockercfg metadata key and - // parse them as an alternate .dockercfg - if cfg, err := credentialprovider.ReadDockerConfigFileFromUrl(dockerConfigKey, g.Client, metadataHeader); err != nil { - glog.Errorf("while reading 'google-dockercfg' metadata: %v", err) - } else { - return cfg - } - - return credentialprovider.DockerConfig{} -} - -// LazyProvide implements DockerConfigProvider. Should never be called. -func (g *dockerConfigUrlKeyProvider) LazyProvide() *credentialprovider.DockerConfigEntry { - return nil -} - -// Provide implements DockerConfigProvider -func (g *dockerConfigUrlKeyProvider) Provide() credentialprovider.DockerConfig { - // Read the contents of the google-dockercfg-url key and load a .dockercfg from there - if url, err := credentialprovider.ReadUrl(dockerConfigUrlKey, g.Client, metadataHeader); err != nil { - glog.Errorf("while reading 'google-dockercfg-url' metadata: %v", err) - } else { - if strings.HasPrefix(string(url), "http") { - if cfg, err := credentialprovider.ReadDockerConfigFileFromUrl(string(url), g.Client, nil); err != nil { - glog.Errorf("while reading 'google-dockercfg-url'-specified url: %s, %v", string(url), err) - } else { - return cfg - } - } else { - // TODO(mattmoor): support reading alternate scheme URLs (e.g. gs:// or s3://) - glog.Errorf("Unsupported URL scheme: %s", string(url)) - } - } - - return credentialprovider.DockerConfig{} -} - -// Enabled implements a special metadata-based check, which verifies the -// storage scope is available on the GCE VM. -func (g *containerRegistryProvider) Enabled() bool { - value, err := credentialprovider.ReadUrl(metadataScopes+"?alt=json", g.Client, metadataHeader) - if err != nil { - return false - } - var scopes []string - if err := json.Unmarshal([]byte(value), &scopes); err != nil { - return false - } - - for _, v := range scopes { - // cloudPlatformScope implies storage scope. - if strings.HasPrefix(v, storageScopePrefix) || strings.HasPrefix(v, cloudPlatformScopePrefix) { - return true - } - } - glog.Warningf("Google container registry is disabled, no storage scope is available: %s", value) - return false -} - -// tokenBlob is used to decode the JSON blob containing an access token -// that is returned by GCE metadata. -type tokenBlob struct { - AccessToken string `json:"access_token"` -} - -// LazyProvide implements DockerConfigProvider. Should never be called. -func (g *containerRegistryProvider) LazyProvide() *credentialprovider.DockerConfigEntry { - return nil -} - -// Provide implements DockerConfigProvider -func (g *containerRegistryProvider) Provide() credentialprovider.DockerConfig { - cfg := credentialprovider.DockerConfig{} - - tokenJsonBlob, err := credentialprovider.ReadUrl(metadataToken, g.Client, metadataHeader) - if err != nil { - glog.Errorf("while reading access token endpoint: %v", err) - return cfg - } - - email, err := credentialprovider.ReadUrl(metadataEmail, g.Client, metadataHeader) - if err != nil { - glog.Errorf("while reading email endpoint: %v", err) - return cfg - } - - var parsedBlob tokenBlob - if err := json.Unmarshal([]byte(tokenJsonBlob), &parsedBlob); err != nil { - glog.Errorf("while parsing json blob %s: %v", tokenJsonBlob, err) - return cfg - } - - entry := credentialprovider.DockerConfigEntry{ - Username: "_token", - Password: parsedBlob.AccessToken, - Email: string(email), - } - - // Add our entry for each of the supported container registry URLs - for _, k := range containerRegistryUrls { - cfg[k] = entry - } - return cfg -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata_test.go deleted file mode 100644 index b65b13a01..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/gcp/metadata_test.go +++ /dev/null @@ -1,342 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 gcp_credentials - -import ( - "encoding/base64" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/credentialprovider" - utilnet "k8s.io/kubernetes/pkg/util/net" -) - -func TestDockerKeyringFromGoogleDockerConfigMetadata(t *testing.T) { - registryUrl := "hello.kubernetes.io" - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "https://%s": { - "email": %q, - "auth": %q - } -}`, registryUrl, email, auth) - - const probeEndpoint = "/computeMetadata/v1/" - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Only serve the one metadata key. - if probeEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - } else if strings.HasSuffix(dockerConfigKey, r.URL.Path) { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintln(w, sampleDockerConfig) - } else { - w.WriteHeader(http.StatusNotFound) - } - })) - defer server.Close() - - // Make a transport that reroutes all traffic to the example server - transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL + req.URL.Path) - }, - }) - - keyring := &credentialprovider.BasicDockerKeyring{} - provider := &dockerConfigKeyProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - } - - if !provider.Enabled() { - t.Errorf("Provider is unexpectedly disabled") - } - - keyring.Add(provider.Provide()) - - creds, ok := keyring.Lookup(registryUrl) - if !ok { - t.Errorf("Didn't find expected URL: %s", registryUrl) - return - } - if len(creds) > 1 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if username != val.Username { - t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username) - } - if password != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } -} - -func TestDockerKeyringFromGoogleDockerConfigMetadataUrl(t *testing.T) { - registryUrl := "hello.kubernetes.io" - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "https://%s": { - "email": %q, - "auth": %q - } -}`, registryUrl, email, auth) - - const probeEndpoint = "/computeMetadata/v1/" - const valueEndpoint = "/my/value" - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Only serve the URL key and the value endpoint - if probeEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - } else if valueEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintln(w, sampleDockerConfig) - } else if strings.HasSuffix(dockerConfigUrlKey, r.URL.Path) { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/text") - fmt.Fprint(w, "http://foo.bar.com"+valueEndpoint) - } else { - w.WriteHeader(http.StatusNotFound) - } - })) - defer server.Close() - - // Make a transport that reroutes all traffic to the example server - transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL + req.URL.Path) - }, - }) - - keyring := &credentialprovider.BasicDockerKeyring{} - provider := &dockerConfigUrlKeyProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - } - - if !provider.Enabled() { - t.Errorf("Provider is unexpectedly disabled") - } - - keyring.Add(provider.Provide()) - - creds, ok := keyring.Lookup(registryUrl) - if !ok { - t.Errorf("Didn't find expected URL: %s", registryUrl) - return - } - if len(creds) > 1 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if username != val.Username { - t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username) - } - if password != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } -} - -func TestContainerRegistryBasics(t *testing.T) { - registryUrl := "container.cloud.google.com" - email := "1234@project.gserviceaccount.com" - token := &tokenBlob{AccessToken: "ya26.lots-of-indiscernible-garbage"} - - const ( - defaultEndpoint = "/computeMetadata/v1/instance/service-accounts/default/" - scopeEndpoint = defaultEndpoint + "scopes" - emailEndpoint = defaultEndpoint + "email" - tokenEndpoint = defaultEndpoint + "token" - ) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Only serve the URL key and the value endpoint - if scopeEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `["%s.read_write"]`, storageScopePrefix) - } else if emailEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - fmt.Fprint(w, email) - } else if tokenEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - bytes, err := json.Marshal(token) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - fmt.Fprintln(w, string(bytes)) - } else { - w.WriteHeader(http.StatusNotFound) - } - })) - defer server.Close() - - // Make a transport that reroutes all traffic to the example server - transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL + req.URL.Path) - }, - }) - - keyring := &credentialprovider.BasicDockerKeyring{} - provider := &containerRegistryProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - } - - if !provider.Enabled() { - t.Errorf("Provider is unexpectedly disabled") - } - - keyring.Add(provider.Provide()) - - creds, ok := keyring.Lookup(registryUrl) - if !ok { - t.Errorf("Didn't find expected URL: %s", registryUrl) - return - } - if len(creds) > 1 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if "_token" != val.Username { - t.Errorf("Unexpected username value, want: %s, got: %s", "_token", val.Username) - } - if token.AccessToken != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", token.AccessToken, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } -} - -func TestContainerRegistryNoStorageScope(t *testing.T) { - const ( - defaultEndpoint = "/computeMetadata/v1/instance/service-accounts/default/" - scopeEndpoint = defaultEndpoint + "scopes" - ) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Only serve the URL key and the value endpoint - if scopeEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - fmt.Fprint(w, `["https://www.googleapis.com/auth/compute.read_write"]`) - } else { - w.WriteHeader(http.StatusNotFound) - } - })) - defer server.Close() - - // Make a transport that reroutes all traffic to the example server - transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL + req.URL.Path) - }, - }) - - provider := &containerRegistryProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - } - - if provider.Enabled() { - t.Errorf("Provider is unexpectedly enabled") - } -} - -func TestComputePlatformScopeSubstitutesStorageScope(t *testing.T) { - const ( - defaultEndpoint = "/computeMetadata/v1/instance/service-accounts/default/" - scopeEndpoint = defaultEndpoint + "scopes" - ) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Only serve the URL key and the value endpoint - if scopeEndpoint == r.URL.Path { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - fmt.Fprint(w, `["https://www.googleapis.com/auth/compute.read_write","https://www.googleapis.com/auth/cloud-platform.read-only"]`) - } else { - w.WriteHeader(http.StatusNotFound) - } - })) - defer server.Close() - - // Make a transport that reroutes all traffic to the example server - transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL + req.URL.Path) - }, - }) - - provider := &containerRegistryProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - } - - if !provider.Enabled() { - t.Errorf("Provider is unexpectedly disabled") - } -} - -func TestAllProvidersNoMetadata(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - })) - defer server.Close() - - // Make a transport that reroutes all traffic to the example server - transport := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL + req.URL.Path) - }, - }) - - providers := []credentialprovider.DockerConfigProvider{ - &dockerConfigKeyProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - }, - &dockerConfigUrlKeyProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - }, - &containerRegistryProvider{ - metadataProvider{Client: &http.Client{Transport: transport}}, - }, - } - - for _, provider := range providers { - if provider.Enabled() { - t.Errorf("Provider %s is unexpectedly enabled", reflect.TypeOf(provider).String()) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/keyring_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/keyring_test.go deleted file mode 100644 index 376e08017..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/keyring_test.go +++ /dev/null @@ -1,501 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 credentialprovider - -import ( - "encoding/base64" - "fmt" - "testing" -) - -func TestUrlsMatch(t *testing.T) { - tests := []struct { - globUrl string - targetUrl string - matchExpected bool - }{ - // match when there is no path component - { - globUrl: "*.kubernetes.io", - targetUrl: "prefix.kubernetes.io", - matchExpected: true, - }, - { - globUrl: "prefix.*.io", - targetUrl: "prefix.kubernetes.io", - matchExpected: true, - }, - { - globUrl: "prefix.kubernetes.*", - targetUrl: "prefix.kubernetes.io", - matchExpected: true, - }, - { - globUrl: "*-good.kubernetes.io", - targetUrl: "prefix-good.kubernetes.io", - matchExpected: true, - }, - // match with path components - { - globUrl: "*.kubernetes.io/blah", - targetUrl: "prefix.kubernetes.io/blah", - matchExpected: true, - }, - { - globUrl: "prefix.*.io/foo", - targetUrl: "prefix.kubernetes.io/foo/bar", - matchExpected: true, - }, - // match with path components and ports - { - globUrl: "*.kubernetes.io:1111/blah", - targetUrl: "prefix.kubernetes.io:1111/blah", - matchExpected: true, - }, - { - globUrl: "prefix.*.io:1111/foo", - targetUrl: "prefix.kubernetes.io:1111/foo/bar", - matchExpected: true, - }, - // no match when number of parts mismatch - { - globUrl: "*.kubernetes.io", - targetUrl: "kubernetes.io", - matchExpected: false, - }, - { - globUrl: "*.*.kubernetes.io", - targetUrl: "prefix.kubernetes.io", - matchExpected: false, - }, - { - globUrl: "*.*.kubernetes.io", - targetUrl: "kubernetes.io", - matchExpected: false, - }, - // no match when some parts mismatch - { - globUrl: "kubernetes.io", - targetUrl: "kubernetes.com", - matchExpected: false, - }, - { - globUrl: "k*.io", - targetUrl: "quay.io", - matchExpected: false, - }, - // no match when ports mismatch - { - globUrl: "*.kubernetes.io:1234/blah", - targetUrl: "prefix.kubernetes.io:1111/blah", - matchExpected: false, - }, - { - globUrl: "prefix.*.io/foo", - targetUrl: "prefix.kubernetes.io:1111/foo/bar", - matchExpected: false, - }, - } - for _, test := range tests { - matched, _ := urlsMatchStr(test.globUrl, test.targetUrl) - if matched != test.matchExpected { - t.Errorf("Expected match result of %s and %s to be %t, but was %t", - test.globUrl, test.targetUrl, test.matchExpected, matched) - } - } -} - -func TestDockerKeyringForGlob(t *testing.T) { - tests := []struct { - globUrl string - targetUrl string - }{ - { - globUrl: "https://hello.kubernetes.io", - targetUrl: "hello.kubernetes.io", - }, - { - globUrl: "https://*.docker.io", - targetUrl: "prefix.docker.io", - }, - { - globUrl: "https://prefix.*.io", - targetUrl: "prefix.docker.io", - }, - { - globUrl: "https://prefix.docker.*", - targetUrl: "prefix.docker.io", - }, - { - globUrl: "https://*.docker.io/path", - targetUrl: "prefix.docker.io/path", - }, - { - globUrl: "https://prefix.*.io/path", - targetUrl: "prefix.docker.io/path/subpath", - }, - { - globUrl: "https://prefix.docker.*/path", - targetUrl: "prefix.docker.io/path", - }, - { - globUrl: "https://*.docker.io:8888", - targetUrl: "prefix.docker.io:8888", - }, - { - globUrl: "https://prefix.*.io:8888", - targetUrl: "prefix.docker.io:8888", - }, - { - globUrl: "https://prefix.docker.*:8888", - targetUrl: "prefix.docker.io:8888", - }, - { - globUrl: "https://*.docker.io/path:1111", - targetUrl: "prefix.docker.io/path:1111", - }, - { - globUrl: "https://*.docker.io/v1/", - targetUrl: "prefix.docker.io/path:1111", - }, - { - globUrl: "https://*.docker.io/v2/", - targetUrl: "prefix.docker.io/path:1111", - }, - { - globUrl: "https://prefix.docker.*/path:1111", - targetUrl: "prefix.docker.io/path:1111", - }, - { - globUrl: "prefix.docker.io:1111", - targetUrl: "prefix.docker.io:1111/path", - }, - { - globUrl: "*.docker.io:1111", - targetUrl: "prefix.docker.io:1111/path", - }, - } - for i, test := range tests { - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "%s": { - "email": %q, - "auth": %q - } -}`, test.globUrl, email, auth) - - keyring := &BasicDockerKeyring{} - if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil { - t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err) - } else { - keyring.Add(cfg) - } - - creds, ok := keyring.Lookup(test.targetUrl + "/foo/bar") - if !ok { - t.Errorf("%d: Didn't find expected URL: %s", i, test.targetUrl) - continue - } - val := creds[0] - - if username != val.Username { - t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username) - } - if password != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } - } -} - -func TestKeyringMiss(t *testing.T) { - tests := []struct { - globUrl string - lookupUrl string - }{ - { - globUrl: "https://hello.kubernetes.io", - lookupUrl: "world.mesos.org/foo/bar", - }, - { - globUrl: "https://*.docker.com", - lookupUrl: "prefix.docker.io", - }, - { - globUrl: "https://suffix.*.io", - lookupUrl: "prefix.docker.io", - }, - { - globUrl: "https://prefix.docker.c*", - lookupUrl: "prefix.docker.io", - }, - { - globUrl: "https://prefix.*.io/path:1111", - lookupUrl: "prefix.docker.io/path/subpath:1111", - }, - { - globUrl: "suffix.*.io", - lookupUrl: "prefix.docker.io", - }, - } - for _, test := range tests { - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "%s": { - "email": %q, - "auth": %q - } -}`, test.globUrl, email, auth) - - keyring := &BasicDockerKeyring{} - if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil { - t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err) - } else { - keyring.Add(cfg) - } - - _, ok := keyring.Lookup(test.lookupUrl + "/foo/bar") - if ok { - t.Errorf("Expected not to find URL %s, but found", test.lookupUrl) - } - } - -} - -func TestKeyringMissWithDockerHubCredentials(t *testing.T) { - url := defaultRegistryKey - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "https://%s": { - "email": %q, - "auth": %q - } -}`, url, email, auth) - - keyring := &BasicDockerKeyring{} - if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil { - t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err) - } else { - keyring.Add(cfg) - } - - val, ok := keyring.Lookup("world.mesos.org/foo/bar") - if ok { - t.Errorf("Found unexpected credential: %+v", val) - } -} - -func TestKeyringHitWithUnqualifiedDockerHub(t *testing.T) { - url := defaultRegistryKey - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "https://%s": { - "email": %q, - "auth": %q - } -}`, url, email, auth) - - keyring := &BasicDockerKeyring{} - if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil { - t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err) - } else { - keyring.Add(cfg) - } - - creds, ok := keyring.Lookup("google/docker-registry") - if !ok { - t.Errorf("Didn't find expected URL: %s", url) - return - } - if len(creds) > 1 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if username != val.Username { - t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username) - } - if password != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } -} - -func TestKeyringHitWithUnqualifiedLibraryDockerHub(t *testing.T) { - url := defaultRegistryKey - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "https://%s": { - "email": %q, - "auth": %q - } -}`, url, email, auth) - - keyring := &BasicDockerKeyring{} - if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil { - t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err) - } else { - keyring.Add(cfg) - } - - creds, ok := keyring.Lookup("jenkins") - if !ok { - t.Errorf("Didn't find expected URL: %s", url) - return - } - if len(creds) > 1 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if username != val.Username { - t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username) - } - if password != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } -} - -func TestKeyringHitWithQualifiedDockerHub(t *testing.T) { - url := defaultRegistryKey - email := "foo@bar.baz" - username := "foo" - password := "bar" - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))) - sampleDockerConfig := fmt.Sprintf(`{ - "https://%s": { - "email": %q, - "auth": %q - } -}`, url, email, auth) - - keyring := &BasicDockerKeyring{} - if cfg, err := readDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil { - t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err) - } else { - keyring.Add(cfg) - } - - creds, ok := keyring.Lookup(url + "/google/docker-registry") - if !ok { - t.Errorf("Didn't find expected URL: %s", url) - return - } - if len(creds) > 2 { - t.Errorf("Got more hits than expected: %s", creds) - } - val := creds[0] - - if username != val.Username { - t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username) - } - if password != val.Password { - t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password) - } - if email != val.Email { - t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email) - } -} - -func TestIsDefaultRegistryMatch(t *testing.T) { - samples := []map[bool]string{ - {true: "foo/bar"}, - {true: "docker.io/foo/bar"}, - {true: "index.docker.io/foo/bar"}, - {true: "foo"}, - {false: ""}, - {false: "registry.tld/foo/bar"}, - {false: "registry:5000/foo/bar"}, - {false: "myhostdocker.io/foo/bar"}, - } - for _, sample := range samples { - for expected, imageName := range sample { - if got := isDefaultRegistryMatch(imageName); got != expected { - t.Errorf("Expected '%s' to be %t, got %t", imageName, expected, got) - } - } - } -} - -type testProvider struct { - Count int -} - -// Enabled implements dockerConfigProvider -func (d *testProvider) Enabled() bool { - return true -} - -// LazyProvide implements dockerConfigProvider. Should never be called. -func (d *testProvider) LazyProvide() *DockerConfigEntry { - return nil -} - -// Provide implements dockerConfigProvider -func (d *testProvider) Provide() DockerConfig { - d.Count += 1 - return DockerConfig{} -} - -func TestLazyKeyring(t *testing.T) { - provider := &testProvider{ - Count: 0, - } - lazy := &lazyDockerKeyring{ - Providers: []DockerConfigProvider{ - provider, - }, - } - - if provider.Count != 0 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } - lazy.Lookup("foo") - if provider.Count != 1 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } - lazy.Lookup("foo") - if provider.Count != 2 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } - lazy.Lookup("foo") - if provider.Count != 3 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/provider_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/provider_test.go deleted file mode 100644 index 099d839fb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/credentialprovider/provider_test.go +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 credentialprovider - -import ( - "testing" - "time" -) - -func TestCachingProvider(t *testing.T) { - provider := &testProvider{ - Count: 0, - } - - cache := &CachingDockerConfigProvider{ - Provider: provider, - Lifetime: 1 * time.Second, - } - - if provider.Count != 0 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } - cache.Provide() - cache.Provide() - cache.Provide() - cache.Provide() - if provider.Count != 1 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } - - time.Sleep(cache.Lifetime) - cache.Provide() - cache.Provide() - cache.Provide() - cache.Provide() - if provider.Count != 2 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } - - time.Sleep(cache.Lifetime) - cache.Provide() - cache.Provide() - cache.Provide() - cache.Provide() - if provider.Count != 3 { - t.Errorf("Unexpected number of Provide calls: %v", provider.Count) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fieldpath/fieldpath_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fieldpath/fieldpath_test.go deleted file mode 100644 index d510426ee..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fieldpath/fieldpath_test.go +++ /dev/null @@ -1,117 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 fieldpath - -import ( - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func TestExtractFieldPathAsString(t *testing.T) { - cases := []struct { - name string - fieldPath string - obj interface{} - expectedValue string - expectedMessageFragment string - }{ - { - name: "not an API object", - fieldPath: "metadata.name", - obj: "", - expectedMessageFragment: "expected struct", - }, - { - name: "ok - namespace", - fieldPath: "metadata.namespace", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: "object-namespace", - }, - }, - expectedValue: "object-namespace", - }, - { - name: "ok - name", - fieldPath: "metadata.name", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "object-name", - }, - }, - expectedValue: "object-name", - }, - { - name: "ok - labels", - fieldPath: "metadata.labels", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"key": "value"}, - }, - }, - expectedValue: "key=\"value\"\n", - }, - { - name: "ok - labels bslash n", - fieldPath: "metadata.labels", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"key": "value\n"}, - }, - }, - expectedValue: "key=\"value\\n\"\n", - }, - { - name: "ok - annotations", - fieldPath: "metadata.annotations", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"builder": "john-doe"}, - }, - }, - expectedValue: "builder=\"john-doe\"\n", - }, - - { - name: "invalid expression", - fieldPath: "metadata.whoops", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: "object-namespace", - }, - }, - expectedMessageFragment: "Unsupported fieldPath", - }, - } - - for _, tc := range cases { - actual, err := ExtractFieldPathAsString(tc.obj, tc.fieldPath) - if err != nil { - if tc.expectedMessageFragment != "" { - if !strings.Contains(err.Error(), tc.expectedMessageFragment) { - t.Errorf("%v: Unexpected error message: %q, expected to contain %q", tc.name, err, tc.expectedMessageFragment) - } - } else { - t.Errorf("%v: unexpected error: %v", tc.name, err) - } - } else if e := tc.expectedValue; e != "" && e != actual { - t.Errorf("%v: Unexpected result; got %q, expected %q", tc.name, actual, e) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fields/fields_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fields/fields_test.go deleted file mode 100644 index 9f6f3fc35..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fields/fields_test.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 fields - -import ( - "testing" -) - -func matches(t *testing.T, ls Set, want string) { - if ls.String() != want { - t.Errorf("Expected '%s', but got '%s'", want, ls.String()) - } -} - -func TestSetString(t *testing.T) { - matches(t, Set{"x": "y"}, "x=y") - matches(t, Set{"foo": "bar"}, "foo=bar") - matches(t, Set{"foo": "bar", "baz": "qup"}, "baz=qup,foo=bar") -} - -func TestFieldHas(t *testing.T) { - fieldHasTests := []struct { - Ls Fields - Key string - Has bool - }{ - {Set{"x": "y"}, "x", true}, - {Set{"x": ""}, "x", true}, - {Set{"x": "y"}, "foo", false}, - } - for _, lh := range fieldHasTests { - if has := lh.Ls.Has(lh.Key); has != lh.Has { - t.Errorf("%#v.Has(%#v) => %v, expected %v", lh.Ls, lh.Key, has, lh.Has) - } - } -} - -func TestFieldGet(t *testing.T) { - ls := Set{"x": "y"} - if ls.Get("x") != "y" { - t.Errorf("Set.Get is broken") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fields/selector_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fields/selector_test.go deleted file mode 100644 index 7651ae6bb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/fields/selector_test.go +++ /dev/null @@ -1,208 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 fields - -import ( - "testing" -) - -func TestSelectorParse(t *testing.T) { - testGoodStrings := []string{ - "x=a,y=b,z=c", - "", - "x!=a,y=b", - } - testBadStrings := []string{ - "x=a||y=b", - "x==a==b", - } - for _, test := range testGoodStrings { - lq, err := ParseSelector(test) - if err != nil { - t.Errorf("%v: error %v (%#v)\n", test, err, err) - } - if test != lq.String() { - t.Errorf("%v restring gave: %v\n", test, lq.String()) - } - } - for _, test := range testBadStrings { - _, err := ParseSelector(test) - if err == nil { - t.Errorf("%v: did not get expected error\n", test) - } - } -} - -func TestDeterministicParse(t *testing.T) { - s1, err := ParseSelector("x=a,a=x") - s2, err2 := ParseSelector("a=x,x=a") - if err != nil || err2 != nil { - t.Errorf("Unexpected parse error") - } - if s1.String() != s2.String() { - t.Errorf("Non-deterministic parse") - } -} - -func expectMatch(t *testing.T, selector string, ls Set) { - lq, err := ParseSelector(selector) - if err != nil { - t.Errorf("Unable to parse %v as a selector\n", selector) - return - } - if !lq.Matches(ls) { - t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls) - } -} - -func expectNoMatch(t *testing.T, selector string, ls Set) { - lq, err := ParseSelector(selector) - if err != nil { - t.Errorf("Unable to parse %v as a selector\n", selector) - return - } - if lq.Matches(ls) { - t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls) - } -} - -func TestEverything(t *testing.T) { - if !Everything().Matches(Set{"x": "y"}) { - t.Errorf("Nil selector didn't match") - } - if !Everything().Empty() { - t.Errorf("Everything was not empty") - } -} - -func TestSelectorMatches(t *testing.T) { - expectMatch(t, "", Set{"x": "y"}) - expectMatch(t, "x=y", Set{"x": "y"}) - expectMatch(t, "x=y,z=w", Set{"x": "y", "z": "w"}) - expectMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "a"}) - expectMatch(t, "notin=in", Set{"notin": "in"}) // in and notin in exactMatch - expectNoMatch(t, "x=y", Set{"x": "z"}) - expectNoMatch(t, "x=y,z=w", Set{"x": "w", "z": "w"}) - expectNoMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "w"}) - - labelset := Set{ - "foo": "bar", - "baz": "blah", - } - expectMatch(t, "foo=bar", labelset) - expectMatch(t, "baz=blah", labelset) - expectMatch(t, "foo=bar,baz=blah", labelset) - expectNoMatch(t, "foo=blah", labelset) - expectNoMatch(t, "baz=bar", labelset) - expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", labelset) -} - -func TestOneTermEqualSelector(t *testing.T) { - if !OneTermEqualSelector("x", "y").Matches(Set{"x": "y"}) { - t.Errorf("No match when match expected.") - } - if OneTermEqualSelector("x", "y").Matches(Set{"x": "z"}) { - t.Errorf("Match when none expected.") - } -} - -func expectMatchDirect(t *testing.T, selector, ls Set) { - if !SelectorFromSet(selector).Matches(ls) { - t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls) - } -} - -func expectNoMatchDirect(t *testing.T, selector, ls Set) { - if SelectorFromSet(selector).Matches(ls) { - t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls) - } -} - -func TestSetMatches(t *testing.T) { - labelset := Set{ - "foo": "bar", - "baz": "blah", - } - expectMatchDirect(t, Set{}, labelset) - expectMatchDirect(t, Set{"foo": "bar"}, labelset) - expectMatchDirect(t, Set{"baz": "blah"}, labelset) - expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset) - expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset) - expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset) - expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset) -} - -func TestNilMapIsValid(t *testing.T) { - selector := Set(nil).AsSelector() - if selector == nil { - t.Errorf("Selector for nil set should be Everything") - } - if !selector.Empty() { - t.Errorf("Selector for nil set should be Empty") - } -} - -func TestSetIsEmpty(t *testing.T) { - if !(Set{}).AsSelector().Empty() { - t.Errorf("Empty set should be empty") - } - if !(andTerm(nil)).Empty() { - t.Errorf("Nil andTerm should be empty") - } - if (&hasTerm{}).Empty() { - t.Errorf("hasTerm should not be empty") - } - if (¬HasTerm{}).Empty() { - t.Errorf("notHasTerm should not be empty") - } - if !(andTerm{andTerm{}}).Empty() { - t.Errorf("Nested andTerm should be empty") - } - if (andTerm{&hasTerm{"a", "b"}}).Empty() { - t.Errorf("Nested andTerm should not be empty") - } -} - -func TestRequiresExactMatch(t *testing.T) { - testCases := map[string]struct { - S Selector - Label string - Value string - Found bool - }{ - "empty set": {Set{}.AsSelector(), "test", "", false}, - "nil andTerm": {andTerm(nil), "test", "", false}, - "empty hasTerm": {&hasTerm{}, "test", "", false}, - "skipped hasTerm": {&hasTerm{"a", "b"}, "test", "", false}, - "valid hasTerm": {&hasTerm{"test", "b"}, "test", "b", true}, - "valid hasTerm no value": {&hasTerm{"test", ""}, "test", "", true}, - "valid notHasTerm": {¬HasTerm{"test", "b"}, "test", "", false}, - "valid notHasTerm no value": {¬HasTerm{"test", ""}, "test", "", false}, - "nested andTerm": {andTerm{andTerm{}}, "test", "", false}, - "nested andTerm matches": {andTerm{&hasTerm{"test", "b"}}, "test", "b", true}, - "andTerm with non-match": {andTerm{&hasTerm{}, &hasTerm{"test", "b"}}, "test", "b", true}, - } - for k, v := range testCases { - value, found := v.S.RequiresExactMatch(v.Label) - if value != v.Value { - t.Errorf("%s: expected value %s, got %s", k, v.Value, value) - } - if found != v.Found { - t.Errorf("%s: expected found %t, got %t", k, v.Found, found) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/healthz/healthz_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/healthz/healthz_test.go deleted file mode 100644 index bfd833eb8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/healthz/healthz_test.go +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 healthz - -import ( - "errors" - "fmt" - "net/http" - "net/http/httptest" - "testing" -) - -func TestInstallHandler(t *testing.T) { - mux := http.NewServeMux() - InstallHandler(mux) - req, err := http.NewRequest("GET", "http://example.com/healthz", nil) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - w := httptest.NewRecorder() - mux.ServeHTTP(w, req) - if w.Code != http.StatusOK { - t.Errorf("Expected %v, got %v", http.StatusOK, w.Code) - } - if w.Body.String() != "ok" { - t.Errorf("Expected %v, got %v", "ok", w.Body.String()) - } -} - -func TestMulitipleChecks(t *testing.T) { - tests := []struct { - path string - expectedResponse string - expectedStatus int - addBadCheck bool - }{ - {"/healthz?verbose", "[+]ping ok\nhealthz check passed\n", http.StatusOK, false}, - {"/healthz/ping", "ok", http.StatusOK, false}, - {"/healthz", "ok", http.StatusOK, false}, - {"/healthz?verbose", "[+]ping ok\n[-]bad failed: this will fail\nhealthz check failed\n", http.StatusInternalServerError, true}, - {"/healthz/ping", "ok", http.StatusOK, true}, - {"/healthz/bad", "Internal server error: this will fail\n", http.StatusInternalServerError, true}, - {"/healthz", "[+]ping ok\n[-]bad failed: this will fail\nhealthz check failed\n", http.StatusInternalServerError, true}, - } - - for i, test := range tests { - mux := http.NewServeMux() - checks := []HealthzChecker{PingHealthz} - if test.addBadCheck { - checks = append(checks, NamedCheck("bad", func(_ *http.Request) error { - return errors.New("this will fail") - })) - } - InstallHandler(mux, checks...) - req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com%v", test.path), nil) - if err != nil { - t.Fatalf("case[%d] Unexpected error: %v", i, err) - } - w := httptest.NewRecorder() - mux.ServeHTTP(w, req) - if w.Code != test.expectedStatus { - t.Errorf("case[%d] Expected: %v, got: %v", i, test.expectedStatus, w.Code) - } - if w.Body.String() != test.expectedResponse { - t.Errorf("case[%d] Expected:\n%v\ngot:\n%v\n", i, test.expectedResponse, w.Body.String()) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/annotate.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/annotate.go deleted file mode 100644 index 3a081ad2d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/annotate.go +++ /dev/null @@ -1,378 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "regexp" - "strings" - - "github.com/golang/glog" - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/strategicpatch" -) - -// AnnotateOptions have the data required to perform the annotate operation -type AnnotateOptions struct { - resources []string - newAnnotations map[string]string - removeAnnotations []string - builder *resource.Builder - filenames []string - selector string - - overwrite bool - all bool - resourceVersion string - - changeCause string - recordChangeCause bool - - f *cmdutil.Factory - out io.Writer - cmd *cobra.Command - - recursive bool -} - -const ( - annotate_resources = ` - pod (po), service (svc), replicationcontroller (rc), - node (no), event (ev), componentstatuse (cs), - limitrange (limits), persistentvolume (pv), persistentvolumeclaim (pvc), - horizontalpodautoscaler (hpa), resourcequota (quota), secret -` - - annotate_long = `Update the annotations on one or more resources. - -An annotation is a key/value pair that can hold larger (compared to a label), and possibly not human-readable, data. -It is intended to store non-identifying auxiliary data, especially data manipulated by tools and system extensions. -If --overwrite is true, then existing annotations can be overwritten, otherwise attempting to overwrite an annotation will result in an error. -If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used. - -Possible resources include (case insensitive):` + annotate_resources - - annotate_example = `# Update pod 'foo' with the annotation 'description' and the value 'my frontend'. -# If the same annotation is set multiple times, only the last value will be applied -kubectl annotate pods foo description='my frontend' - -# Update a pod identified by type and name in "pod.json" -kubectl annotate -f pod.json description='my frontend' - -# Update pod 'foo' with the annotation 'description' and the value 'my frontend running nginx', overwriting any existing value. -kubectl annotate --overwrite pods foo description='my frontend running nginx' - -# Update all pods in the namespace -kubectl annotate pods --all description='my frontend running nginx' - -# Update pod 'foo' only if the resource is unchanged from version 1. -kubectl annotate pods foo description='my frontend running nginx' --resource-version=1 - -# Update pod 'foo' by removing an annotation named 'description' if it exists. -# Does not require the --overwrite flag. -kubectl annotate pods foo description-` -) - -func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &AnnotateOptions{} - - validArgs, argAliases := []string{}, []string{} - resources := regexp.MustCompile(`\s*,`).Split(annotate_resources, -1) - for _, r := range resources { - validArgs = append(validArgs, strings.Fields(r)[0]) - argAliases = kubectl.ResourceAliases(validArgs) - } - - cmd := &cobra.Command{ - Use: "annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", - Short: "Update the annotations on a resource", - Long: annotate_long, - Example: annotate_example, - Run: func(cmd *cobra.Command, args []string) { - if err := options.Complete(f, out, cmd, args); err != nil { - cmdutil.CheckErr(err) - } - if err := options.Validate(args); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) - } - if err := options.RunAnnotate(); err != nil { - cmdutil.CheckErr(err) - } - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - cmd.Flags().StringVarP(&options.selector, "selector", "l", "", "Selector (label query) to filter on") - cmd.Flags().BoolVar(&options.overwrite, "overwrite", false, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") - cmd.Flags().BoolVar(&options.all, "all", false, "select all resources in the namespace of the specified resource types") - cmd.Flags().StringVar(&options.resourceVersion, "resource-version", "", "If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") - usage := "Filename, directory, or URL to a file identifying the resource to update the annotation" - kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.recursive) - cmdutil.AddRecordFlag(cmd) - return cmd -} - -// Complete adapts from the command line args and factory to the data required. -func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { - - namespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - // retrieves resource and annotation args from args - // also checks args to verify that all resources are specified before annotations - annotationArgs := []string{} - metAnnotaionArg := false - for _, s := range args { - isAnnotation := strings.Contains(s, "=") || strings.HasSuffix(s, "-") - switch { - case !metAnnotaionArg && isAnnotation: - metAnnotaionArg = true - fallthrough - case metAnnotaionArg && isAnnotation: - annotationArgs = append(annotationArgs, s) - case !metAnnotaionArg && !isAnnotation: - o.resources = append(o.resources, s) - case metAnnotaionArg && !isAnnotation: - return fmt.Errorf("all resources must be specified before annotation changes: %s", s) - } - } - if len(o.resources) < 1 && len(o.filenames) == 0 { - return fmt.Errorf("one or more resources must be specified as or /") - } - if len(annotationArgs) < 1 { - return fmt.Errorf("at least one annotation update is required") - } - - if o.newAnnotations, o.removeAnnotations, err = parseAnnotations(annotationArgs); err != nil { - return err - } - - o.recordChangeCause = cmdutil.GetRecordFlag(cmd) - o.changeCause = f.Command() - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.recursive, o.filenames...). - SelectorParam(o.selector). - ResourceTypeOrNameArgs(o.all, o.resources...). - Flatten(). - Latest() - - o.f = f - o.out = out - o.cmd = cmd - - return nil -} - -// Validate checks to the AnnotateOptions to see if there is sufficient information run the command. -func (o AnnotateOptions) Validate(args []string) error { - if err := validateAnnotations(o.removeAnnotations, o.newAnnotations); err != nil { - return err - } - - // only apply resource version locking on a single resource - if len(o.resources) > 1 && len(o.resourceVersion) > 0 { - return fmt.Errorf("--resource-version may only be used with a single resource") - } - - return nil -} - -// RunAnnotate does the work -func (o AnnotateOptions) RunAnnotate() error { - r := o.builder.Do() - if err := r.Err(); err != nil { - return err - } - - return r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - obj, err := info.Mapping.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupVersion().String()) - if err != nil { - return err - } - name, namespace := info.Name, info.Namespace - oldData, err := json.Marshal(obj) - if err != nil { - return err - } - // If we should record change-cause, add it to new annotations - if cmdutil.ContainsChangeCause(info) || o.recordChangeCause { - o.newAnnotations[kubectl.ChangeCauseAnnotation] = o.changeCause - } - if err := o.updateAnnotations(obj); err != nil { - return err - } - newData, err := json.Marshal(obj) - if err != nil { - return err - } - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj) - createdPatch := err == nil - if err != nil { - glog.V(2).Infof("couldn't compute patch: %v", err) - } - - mapping := info.ResourceMapping() - client, err := o.f.ClientForMapping(mapping) - if err != nil { - return err - } - helper := resource.NewHelper(client, mapping) - - var outputObj runtime.Object - if createdPatch { - outputObj, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) - } else { - outputObj, err = helper.Replace(namespace, name, false, obj) - } - if err != nil { - return err - } - - mapper, _ := o.f.Object(cmdutil.GetIncludeThirdPartyAPIs(o.cmd)) - outputFormat := cmdutil.GetFlagString(o.cmd, "output") - if outputFormat != "" { - return o.f.PrintObject(o.cmd, mapper, outputObj, o.out) - } - - cmdutil.PrintSuccess(mapper, false, o.out, info.Mapping.Resource, info.Name, "annotated") - return nil - }) -} - -// parseAnnotations retrieves new and remove annotations from annotation args -func parseAnnotations(annotationArgs []string) (map[string]string, []string, error) { - var invalidBuf bytes.Buffer - newAnnotations := map[string]string{} - removeAnnotations := []string{} - for _, annotationArg := range annotationArgs { - if strings.Index(annotationArg, "=") != -1 { - parts := strings.SplitN(annotationArg, "=", 2) - if len(parts) != 2 || len(parts[1]) == 0 { - if invalidBuf.Len() > 0 { - invalidBuf.WriteString(", ") - } - invalidBuf.WriteString(fmt.Sprintf(annotationArg)) - } else { - newAnnotations[parts[0]] = parts[1] - } - } else if strings.HasSuffix(annotationArg, "-") { - removeAnnotations = append(removeAnnotations, annotationArg[:len(annotationArg)-1]) - } else { - if invalidBuf.Len() > 0 { - invalidBuf.WriteString(", ") - } - invalidBuf.WriteString(fmt.Sprintf(annotationArg)) - } - } - if invalidBuf.Len() > 0 { - return newAnnotations, removeAnnotations, fmt.Errorf("invalid annotation format: %s", invalidBuf.String()) - } - - return newAnnotations, removeAnnotations, nil -} - -// validateAnnotations checks the format of annotation args and checks removed annotations aren't in the new annotations map -func validateAnnotations(removeAnnotations []string, newAnnotations map[string]string) error { - var modifyRemoveBuf bytes.Buffer - for _, removeAnnotation := range removeAnnotations { - if _, found := newAnnotations[removeAnnotation]; found { - if modifyRemoveBuf.Len() > 0 { - modifyRemoveBuf.WriteString(", ") - } - modifyRemoveBuf.WriteString(fmt.Sprintf(removeAnnotation)) - } - } - if modifyRemoveBuf.Len() > 0 { - return fmt.Errorf("can not both modify and remove the following annotation(s) in the same command: %s", modifyRemoveBuf.String()) - } - - return nil -} - -// validateNoAnnotationOverwrites validates that when overwrite is false, to-be-updated annotations don't exist in the object annotation map (yet) -func validateNoAnnotationOverwrites(accessor meta.Object, annotations map[string]string) error { - var buf bytes.Buffer - for key := range annotations { - // change-cause annotation can always be overwritten - if key == kubectl.ChangeCauseAnnotation { - continue - } - if value, found := accessor.GetAnnotations()[key]; found { - if buf.Len() > 0 { - buf.WriteString("; ") - } - buf.WriteString(fmt.Sprintf("'%s' already has a value (%s)", key, value)) - } - } - if buf.Len() > 0 { - return fmt.Errorf("--overwrite is false but found the following declared annotation(s): %s", buf.String()) - } - return nil -} - -// updateAnnotations updates annotations of obj -func (o AnnotateOptions) updateAnnotations(obj runtime.Object) error { - accessor, err := meta.Accessor(obj) - if err != nil { - return err - } - if !o.overwrite { - if err := validateNoAnnotationOverwrites(accessor, o.newAnnotations); err != nil { - return err - } - } - - annotations := accessor.GetAnnotations() - if annotations == nil { - annotations = make(map[string]string) - } - - for key, value := range o.newAnnotations { - annotations[key] = value - } - for _, annotation := range o.removeAnnotations { - delete(annotations, annotation) - } - accessor.SetAnnotations(annotations) - - if len(o.resourceVersion) != 0 { - accessor.SetResourceVersion(o.resourceVersion) - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/annotate_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/annotate_test.go deleted file mode 100644 index 2cd94445e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/annotate_test.go +++ /dev/null @@ -1,571 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestValidateAnnotationOverwrites(t *testing.T) { - tests := []struct { - meta *api.ObjectMeta - annotations map[string]string - expectErr bool - scenario string - }{ - { - meta: &api.ObjectMeta{ - Annotations: map[string]string{ - "a": "A", - "b": "B", - }, - }, - annotations: map[string]string{ - "a": "a", - "c": "C", - }, - scenario: "share first annotation", - expectErr: true, - }, - { - meta: &api.ObjectMeta{ - Annotations: map[string]string{ - "a": "A", - "c": "C", - }, - }, - annotations: map[string]string{ - "b": "B", - "c": "c", - }, - scenario: "share second annotation", - expectErr: true, - }, - { - meta: &api.ObjectMeta{ - Annotations: map[string]string{ - "a": "A", - "c": "C", - }, - }, - annotations: map[string]string{ - "b": "B", - "d": "D", - }, - scenario: "no overlap", - }, - { - meta: &api.ObjectMeta{}, - annotations: map[string]string{ - "a": "A", - "b": "B", - }, - scenario: "no annotations", - }, - } - for _, test := range tests { - err := validateNoAnnotationOverwrites(test.meta, test.annotations) - if test.expectErr && err == nil { - t.Errorf("%s: unexpected non-error", test.scenario) - } else if !test.expectErr && err != nil { - t.Errorf("%s: unexpected error: %v", test.scenario, err) - } - } -} - -func TestParseAnnotations(t *testing.T) { - testURL := "https://test.com/index.htm?id=123#u=user-name" - testJSON := `'{"kind":"SerializedReference","apiVersion":"v1","reference":{"kind":"ReplicationController","namespace":"default","name":"my-nginx","uid":"c544ee78-2665-11e5-8051-42010af0c213","apiVersion":"v1","resourceVersion":"61368"}}'` - tests := []struct { - annotations []string - expected map[string]string - expectedRemove []string - scenario string - expectedErr string - expectErr bool - }{ - { - annotations: []string{"a=b", "c=d"}, - expected: map[string]string{"a": "b", "c": "d"}, - expectedRemove: []string{}, - scenario: "add two annotations", - expectErr: false, - }, - { - annotations: []string{"url=" + testURL, "kubernetes.io/created-by=" + testJSON}, - expected: map[string]string{"url": testURL, "kubernetes.io/created-by": testJSON}, - expectedRemove: []string{}, - scenario: "add annotations with special characters", - expectErr: false, - }, - { - annotations: []string{}, - expected: map[string]string{}, - expectedRemove: []string{}, - scenario: "add no annotations", - expectErr: false, - }, - { - annotations: []string{"a=b", "c=d", "e-"}, - expected: map[string]string{"a": "b", "c": "d"}, - expectedRemove: []string{"e"}, - scenario: "add two annotations, remove one", - expectErr: false, - }, - { - annotations: []string{"ab", "c=d"}, - expectedErr: "invalid annotation format: ab", - scenario: "incorrect annotation input (missing =value)", - expectErr: true, - }, - { - annotations: []string{"a="}, - expectedErr: "invalid annotation format: a=", - scenario: "incorrect annotation input (missing value)", - expectErr: true, - }, - { - annotations: []string{"ab", "a="}, - expectedErr: "invalid annotation format: ab, a=", - scenario: "incorrect multiple annotation input (missing value)", - expectErr: true, - }, - } - for _, test := range tests { - annotations, remove, err := parseAnnotations(test.annotations) - switch { - case test.expectErr && err == nil: - t.Errorf("%s: unexpected non-error, should return %v", test.scenario, test.expectedErr) - case test.expectErr && err.Error() != test.expectedErr: - t.Errorf("%s: unexpected error %v, expected %v", test.scenario, err, test.expectedErr) - case !test.expectErr && err != nil: - t.Errorf("%s: unexpected error %v", test.scenario, err) - case !test.expectErr && !reflect.DeepEqual(annotations, test.expected): - t.Errorf("%s: expected %v, got %v", test.scenario, test.expected, annotations) - case !test.expectErr && !reflect.DeepEqual(remove, test.expectedRemove): - t.Errorf("%s: expected %v, got %v", test.scenario, test.expectedRemove, remove) - } - } -} - -func TestValidateAnnotations(t *testing.T) { - tests := []struct { - removeAnnotations []string - newAnnotations map[string]string - expectedErr string - scenario string - }{ - { - expectedErr: "can not both modify and remove the following annotation(s) in the same command: a", - removeAnnotations: []string{"a"}, - newAnnotations: map[string]string{"a": "b", "c": "d"}, - scenario: "remove an added annotation", - }, - { - expectedErr: "can not both modify and remove the following annotation(s) in the same command: a, c", - removeAnnotations: []string{"a", "c"}, - newAnnotations: map[string]string{"a": "b", "c": "d"}, - scenario: "remove added annotations", - }, - } - for _, test := range tests { - if err := validateAnnotations(test.removeAnnotations, test.newAnnotations); err == nil { - t.Errorf("%s: unexpected non-error", test.scenario) - } else if err.Error() != test.expectedErr { - t.Errorf("%s: expected error %s, got %s", test.scenario, test.expectedErr, err.Error()) - } - } -} - -func TestUpdateAnnotations(t *testing.T) { - tests := []struct { - obj runtime.Object - overwrite bool - version string - annotations map[string]string - remove []string - expected runtime.Object - expectErr bool - }{ - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b"}, - }, - }, - annotations: map[string]string{"a": "b"}, - expectErr: true, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b"}, - }, - }, - annotations: map[string]string{"a": "c"}, - overwrite: true, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "c"}, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b"}, - }, - }, - annotations: map[string]string{"c": "d"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b", "c": "d"}, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b"}, - }, - }, - annotations: map[string]string{"c": "d"}, - version: "2", - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b", "c": "d"}, - ResourceVersion: "2", - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b"}, - }, - }, - annotations: map[string]string{}, - remove: []string{"a"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{}, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b", "c": "d"}, - }, - }, - annotations: map[string]string{"e": "f"}, - remove: []string{"a"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{ - "c": "d", - "e": "f", - }, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b", "c": "d"}, - }, - }, - annotations: map[string]string{"e": "f"}, - remove: []string{"g"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{ - "a": "b", - "c": "d", - "e": "f", - }, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b", "c": "d"}, - }, - }, - remove: []string{"e"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{ - "a": "b", - "c": "d", - }, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{}, - }, - annotations: map[string]string{"a": "b"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{"a": "b"}, - }, - }, - }, - } - for _, test := range tests { - options := &AnnotateOptions{ - overwrite: test.overwrite, - newAnnotations: test.annotations, - removeAnnotations: test.remove, - resourceVersion: test.version, - } - err := options.updateAnnotations(test.obj) - if test.expectErr { - if err == nil { - t.Errorf("unexpected non-error: %v", test) - } - continue - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v %v", err, test) - } - if !reflect.DeepEqual(test.obj, test.expected) { - t.Errorf("expected: %v, got %v", test.expected, test.obj) - } - } -} - -func TestAnnotateErrors(t *testing.T) { - testCases := map[string]struct { - args []string - flags map[string]string - errFn func(error) bool - }{ - "no args": { - args: []string{}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "one or more resources must be specified") }, - }, - "not enough annotations": { - args: []string{"pods"}, - errFn: func(err error) bool { - return strings.Contains(err.Error(), "at least one annotation update is required") - }, - }, - "no resources remove annotations": { - args: []string{"pods-"}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "one or more resources must be specified") }, - }, - "no resources add annotations": { - args: []string{"pods=bar"}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "one or more resources must be specified") }, - }, - } - - for k, testCase := range testCases { - f, tf, _ := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(f, buf) - cmd.SetOutput(buf) - - for k, v := range testCase.flags { - cmd.Flags().Set(k, v) - } - options := &AnnotateOptions{} - err := options.Complete(f, buf, cmd, testCase.args) - if !testCase.errFn(err) { - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - if tf.Printer.(*testPrinter).Objects != nil { - t.Errorf("unexpected print to default printer") - } - if buf.Len() > 0 { - t.Errorf("buffer should be empty: %s", string(buf.Bytes())) - } - } -} - -func TestAnnotateObject(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.Method { - case "GET": - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - case "PATCH": - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - default: - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(f, buf) - cmd.SetOutput(buf) - options := &AnnotateOptions{} - args := []string{"pods/foo", "a=b", "c-"} - if err := options.Complete(f, buf, cmd, args); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if err := options.Validate(args); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if err := options.RunAnnotate(); err != nil { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestAnnotateObjectFromFile(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.Method { - case "GET": - switch req.URL.Path { - case "/namespaces/test/replicationcontrollers/cassandra": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - case "PATCH": - switch req.URL.Path { - case "/namespaces/test/replicationcontrollers/cassandra": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - default: - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(f, buf) - cmd.SetOutput(buf) - options := &AnnotateOptions{} - options.filenames = []string{"../../../examples/cassandra/cassandra-controller.yaml"} - args := []string{"a=b", "c-"} - if err := options.Complete(f, buf, cmd, args); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if err := options.Validate(args); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if err := options.RunAnnotate(); err != nil { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestAnnotateMultipleObjects(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.Method { - case "GET": - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - case "PATCH": - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - case "/namespaces/test/pods/bar": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[1])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - default: - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdAnnotate(f, buf) - cmd.SetOutput(buf) - options := &AnnotateOptions{} - options.all = true - args := []string{"pods", "a=b", "c-"} - if err := options.Complete(f, buf, cmd, args); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if err := options.Validate(args); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if err := options.RunAnnotate(); err != nil { - t.Fatalf("unexpected error: %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apiversions.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apiversions.go deleted file mode 100644 index 3c53a5fd1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apiversions.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "os" - "sort" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api/unversioned" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -func NewCmdApiVersions(f *cmdutil.Factory, out io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "api-versions", - // apiversions is deprecated. - Aliases: []string{"apiversions"}, - Short: "Print the supported API versions on the server, in the form of \"group/version\".", - Run: func(cmd *cobra.Command, args []string) { - err := RunApiVersions(f, out) - cmdutil.CheckErr(err) - }, - } - return cmd -} - -func RunApiVersions(f *cmdutil.Factory, w io.Writer) error { - if len(os.Args) > 1 && os.Args[1] == "apiversions" { - printDeprecationWarning("api-versions", "apiversions") - } - - client, err := f.Client() - if err != nil { - return err - } - - groupList, err := client.Discovery().ServerGroups() - if err != nil { - return fmt.Errorf("Couldn't get available api versions from server: %v\n", err) - } - apiVersions := unversioned.ExtractGroupVersions(groupList) - sort.Strings(apiVersions) - for _, v := range apiVersions { - fmt.Fprintln(w, v) - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go deleted file mode 100644 index d63b79200..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apply.go +++ /dev/null @@ -1,217 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/strategicpatch" -) - -// ApplyOptions stores cmd.Flag values for apply. As new fields are added, -// add them here instead of referencing the cmd.Flags() -type ApplyOptions struct { - Filenames []string - Recursive bool -} - -const ( - apply_long = `Apply a configuration to a resource by filename or stdin. -The resource will be created if it doesn't exist yet. -To use 'apply', always create the resource initially with either 'apply' or 'create --save-config'. - -JSON and YAML formats are accepted.` - apply_example = `# Apply the configuration in pod.json to a pod. -kubectl apply -f ./pod.json - -# Apply the JSON passed into stdin to a pod. -cat pod.json | kubectl apply -f -` -) - -func NewCmdApply(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ApplyOptions{} - - cmd := &cobra.Command{ - Use: "apply -f FILENAME", - Short: "Apply a configuration to a resource by filename or stdin", - Long: apply_long, - Example: apply_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(validateArgs(cmd, args)) - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - cmdutil.CheckErr(RunApply(f, cmd, out, options)) - }, - } - - usage := "Filename, directory, or URL to file that contains the configuration to apply" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmd.MarkFlagRequired("filename") - cmdutil.AddValidateFlags(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func validateArgs(cmd *cobra.Command, args []string) error { - if len(args) != 0 { - return cmdutil.UsageError(cmd, "Unexpected args: %v", args) - } - - return nil -} - -func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *ApplyOptions) error { - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) - if err != nil { - return err - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - Schema(schema). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - encoder := f.JSONEncoder() - decoder := f.Decoder(false) - - count := 0 - err = r.Visit(func(info *resource.Info, err error) error { - // In this method, info.Object contains the object retrieved from the server - // and info.VersionedObject contains the object decoded from the input source. - if err != nil { - return err - } - - // Get the modified configuration of the object. Embed the result - // as an annotation in the modified configuration, so that it will appear - // in the patch sent to the server. - modified, err := kubectl.GetModifiedConfiguration(info, true, encoder) - if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving modified configuration from:\n%v\nfor:", info), info.Source, err) - } - - if err := info.Get(); err != nil { - if !errors.IsNotFound(err) { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) - } - // Create the resource if it doesn't exist - // First, update the annotation used by kubectl apply - if err := kubectl.CreateApplyAnnotation(info, encoder); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - } - - // Then create the resource and skip the three-way merge - if err := createAndRefresh(info); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - count++ - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") - return nil - } - - // Serialize the current configuration of the object from the server. - current, err := runtime.Encode(encoder, info.Object) - if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("serializing current configuration from:\n%v\nfor:", info), info.Source, err) - } - - // Retrieve the original configuration of the object from the annotation. - original, err := kubectl.GetOriginalConfiguration(info) - if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving original configuration from:\n%v\nfor:", info), info.Source, err) - } - - // Create the versioned struct from the original from the server for - // strategic patch. - // TODO: Move all structs in apply to use raw data. Can be done once - // builder has a RawResult method which delivers raw data instead of - // internal objects. - versionedObject, _, err := decoder.Decode(current, nil, nil) - if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("converting encoded server-side object back to versioned struct:\n%v\nfor:", info), info.Source, err) - } - - // Compute a three way strategic merge patch to send to server. - patch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, versionedObject, true) - if err != nil { - format := "creating patch with:\noriginal:\n%s\nmodified:\n%s\ncurrent:\n%s\nfrom:\n%v\nfor:" - return cmdutil.AddSourceToErr(fmt.Sprintf(format, original, modified, current, info), info.Source, err) - } - - helper := resource.NewHelper(info.Client, info.Mapping) - _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) - if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err) - } - - if cmdutil.ShouldRecord(cmd, info) { - patch, err = cmdutil.ChangeResourcePatch(info, f.Command()) - if err != nil { - return err - } - _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) - if err != nil { - return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err) - } - } - - count++ - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "configured") - return nil - }) - - if err != nil { - return err - } - - if count == 0 { - return fmt.Errorf("no objects passed to apply") - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apply_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apply_test.go deleted file mode 100644 index a46e0699d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/apply_test.go +++ /dev/null @@ -1,317 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "net/http" - "os" - "testing" - - "github.com/ghodss/yaml" - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestApplyExtraArgsFail(t *testing.T) { - buf := bytes.NewBuffer([]byte{}) - - f, _, _ := NewAPIFactory() - c := NewCmdApply(f, buf) - if validateApplyArgs(c, []string{"rc"}) == nil { - t.Fatalf("unexpected non-error") - } -} - -func validateApplyArgs(cmd *cobra.Command, args []string) error { - if len(args) != 0 { - return cmdutil.UsageError(cmd, "Unexpected args: %v", args) - } - return nil -} - -const ( - filenameRC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc.yaml" - filenameSVC = "../../../test/fixtures/pkg/kubectl/cmd/apply/service.yaml" - filenameRCSVC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-service.yaml" -) - -func readBytesFromFile(t *testing.T, filename string) []byte { - file, err := os.Open(filename) - if err != nil { - t.Fatal(err) - } - - data, err := ioutil.ReadAll(file) - if err != nil { - t.Fatal(err) - } - - return data -} - -func readReplicationControllerFromFile(t *testing.T, filename string) *api.ReplicationController { - data := readBytesFromFile(t, filename) - rc := api.ReplicationController{} - // TODO(jackgr): Replace with a call to testapi.Codec().Decode(). - if err := yaml.Unmarshal(data, &rc); err != nil { - t.Fatal(err) - } - - return &rc -} - -func readServiceFromFile(t *testing.T, filename string) *api.Service { - data := readBytesFromFile(t, filename) - svc := api.Service{} - // TODO(jackgr): Replace with a call to testapi.Codec().Decode(). - if err := yaml.Unmarshal(data, &svc); err != nil { - t.Fatal(err) - } - - return &svc -} - -func annotateRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object, kind string) (string, []byte) { - originalAccessor, err := meta.Accessor(originalObj) - if err != nil { - t.Fatal(err) - } - - originalLabels := originalAccessor.GetLabels() - originalLabels["DELETE_ME"] = "DELETE_ME" - originalAccessor.SetLabels(originalLabels) - original, err := json.Marshal(originalObj) - if err != nil { - t.Fatal(err) - } - - currentAccessor, err := meta.Accessor(currentObj) - if err != nil { - t.Fatal(err) - } - - currentAnnotations := currentAccessor.GetAnnotations() - if currentAnnotations == nil { - currentAnnotations = make(map[string]string) - } - currentAnnotations[kubectl.LastAppliedConfigAnnotation] = string(original) - currentAccessor.SetAnnotations(currentAnnotations) - current, err := json.Marshal(currentObj) - if err != nil { - t.Fatal(err) - } - - return currentAccessor.GetName(), current -} - -func readAndAnnotateReplicationController(t *testing.T, filename string) (string, []byte) { - rc1 := readReplicationControllerFromFile(t, filename) - rc2 := readReplicationControllerFromFile(t, filename) - return annotateRuntimeObject(t, rc1, rc2, "ReplicationController") -} - -func readAndAnnotateService(t *testing.T, filename string) (string, []byte) { - svc1 := readServiceFromFile(t, filename) - svc2 := readServiceFromFile(t, filename) - return annotateRuntimeObject(t, svc1, svc2, "Service") -} - -func validatePatchApplication(t *testing.T, req *http.Request) { - patch, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatal(err) - } - - patchMap := map[string]interface{}{} - if err := json.Unmarshal(patch, &patchMap); err != nil { - t.Fatal(err) - } - - annotationsMap := walkMapPath(t, patchMap, []string{"metadata", "annotations"}) - if _, ok := annotationsMap[kubectl.LastAppliedConfigAnnotation]; !ok { - t.Fatalf("patch does not contain annotation:\n%s\n", patch) - } - - labelMap := walkMapPath(t, patchMap, []string{"metadata", "labels"}) - if deleteMe, ok := labelMap["DELETE_ME"]; !ok || deleteMe != nil { - t.Fatalf("patch does not remove deleted key: DELETE_ME:\n%s\n", patch) - } -} - -func walkMapPath(t *testing.T, start map[string]interface{}, path []string) map[string]interface{} { - finish := start - for i := 0; i < len(path); i++ { - var ok bool - finish, ok = finish[path[i]].(map[string]interface{}) - if !ok { - t.Fatalf("key:%s of path:%v not found in map:%v", path[i], path, start) - } - } - - return finish -} - -func TestApplyObject(t *testing.T) { - initTestErrorHandler(t) - nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) - pathRC := "/namespaces/test/replicationcontrollers/" + nameRC - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathRC && m == "GET": - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Body: bodyRC}, nil - case p == pathRC && m == "PATCH": - validatePatchApplication(t, req) - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Body: bodyRC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply(f, buf) - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // uses the name from the file, not the response - expectRC := "replicationcontroller/" + nameRC + "\n" - if buf.String() != expectRC { - t.Fatalf("unexpected output: %s\nexpected: %s", buf.String(), expectRC) - } -} - -func TestApplyNonExistObject(t *testing.T) { - nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) - pathRC := "/namespaces/test/replicationcontrollers" - pathNameRC := pathRC + "/" + nameRC - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathNameRC && m == "GET": - return &http.Response{StatusCode: 404, Body: ioutil.NopCloser(bytes.NewReader(nil))}, nil - case p == pathRC && m == "POST": - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 201, Body: bodyRC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply(f, buf) - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // uses the name from the file, not the response - expectRC := "replicationcontroller/" + nameRC + "\n" - if buf.String() != expectRC { - t.Errorf("unexpected output: %s\nexpected: %s", buf.String(), expectRC) - } -} - -func TestApplyMultipleObjectsAsList(t *testing.T) { - testApplyMultipleObjects(t, true) -} - -func TestApplyMultipleObjectsAsFiles(t *testing.T) { - testApplyMultipleObjects(t, false) -} - -func testApplyMultipleObjects(t *testing.T, asList bool) { - nameRC, currentRC := readAndAnnotateReplicationController(t, filenameRC) - pathRC := "/namespaces/test/replicationcontrollers/" + nameRC - - nameSVC, currentSVC := readAndAnnotateService(t, filenameSVC) - pathSVC := "/namespaces/test/services/" + nameSVC - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == pathRC && m == "GET": - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Body: bodyRC}, nil - case p == pathRC && m == "PATCH": - validatePatchApplication(t, req) - bodyRC := ioutil.NopCloser(bytes.NewReader(currentRC)) - return &http.Response{StatusCode: 200, Body: bodyRC}, nil - case p == pathSVC && m == "GET": - bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) - return &http.Response{StatusCode: 200, Body: bodySVC}, nil - case p == pathSVC && m == "PATCH": - validatePatchApplication(t, req) - bodySVC := ioutil.NopCloser(bytes.NewReader(currentSVC)) - return &http.Response{StatusCode: 200, Body: bodySVC}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdApply(f, buf) - if asList { - cmd.Flags().Set("filename", filenameRCSVC) - } else { - cmd.Flags().Set("filename", filenameRC) - cmd.Flags().Set("filename", filenameSVC) - } - cmd.Flags().Set("output", "name") - - cmd.Run(cmd, []string{}) - - // Names should come from the REST response, NOT the files - expectRC := "replicationcontroller/" + nameRC + "\n" - expectSVC := "service/" + nameSVC + "\n" - // Test both possible orders since output is non-deterministic. - expectOne := expectRC + expectSVC - expectTwo := expectSVC + expectRC - if buf.String() != expectOne && buf.String() != expectTwo { - t.Fatalf("unexpected output: %s\nexpected: %s OR %s", buf.String(), expectOne, expectTwo) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/attach.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/attach.go deleted file mode 100644 index 3150bccae..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/attach.go +++ /dev/null @@ -1,245 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "net/url" - - "github.com/golang/glog" - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/remotecommand" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" - utilerrors "k8s.io/kubernetes/pkg/util/errors" - "k8s.io/kubernetes/pkg/util/interrupt" - "k8s.io/kubernetes/pkg/util/term" -) - -const ( - attach_example = `# Get output from running pod 123456-7890, using the first container by default -kubectl attach 123456-7890 - -# Get output from ruby-container from pod 123456-7890 -kubectl attach 123456-7890 -c ruby-container - -# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890 -# and sends stdout/stderr from 'bash' back to the client -kubectl attach 123456-7890 -c ruby-container -i -t` -) - -func NewCmdAttach(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command { - options := &AttachOptions{ - In: cmdIn, - Out: cmdOut, - Err: cmdErr, - - CommandName: "kubectl attach", - - Attach: &DefaultRemoteAttach{}, - } - cmd := &cobra.Command{ - Use: "attach POD -c CONTAINER", - Short: "Attach to a running container.", - Long: "Attach to a process that is already running inside an existing container.", - Example: attach_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.Complete(f, cmd, args)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.Run()) - }, - } - // TODO support UID - cmd.Flags().StringVarP(&options.ContainerName, "container", "c", "", "Container name. If omitted, the first container in the pod will be chosen") - cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", false, "Pass stdin to the container") - cmd.Flags().BoolVarP(&options.TTY, "tty", "t", false, "Stdin is a TTY") - return cmd -} - -// RemoteAttach defines the interface accepted by the Attach command - provided for test stubbing -type RemoteAttach interface { - Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error -} - -// DefaultRemoteAttach is the standard implementation of attaching -type DefaultRemoteAttach struct{} - -func (*DefaultRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { - exec, err := remotecommand.NewExecutor(config, method, url) - if err != nil { - return err - } - return exec.Stream(remotecommandserver.SupportedStreamingProtocols, stdin, stdout, stderr, tty) -} - -// AttachOptions declare the arguments accepted by the Exec command -type AttachOptions struct { - Namespace string - PodName string - ContainerName string - Stdin bool - TTY bool - CommandName string - - // InterruptParent, if set, is used to handle interrupts while attached - InterruptParent *interrupt.Handler - - In io.Reader - Out io.Writer - Err io.Writer - - Pod *api.Pod - - Attach RemoteAttach - Client *client.Client - Config *restclient.Config -} - -// Complete verifies command line arguments and loads data from the command environment -func (p *AttachOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, argsIn []string) error { - if len(argsIn) == 0 { - return cmdutil.UsageError(cmd, "POD is required for attach") - } - if len(argsIn) > 1 { - return cmdutil.UsageError(cmd, fmt.Sprintf("expected a single argument: POD, saw %d: %s", len(argsIn), argsIn)) - } - p.PodName = argsIn[0] - - namespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } - p.Namespace = namespace - - config, err := f.ClientConfig() - if err != nil { - return err - } - p.Config = config - - client, err := f.Client() - if err != nil { - return err - } - p.Client = client - - return nil -} - -// Validate checks that the provided attach options are specified. -func (p *AttachOptions) Validate() error { - allErrs := []error{} - if len(p.PodName) == 0 { - allErrs = append(allErrs, fmt.Errorf("pod name must be specified")) - } - if p.Out == nil || p.Err == nil { - allErrs = append(allErrs, fmt.Errorf("both output and error output must be provided")) - } - if p.Attach == nil || p.Client == nil || p.Config == nil { - allErrs = append(allErrs, fmt.Errorf("client, client config, and attach must be provided")) - } - return utilerrors.NewAggregate(allErrs) -} - -// Run executes a validated remote execution against a pod. -func (p *AttachOptions) Run() error { - if p.Pod == nil { - pod, err := p.Client.Pods(p.Namespace).Get(p.PodName) - if err != nil { - return err - } - if pod.Status.Phase != api.PodRunning { - return fmt.Errorf("pod %s is not running and cannot be attached to; current phase is %s", p.PodName, pod.Status.Phase) - } - p.Pod = pod - // TODO: convert this to a clean "wait" behavior - } - pod := p.Pod - - // ensure we can recover the terminal while attached - t := term.TTY{Parent: p.InterruptParent} - - // check for TTY - tty := p.TTY - containerToAttach := p.GetContainer(pod) - if tty && !containerToAttach.TTY { - tty = false - fmt.Fprintf(p.Err, "Unable to use a TTY - container %s did not allocate one\n", containerToAttach.Name) - } - if p.Stdin { - t.In = p.In - if tty && !t.IsTerminal() { - tty = false - fmt.Fprintln(p.Err, "Unable to use a TTY - input is not a terminal or the right kind of file") - } - } - t.Raw = tty - - fn := func() error { - if tty { - fmt.Fprintln(p.Out, "\nHit enter for command prompt") - } - // TODO: consider abstracting into a client invocation or client helper - req := p.Client.RESTClient.Post(). - Resource("pods"). - Name(pod.Name). - Namespace(pod.Namespace). - SubResource("attach") - req.VersionedParams(&api.PodAttachOptions{ - Container: containerToAttach.Name, - Stdin: p.In != nil, - Stdout: p.Out != nil, - Stderr: p.Err != nil, - TTY: tty, - }, api.ParameterCodec) - - return p.Attach.Attach("POST", req.URL(), p.Config, p.In, p.Out, p.Err, tty) - } - - if err := t.Safe(fn); err != nil { - return err - } - - if p.Stdin && tty && pod.Spec.RestartPolicy == api.RestartPolicyAlways { - fmt.Fprintf(p.Out, "Session ended, resume using '%s %s -c %s -i -t' command when the pod is running\n", p.CommandName, pod.Name, containerToAttach.Name) - } - return nil -} - -// GetContainer returns the container to attach to, with a fallback. -func (p *AttachOptions) GetContainer(pod *api.Pod) api.Container { - if len(p.ContainerName) > 0 { - for _, container := range pod.Spec.Containers { - if container.Name == p.ContainerName { - return container - } - } - } - - glog.V(4).Infof("defaulting container name to %s", pod.Spec.Containers[0].Name) - return pod.Spec.Containers[0] -} - -// GetContainerName returns the name of the container to attach to, with a fallback. -func (p *AttachOptions) GetContainerName(pod *api.Pod) string { - return p.GetContainer(pod).Name -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/attach_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/attach_test.go deleted file mode 100644 index fcefb74fb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/attach_test.go +++ /dev/null @@ -1,279 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "fmt" - "io" - "net/http" - "net/url" - "strings" - "testing" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -type fakeRemoteAttach struct { - method string - url *url.URL - attachErr error -} - -func (f *fakeRemoteAttach) Attach(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { - f.method = method - f.url = url - return f.attachErr -} - -func TestPodAndContainerAttach(t *testing.T) { - tests := []struct { - args []string - p *AttachOptions - name string - expectError bool - expectedPod string - expectedContainer string - }{ - { - p: &AttachOptions{}, - expectError: true, - name: "empty", - }, - { - p: &AttachOptions{}, - args: []string{"foo", "bar"}, - expectError: true, - name: "too many args", - }, - { - p: &AttachOptions{}, - args: []string{"foo"}, - expectedPod: "foo", - name: "no container, no flags", - }, - { - p: &AttachOptions{ContainerName: "bar"}, - args: []string{"foo"}, - expectedPod: "foo", - expectedContainer: "bar", - name: "container in flag", - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{} - - cmd := &cobra.Command{} - options := test.p - err := options.Complete(f, cmd, test.args) - if test.expectError && err == nil { - t.Errorf("unexpected non-error (%s)", test.name) - } - if !test.expectError && err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.name) - } - if err != nil { - continue - } - if options.PodName != test.expectedPod { - t.Errorf("expected: %s, got: %s (%s)", test.expectedPod, options.PodName, test.name) - } - if options.ContainerName != test.expectedContainer { - t.Errorf("expected: %s, got: %s (%s)", test.expectedContainer, options.ContainerName, test.name) - } - } -} - -func TestAttach(t *testing.T) { - version := testapi.Default.GroupVersion().Version - tests := []struct { - name, version, podPath, attachPath, container string - pod *api.Pod - attachErr bool - }{ - { - name: "pod attach", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - attachPath: "/api/" + version + "/namespaces/test/pods/foo/attach", - pod: attachPod(), - }, - { - name: "pod attach error", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - attachPath: "/api/" + version + "/namespaces/test/pods/foo/attach", - pod: attachPod(), - attachErr: true, - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: test.version}}} - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) - ex := &fakeRemoteAttach{} - if test.attachErr { - ex.attachErr = fmt.Errorf("attach error") - } - params := &AttachOptions{ - ContainerName: "bar", - In: bufIn, - Out: bufOut, - Err: bufErr, - Attach: ex, - } - cmd := &cobra.Command{} - if err := params.Complete(f, cmd, []string{"foo"}); err != nil { - t.Fatal(err) - } - err := params.Run() - if test.attachErr && err != ex.attachErr { - t.Errorf("%s: Unexpected exec error: %v", test.name, err) - continue - } - if !test.attachErr && err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - continue - } - if test.attachErr { - continue - } - if ex.url.Path != test.attachPath { - t.Errorf("%s: Did not get expected path for exec request", test.name) - continue - } - if ex.method != "POST" { - t.Errorf("%s: Did not get method for attach request: %s", test.name, ex.method) - } - if ex.url.Query().Get("container") != "bar" { - t.Errorf("%s: Did not have query parameters: %s", test.name, ex.url.Query()) - } - } -} - -func TestAttachWarnings(t *testing.T) { - version := testapi.Default.GroupVersion().Version - tests := []struct { - name, container, version, podPath, expectedErr, expectedOut string - pod *api.Pod - stdin, tty bool - }{ - { - name: "fallback tty if not supported", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - pod: attachPod(), - stdin: true, - tty: true, - expectedErr: "Unable to use a TTY - container bar did not allocate one", - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Body: body}, nil - default: - t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: test.version}}} - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) - ex := &fakeRemoteAttach{} - params := &AttachOptions{ - ContainerName: test.container, - In: bufIn, - Out: bufOut, - Err: bufErr, - Stdin: test.stdin, - TTY: test.tty, - Attach: ex, - } - cmd := &cobra.Command{} - if err := params.Complete(f, cmd, []string{"foo"}); err != nil { - t.Fatal(err) - } - if err := params.Run(); err != nil { - t.Fatal(err) - } - - if test.stdin && test.tty { - if !test.pod.Spec.Containers[0].TTY { - if !strings.Contains(bufErr.String(), test.expectedErr) { - t.Errorf("%s: Expected TTY fallback warning for attach request: %s", test.name, bufErr.String()) - continue - } - } - } - } -} - -func attachPod() *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{ - { - Name: "bar", - }, - }, - }, - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/autoscale.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/autoscale.go deleted file mode 100644 index cb40c6def..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/autoscale.go +++ /dev/null @@ -1,204 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - utilerrors "k8s.io/kubernetes/pkg/util/errors" - - "github.com/spf13/cobra" -) - -// AutoscaleOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type AutoscaleOptions struct { - Filenames []string - Recursive bool -} - -const ( - autoscaleLong = `Creates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster. - -Looks up a Deployment, ReplicaSet, or ReplicationController by name and creates an autoscaler that uses the given resource as a reference. -An autoscaler can automatically increase or decrease number of pods deployed within the system as needed.` - - autoscaleExample = `# Auto scale a deployment "foo", with the number of pods between 2 to 10, target CPU utilization at a default value that server applies: -kubectl autoscale deployment foo --min=2 --max=10 - -# Auto scale a replication controller "foo", with the number of pods between 1 to 5, target CPU utilization at 80%: -kubectl autoscale rc foo --max=5 --cpu-percent=80` -) - -func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &AutoscaleOptions{} - - cmd := &cobra.Command{ - Use: "autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS [--cpu-percent=CPU] [flags]", - Short: "Auto-scale a Deployment, ReplicaSet, or ReplicationController", - Long: autoscaleLong, - Example: autoscaleExample, - Run: func(cmd *cobra.Command, args []string) { - err := RunAutoscale(f, out, cmd, args, options) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().String("generator", "horizontalpodautoscaler/v1beta1", "The name of the API generator to use. Currently there is only 1 generator.") - cmd.Flags().Int("min", -1, "The lower limit for the number of pods that can be set by the autoscaler. If it's not specified or negative, the server will apply a default value.") - cmd.Flags().Int("max", -1, "The upper limit for the number of pods that can be set by the autoscaler. Required.") - cmd.MarkFlagRequired("max") - cmd.Flags().Int("cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, the server will apply a default value.")) - cmd.Flags().String("name", "", "The name for the newly created object. If not specified, the name of the input resource will be used.") - cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without creating it.") - usage := "Filename, directory, or URL to a file identifying the resource to autoscale." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *AutoscaleOptions) error { - namespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - // validate flags - if err := validateFlags(cmd); err != nil { - return err - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - ResourceTypeOrNameArgs(false, args...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - // Get the generator, setup and validate all required parameters - generatorName := cmdutil.GetFlagString(cmd, "generator") - generators := f.Generators("autoscale") - generator, found := generators[generatorName] - if !found { - return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) - } - names := generator.ParamNames() - - count := 0 - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - mapping := info.ResourceMapping() - if err := f.CanBeAutoscaled(mapping.GroupVersionKind.GroupKind()); err != nil { - return err - } - - name := info.Name - params := kubectl.MakeParams(cmd, names) - params["default-name"] = name - - params["scaleRef-kind"] = mapping.GroupVersionKind.Kind - params["scaleRef-name"] = name - params["scaleRef-apiVersion"] = mapping.GroupVersionKind.GroupVersion().String() - - if err = kubectl.ValidateParams(names, params); err != nil { - return err - } - // Check for invalid flags used against the present generator. - if err := kubectl.EnsureFlagsValid(cmd, generators, generatorName); err != nil { - return err - } - - // Generate new object - object, err := generator.Generate(params) - if err != nil { - return err - } - - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - Decoder: f.Decoder(true), - } - hpa, err := resourceMapper.InfoForObject(object, nil) - if err != nil { - return err - } - if cmdutil.ShouldRecord(cmd, hpa) { - if err := cmdutil.RecordChangeCause(hpa.Object, f.Command()); err != nil { - return err - } - object = hpa.Object - } - // TODO: extract this flag to a central location, when such a location exists. - if cmdutil.GetFlagBool(cmd, "dry-run") { - return f.PrintObject(cmd, mapper, object, out) - } - - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), hpa, f.JSONEncoder()); err != nil { - return err - } - - object, err = resource.NewHelper(hpa.Client, hpa.Mapping).Create(namespace, false, object) - if err != nil { - return err - } - - count++ - if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return f.PrintObject(cmd, mapper, object, out) - } - - cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, "autoscaled") - return nil - }) - if err != nil { - return err - } - if count == 0 { - return fmt.Errorf("no objects passed to autoscale") - } - return nil -} - -func validateFlags(cmd *cobra.Command) error { - errs := []error{} - max, min, cpu := cmdutil.GetFlagInt(cmd, "max"), cmdutil.GetFlagInt(cmd, "min"), cmdutil.GetFlagInt(cmd, "cpu-percent") - if max < 1 || max < min { - errs = append(errs, fmt.Errorf("--max=MAXPODS is required, and must be at least 1 and --min=MINPODS")) - } - if cpu > 100 { - errs = append(errs, fmt.Errorf("CPU utilization (%%) cannot exceed 100")) - } - return utilerrors.NewAggregate(errs) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo.go deleted file mode 100644 index 9fc303586..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/clusterinfo.go +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "os" - "strconv" - - "k8s.io/kubernetes/pkg/api" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - - "github.com/daviddengcn/go-colortext" - "github.com/spf13/cobra" -) - -func NewCmdClusterInfo(f *cmdutil.Factory, out io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "cluster-info", - // clusterinfo is deprecated. - Aliases: []string{"clusterinfo"}, - Short: "Display cluster info", - Long: "Display addresses of the master and services with label kubernetes.io/cluster-service=true", - Run: func(cmd *cobra.Command, args []string) { - err := RunClusterInfo(f, out, cmd) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func RunClusterInfo(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { - if len(os.Args) > 1 && os.Args[1] == "clusterinfo" { - printDeprecationWarning("cluster-info", "clusterinfo") - } - - client, err := f.ClientConfig() - if err != nil { - return err - } - printService(out, "Kubernetes master", client.Host) - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - cmdNamespace := cmdutil.GetFlagString(cmd, "namespace") - if cmdNamespace == "" { - cmdNamespace = api.NamespaceSystem - } - - // TODO use generalized labels once they are implemented (#341) - b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace(). - SelectorParam("kubernetes.io/cluster-service=true"). - ResourceTypeOrNameArgs(false, []string{"services"}...). - Latest() - b.Do().Visit(func(r *resource.Info, err error) error { - if err != nil { - return err - } - services := r.Object.(*api.ServiceList).Items - for _, service := range services { - var link string - if len(service.Status.LoadBalancer.Ingress) > 0 { - ingress := service.Status.LoadBalancer.Ingress[0] - ip := ingress.IP - if ip == "" { - ip = ingress.Hostname - } - for _, port := range service.Spec.Ports { - link += "http://" + ip + ":" + strconv.Itoa(int(port.Port)) + " " - } - } else { - if len(client.GroupVersion.Group) == 0 { - link = client.Host + "/api/" + client.GroupVersion.Version + "/proxy/namespaces/" + service.ObjectMeta.Namespace + "/services/" + service.ObjectMeta.Name - } else { - link = client.Host + "/api/" + client.GroupVersion.Group + "/" + client.GroupVersion.Version + "/proxy/namespaces/" + service.ObjectMeta.Namespace + "/services/" + service.ObjectMeta.Name - - } - } - name := service.ObjectMeta.Labels["kubernetes.io/name"] - if len(name) == 0 { - name = service.ObjectMeta.Name - } - printService(out, name, link) - } - return nil - }) - return nil - - // TODO consider printing more information about cluster -} - -func printService(out io.Writer, name, link string) { - ct.ChangeColor(ct.Green, false, ct.None, false) - fmt.Fprint(out, name) - ct.ResetColor() - fmt.Fprintf(out, " is running at ") - ct.ChangeColor(ct.Yellow, false, ct.None, false) - fmt.Fprint(out, link) - ct.ResetColor() - fmt.Fprintln(out, "") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go deleted file mode 100644 index 6225a4573..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go +++ /dev/null @@ -1,253 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "io" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config" - "k8s.io/kubernetes/pkg/kubectl/cmd/rollout" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/util/flag" - - "github.com/spf13/cobra" -) - -const ( - bash_completion_func = `# call kubectl get $1, -__kubectl_namespace_flag() -{ - local ret two_word_ns - ret="" - two_word_ns=false - for w in "${words[@]}"; do - if [ "$two_word_ns" = true ]; then - ret="--namespace=${w}" - two_word_ns=false - continue - fi - case "${w}" in - --namespace=*) - ret=${w} - ;; - --namespace) - two_word_ns=true - ;; - --all-namespaces) - ret=${w} - ;; - esac - done - echo $ret -} - -__kubectl_get_namespaces() -{ - local template kubectl_out - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) ) - fi -} - -__kubectl_parse_get() -{ - local template - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - local kubectl_out - if kubectl_out=$(kubectl get $(__kubectl_namespace_flag) -o template --template="${template}" "$1" 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) ) - fi -} - -__kubectl_get_resource() -{ - if [[ ${#nouns[@]} -eq 0 ]]; then - return 1 - fi - __kubectl_parse_get "${nouns[${#nouns[@]} -1]}" -} - -__kubectl_get_resource_pod() -{ - __kubectl_parse_get "pod" -} - -__kubectl_get_resource_rc() -{ - __kubectl_parse_get "rc" -} - -# $1 is the name of the pod we want to get the list of containers inside -__kubectl_get_containers() -{ - local template - template="{{ range .spec.containers }}{{ .name }} {{ end }}" - __debug "${FUNCNAME} nouns are ${nouns[*]}" - - local len="${#nouns[@]}" - if [[ ${len} -ne 1 ]]; then - return - fi - local last=${nouns[${len} -1]} - local kubectl_out - if kubectl_out=$(kubectl get $(__kubectl_namespace_flag) -o template --template="${template}" pods "${last}" 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) ) - fi -} - -# Require both a pod and a container to be specified -__kubectl_require_pod_and_container() -{ - if [[ ${#nouns[@]} -eq 0 ]]; then - __kubectl_parse_get pods - return 0 - fi; - __kubectl_get_containers - return 0 -} - -__custom_func() { - case ${last_command} in - kubectl_get | kubectl_describe | kubectl_delete | kubectl_label | kubectl_stop | kubectl_edit | kubectl_patch |\ - kubectl_annotate | kubectl_expose) - __kubectl_get_resource - return - ;; - kubectl_logs) - __kubectl_require_pod_and_container - return - ;; - kubectl_exec) - __kubectl_get_resource_pod - return - ;; - kubectl_rolling-update) - __kubectl_get_resource_rc - return - ;; - *) - ;; - esac -} -` - - // If you add a resource to this list, please also take a look at pkg/kubectl/kubectl.go - // and add a short forms entry in expandResourceShortcut() when appropriate. - valid_resources = `Valid resource types include: - * componentstatuses (aka 'cs') - * configmaps - * daemonsets (aka 'ds') - * deployments - * events (aka 'ev') - * endpoints (aka 'ep') - * horizontalpodautoscalers (aka 'hpa') - * ingress (aka 'ing') - * jobs - * limitranges (aka 'limits') - * nodes (aka 'no') - * namespaces (aka 'ns') - * pods (aka 'po') - * persistentvolumes (aka 'pv') - * persistentvolumeclaims (aka 'pvc') - * quota - * resourcequotas (aka 'quota') - * replicasets (aka 'rs') - * replicationcontrollers (aka 'rc') - * secrets - * serviceaccounts (aka 'sa') - * services (aka 'svc') -` -) - -// NewKubectlCommand creates the `kubectl` command and its nested children. -func NewKubectlCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command { - // Parent command to which all subcommands are added. - cmds := &cobra.Command{ - Use: "kubectl", - Short: "kubectl controls the Kubernetes cluster manager", - Long: `kubectl controls the Kubernetes cluster manager. - -Find more information at https://github.com/kubernetes/kubernetes.`, - Run: runHelp, - BashCompletionFunction: bash_completion_func, - } - - f.BindFlags(cmds.PersistentFlags()) - f.BindExternalFlags(cmds.PersistentFlags()) - - // From this point and forward we get warnings on flags that contain "_" separators - cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc) - - cmds.AddCommand(NewCmdGet(f, out)) - cmds.AddCommand(NewCmdDescribe(f, out)) - cmds.AddCommand(NewCmdCreate(f, out)) - cmds.AddCommand(NewCmdReplace(f, out)) - cmds.AddCommand(NewCmdPatch(f, out)) - cmds.AddCommand(NewCmdDelete(f, out)) - cmds.AddCommand(NewCmdEdit(f, out, err)) - cmds.AddCommand(NewCmdApply(f, out)) - - cmds.AddCommand(NewCmdNamespace(out)) - cmds.AddCommand(NewCmdLogs(f, out)) - cmds.AddCommand(NewCmdRollingUpdate(f, out)) - cmds.AddCommand(NewCmdScale(f, out)) - cmds.AddCommand(NewCmdCordon(f, out)) - cmds.AddCommand(NewCmdDrain(f, out)) - cmds.AddCommand(NewCmdUncordon(f, out)) - - cmds.AddCommand(NewCmdAttach(f, in, out, err)) - cmds.AddCommand(NewCmdExec(f, in, out, err)) - cmds.AddCommand(NewCmdPortForward(f, out, err)) - cmds.AddCommand(NewCmdProxy(f, out)) - - cmds.AddCommand(NewCmdRun(f, in, out, err)) - cmds.AddCommand(NewCmdStop(f, out)) - cmds.AddCommand(NewCmdExposeService(f, out)) - cmds.AddCommand(NewCmdAutoscale(f, out)) - cmds.AddCommand(rollout.NewCmdRollout(f, out)) - - cmds.AddCommand(NewCmdLabel(f, out)) - cmds.AddCommand(NewCmdAnnotate(f, out)) - - cmds.AddCommand(cmdconfig.NewCmdConfig(clientcmd.NewDefaultPathOptions(), out)) - cmds.AddCommand(NewCmdClusterInfo(f, out)) - cmds.AddCommand(NewCmdApiVersions(f, out)) - cmds.AddCommand(NewCmdVersion(f, out)) - cmds.AddCommand(NewCmdExplain(f, out)) - cmds.AddCommand(NewCmdConvert(f, out)) - - if cmds.Flag("namespace").Annotations == nil { - cmds.Flag("namespace").Annotations = map[string][]string{} - } - cmds.Flag("namespace").Annotations[cobra.BashCompCustom] = append( - cmds.Flag("namespace").Annotations[cobra.BashCompCustom], - "__kubectl_get_namespaces", - ) - - return cmds -} - -func runHelp(cmd *cobra.Command, args []string) { - cmd.Help() -} - -func printDeprecationWarning(command, alias string) { - glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_test.go deleted file mode 100644 index 500b7a7d2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/cmd_test.go +++ /dev/null @@ -1,799 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer" - "k8s.io/kubernetes/pkg/util" -) - -func initTestErrorHandler(t *testing.T) { - cmdutil.BehaviorOnFatal(func(str string) { - t.Errorf("Error running command: %s", str) - }) -} - -type internalType struct { - Kind string - APIVersion string - - Name string -} - -type externalType struct { - Kind string `json:"kind"` - APIVersion string `json:"apiVersion"` - - Name string `json:"name"` -} - -type ExternalType2 struct { - Kind string `json:"kind"` - APIVersion string `json:"apiVersion"` - - Name string `json:"name"` -} - -func (obj *internalType) GetObjectKind() unversioned.ObjectKind { return obj } -func (obj *internalType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { - obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() -} -func (obj *internalType) GroupVersionKind() *unversioned.GroupVersionKind { - return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) -} -func (obj *externalType) GetObjectKind() unversioned.ObjectKind { return obj } -func (obj *externalType) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { - obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() -} -func (obj *externalType) GroupVersionKind() *unversioned.GroupVersionKind { - return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) -} -func (obj *ExternalType2) GetObjectKind() unversioned.ObjectKind { return obj } -func (obj *ExternalType2) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { - obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind() -} -func (obj *ExternalType2) GroupVersionKind() *unversioned.GroupVersionKind { - return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind) -} - -var versionErr = errors.New("not a version") - -func versionErrIfFalse(b bool) error { - if b { - return nil - } - return versionErr -} - -var validVersion = testapi.Default.GroupVersion().Version -var internalGV = unversioned.GroupVersion{Group: "apitest", Version: runtime.APIVersionInternal} -var unlikelyGV = unversioned.GroupVersion{Group: "apitest", Version: "unlikelyversion"} -var validVersionGV = unversioned.GroupVersion{Group: "apitest", Version: validVersion} - -func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { - scheme := runtime.NewScheme() - scheme.AddKnownTypeWithName(internalGV.WithKind("Type"), &internalType{}) - scheme.AddKnownTypeWithName(unlikelyGV.WithKind("Type"), &externalType{}) - //This tests that kubectl will not confuse the external scheme with the internal scheme, even when they accidentally have versions of the same name. - scheme.AddKnownTypeWithName(validVersionGV.WithKind("Type"), &ExternalType2{}) - - codecs := serializer.NewCodecFactory(scheme) - codec := codecs.LegacyCodec(unlikelyGV) - mapper := meta.NewDefaultRESTMapper([]unversioned.GroupVersion{unlikelyGV, validVersionGV}, func(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) { - return &meta.VersionInterfaces{ - ObjectConvertor: scheme, - MetadataAccessor: meta.NewAccessor(), - }, versionErrIfFalse(version == validVersionGV || version == unlikelyGV) - }) - for _, gv := range []unversioned.GroupVersion{unlikelyGV, validVersionGV} { - for kind := range scheme.KnownTypes(gv) { - gvk := gv.WithKind(kind) - - scope := meta.RESTScopeNamespace - mapper.Add(gvk, scope) - } - } - - return scheme, mapper, codec -} - -type testPrinter struct { - Objects []runtime.Object - Err error -} - -func (t *testPrinter) PrintObj(obj runtime.Object, out io.Writer) error { - t.Objects = append(t.Objects, obj) - fmt.Fprintf(out, "%#v", obj) - return t.Err -} - -// TODO: implement HandledResources() -func (t *testPrinter) HandledResources() []string { - return []string{} -} - -type testDescriber struct { - Name, Namespace string - Settings kubectl.DescriberSettings - Output string - Err error -} - -func (t *testDescriber) Describe(namespace, name string, describerSettings kubectl.DescriberSettings) (output string, err error) { - t.Namespace, t.Name = namespace, name - t.Settings = describerSettings - return t.Output, t.Err -} - -type testFactory struct { - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - Client kubectl.RESTClient - Describer kubectl.Describer - Printer kubectl.ResourcePrinter - Validator validation.Schema - Namespace string - ClientConfig *restclient.Config - Err error -} - -func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { - scheme, mapper, codec := newExternalScheme() - t := &testFactory{ - Validator: validation.NullSchema{}, - Mapper: mapper, - Typer: scheme, - } - return &cmdutil.Factory{ - Object: func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) { - priorityRESTMapper := meta.PriorityRESTMapper{ - Delegate: t.Mapper, - ResourcePriority: []unversioned.GroupVersionResource{ - {Group: meta.AnyGroup, Version: "v1", Resource: meta.AnyResource}, - }, - KindPriority: []unversioned.GroupVersionKind{ - {Group: meta.AnyGroup, Version: "v1", Kind: meta.AnyKind}, - }, - } - return priorityRESTMapper, t.Typer - }, - ClientForMapping: func(*meta.RESTMapping) (resource.RESTClient, error) { - return t.Client, t.Err - }, - Decoder: func(bool) runtime.Decoder { - return codec - }, - JSONEncoder: func() runtime.Encoder { - return codec - }, - Describer: func(*meta.RESTMapping) (kubectl.Describer, error) { - return t.Describer, t.Err - }, - Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, showLabels bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error) { - return t.Printer, t.Err - }, - Validator: func(validate bool, cacheDir string) (validation.Schema, error) { - return t.Validator, t.Err - }, - DefaultNamespace: func() (string, bool, error) { - return t.Namespace, false, t.Err - }, - ClientConfig: func() (*restclient.Config, error) { - return t.ClientConfig, t.Err - }, - }, t, codec -} - -func NewMixedFactory(apiClient resource.RESTClient) (*cmdutil.Factory, *testFactory, runtime.Codec) { - f, t, c := NewTestFactory() - var multiRESTMapper meta.MultiRESTMapper - multiRESTMapper = append(multiRESTMapper, t.Mapper) - multiRESTMapper = append(multiRESTMapper, testapi.Default.RESTMapper()) - f.Object = func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) { - priorityRESTMapper := meta.PriorityRESTMapper{ - Delegate: multiRESTMapper, - ResourcePriority: []unversioned.GroupVersionResource{ - {Group: meta.AnyGroup, Version: "v1", Resource: meta.AnyResource}, - }, - KindPriority: []unversioned.GroupVersionKind{ - {Group: meta.AnyGroup, Version: "v1", Kind: meta.AnyKind}, - }, - } - return priorityRESTMapper, runtime.MultiObjectTyper{t.Typer, api.Scheme} - } - f.ClientForMapping = func(m *meta.RESTMapping) (resource.RESTClient, error) { - if m.ObjectConvertor == api.Scheme { - return apiClient, t.Err - } - return t.Client, t.Err - } - return f, t, c -} - -func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { - t := &testFactory{ - Validator: validation.NullSchema{}, - } - - f := &cmdutil.Factory{ - Object: func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) { - return testapi.Default.RESTMapper(), api.Scheme - }, - Client: func() (*client.Client, error) { - // Swap out the HTTP client out of the client with the fake's version. - fakeClient := t.Client.(*fake.RESTClient) - c := client.NewOrDie(t.ClientConfig) - c.Client = fakeClient.Client - c.ExtensionsClient.Client = fakeClient.Client - return c, t.Err - }, - ClientForMapping: func(*meta.RESTMapping) (resource.RESTClient, error) { - return t.Client, t.Err - }, - Decoder: func(bool) runtime.Decoder { - return testapi.Default.Codec() - }, - JSONEncoder: func() runtime.Encoder { - return testapi.Default.Codec() - }, - Describer: func(*meta.RESTMapping) (kubectl.Describer, error) { - return t.Describer, t.Err - }, - Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, showAll bool, showLabels bool, absoluteTimestamps bool, columnLabels []string) (kubectl.ResourcePrinter, error) { - return t.Printer, t.Err - }, - Validator: func(validate bool, cacheDir string) (validation.Schema, error) { - return t.Validator, t.Err - }, - DefaultNamespace: func() (string, bool, error) { - return t.Namespace, false, t.Err - }, - ClientConfig: func() (*restclient.Config, error) { - return t.ClientConfig, t.Err - }, - Generators: func(cmdName string) map[string]kubectl.Generator { - return cmdutil.DefaultGenerators(cmdName) - }, - LogsForObject: func(object, options runtime.Object) (*restclient.Request, error) { - fakeClient := t.Client.(*fake.RESTClient) - c := client.NewOrDie(t.ClientConfig) - c.Client = fakeClient.Client - - switch t := object.(type) { - case *api.Pod: - opts, ok := options.(*api.PodLogOptions) - if !ok { - return nil, errors.New("provided options object is not a PodLogOptions") - } - return c.Pods(t.Namespace).GetLogs(t.Name, opts), nil - default: - fqKind, err := api.Scheme.ObjectKind(object) - if err != nil { - return nil, err - } - return nil, fmt.Errorf("cannot get the logs from %v", fqKind) - } - }, - } - rf := cmdutil.NewFactory(nil) - f.MapBasedSelectorForObject = rf.MapBasedSelectorForObject - f.PortsForObject = rf.PortsForObject - f.LabelsForObject = rf.LabelsForObject - f.CanBeExposed = rf.CanBeExposed - return f, t, testapi.Default.Codec() -} - -func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj)))) -} - -func stringBody(body string) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(body))) -} - -// TODO(jlowdermilk): refactor the Factory so we can test client versions properly, -// with different client/server version skew scenarios. -// Verify that resource.RESTClients constructed from a factory respect mapping.APIVersion -//func TestClientVersions(t *testing.T) { -// f := cmdutil.NewFactory(nil) -// -// version := testapi.Default.Version() -// mapping := &meta.RESTMapping{ -// APIVersion: version, -// } -// c, err := f.ClientForMapping(mapping) -// if err != nil { -// t.Errorf("unexpected error: %v", err) -// } -// client := c.(*client.RESTClient) -// if client.APIVersion() != version { -// t.Errorf("unexpected Client APIVersion: %s %v", client.APIVersion, client) -// } -//} - -func Example_printReplicationControllerWithNamespace() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, false, false, []string{}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - ctrl := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "beep", - Labels: map[string]string{"foo": "bar"}, - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - }, - }, - }, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 1, - }, - } - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, ctrl, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAMESPACE NAME DESIRED CURRENT AGE - // beep foo 1 1 10y -} - -func Example_printMultiContainersReplicationControllerWithWide() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, false, true, false, false, false, []string{}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - ctrl := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar"}, - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - { - Name: "foo2", - Image: "someimage2", - }, - }, - }, - }, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 1, - }, - } - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, ctrl, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME DESIRED CURRENT AGE CONTAINER(S) IMAGE(S) SELECTOR - // foo 1 1 10y foo,foo2 someimage,someimage2 foo=bar -} - -func Example_printReplicationController() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, false, false, false, []string{}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - ctrl := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar"}, - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - { - Name: "foo2", - Image: "someimage", - }, - }, - }, - }, - }, - Status: api.ReplicationControllerStatus{ - Replicas: 1, - }, - } - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, ctrl, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME DESIRED CURRENT AGE - // foo 1 1 10y -} - -func Example_printPodWithWideFormat() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, false, true, false, false, false, []string{}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - nodeName := "kubernetes-minion-abcd" - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - } - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, pod, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME READY STATUS RESTARTS AGE NODE - // test1 1/2 podPhase 6 10y kubernetes-minion-abcd -} - -func Example_printPodWithShowLabels() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, false, true, false, []string{}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - nodeName := "kubernetes-minion-abcd" - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - Labels: map[string]string{ - "l1": "key", - "l2": "value", - }, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - } - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, pod, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME READY STATUS RESTARTS AGE LABELS - // test1 1/2 podPhase 6 10y l1=key,l2=value -} - -func newAllPhasePodList() *api.PodList { - nodeName := "kubernetes-minion-abcd" - return &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "test1", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: api.PodPending, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "test2", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: api.PodRunning, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "test3", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: api.PodSucceeded, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "test4", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: api.PodFailed, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "test5", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: api.PodSpec{ - Containers: make([]api.Container, 2), - NodeName: nodeName, - }, - Status: api.PodStatus{ - Phase: api.PodUnknown, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }}, - } -} - -func Example_printPodHideTerminated() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, false, false, false, []string{}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - podList := newAllPhasePodList() - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, podList, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME READY STATUS RESTARTS AGE - // test1 1/2 Pending 6 10y - // test2 1/2 Running 6 10y - // test5 1/2 Unknown 6 10y -} - -func Example_printPodShowAll() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, false, false, true, false, false, []string{}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - podList := newAllPhasePodList() - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, podList, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // NAME READY STATUS RESTARTS AGE - // test1 1/2 Pending 6 10y - // test2 1/2 Running 6 10y - // test3 1/2 Succeeded 6 10y - // test4 1/2 Failed 6 10y - // test5 1/2 Unknown 6 10y -} - -func Example_printServiceWithNamespacesAndLabels() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false, true, false, false, false, false, []string{"l1"}) - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: nil, - } - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - svc := &api.ServiceList{ - Items: []api.Service{ - { - ObjectMeta: api.ObjectMeta{ - Name: "svc1", - Namespace: "ns1", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - Labels: map[string]string{ - "l1": "value", - }, - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - {Protocol: "UDP", Port: 53}, - {Protocol: "TCP", Port: 53}, - }, - Selector: map[string]string{ - "s": "magic", - }, - ClusterIP: "10.1.1.1", - }, - Status: api.ServiceStatus{}, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "svc2", - Namespace: "ns2", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - Labels: map[string]string{ - "l1": "dolla-bill-yall", - }, - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - {Protocol: "TCP", Port: 80}, - {Protocol: "TCP", Port: 8080}, - }, - Selector: map[string]string{ - "s": "kazam", - }, - ClusterIP: "10.1.1.2", - }, - Status: api.ServiceStatus{}, - }}, - } - ld := util.NewLineDelimiter(os.Stdout, "|") - defer ld.Flush() - - mapper, _ := f.Object(false) - err := f.PrintObject(cmd, mapper, svc, ld) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // |NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE L1| - // |ns1 svc1 10.1.1.1 53/UDP,53/TCP 10y value| - // |ns2 svc2 10.1.1.2 80/TCP,8080/TCP 10y dolla-bill-yall| - // || -} - -func TestNormalizationFuncGlobalExistence(t *testing.T) { - // This test can be safely deleted when we will not support multiple flag formats - root := NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr) - - if root.Parent() != nil { - t.Fatal("We expect the root command to be returned") - } - if root.GlobalNormalizationFunc() == nil { - t.Fatal("We expect that root command has a global normalization function") - } - - if reflect.ValueOf(root.GlobalNormalizationFunc()).Pointer() != reflect.ValueOf(root.Flags().GetNormalizeFunc()).Pointer() { - t.Fatal("root command seems to have a wrong normalization function") - } - - sub := root - for sub.HasSubCommands() { - sub = sub.Commands()[0] - } - - // In case of failure of this test check this PR: spf13/cobra#110 - if reflect.ValueOf(sub.Flags().GetNormalizeFunc()).Pointer() != reflect.ValueOf(root.Flags().GetNormalizeFunc()).Pointer() { - t.Fatal("child and root commands should have the same normalization functions") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go deleted file mode 100644 index a28563468..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config.go +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "io" - "path" - "strconv" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" -) - -func NewCmdConfig(pathOptions *clientcmd.PathOptions, out io.Writer) *cobra.Command { - if len(pathOptions.ExplicitFileFlag) == 0 { - pathOptions.ExplicitFileFlag = clientcmd.RecommendedConfigPathFlag - } - - cmd := &cobra.Command{ - Use: "config SUBCOMMAND", - Short: "config modifies kubeconfig files", - Long: `config modifies kubeconfig files using subcommands like "kubectl config set current-context my-context" - -The loading order follows these rules: -1. If the --` + pathOptions.ExplicitFileFlag + ` flag is set, then only that file is loaded. The flag may only be set once and no merging takes place. -2. If $` + pathOptions.EnvVar + ` environment variable is set, then it is used a list of paths (normal path delimitting rules for your system). These paths are merged together. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list. -3. Otherwise, ` + path.Join("${HOME}", pathOptions.GlobalFileSubpath) + ` is used and no merging takes place. -`, - Run: func(cmd *cobra.Command, args []string) { - cmd.Help() - }, - } - - // file paths are common to all sub commands - cmd.PersistentFlags().StringVar(&pathOptions.LoadingRules.ExplicitPath, pathOptions.ExplicitFileFlag, pathOptions.LoadingRules.ExplicitPath, "use a particular kubeconfig file") - - cmd.AddCommand(NewCmdConfigView(out, pathOptions)) - cmd.AddCommand(NewCmdConfigSetCluster(out, pathOptions)) - cmd.AddCommand(NewCmdConfigSetAuthInfo(out, pathOptions)) - cmd.AddCommand(NewCmdConfigSetContext(out, pathOptions)) - cmd.AddCommand(NewCmdConfigSet(out, pathOptions)) - cmd.AddCommand(NewCmdConfigUnset(out, pathOptions)) - cmd.AddCommand(NewCmdConfigCurrentContext(out, pathOptions)) - cmd.AddCommand(NewCmdConfigUseContext(out, pathOptions)) - - return cmd -} - -func toBool(propertyValue string) (bool, error) { - boolValue := false - if len(propertyValue) != 0 { - var err error - boolValue, err = strconv.ParseBool(propertyValue) - if err != nil { - return false, err - } - } - - return boolValue, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config_test.go deleted file mode 100644 index 33ba5f475..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/config_test.go +++ /dev/null @@ -1,851 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "path" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/util/diff" -) - -func newRedFederalCowHammerConfig() clientcmdapi.Config { - return clientcmdapi.Config{ - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "red-user": {Token: "red-token"}}, - Clusters: map[string]*clientcmdapi.Cluster{ - "cow-cluster": {Server: "http://cow.org:8080"}}, - Contexts: map[string]*clientcmdapi.Context{ - "federal-context": {AuthInfo: "red-user", Cluster: "cow-cluster"}}, - CurrentContext: "federal-context", - } -} - -func Example_view() { - expectedConfig := newRedFederalCowHammerConfig() - test := configCommandTest{ - args: []string{"view"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - output := test.run(nil) - fmt.Printf("%v", output) - // Output: - // apiVersion: v1 - // clusters: - // - cluster: - // server: http://cow.org:8080 - // name: cow-cluster - // contexts: - // - context: - // cluster: cow-cluster - // user: red-user - // name: federal-context - // current-context: federal-context - // kind: Config - // preferences: {} - // users: - // - name: red-user - // user: - // token: red-token -} - -func TestCurrentContext(t *testing.T) { - startingConfig := newRedFederalCowHammerConfig() - test := configCommandTest{ - args: []string{"current-context"}, - startingConfig: startingConfig, - expectedConfig: startingConfig, - expectedOutputs: []string{startingConfig.CurrentContext}, - } - test.run(t) -} - -func TestSetCurrentContext(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - startingConfig := newRedFederalCowHammerConfig() - - newContextName := "the-new-context" - - startingConfig.Contexts[newContextName] = clientcmdapi.NewContext() - expectedConfig.Contexts[newContextName] = clientcmdapi.NewContext() - - expectedConfig.CurrentContext = newContextName - - test := configCommandTest{ - args: []string{"use-context", "the-new-context"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestSetNonExistentContext(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - test := configCommandTest{ - args: []string{"use-context", "non-existent-config"}, - startingConfig: expectedConfig, - expectedConfig: expectedConfig, - expectedOutputs: []string{`no context exists with the name: "non-existent-config"`}, - } - test.run(t) -} - -func TestSetIntoExistingStruct(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.AuthInfos["red-user"].Password = "new-path-value" - test := configCommandTest{ - args: []string{"set", "users.red-user.password", "new-path-value"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestSetWithPathPrefixIntoExistingStruct(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["cow-cluster"].Server = "http://cow.org:8080/foo/baz" - test := configCommandTest{ - args: []string{"set", "clusters.cow-cluster.server", "http://cow.org:8080/foo/baz"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) - - dc := clientcmd.NewDefaultClientConfig(expectedConfig, &clientcmd.ConfigOverrides{}) - dcc, err := dc.ClientConfig() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - expectedHost := "http://cow.org:8080/foo/baz" - if expectedHost != dcc.Host { - t.Fatalf("expected client.Config.Host = %q instead of %q", expectedHost, dcc.Host) - } -} - -func TestUnsetStruct(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - delete(expectedConfig.AuthInfos, "red-user") - test := configCommandTest{ - args: []string{"unset", "users.red-user"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestUnsetField(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.AuthInfos["red-user"] = clientcmdapi.NewAuthInfo() - test := configCommandTest{ - args: []string{"unset", "users.red-user.token"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestSetIntoNewStruct(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - cluster := clientcmdapi.NewCluster() - cluster.Server = "new-server-value" - expectedConfig.Clusters["big-cluster"] = cluster - test := configCommandTest{ - args: []string{"set", "clusters.big-cluster.server", "new-server-value"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestSetBoolean(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - cluster := clientcmdapi.NewCluster() - cluster.InsecureSkipTLSVerify = true - expectedConfig.Clusters["big-cluster"] = cluster - test := configCommandTest{ - args: []string{"set", "clusters.big-cluster.insecure-skip-tls-verify", "true"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestSetIntoNewConfig(t *testing.T) { - expectedConfig := *clientcmdapi.NewConfig() - context := clientcmdapi.NewContext() - context.AuthInfo = "fake-user" - expectedConfig.Contexts["new-context"] = context - test := configCommandTest{ - args: []string{"set", "contexts.new-context.user", "fake-user"}, - startingConfig: *clientcmdapi.NewConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestNewEmptyAuth(t *testing.T) { - expectedConfig := *clientcmdapi.NewConfig() - expectedConfig.AuthInfos["the-user-name"] = clientcmdapi.NewAuthInfo() - test := configCommandTest{ - args: []string{"set-credentials", "the-user-name"}, - startingConfig: *clientcmdapi.NewConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestAdditionalAuth(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - authInfo := clientcmdapi.NewAuthInfo() - authInfo.Token = "token" - expectedConfig.AuthInfos["another-user"] = authInfo - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestEmbedClientCert(t *testing.T) { - fakeCertFile, _ := ioutil.TempFile("", "") - defer os.Remove(fakeCertFile.Name()) - fakeData := []byte("fake-data") - ioutil.WriteFile(fakeCertFile.Name(), fakeData, 0600) - expectedConfig := newRedFederalCowHammerConfig() - authInfo := clientcmdapi.NewAuthInfo() - authInfo.ClientCertificateData = fakeData - expectedConfig.AuthInfos["another-user"] = authInfo - - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=" + fakeCertFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestEmbedClientKey(t *testing.T) { - fakeKeyFile, _ := ioutil.TempFile("", "") - defer os.Remove(fakeKeyFile.Name()) - fakeData := []byte("fake-data") - ioutil.WriteFile(fakeKeyFile.Name(), fakeData, 0600) - expectedConfig := newRedFederalCowHammerConfig() - authInfo := clientcmdapi.NewAuthInfo() - authInfo.ClientKeyData = fakeData - expectedConfig.AuthInfos["another-user"] = authInfo - - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagKeyFile + "=" + fakeKeyFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestEmbedNoKeyOrCertDisallowed(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagEmbedCerts + "=true"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - expectedOutputs: []string{"--client-certificate", "--client-key", "embed"}, - } - - test.run(t) -} - -func TestEmptyTokenAndCertAllowed(t *testing.T) { - fakeCertFile, _ := ioutil.TempFile("", "cert-file") - - expectedConfig := newRedFederalCowHammerConfig() - authInfo := clientcmdapi.NewAuthInfo() - authInfo.ClientCertificate = path.Base(fakeCertFile.Name()) - expectedConfig.AuthInfos["another-user"] = authInfo - - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=" + fakeCertFile.Name(), "--" + clientcmd.FlagBearerToken + "="}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestTokenAndCertAllowed(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - authInfo := clientcmdapi.NewAuthInfo() - authInfo.Token = "token" - authInfo.ClientCertificate = "/cert-file" - expectedConfig.AuthInfos["another-user"] = authInfo - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=/cert-file", "--" + clientcmd.FlagBearerToken + "=token"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestTokenAndBasicDisallowed(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagUsername + "=myuser", "--" + clientcmd.FlagBearerToken + "=token"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - expectedOutputs: []string{"--token", "--username"}, - } - - test.run(t) -} - -func TestBasicClearsToken(t *testing.T) { - authInfoWithToken := clientcmdapi.NewAuthInfo() - authInfoWithToken.Token = "token" - - authInfoWithBasic := clientcmdapi.NewAuthInfo() - authInfoWithBasic.Username = "myuser" - authInfoWithBasic.Password = "mypass" - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.AuthInfos["another-user"] = authInfoWithToken - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.AuthInfos["another-user"] = authInfoWithBasic - - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagUsername + "=myuser", "--" + clientcmd.FlagPassword + "=mypass"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestTokenClearsBasic(t *testing.T) { - authInfoWithBasic := clientcmdapi.NewAuthInfo() - authInfoWithBasic.Username = "myuser" - authInfoWithBasic.Password = "mypass" - - authInfoWithToken := clientcmdapi.NewAuthInfo() - authInfoWithToken.Token = "token" - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.AuthInfos["another-user"] = authInfoWithBasic - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.AuthInfos["another-user"] = authInfoWithToken - - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestTokenLeavesCert(t *testing.T) { - authInfoWithCerts := clientcmdapi.NewAuthInfo() - authInfoWithCerts.ClientCertificate = "cert" - authInfoWithCerts.ClientCertificateData = []byte("certdata") - authInfoWithCerts.ClientKey = "key" - authInfoWithCerts.ClientKeyData = []byte("keydata") - - authInfoWithTokenAndCerts := clientcmdapi.NewAuthInfo() - authInfoWithTokenAndCerts.Token = "token" - authInfoWithTokenAndCerts.ClientCertificate = "cert" - authInfoWithTokenAndCerts.ClientCertificateData = []byte("certdata") - authInfoWithTokenAndCerts.ClientKey = "key" - authInfoWithTokenAndCerts.ClientKeyData = []byte("keydata") - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.AuthInfos["another-user"] = authInfoWithCerts - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.AuthInfos["another-user"] = authInfoWithTokenAndCerts - - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagBearerToken + "=token"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestCertLeavesToken(t *testing.T) { - authInfoWithToken := clientcmdapi.NewAuthInfo() - authInfoWithToken.Token = "token" - - authInfoWithTokenAndCerts := clientcmdapi.NewAuthInfo() - authInfoWithTokenAndCerts.Token = "token" - authInfoWithTokenAndCerts.ClientCertificate = "/cert" - authInfoWithTokenAndCerts.ClientKey = "/key" - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.AuthInfos["another-user"] = authInfoWithToken - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.AuthInfos["another-user"] = authInfoWithTokenAndCerts - - test := configCommandTest{ - args: []string{"set-credentials", "another-user", "--" + clientcmd.FlagCertFile + "=/cert", "--" + clientcmd.FlagKeyFile + "=/key"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestSetBytesBad(t *testing.T) { - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() - - test := configCommandTest{ - args: []string{"set", "clusters.another-cluster.certificate-authority-data", "cadata"}, - startingConfig: startingConfig, - expectedConfig: startingConfig, - } - - test.run(t) -} - -func TestSetBytes(t *testing.T) { - clusterInfoWithCAData := clientcmdapi.NewCluster() - clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData - - test := configCommandTest{ - args: []string{"set", "clusters.another-cluster.certificate-authority-data", "cadata", "--set-raw-bytes"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestSetBase64Bytes(t *testing.T) { - clusterInfoWithCAData := clientcmdapi.NewCluster() - clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData - - test := configCommandTest{ - args: []string{"set", "clusters.another-cluster.certificate-authority-data", "Y2FkYXRh"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestUnsetBytes(t *testing.T) { - clusterInfoWithCAData := clientcmdapi.NewCluster() - clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clusterInfoWithCAData - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["another-cluster"] = clientcmdapi.NewCluster() - - test := configCommandTest{ - args: []string{"unset", "clusters.another-cluster.certificate-authority-data"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestCAClearsInsecure(t *testing.T) { - fakeCAFile, _ := ioutil.TempFile("", "ca-file") - - clusterInfoWithInsecure := clientcmdapi.NewCluster() - clusterInfoWithInsecure.InsecureSkipTLSVerify = true - - clusterInfoWithCA := clientcmdapi.NewCluster() - clusterInfoWithCA.CertificateAuthority = path.Base(fakeCAFile.Name()) - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clusterInfoWithInsecure - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["another-cluster"] = clusterInfoWithCA - - test := configCommandTest{ - args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=" + fakeCAFile.Name()}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestCAClearsCAData(t *testing.T) { - clusterInfoWithCAData := clientcmdapi.NewCluster() - clusterInfoWithCAData.CertificateAuthorityData = []byte("cadata") - - clusterInfoWithCA := clientcmdapi.NewCluster() - clusterInfoWithCA.CertificateAuthority = "/cafile" - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clusterInfoWithCAData - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["another-cluster"] = clusterInfoWithCA - - test := configCommandTest{ - args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=/cafile", "--" + clientcmd.FlagInsecure + "=false"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestInsecureClearsCA(t *testing.T) { - clusterInfoWithInsecure := clientcmdapi.NewCluster() - clusterInfoWithInsecure.InsecureSkipTLSVerify = true - - clusterInfoWithCA := clientcmdapi.NewCluster() - clusterInfoWithCA.CertificateAuthority = "cafile" - clusterInfoWithCA.CertificateAuthorityData = []byte("cadata") - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clusterInfoWithCA - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["another-cluster"] = clusterInfoWithInsecure - - test := configCommandTest{ - args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagInsecure + "=true"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestCADataClearsCA(t *testing.T) { - fakeCAFile, _ := ioutil.TempFile("", "") - defer os.Remove(fakeCAFile.Name()) - fakeData := []byte("cadata") - ioutil.WriteFile(fakeCAFile.Name(), fakeData, 0600) - - clusterInfoWithCAData := clientcmdapi.NewCluster() - clusterInfoWithCAData.CertificateAuthorityData = fakeData - - clusterInfoWithCA := clientcmdapi.NewCluster() - clusterInfoWithCA.CertificateAuthority = "cafile" - - startingConfig := newRedFederalCowHammerConfig() - startingConfig.Clusters["another-cluster"] = clusterInfoWithCA - - expectedConfig := newRedFederalCowHammerConfig() - expectedConfig.Clusters["another-cluster"] = clusterInfoWithCAData - - test := configCommandTest{ - args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=" + fakeCAFile.Name(), "--" + clientcmd.FlagEmbedCerts + "=true"}, - startingConfig: startingConfig, - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestEmbedNoCADisallowed(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - test := configCommandTest{ - args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagEmbedCerts + "=true"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - expectedOutputs: []string{"--certificate-authority", "embed"}, - } - - test.run(t) -} - -func TestCAAndInsecureDisallowed(t *testing.T) { - test := configCommandTest{ - args: []string{"set-cluster", "another-cluster", "--" + clientcmd.FlagCAFile + "=cafile", "--" + clientcmd.FlagInsecure + "=true"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: newRedFederalCowHammerConfig(), - expectedOutputs: []string{"certificate", "insecure"}, - } - - test.run(t) -} - -func TestMergeExistingAuth(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - authInfo := expectedConfig.AuthInfos["red-user"] - authInfo.ClientKey = "/key" - expectedConfig.AuthInfos["red-user"] = authInfo - test := configCommandTest{ - args: []string{"set-credentials", "red-user", "--" + clientcmd.FlagKeyFile + "=/key"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestNewEmptyCluster(t *testing.T) { - expectedConfig := *clientcmdapi.NewConfig() - expectedConfig.Clusters["new-cluster"] = clientcmdapi.NewCluster() - test := configCommandTest{ - args: []string{"set-cluster", "new-cluster"}, - startingConfig: *clientcmdapi.NewConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestAdditionalCluster(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - cluster := clientcmdapi.NewCluster() - cluster.CertificateAuthority = "/ca-location" - cluster.InsecureSkipTLSVerify = false - cluster.Server = "serverlocation" - expectedConfig.Clusters["different-cluster"] = cluster - test := configCommandTest{ - args: []string{"set-cluster", "different-cluster", "--" + clientcmd.FlagAPIServer + "=serverlocation", "--" + clientcmd.FlagInsecure + "=false", "--" + clientcmd.FlagCAFile + "=/ca-location"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestOverwriteExistingCluster(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - cluster := clientcmdapi.NewCluster() - cluster.Server = "serverlocation" - expectedConfig.Clusters["cow-cluster"] = cluster - - test := configCommandTest{ - args: []string{"set-cluster", "cow-cluster", "--" + clientcmd.FlagAPIServer + "=serverlocation"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestNewEmptyContext(t *testing.T) { - expectedConfig := *clientcmdapi.NewConfig() - expectedConfig.Contexts["new-context"] = clientcmdapi.NewContext() - test := configCommandTest{ - args: []string{"set-context", "new-context"}, - startingConfig: *clientcmdapi.NewConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestAdditionalContext(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - context := clientcmdapi.NewContext() - context.Cluster = "some-cluster" - context.AuthInfo = "some-user" - context.Namespace = "different-namespace" - expectedConfig.Contexts["different-context"] = context - test := configCommandTest{ - args: []string{"set-context", "different-context", "--" + clientcmd.FlagClusterName + "=some-cluster", "--" + clientcmd.FlagAuthInfoName + "=some-user", "--" + clientcmd.FlagNamespace + "=different-namespace"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestMergeExistingContext(t *testing.T) { - expectedConfig := newRedFederalCowHammerConfig() - context := expectedConfig.Contexts["federal-context"] - context.Namespace = "hammer" - expectedConfig.Contexts["federal-context"] = context - - test := configCommandTest{ - args: []string{"set-context", "federal-context", "--" + clientcmd.FlagNamespace + "=hammer"}, - startingConfig: newRedFederalCowHammerConfig(), - expectedConfig: expectedConfig, - } - - test.run(t) -} - -func TestToBool(t *testing.T) { - type test struct { - in string - out bool - err string - } - - tests := []test{ - {"", false, ""}, - {"true", true, ""}, - {"on", false, `strconv.ParseBool: parsing "on": invalid syntax`}, - } - - for _, curr := range tests { - b, err := toBool(curr.in) - if (len(curr.err) != 0) && err == nil { - t.Errorf("Expected error: %v, but got nil", curr.err) - } - if (len(curr.err) == 0) && err != nil { - t.Errorf("Unexpected error: %v", err) - } - if (err != nil) && (err.Error() != curr.err) { - t.Errorf("Expected %v, got %v", curr.err, err) - - } - if b != curr.out { - t.Errorf("Expected %v, got %v", curr.out, b) - } - } - -} - -func testConfigCommand(args []string, startingConfig clientcmdapi.Config, t *testing.T) (string, clientcmdapi.Config) { - fakeKubeFile, _ := ioutil.TempFile("", "") - defer os.Remove(fakeKubeFile.Name()) - err := clientcmd.WriteToFile(startingConfig, fakeKubeFile.Name()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - argsToUse := make([]string, 0, 2+len(args)) - argsToUse = append(argsToUse, "--kubeconfig="+fakeKubeFile.Name()) - argsToUse = append(argsToUse, args...) - - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdConfig(clientcmd.NewDefaultPathOptions(), buf) - cmd.SetArgs(argsToUse) - cmd.Execute() - - // outBytes, _ := ioutil.ReadFile(fakeKubeFile.Name()) - config := clientcmd.GetConfigFromFileOrDie(fakeKubeFile.Name()) - - return buf.String(), *config -} - -type configCommandTest struct { - args []string - startingConfig clientcmdapi.Config - expectedConfig clientcmdapi.Config - expectedOutputs []string -} - -func (test configCommandTest) run(t *testing.T) string { - out, actualConfig := testConfigCommand(test.args, test.startingConfig, t) - - testSetNilMapsToEmpties(reflect.ValueOf(&test.expectedConfig)) - testSetNilMapsToEmpties(reflect.ValueOf(&actualConfig)) - testClearLocationOfOrigin(&actualConfig) - - if !api.Semantic.DeepEqual(test.expectedConfig, actualConfig) { - t.Errorf("diff: %v", diff.ObjectDiff(test.expectedConfig, actualConfig)) - t.Errorf("expected: %#v\n actual: %#v", test.expectedConfig, actualConfig) - } - - for _, expectedOutput := range test.expectedOutputs { - if !strings.Contains(out, expectedOutput) { - t.Errorf("expected '%s' in output, got '%s'", expectedOutput, out) - } - } - - return out -} -func testClearLocationOfOrigin(config *clientcmdapi.Config) { - for key, obj := range config.AuthInfos { - obj.LocationOfOrigin = "" - config.AuthInfos[key] = obj - } - for key, obj := range config.Clusters { - obj.LocationOfOrigin = "" - config.Clusters[key] = obj - } - for key, obj := range config.Contexts { - obj.LocationOfOrigin = "" - config.Contexts[key] = obj - } -} -func testSetNilMapsToEmpties(curr reflect.Value) { - actualCurrValue := curr - if curr.Kind() == reflect.Ptr { - actualCurrValue = curr.Elem() - } - - switch actualCurrValue.Kind() { - case reflect.Map: - for _, mapKey := range actualCurrValue.MapKeys() { - currMapValue := actualCurrValue.MapIndex(mapKey) - testSetNilMapsToEmpties(currMapValue) - } - - case reflect.Struct: - for fieldIndex := 0; fieldIndex < actualCurrValue.NumField(); fieldIndex++ { - currFieldValue := actualCurrValue.Field(fieldIndex) - - if currFieldValue.Kind() == reflect.Map && currFieldValue.IsNil() { - newValue := reflect.MakeMap(currFieldValue.Type()) - currFieldValue.Set(newValue) - } else { - testSetNilMapsToEmpties(currFieldValue.Addr()) - } - } - - } - -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_authinfo.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_authinfo.go deleted file mode 100644 index 2fd8cf2cb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_authinfo.go +++ /dev/null @@ -1,237 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "errors" - "fmt" - "io" - "io/ioutil" - "path/filepath" - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/flag" -) - -type createAuthInfoOptions struct { - configAccess clientcmd.ConfigAccess - name string - authPath util.StringFlag - clientCertificate util.StringFlag - clientKey util.StringFlag - token util.StringFlag - username util.StringFlag - password util.StringFlag - embedCertData flag.Tristate -} - -var create_authinfo_long = fmt.Sprintf(`Sets a user entry in kubeconfig -Specifying a name that already exists will merge new fields on top of existing values. - - Client-certificate flags: - --%v=certfile --%v=keyfile - - Bearer token flags: - --%v=bearer_token - - Basic auth flags: - --%v=basic_user --%v=basic_password - - Bearer token and basic auth are mutually exclusive. -`, clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword) - -const create_authinfo_example = `# Set only the "client-key" field on the "cluster-admin" -# entry, without touching other values: -kubectl config set-credentials cluster-admin --client-key=~/.kube/admin.key - -# Set basic auth for the "cluster-admin" entry -kubectl config set-credentials cluster-admin --username=admin --password=uXFGweU9l35qcif - -# Embed client certificate data in the "cluster-admin" entry -kubectl config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true` - -func NewCmdConfigSetAuthInfo(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &createAuthInfoOptions{configAccess: configAccess} - - cmd := &cobra.Command{ - Use: fmt.Sprintf("set-credentials NAME [--%v=path/to/certfile] [--%v=path/to/keyfile] [--%v=bearer_token] [--%v=basic_user] [--%v=basic_password]", clientcmd.FlagCertFile, clientcmd.FlagKeyFile, clientcmd.FlagBearerToken, clientcmd.FlagUsername, clientcmd.FlagPassword), - Short: "Sets a user entry in kubeconfig", - Long: create_authinfo_long, - Example: create_authinfo_example, - Run: func(cmd *cobra.Command, args []string) { - if !options.complete(cmd) { - return - } - - err := options.run() - if err != nil { - fmt.Fprintf(out, "%v\n", err) - } else { - fmt.Fprintf(out, "user %q set.\n", options.name) - } - }, - } - - cmd.Flags().Var(&options.clientCertificate, clientcmd.FlagCertFile, "path to "+clientcmd.FlagCertFile+" file for the user entry in kubeconfig") - cmd.MarkFlagFilename(clientcmd.FlagCertFile) - cmd.Flags().Var(&options.clientKey, clientcmd.FlagKeyFile, "path to "+clientcmd.FlagKeyFile+" file for the user entry in kubeconfig") - cmd.MarkFlagFilename(clientcmd.FlagKeyFile) - cmd.Flags().Var(&options.token, clientcmd.FlagBearerToken, clientcmd.FlagBearerToken+" for the user entry in kubeconfig") - cmd.Flags().Var(&options.username, clientcmd.FlagUsername, clientcmd.FlagUsername+" for the user entry in kubeconfig") - cmd.Flags().Var(&options.password, clientcmd.FlagPassword, clientcmd.FlagPassword+" for the user entry in kubeconfig") - f := cmd.Flags().VarPF(&options.embedCertData, clientcmd.FlagEmbedCerts, "", "embed client cert/key for the user entry in kubeconfig") - f.NoOptDefVal = "true" - - return cmd -} - -func (o createAuthInfoOptions) run() error { - err := o.validate() - if err != nil { - return err - } - - config, err := o.configAccess.GetStartingConfig() - if err != nil { - return err - } - - startingStanza, exists := config.AuthInfos[o.name] - if !exists { - startingStanza = clientcmdapi.NewAuthInfo() - } - authInfo := o.modifyAuthInfo(*startingStanza) - config.AuthInfos[o.name] = &authInfo - - if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil { - return err - } - - return nil -} - -// authInfo builds an AuthInfo object from the options -func (o *createAuthInfoOptions) modifyAuthInfo(existingAuthInfo clientcmdapi.AuthInfo) clientcmdapi.AuthInfo { - modifiedAuthInfo := existingAuthInfo - - var setToken, setBasic bool - - if o.clientCertificate.Provided() { - certPath := o.clientCertificate.Value() - if o.embedCertData.Value() { - modifiedAuthInfo.ClientCertificateData, _ = ioutil.ReadFile(certPath) - modifiedAuthInfo.ClientCertificate = "" - } else { - certPath, _ = filepath.Abs(certPath) - modifiedAuthInfo.ClientCertificate = certPath - if len(modifiedAuthInfo.ClientCertificate) > 0 { - modifiedAuthInfo.ClientCertificateData = nil - } - } - } - if o.clientKey.Provided() { - keyPath := o.clientKey.Value() - if o.embedCertData.Value() { - modifiedAuthInfo.ClientKeyData, _ = ioutil.ReadFile(keyPath) - modifiedAuthInfo.ClientKey = "" - } else { - keyPath, _ = filepath.Abs(keyPath) - modifiedAuthInfo.ClientKey = keyPath - if len(modifiedAuthInfo.ClientKey) > 0 { - modifiedAuthInfo.ClientKeyData = nil - } - } - } - - if o.token.Provided() { - modifiedAuthInfo.Token = o.token.Value() - setToken = len(modifiedAuthInfo.Token) > 0 - } - - if o.username.Provided() { - modifiedAuthInfo.Username = o.username.Value() - setBasic = setBasic || len(modifiedAuthInfo.Username) > 0 - } - if o.password.Provided() { - modifiedAuthInfo.Password = o.password.Value() - setBasic = setBasic || len(modifiedAuthInfo.Password) > 0 - } - - // If any auth info was set, make sure any other existing auth types are cleared - if setToken || setBasic { - if !setToken { - modifiedAuthInfo.Token = "" - } - if !setBasic { - modifiedAuthInfo.Username = "" - modifiedAuthInfo.Password = "" - } - } - - return modifiedAuthInfo -} - -func (o *createAuthInfoOptions) complete(cmd *cobra.Command) bool { - args := cmd.Flags().Args() - if len(args) != 1 { - cmd.Help() - return false - } - - o.name = args[0] - return true -} - -func (o createAuthInfoOptions) validate() error { - if len(o.name) == 0 { - return errors.New("you must specify a non-empty user name") - } - methods := []string{} - if len(o.token.Value()) > 0 { - methods = append(methods, fmt.Sprintf("--%v", clientcmd.FlagBearerToken)) - } - if len(o.username.Value()) > 0 || len(o.password.Value()) > 0 { - methods = append(methods, fmt.Sprintf("--%v/--%v", clientcmd.FlagUsername, clientcmd.FlagPassword)) - } - if len(methods) > 1 { - return fmt.Errorf("you cannot specify more than one authentication method at the same time: %v", strings.Join(methods, ", ")) - } - if o.embedCertData.Value() { - certPath := o.clientCertificate.Value() - keyPath := o.clientKey.Value() - if certPath == "" && keyPath == "" { - return fmt.Errorf("you must specify a --%s or --%s to embed", clientcmd.FlagCertFile, clientcmd.FlagKeyFile) - } - if certPath != "" { - if _, err := ioutil.ReadFile(certPath); err != nil { - return fmt.Errorf("error reading %s data from %s: %v", clientcmd.FlagCertFile, certPath, err) - } - } - if keyPath != "" { - if _, err := ioutil.ReadFile(keyPath); err != nil { - return fmt.Errorf("error reading %s data from %s: %v", clientcmd.FlagKeyFile, keyPath, err) - } - } - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_cluster.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_cluster.go deleted file mode 100644 index dc9de40a0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_cluster.go +++ /dev/null @@ -1,182 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "errors" - "fmt" - "io" - "io/ioutil" - "path/filepath" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/flag" -) - -type createClusterOptions struct { - configAccess clientcmd.ConfigAccess - name string - server util.StringFlag - apiVersion util.StringFlag - insecureSkipTLSVerify flag.Tristate - certificateAuthority util.StringFlag - embedCAData flag.Tristate -} - -const ( - create_cluster_long = `Sets a cluster entry in kubeconfig. -Specifying a name that already exists will merge new fields on top of existing values for those fields.` - create_cluster_example = `# Set only the server field on the e2e cluster entry without touching other values. -kubectl config set-cluster e2e --server=https://1.2.3.4 - -# Embed certificate authority data for the e2e cluster entry -kubectl config set-cluster e2e --certificate-authority=~/.kube/e2e/kubernetes.ca.crt - -# Disable cert checking for the dev cluster entry -kubectl config set-cluster e2e --insecure-skip-tls-verify=true` -) - -func NewCmdConfigSetCluster(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &createClusterOptions{configAccess: configAccess} - - cmd := &cobra.Command{ - Use: fmt.Sprintf("set-cluster NAME [--%v=server] [--%v=path/to/certficate/authority] [--%v=true]", clientcmd.FlagAPIServer, clientcmd.FlagCAFile, clientcmd.FlagInsecure), - Short: "Sets a cluster entry in kubeconfig", - Long: create_cluster_long, - Example: create_cluster_example, - Run: func(cmd *cobra.Command, args []string) { - if !options.complete(cmd) { - return - } - - err := options.run() - if err != nil { - fmt.Fprintf(out, "%v\n", err) - } else { - fmt.Fprintf(out, "cluster %q set.\n", options.name) - } - }, - } - - options.insecureSkipTLSVerify.Default(false) - - cmd.Flags().Var(&options.server, clientcmd.FlagAPIServer, clientcmd.FlagAPIServer+" for the cluster entry in kubeconfig") - cmd.Flags().Var(&options.apiVersion, clientcmd.FlagAPIVersion, clientcmd.FlagAPIVersion+" for the cluster entry in kubeconfig") - f := cmd.Flags().VarPF(&options.insecureSkipTLSVerify, clientcmd.FlagInsecure, "", clientcmd.FlagInsecure+" for the cluster entry in kubeconfig") - f.NoOptDefVal = "true" - cmd.Flags().Var(&options.certificateAuthority, clientcmd.FlagCAFile, "path to "+clientcmd.FlagCAFile+" file for the cluster entry in kubeconfig") - cmd.MarkFlagFilename(clientcmd.FlagCAFile) - f = cmd.Flags().VarPF(&options.embedCAData, clientcmd.FlagEmbedCerts, "", clientcmd.FlagEmbedCerts+" for the cluster entry in kubeconfig") - f.NoOptDefVal = "true" - - return cmd -} - -func (o createClusterOptions) run() error { - err := o.validate() - if err != nil { - return err - } - - config, err := o.configAccess.GetStartingConfig() - if err != nil { - return err - } - - startingStanza, exists := config.Clusters[o.name] - if !exists { - startingStanza = clientcmdapi.NewCluster() - } - cluster := o.modifyCluster(*startingStanza) - config.Clusters[o.name] = &cluster - - if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil { - return err - } - - return nil -} - -// cluster builds a Cluster object from the options -func (o *createClusterOptions) modifyCluster(existingCluster clientcmdapi.Cluster) clientcmdapi.Cluster { - modifiedCluster := existingCluster - - if o.server.Provided() { - modifiedCluster.Server = o.server.Value() - } - if o.insecureSkipTLSVerify.Provided() { - modifiedCluster.InsecureSkipTLSVerify = o.insecureSkipTLSVerify.Value() - // Specifying insecure mode clears any certificate authority - if modifiedCluster.InsecureSkipTLSVerify { - modifiedCluster.CertificateAuthority = "" - modifiedCluster.CertificateAuthorityData = nil - } - } - if o.certificateAuthority.Provided() { - caPath := o.certificateAuthority.Value() - if o.embedCAData.Value() { - modifiedCluster.CertificateAuthorityData, _ = ioutil.ReadFile(caPath) - modifiedCluster.InsecureSkipTLSVerify = false - modifiedCluster.CertificateAuthority = "" - } else { - caPath, _ = filepath.Abs(caPath) - modifiedCluster.CertificateAuthority = caPath - // Specifying a certificate authority file clears certificate authority data and insecure mode - if caPath != "" { - modifiedCluster.InsecureSkipTLSVerify = false - modifiedCluster.CertificateAuthorityData = nil - } - } - } - - return modifiedCluster -} - -func (o *createClusterOptions) complete(cmd *cobra.Command) bool { - args := cmd.Flags().Args() - if len(args) != 1 { - cmd.Help() - return false - } - - o.name = args[0] - return true -} - -func (o createClusterOptions) validate() error { - if len(o.name) == 0 { - return errors.New("you must specify a non-empty cluster name") - } - if o.insecureSkipTLSVerify.Value() && o.certificateAuthority.Value() != "" { - return errors.New("you cannot specify a certificate authority and insecure mode at the same time") - } - if o.embedCAData.Value() { - caPath := o.certificateAuthority.Value() - if caPath == "" { - return fmt.Errorf("you must specify a --%s to embed", clientcmd.FlagCAFile) - } - if _, err := ioutil.ReadFile(caPath); err != nil { - return fmt.Errorf("could not read %s data from %s: %v", clientcmd.FlagCAFile, caPath, err) - } - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_context.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_context.go deleted file mode 100644 index 7f0ca2170..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/create_context.go +++ /dev/null @@ -1,133 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "errors" - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/util" -) - -type createContextOptions struct { - configAccess clientcmd.ConfigAccess - name string - cluster util.StringFlag - authInfo util.StringFlag - namespace util.StringFlag -} - -const ( - create_context_long = `Sets a context entry in kubeconfig -Specifying a name that already exists will merge new fields on top of existing values for those fields.` - create_context_example = `# Set the user field on the gce context entry without touching other values -kubectl config set-context gce --user=cluster-admin` -) - -func NewCmdConfigSetContext(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &createContextOptions{configAccess: configAccess} - - cmd := &cobra.Command{ - Use: fmt.Sprintf("set-context NAME [--%v=cluster_nickname] [--%v=user_nickname] [--%v=namespace]", clientcmd.FlagClusterName, clientcmd.FlagAuthInfoName, clientcmd.FlagNamespace), - Short: "Sets a context entry in kubeconfig", - Long: create_context_long, - Example: create_context_example, - Run: func(cmd *cobra.Command, args []string) { - if !options.complete(cmd) { - return - } - - err := options.run() - if err != nil { - fmt.Fprintf(out, "%v\n", err) - } else { - fmt.Fprintf(out, "context %q set.\n", options.name) - } - }, - } - - cmd.Flags().Var(&options.cluster, clientcmd.FlagClusterName, clientcmd.FlagClusterName+" for the context entry in kubeconfig") - cmd.Flags().Var(&options.authInfo, clientcmd.FlagAuthInfoName, clientcmd.FlagAuthInfoName+" for the context entry in kubeconfig") - cmd.Flags().Var(&options.namespace, clientcmd.FlagNamespace, clientcmd.FlagNamespace+" for the context entry in kubeconfig") - - return cmd -} - -func (o createContextOptions) run() error { - err := o.validate() - if err != nil { - return err - } - - config, err := o.configAccess.GetStartingConfig() - if err != nil { - return err - } - - startingStanza, exists := config.Contexts[o.name] - if !exists { - startingStanza = clientcmdapi.NewContext() - } - context := o.modifyContext(*startingStanza) - config.Contexts[o.name] = &context - - if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil { - return err - } - - return nil -} - -func (o *createContextOptions) modifyContext(existingContext clientcmdapi.Context) clientcmdapi.Context { - modifiedContext := existingContext - - if o.cluster.Provided() { - modifiedContext.Cluster = o.cluster.Value() - } - if o.authInfo.Provided() { - modifiedContext.AuthInfo = o.authInfo.Value() - } - if o.namespace.Provided() { - modifiedContext.Namespace = o.namespace.Value() - } - - return modifiedContext -} - -func (o *createContextOptions) complete(cmd *cobra.Command) bool { - args := cmd.Flags().Args() - if len(args) != 1 { - cmd.Help() - return false - } - - o.name = args[0] - return true -} - -func (o createContextOptions) validate() error { - if len(o.name) == 0 { - return errors.New("you must specify a non-empty context name") - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/current_context.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/current_context.go deleted file mode 100644 index f2941c6db..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/current_context.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -type CurrentContextOptions struct { - ConfigAccess clientcmd.ConfigAccess -} - -const ( - current_context_long = `Displays the current-context` - current_context_example = `# Display the current-context -kubectl config current-context` -) - -func NewCmdConfigCurrentContext(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &CurrentContextOptions{ConfigAccess: configAccess} - - cmd := &cobra.Command{ - Use: "current-context", - Short: "Displays the current-context", - Long: current_context_long, - Example: current_context_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunCurrentContext(out, args, options) - cmdutil.CheckErr(err) - }, - } - - return cmd -} - -func RunCurrentContext(out io.Writer, args []string, options *CurrentContextOptions) error { - config, err := options.ConfigAccess.GetStartingConfig() - if err != nil { - return err - } - - if config.CurrentContext == "" { - err = fmt.Errorf("current-context is not set\n") - return err - } - - fmt.Fprintf(out, "%s\n", config.CurrentContext) - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/current_context_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/current_context_test.go deleted file mode 100644 index 7a68415f6..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/current_context_test.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "bytes" - "io/ioutil" - "os" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" -) - -type currentContextTest struct { - startingConfig clientcmdapi.Config - expectedError string -} - -func newFederalContextConfig() clientcmdapi.Config { - return clientcmdapi.Config{ - CurrentContext: "federal-context", - } -} - -func TestCurrentContextWithSetContext(t *testing.T) { - test := currentContextTest{ - startingConfig: newFederalContextConfig(), - expectedError: "", - } - - test.run(t) -} - -func TestCurrentContextWithUnsetContext(t *testing.T) { - test := currentContextTest{ - startingConfig: *clientcmdapi.NewConfig(), - expectedError: "current-context is not set", - } - - test.run(t) -} - -func (test currentContextTest) run(t *testing.T) { - fakeKubeFile, _ := ioutil.TempFile("", "") - defer os.Remove(fakeKubeFile.Name()) - err := clientcmd.WriteToFile(test.startingConfig, fakeKubeFile.Name()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - pathOptions := clientcmd.NewDefaultPathOptions() - pathOptions.GlobalFile = fakeKubeFile.Name() - pathOptions.EnvVar = "" - options := CurrentContextOptions{ - ConfigAccess: pathOptions, - } - - buf := bytes.NewBuffer([]byte{}) - err = RunCurrentContext(buf, []string{}, &options) - if len(test.expectedError) != 0 { - if err == nil { - t.Errorf("Did not get %v", test.expectedError) - } else { - if !strings.Contains(err.Error(), test.expectedError) { - t.Errorf("Expected %v, but got %v", test.expectedError, err) - } - } - return - } - - if err != nil { - t.Errorf("Unexpected error: %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/navigation_step_parser.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/navigation_step_parser.go deleted file mode 100644 index 0be5f241e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/navigation_step_parser.go +++ /dev/null @@ -1,152 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "fmt" - "reflect" - "strings" - - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/util/sets" -) - -type navigationSteps struct { - steps []navigationStep - currentStepIndex int -} - -type navigationStep struct { - stepValue string - stepType reflect.Type -} - -func newNavigationSteps(path string) (*navigationSteps, error) { - steps := []navigationStep{} - individualParts := strings.Split(path, ".") - - currType := reflect.TypeOf(clientcmdapi.Config{}) - currPartIndex := 0 - for currPartIndex < len(individualParts) { - switch currType.Kind() { - case reflect.Map: - // if we're in a map, we need to locate a name. That name may contain dots, so we need to know what tokens are legal for the map's value type - // for example, we could have a set request like: `set clusters.10.10.12.56.insecure-skip-tls-verify true`. We enter this case with - // steps representing 10, 10, 12, 56, insecure-skip-tls-verify. The name is "10.10.12.56", so we want to collect all those parts together and - // store them as a single step. In order to do that, we need to determine what set of tokens is a legal step AFTER the name of the map key - // This set of reflective code pulls the type of the map values, uses that type to look up the set of legal tags. Those legal tags are used to - // walk the list of remaining parts until we find a match to a legal tag or the end of the string. That name is used to burn all the used parts. - mapValueType := currType.Elem().Elem() - mapValueOptions, err := getPotentialTypeValues(mapValueType) - if err != nil { - return nil, err - } - nextPart := findNameStep(individualParts[currPartIndex:], sets.StringKeySet(mapValueOptions)) - - steps = append(steps, navigationStep{nextPart, mapValueType}) - currPartIndex += len(strings.Split(nextPart, ".")) - currType = mapValueType - - case reflect.Struct: - nextPart := individualParts[currPartIndex] - - options, err := getPotentialTypeValues(currType) - if err != nil { - return nil, err - } - fieldType, exists := options[nextPart] - if !exists { - return nil, fmt.Errorf("unable to parse %v after %v at %v", path, steps, currType) - } - - steps = append(steps, navigationStep{nextPart, fieldType}) - currPartIndex += len(strings.Split(nextPart, ".")) - currType = fieldType - } - } - - return &navigationSteps{steps, 0}, nil -} - -func (s *navigationSteps) pop() navigationStep { - if s.moreStepsRemaining() { - s.currentStepIndex++ - return s.steps[s.currentStepIndex-1] - } - return navigationStep{} -} - -func (s *navigationSteps) peek() navigationStep { - if s.moreStepsRemaining() { - return s.steps[s.currentStepIndex] - } - return navigationStep{} -} - -func (s *navigationSteps) moreStepsRemaining() bool { - return len(s.steps) > s.currentStepIndex -} - -// findNameStep takes the list of parts and a set of valid tags that can be used after the name. It then walks the list of parts -// until it find a valid "next" tag or until it reaches the end of the parts and then builds the name back up out of the individual parts -func findNameStep(parts []string, typeOptions sets.String) string { - if len(parts) == 0 { - return "" - } - - numberOfPartsInStep := findKnownValue(parts[1:], typeOptions) + 1 - // if we didn't find a known value, then the entire thing must be a name - if numberOfPartsInStep == 0 { - numberOfPartsInStep = len(parts) - } - nextParts := parts[0:numberOfPartsInStep] - - return strings.Join(nextParts, ".") -} - -// getPotentialTypeValues takes a type and looks up the tags used to represent its fields when serialized. -func getPotentialTypeValues(typeValue reflect.Type) (map[string]reflect.Type, error) { - if typeValue.Kind() == reflect.Ptr { - typeValue = typeValue.Elem() - } - - if typeValue.Kind() != reflect.Struct { - return nil, fmt.Errorf("%v is not of type struct", typeValue) - } - - ret := make(map[string]reflect.Type) - - for fieldIndex := 0; fieldIndex < typeValue.NumField(); fieldIndex++ { - fieldType := typeValue.Field(fieldIndex) - yamlTag := fieldType.Tag.Get("json") - yamlTagName := strings.Split(yamlTag, ",")[0] - - ret[yamlTagName] = fieldType.Type - } - - return ret, nil -} - -func findKnownValue(parts []string, valueOptions sets.String) int { - for i := range parts { - if valueOptions.Has(parts[i]) { - return i - } - } - - return -1 -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/navigation_step_parser_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/navigation_step_parser_test.go deleted file mode 100644 index 2bca8d089..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/navigation_step_parser_test.go +++ /dev/null @@ -1,96 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "reflect" - "strings" - "testing" - - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/util/diff" -) - -type stepParserTest struct { - path string - expectedNavigationSteps navigationSteps - expectedError string -} - -func TestParseWithDots(t *testing.T) { - test := stepParserTest{ - path: "clusters.my.dot.delimited.name.server", - expectedNavigationSteps: navigationSteps{ - steps: []navigationStep{ - {"clusters", reflect.TypeOf(make(map[string]*clientcmdapi.Cluster))}, - {"my.dot.delimited.name", reflect.TypeOf(clientcmdapi.Cluster{})}, - {"server", reflect.TypeOf("")}, - }, - }, - } - - test.run(t) -} - -func TestParseWithDotsEndingWithName(t *testing.T) { - test := stepParserTest{ - path: "contexts.10.12.12.12", - expectedNavigationSteps: navigationSteps{ - steps: []navigationStep{ - {"contexts", reflect.TypeOf(make(map[string]*clientcmdapi.Context))}, - {"10.12.12.12", reflect.TypeOf(clientcmdapi.Context{})}, - }, - }, - } - - test.run(t) -} - -func TestParseWithBadValue(t *testing.T) { - test := stepParserTest{ - path: "user.bad", - expectedNavigationSteps: navigationSteps{ - steps: []navigationStep{}, - }, - expectedError: "unable to parse user.bad after [] at api.Config", - } - - test.run(t) -} - -func (test stepParserTest) run(t *testing.T) { - actualSteps, err := newNavigationSteps(test.path) - if len(test.expectedError) != 0 { - if err == nil { - t.Errorf("Did not get %v", test.expectedError) - } else { - if !strings.Contains(err.Error(), test.expectedError) { - t.Errorf("Expected %v, but got %v", test.expectedError, err) - } - } - return - } - - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - if !reflect.DeepEqual(test.expectedNavigationSteps, *actualSteps) { - t.Errorf("diff: %v", diff.ObjectDiff(test.expectedNavigationSteps, *actualSteps)) - t.Errorf("expected: %#v\n actual: %#v", test.expectedNavigationSteps, *actualSteps) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/set.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/set.go deleted file mode 100644 index c1c078bcb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/set.go +++ /dev/null @@ -1,246 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "encoding/base64" - "errors" - "fmt" - "io" - "reflect" - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - "k8s.io/kubernetes/pkg/util/flag" -) - -const ( - cannotHaveStepsAfterError = "Cannot have steps after %v. %v are remaining" - additionStepRequiredUnlessUnsettingError = "Must have additional steps after %v unless you are unsetting it" -) - -type setOptions struct { - configAccess clientcmd.ConfigAccess - propertyName string - propertyValue string - setRawBytes flag.Tristate -} - -const set_long = `Sets an individual value in a kubeconfig file -PROPERTY_NAME is a dot delimited name where each token represents either a attribute name or a map key. Map keys may not contain dots. -PROPERTY_VALUE is the new value you wish to set. Binary fields such as 'certificate-authority-data' expect a base64 encoded string unless the --set-raw-bytes flag is used.` - -func NewCmdConfigSet(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &setOptions{configAccess: configAccess} - - cmd := &cobra.Command{ - Use: "set PROPERTY_NAME PROPERTY_VALUE", - Short: "Sets an individual value in a kubeconfig file", - Long: set_long, - Run: func(cmd *cobra.Command, args []string) { - if !options.complete(cmd) { - return - } - - err := options.run() - if err != nil { - fmt.Fprintf(out, "%v\n", err) - } else { - fmt.Fprintf(out, "property %q set.\n", options.propertyName) - } - }, - } - - f := cmd.Flags().VarPF(&options.setRawBytes, "set-raw-bytes", "", "When writing a []byte PROPERTY_VALUE, write the given string directly without base64 decoding.") - f.NoOptDefVal = "true" - return cmd -} - -func (o setOptions) run() error { - err := o.validate() - if err != nil { - return err - } - - config, err := o.configAccess.GetStartingConfig() - if err != nil { - return err - } - steps, err := newNavigationSteps(o.propertyName) - if err != nil { - return err - } - - setRawBytes := false - if o.setRawBytes.Provided() { - setRawBytes = o.setRawBytes.Value() - } - - err = modifyConfig(reflect.ValueOf(config), steps, o.propertyValue, false, setRawBytes) - if err != nil { - return err - } - - if err := clientcmd.ModifyConfig(o.configAccess, *config, false); err != nil { - return err - } - - return nil -} - -func (o *setOptions) complete(cmd *cobra.Command) bool { - endingArgs := cmd.Flags().Args() - if len(endingArgs) != 2 { - cmd.Help() - return false - } - - o.propertyValue = endingArgs[1] - o.propertyName = endingArgs[0] - return true -} - -func (o setOptions) validate() error { - if len(o.propertyValue) == 0 { - return errors.New("you cannot use set to unset a property") - } - - if len(o.propertyName) == 0 { - return errors.New("you must specify a property") - } - - return nil -} - -func modifyConfig(curr reflect.Value, steps *navigationSteps, propertyValue string, unset bool, setRawBytes bool) error { - currStep := steps.pop() - - actualCurrValue := curr - if curr.Kind() == reflect.Ptr { - actualCurrValue = curr.Elem() - } - - switch actualCurrValue.Kind() { - case reflect.Map: - if !steps.moreStepsRemaining() && !unset { - return fmt.Errorf("can't set a map to a value: %v", actualCurrValue) - } - - mapKey := reflect.ValueOf(currStep.stepValue) - mapValueType := curr.Type().Elem().Elem() - - if !steps.moreStepsRemaining() && unset { - actualCurrValue.SetMapIndex(mapKey, reflect.Value{}) - return nil - } - - currMapValue := actualCurrValue.MapIndex(mapKey) - - needToSetNewMapValue := currMapValue.Kind() == reflect.Invalid - if needToSetNewMapValue { - currMapValue = reflect.New(mapValueType.Elem()).Elem().Addr() - actualCurrValue.SetMapIndex(mapKey, currMapValue) - } - - err := modifyConfig(currMapValue, steps, propertyValue, unset, setRawBytes) - if err != nil { - return err - } - - return nil - - case reflect.String: - if steps.moreStepsRemaining() { - return fmt.Errorf("can't have more steps after a string. %v", steps) - } - actualCurrValue.SetString(propertyValue) - return nil - - case reflect.Slice: - if steps.moreStepsRemaining() { - return fmt.Errorf("can't have more steps after bytes. %v", steps) - } - innerKind := actualCurrValue.Type().Elem().Kind() - if innerKind != reflect.Uint8 { - return fmt.Errorf("unrecognized slice type. %v", innerKind) - } - - if unset { - actualCurrValue.Set(reflect.Zero(actualCurrValue.Type())) - return nil - } - - if setRawBytes { - actualCurrValue.SetBytes([]byte(propertyValue)) - } else { - val, err := base64.StdEncoding.DecodeString(propertyValue) - if err != nil { - return fmt.Errorf("error decoding input value: %v", err) - } - actualCurrValue.SetBytes(val) - } - return nil - - case reflect.Bool: - if steps.moreStepsRemaining() { - return fmt.Errorf("can't have more steps after a bool. %v", steps) - } - boolValue, err := toBool(propertyValue) - if err != nil { - return err - } - actualCurrValue.SetBool(boolValue) - return nil - - case reflect.Struct: - for fieldIndex := 0; fieldIndex < actualCurrValue.NumField(); fieldIndex++ { - currFieldValue := actualCurrValue.Field(fieldIndex) - currFieldType := actualCurrValue.Type().Field(fieldIndex) - currYamlTag := currFieldType.Tag.Get("json") - currFieldTypeYamlName := strings.Split(currYamlTag, ",")[0] - - if currFieldTypeYamlName == currStep.stepValue { - thisMapHasNoValue := (currFieldValue.Kind() == reflect.Map && currFieldValue.IsNil()) - - if thisMapHasNoValue { - newValue := reflect.MakeMap(currFieldValue.Type()) - currFieldValue.Set(newValue) - - if !steps.moreStepsRemaining() && unset { - return nil - } - } - - if !steps.moreStepsRemaining() && unset { - // if we're supposed to unset the value or if the value is a map that doesn't exist, create a new value and overwrite - newValue := reflect.New(currFieldValue.Type()).Elem() - currFieldValue.Set(newValue) - return nil - } - - return modifyConfig(currFieldValue.Addr(), steps, propertyValue, unset, setRawBytes) - } - } - - return fmt.Errorf("unable to locate path %#v under %v", currStep, actualCurrValue) - - } - - panic(fmt.Errorf("unrecognized type: %v", actualCurrValue)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/unset.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/unset.go deleted file mode 100644 index f9446df51..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/unset.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "errors" - "fmt" - "io" - "reflect" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" -) - -type unsetOptions struct { - configAccess clientcmd.ConfigAccess - propertyName string -} - -const unset_long = `Unsets an individual value in a kubeconfig file -PROPERTY_NAME is a dot delimited name where each token represents either a attribute name or a map key. Map keys may not contain dots.` - -func NewCmdConfigUnset(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &unsetOptions{configAccess: configAccess} - - cmd := &cobra.Command{ - Use: "unset PROPERTY_NAME", - Short: "Unsets an individual value in a kubeconfig file", - Long: unset_long, - Run: func(cmd *cobra.Command, args []string) { - if !options.complete(cmd) { - return - } - - err := options.run() - if err != nil { - fmt.Fprintf(out, "%v\n", err) - } else { - fmt.Fprintf(out, "property %q unset.\n", options.propertyName) - } - }, - } - - return cmd -} - -func (o unsetOptions) run() error { - err := o.validate() - if err != nil { - return err - } - - config, err := o.configAccess.GetStartingConfig() - if err != nil { - return err - } - - steps, err := newNavigationSteps(o.propertyName) - if err != nil { - return err - } - err = modifyConfig(reflect.ValueOf(config), steps, "", true, true) - if err != nil { - return err - } - - if err := clientcmd.ModifyConfig(o.configAccess, *config, false); err != nil { - return err - } - - return nil -} - -func (o *unsetOptions) complete(cmd *cobra.Command) bool { - endingArgs := cmd.Flags().Args() - if len(endingArgs) != 1 { - cmd.Help() - return false - } - - o.propertyName = endingArgs[0] - return true -} - -func (o unsetOptions) validate() error { - if len(o.propertyName) == 0 { - return errors.New("you must specify a property") - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/use_context.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/use_context.go deleted file mode 100644 index abfe8bbf9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/use_context.go +++ /dev/null @@ -1,102 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "errors" - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" -) - -type useContextOptions struct { - configAccess clientcmd.ConfigAccess - contextName string -} - -func NewCmdConfigUseContext(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command { - options := &useContextOptions{configAccess: configAccess} - - cmd := &cobra.Command{ - Use: "use-context CONTEXT_NAME", - Short: "Sets the current-context in a kubeconfig file", - Long: `Sets the current-context in a kubeconfig file`, - Run: func(cmd *cobra.Command, args []string) { - if !options.complete(cmd) { - return - } - - err := options.run() - if err != nil { - fmt.Fprintf(out, "%v\n", err) - } else { - fmt.Fprintf(out, "switched to context %q.\n", options.contextName) - } - }, - } - - return cmd -} - -func (o useContextOptions) run() error { - config, err := o.configAccess.GetStartingConfig() - if err != nil { - return err - } - - err = o.validate(config) - if err != nil { - return err - } - - config.CurrentContext = o.contextName - - if err := clientcmd.ModifyConfig(o.configAccess, *config, true); err != nil { - return err - } - - return nil -} - -func (o *useContextOptions) complete(cmd *cobra.Command) bool { - endingArgs := cmd.Flags().Args() - if len(endingArgs) != 1 { - cmd.Help() - return false - } - - o.contextName = endingArgs[0] - return true -} - -func (o useContextOptions) validate(config *clientcmdapi.Config) error { - if len(o.contextName) == 0 { - return errors.New("you must specify a current-context") - } - - for name := range config.Contexts { - if name == o.contextName { - return nil - } - } - - return fmt.Errorf("no context exists with the name: %q.", o.contextName) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/view.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/view.go deleted file mode 100644 index 1c1ae5df3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/config/view.go +++ /dev/null @@ -1,162 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "errors" - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/latest" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/util/flag" -) - -type ViewOptions struct { - ConfigAccess clientcmd.ConfigAccess - Merge flag.Tristate - Flatten bool - Minify bool - RawByteData bool -} - -const ( - view_long = `Displays merged kubeconfig settings or a specified kubeconfig file. - -You can use --output jsonpath={...} to extract specific values using a jsonpath expression.` - view_example = `# Show Merged kubeconfig settings. -kubectl config view - -# Get the password for the e2e user -kubectl config view -o jsonpath='{.users[?(@.name == "e2e")].user.password}'` -) - -func NewCmdConfigView(out io.Writer, ConfigAccess clientcmd.ConfigAccess) *cobra.Command { - options := &ViewOptions{ConfigAccess: ConfigAccess} - // Default to yaml - defaultOutputFormat := "yaml" - - cmd := &cobra.Command{ - Use: "view", - Short: "Displays merged kubeconfig settings or a specified kubeconfig file.", - Long: view_long, - Example: view_example, - Run: func(cmd *cobra.Command, args []string) { - options.Complete() - outputFormat := cmdutil.GetFlagString(cmd, "output") - if outputFormat == "wide" { - fmt.Printf("--output wide is not available in kubectl config view; reset to default output format (%s)\n\n", defaultOutputFormat) - cmd.Flags().Set("output", defaultOutputFormat) - } - if outputFormat == "" { - fmt.Printf("reset to default output format (%s) as --output is empty", defaultOutputFormat) - cmd.Flags().Set("output", defaultOutputFormat) - } - - printer, _, err := cmdutil.PrinterForCommand(cmd) - cmdutil.CheckErr(err) - version, err := cmdutil.OutputVersion(cmd, &latest.ExternalVersion) - cmdutil.CheckErr(err) - printer = kubectl.NewVersionedPrinter(printer, clientcmdapi.Scheme, version) - - cmdutil.CheckErr(options.Run(out, printer)) - }, - } - - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().Set("output", defaultOutputFormat) - - options.Merge.Default(true) - f := cmd.Flags().VarPF(&options.Merge, "merge", "", "merge together the full hierarchy of kubeconfig files") - f.NoOptDefVal = "true" - cmd.Flags().BoolVar(&options.RawByteData, "raw", false, "display raw byte data") - cmd.Flags().BoolVar(&options.Flatten, "flatten", false, "flatten the resulting kubeconfig file into self contained output (useful for creating portable kubeconfig files)") - cmd.Flags().BoolVar(&options.Minify, "minify", false, "remove all information not used by current-context from the output") - return cmd -} - -func (o ViewOptions) Run(out io.Writer, printer kubectl.ResourcePrinter) error { - config, err := o.loadConfig() - if err != nil { - return err - } - - if o.Minify { - if err := clientcmdapi.MinifyConfig(config); err != nil { - return err - } - } - - if o.Flatten { - if err := clientcmdapi.FlattenConfig(config); err != nil { - return err - } - } else if !o.RawByteData { - clientcmdapi.ShortenConfig(config) - } - - err = printer.PrintObj(config, out) - if err != nil { - return err - } - - return nil -} - -func (o *ViewOptions) Complete() bool { - if o.ConfigAccess.IsExplicitFile() { - if !o.Merge.Provided() { - o.Merge.Set("false") - } - } - - return true -} - -func (o ViewOptions) loadConfig() (*clientcmdapi.Config, error) { - err := o.Validate() - if err != nil { - return nil, err - } - - config, err := o.getStartingConfig() - return config, err -} - -func (o ViewOptions) Validate() error { - if !o.Merge.Value() && !o.ConfigAccess.IsExplicitFile() { - return errors.New("if merge==false a precise file must to specified") - } - - return nil -} - -// getStartingConfig returns the Config object built from the sources specified by the options, the filename read (only if it was a single file), and an error if something goes wrong -func (o *ViewOptions) getStartingConfig() (*clientcmdapi.Config, error) { - switch { - case !o.Merge.Value(): - return clientcmd.LoadFromFile(o.ConfigAccess.GetExplicitFile()) - - default: - return o.ConfigAccess.GetStartingConfig() - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/convert.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/convert.go deleted file mode 100644 index 103bb9648..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/convert.go +++ /dev/null @@ -1,185 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - - "github.com/spf13/cobra" -) - -const ( - convert_long = `Convert config files between different API versions. Both YAML -and JSON formats are accepted. - -The command takes filename, directory, or URL as input, and convert it into format -of version specified by --output-version flag. If target version is not specified or -not supported, convert to latest version. - -The default output will be printed to stdout in YAML format. One can use -o option -to change to output destination. -` - convert_example = `# Convert 'pod.yaml' to latest version and print to stdout. -kubectl convert -f pod.yaml - -# Convert the live state of the resource specified by 'pod.yaml' to the latest version -# and print to stdout in json format. -kubectl convert -f pod.yaml --local -o json - -# Convert all files under current directory to latest version and create them all. -kubectl convert -f . | kubectl create -f - -` -) - -// NewCmdConvert creates a command object for the generic "convert" action, which -// translates the config file into a given version. -func NewCmdConvert(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ConvertOptions{} - - cmd := &cobra.Command{ - Use: "convert -f FILENAME", - Short: "Convert config files between different API versions", - Long: convert_long, - Example: convert_example, - Run: func(cmd *cobra.Command, args []string) { - err := options.Complete(f, out, cmd, args) - cmdutil.CheckErr(err) - err = options.RunConvert() - cmdutil.CheckErr(err) - }, - } - - usage := "Filename, directory, or URL to file to need to get converted." - kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.recursive) - cmd.MarkFlagRequired("filename") - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().BoolVar(&options.local, "local", true, "If true, convert will NOT try to contact api-server but run locally.") - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -// ConvertOptions have the data required to perform the convert operation -type ConvertOptions struct { - builder *resource.Builder - filenames []string - local bool - - encoder runtime.Encoder - out io.Writer - printer kubectl.ResourcePrinter - - outputVersion unversioned.GroupVersion - - recursive bool -} - -// Complete collects information required to run Convert command from command line. -func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { - o.outputVersion, err = cmdutil.OutputVersion(cmd, ®istered.EnabledVersionsForGroup(api.GroupName)[0]) - if err != nil { - return err - } - if !registered.IsEnabledVersion(o.outputVersion) { - cmdutil.UsageError(cmd, "'%s' is not a registered version.", o.outputVersion) - } - - // build the builder - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - clientMapper := resource.ClientMapperFunc(f.ClientForMapping) - - if o.local { - fmt.Fprintln(out, "running in local mode...") - o.builder = resource.NewBuilder(mapper, typer, resource.DisabledClientForMapping{ClientMapper: clientMapper}, f.Decoder(true)) - } else { - o.builder = resource.NewBuilder(mapper, typer, clientMapper, f.Decoder(true)) - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) - if err != nil { - return err - } - o.builder = o.builder.Schema(schema) - } - cmdNamespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } - o.builder = o.builder.NamespaceParam(cmdNamespace). - ContinueOnError(). - FilenameParam(false, o.recursive, o.filenames...). - Flatten() - - // build the printer - o.out = out - outputFormat := cmdutil.GetFlagString(cmd, "output") - templateFile := cmdutil.GetFlagString(cmd, "template") - if len(outputFormat) == 0 { - if len(templateFile) == 0 { - outputFormat = "yaml" - } else { - outputFormat = "template" - } - } - o.encoder = f.JSONEncoder() - o.printer, _, err = kubectl.GetPrinter(outputFormat, templateFile) - if err != nil { - return err - } - - return nil -} - -// RunConvert implements the generic Convert command -func (o *ConvertOptions) RunConvert() error { - r := o.builder.Do() - err := r.Err() - if err != nil { - return err - } - - count := 0 - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - infos := []*resource.Info{info} - objects, err := resource.AsVersionedObject(infos, false, o.outputVersion.String(), o.encoder) - if err != nil { - return err - } - - count++ - return o.printer.PrintObj(objects, o.out) - }) - if err != nil { - return err - } - if count == 0 { - return fmt.Errorf("no objects passed to convert") - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create.go deleted file mode 100644 index 05cc2e3de..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create.go +++ /dev/null @@ -1,262 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" -) - -// CreateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type CreateOptions struct { - Filenames []string - Recursive bool -} - -const ( - create_long = `Create a resource by filename or stdin. - -JSON and YAML formats are accepted.` - create_example = `# Create a pod using the data in pod.json. -kubectl create -f ./pod.json - -# Create a pod based on the JSON passed into stdin. -cat pod.json | kubectl create -f -` -) - -func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &CreateOptions{} - - cmd := &cobra.Command{ - Use: "create -f FILENAME", - Short: "Create a resource by filename or stdin", - Long: create_long, - Example: create_example, - Run: func(cmd *cobra.Command, args []string) { - if len(options.Filenames) == 0 { - cmd.Help() - return - } - cmdutil.CheckErr(ValidateArgs(cmd, args)) - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - cmdutil.CheckErr(RunCreate(f, cmd, out, options)) - }, - } - - usage := "Filename, directory, or URL to file to use to create the resource" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmd.MarkFlagRequired("filename") - cmdutil.AddValidateFlags(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - - // create subcommands - cmd.AddCommand(NewCmdCreateNamespace(f, out)) - cmd.AddCommand(NewCmdCreateSecret(f, out)) - cmd.AddCommand(NewCmdCreateConfigMap(f, out)) - cmd.AddCommand(NewCmdCreateServiceAccount(f, out)) - return cmd -} - -func ValidateArgs(cmd *cobra.Command, args []string) error { - if len(args) != 0 { - return cmdutil.UsageError(cmd, "Unexpected args: %v", args) - } - return nil -} - -func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateOptions) error { - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) - if err != nil { - return err - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - Schema(schema). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - count := 0 - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - } - - if err := createAndRefresh(info); err != nil { - return cmdutil.AddSourceToErr("creating", info.Source, err) - } - - count++ - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - if !shortOutput { - printObjectSpecificMessage(info.Object, out) - } - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") - return nil - }) - if err != nil { - return err - } - if count == 0 { - return fmt.Errorf("no objects passed to create") - } - return nil -} - -func printObjectSpecificMessage(obj runtime.Object, out io.Writer) { - switch obj := obj.(type) { - case *api.Service: - if obj.Spec.Type == api.ServiceTypeNodePort { - msg := fmt.Sprintf( - `You have exposed your service on an external port on all nodes in your -cluster. If you want to expose this service to the external internet, you may -need to set up firewall rules for the service port(s) (%s) to serve traffic. - -See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details. -`, - makePortsString(obj.Spec.Ports, true)) - out.Write([]byte(msg)) - } - } -} - -func makePortsString(ports []api.ServicePort, useNodePort bool) string { - pieces := make([]string, len(ports)) - for ix := range ports { - var port int32 - if useNodePort { - port = ports[ix].NodePort - } else { - port = ports[ix].Port - } - pieces[ix] = fmt.Sprintf("%s:%d", strings.ToLower(string(ports[ix].Protocol)), port) - } - return strings.Join(pieces, ",") -} - -// createAndRefresh creates an object from input info and refreshes info with that object -func createAndRefresh(info *resource.Info) error { - obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object) - if err != nil { - return err - } - info.Refresh(obj, true) - return nil -} - -// NameFromCommandArgs is a utility function for commands that assume the first argument is a resource name -func NameFromCommandArgs(cmd *cobra.Command, args []string) (string, error) { - if len(args) == 0 { - return "", cmdutil.UsageError(cmd, "NAME is required") - } - return args[0], nil -} - -// CreateSubcommandOptions is an options struct to support create subcommands -type CreateSubcommandOptions struct { - // Name of resource being created - Name string - // StructuredGenerator is the resource generator for the object being created - StructuredGenerator kubectl.StructuredGenerator - // DryRun is true if the command should be simulated but not run against the server - DryRun bool - // OutputFormat - OutputFormat string -} - -// RunCreateSubcommand executes a create subcommand using the specified options -func RunCreateSubcommand(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *CreateSubcommandOptions) error { - namespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } - obj, err := options.StructuredGenerator.StructuredGenerate() - if err != nil { - return err - } - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - gvk, err := typer.ObjectKind(obj) - mapping, err := mapper.RESTMapping(unversioned.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, gvk.Version) - if err != nil { - return err - } - client, err := f.ClientForMapping(mapping) - if err != nil { - return err - } - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - } - info, err := resourceMapper.InfoForObject(obj, nil) - if err != nil { - return err - } - if err := kubectl.UpdateApplyAnnotation(info, f.JSONEncoder()); err != nil { - return err - } - if !options.DryRun { - obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) - if err != nil { - return err - } - } - - if useShortOutput := options.OutputFormat == "name"; useShortOutput || len(options.OutputFormat) == 0 { - cmdutil.PrintSuccess(mapper, useShortOutput, out, mapping.Resource, options.Name, "created") - return nil - } - - return f.PrintObject(cmd, mapper, obj, out) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap.go deleted file mode 100644 index 6af079205..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap.go +++ /dev/null @@ -1,96 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -const ( - configMapLong = `Create a configmap based on a file, directory, or specified literal value. - -A single configmap may package one or more key/value pairs. - -When creating a configmap based on a file, the key will default to the basename of the file, and the value will -default to the file content. If the basename is an invalid key, you may specify an alternate key. - -When creating a configmap based on a directory, each file whose basename is a valid key in the directory will be -packaged into the configmap. Any directory entries except regular files are ignored (e.g. subdirectories, -symlinks, devices, pipes, etc). -` - - configMapExample = ` # Create a new configmap named my-config with keys for each file in folder bar - kubectl create configmap my-config --from-file=path/to/bar - - # Create a new configmap named my-config with specified keys instead of names on disk - kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt - - # Create a new configMap named my-config with key1=config1 and key2=config2 - kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2` -) - -// ConfigMap is a command to ease creating ConfigMaps. -func NewCmdCreateConfigMap(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", - Short: "Create a configMap from a local file, directory or literal value.", - Long: configMapLong, - Example: configMapExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateConfigMap(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.ConfigMapV1GeneratorName) - cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid configmap key.") - cmd.Flags().StringSlice("from-literal", []string{}, "Specify a key and literal value to insert in configmap (i.e. mykey=somevalue)") - return cmd -} - -// CreateConfigMap is the implementation of the create configmap command. -func CreateConfigMap(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.ConfigMapV1GeneratorName: - generator = &kubectl.ConfigMapGeneratorV1{ - Name: name, - FileSources: cmdutil.GetFlagStringSlice(cmd, "from-file"), - LiteralSources: cmdutil.GetFlagStringSlice(cmd, "from-literal"), - } - default: - return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName)) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetFlagBool(cmd, "dry-run"), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap_test.go deleted file mode 100644 index 9c3971e36..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_configmap_test.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestCreateConfigMap(t *testing.T) { - configMap := &api.ConfigMap{} - configMap.Name = "my-configmap" - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/configmaps" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, configMap)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateConfigMap(f, buf) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{configMap.Name}) - expectedOutput := "configmap/" + configMap.Name + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", buf.String(), expectedOutput) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace.go deleted file mode 100644 index 299c5e940..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -const ( - namespaceLong = ` -Create a namespace with the specified name.` - - namespaceExample = ` # Create a new namespace named my-namespace - kubectl create namespace my-namespace` -) - -// NewCmdCreateNamespace is a macro command to create a new namespace -func NewCmdCreateNamespace(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "namespace NAME [--dry-run]", - Aliases: []string{"ns"}, - Short: "Create a namespace with the specified name.", - Long: namespaceLong, - Example: namespaceExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateNamespace(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.NamespaceV1GeneratorName) - - return cmd -} - -// CreateNamespace implements the behavior to run the create namespace command -func CreateNamespace(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.NamespaceV1GeneratorName: - generator = &kubectl.NamespaceGeneratorV1{Name: name} - default: - return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName)) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetFlagBool(cmd, "dry-run"), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace_test.go deleted file mode 100644 index dd74eec4b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_namespace_test.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestCreateNamespace(t *testing.T) { - namespaceObject := &api.Namespace{} - namespaceObject.Name = "my-namespace" - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, namespaceObject)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateNamespace(f, buf) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{namespaceObject.Name}) - expectedOutput := "namespace/" + namespaceObject.Name + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", buf.String(), expectedOutput) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret.go deleted file mode 100644 index 48cb8f99b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret.go +++ /dev/null @@ -1,194 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -// NewCmdCreateSecret groups subcommands to create various types of secrets -func NewCmdCreateSecret(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "secret", - Short: "Create a secret using specified subcommand.", - Long: "Create a secret using specified subcommand.", - Run: func(cmd *cobra.Command, args []string) { - cmd.Help() - }, - } - cmd.AddCommand(NewCmdCreateSecretDockerRegistry(f, cmdOut)) - cmd.AddCommand(NewCmdCreateSecretGeneric(f, cmdOut)) - - return cmd -} - -const ( - secretLong = ` -Create a secret based on a file, directory, or specified literal value. - -A single secret may package one or more key/value pairs. - -When creating a secret based on a file, the key will default to the basename of the file, and the value will -default to the file content. If the basename is an invalid key, you may specify an alternate key. - -When creating a secret based on a directory, each file whose basename is a valid key in the directory will be -packaged into the secret. Any directory entries except regular files are ignored (e.g. subdirectories, -symlinks, devices, pipes, etc). -` - - secretExample = ` # Create a new secret named my-secret with keys for each file in folder bar - kubectl create secret generic my-secret --from-file=path/to/bar - - # Create a new secret named my-secret with specified keys instead of names on disk - kubectl create secret generic my-secret --from-file=ssh-privatekey=~/.ssh/id_rsa --from-file=ssh-publickey=~/.ssh/id_rsa.pub - - # Create a new secret named my-secret with key1=supersecret and key2=topsecret - kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret` -) - -// NewCmdCreateSecretGeneric is a command to create generic secrets from files, directories, or literal values -func NewCmdCreateSecretGeneric(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "generic NAME [--type=string] [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run]", - Short: "Create a secret from a local file, directory or literal value.", - Long: secretLong, - Example: secretExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateSecretGeneric(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretV1GeneratorName) - cmd.Flags().StringSlice("from-file", []string{}, "Key files can be specified using their file path, in which case a default name will be given to them, or optionally with a name and file path, in which case the given name will be used. Specifying a directory will iterate each named file in the directory that is a valid secret key.") - cmd.Flags().StringSlice("from-literal", []string{}, "Specify a key and literal value to insert in secret (i.e. mykey=somevalue)") - cmd.Flags().String("type", "", "The type of secret to create") - return cmd -} - -// CreateSecretGeneric is the implementation of the create secret generic command -func CreateSecretGeneric(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.SecretV1GeneratorName: - generator = &kubectl.SecretGeneratorV1{ - Name: name, - Type: cmdutil.GetFlagString(cmd, "type"), - FileSources: cmdutil.GetFlagStringSlice(cmd, "from-file"), - LiteralSources: cmdutil.GetFlagStringSlice(cmd, "from-literal"), - } - default: - return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName)) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetFlagBool(cmd, "dry-run"), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} - -const ( - secretForDockerRegistryLong = ` -Create a new secret for use with Docker registries. - -Dockercfg secrets are used to authenticate against Docker registries. - -When using the Docker command line to push images, you can authenticate to a given registry by running - 'docker login DOCKER_REGISTRY_SERVER --username=DOCKER_USER --password=DOCKER_PASSWORD --email=DOCKER_EMAIL'. -That produces a ~/.dockercfg file that is used by subsequent 'docker push' and 'docker pull' commands to -authenticate to the registry. - -When creating applications, you may have a Docker registry that requires authentication. In order for the -nodes to pull images on your behalf, they have to have the credentials. You can provide this information -by creating a dockercfg secret and attaching it to your service account.` - - secretForDockerRegistryExample = ` # If you don't already have a .dockercfg file, you can create a dockercfg secret directly by using: - $ kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL` -) - -// NewCmdCreateSecretDockerRegistry is a macro command for creating secrets to work with Docker registries -func NewCmdCreateSecretDockerRegistry(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "docker-registry NAME --docker-username=user --docker-password=password --docker-email=email [--docker-server=string] [--from-literal=key1=value1] [--dry-run]", - Short: "Create a secret for use with a Docker registry.", - Long: secretForDockerRegistryLong, - Example: secretForDockerRegistryExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateSecretDockerRegistry(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.SecretForDockerRegistryV1GeneratorName) - cmd.Flags().String("docker-username", "", "Username for Docker registry authentication") - cmd.MarkFlagRequired("docker-username") - cmd.Flags().String("docker-password", "", "Password for Docker registry authentication") - cmd.MarkFlagRequired("docker-password") - cmd.Flags().String("docker-email", "", "Email for Docker registry") - cmd.MarkFlagRequired("docker-email") - cmd.Flags().String("docker-server", "https://index.docker.io/v1/", "Server location for Docker registry") - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -// CreateSecretDockerRegistry is the implementation of the create secret docker-registry command -func CreateSecretDockerRegistry(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - requiredFlags := []string{"docker-username", "docker-password", "docker-email", "docker-server"} - for _, requiredFlag := range requiredFlags { - if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 { - return cmdutil.UsageError(cmd, "flag %s is required", requiredFlag) - } - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.SecretForDockerRegistryV1GeneratorName: - generator = &kubectl.SecretForDockerRegistryGeneratorV1{ - Name: name, - Username: cmdutil.GetFlagString(cmd, "docker-username"), - Email: cmdutil.GetFlagString(cmd, "docker-email"), - Password: cmdutil.GetFlagString(cmd, "docker-password"), - Server: cmdutil.GetFlagString(cmd, "docker-server"), - } - default: - return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName)) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetFlagBool(cmd, "dry-run"), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret_test.go deleted file mode 100644 index 8365513eb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_secret_test.go +++ /dev/null @@ -1,85 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestCreateSecretGeneric(t *testing.T) { - secretObject := &api.Secret{} - secretObject.Name = "my-secret" - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/secrets" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, secretObject)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateSecretGeneric(f, buf) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{secretObject.Name}) - expectedOutput := "secret/" + secretObject.Name + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", buf.String(), expectedOutput) - } -} - -func TestCreateSecretDockerRegistry(t *testing.T) { - secretObject := &api.Secret{} - secretObject.Name = "my-secret" - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/secrets" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, secretObject)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateSecretDockerRegistry(f, buf) - cmd.Flags().Set("docker-username", "test-user") - cmd.Flags().Set("docker-password", "test-pass") - cmd.Flags().Set("docker-email", "test-email") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{secretObject.Name}) - expectedOutput := "secret/" + secretObject.Name + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", buf.String(), expectedOutput) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount.go deleted file mode 100644 index 61d2d3cc5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -const ( - serviceAccountLong = ` -Create a service account with the specified name.` - - serviceAccountExample = ` # Create a new service account named my-service-account - $ kubectl create serviceaccount my-service-account` -) - -// NewCmdCreateServiceAccount is a macro command to create a new service account -func NewCmdCreateServiceAccount(f *cmdutil.Factory, cmdOut io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "serviceaccount NAME [--dry-run]", - Aliases: []string{"sa"}, - Short: "Create a service account with the specified name.", - Long: serviceAccountLong, - Example: serviceAccountExample, - Run: func(cmd *cobra.Command, args []string) { - err := CreateServiceAccount(f, cmdOut, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - cmdutil.AddGeneratorFlags(cmd, cmdutil.ServiceAccountV1GeneratorName) - return cmd -} - -// CreateServiceAccount implements the behavior to run the create service account command -func CreateServiceAccount(f *cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { - name, err := NameFromCommandArgs(cmd, args) - if err != nil { - return err - } - var generator kubectl.StructuredGenerator - switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { - case cmdutil.ServiceAccountV1GeneratorName: - generator = &kubectl.ServiceAccountGeneratorV1{Name: name} - default: - return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName)) - } - return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ - Name: name, - StructuredGenerator: generator, - DryRun: cmdutil.GetFlagBool(cmd, "dry-run"), - OutputFormat: cmdutil.GetFlagString(cmd, "output"), - }) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount_test.go deleted file mode 100644 index 6573e6d02..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_serviceaccount_test.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestCreateServiceAccount(t *testing.T) { - serviceAccountObject := &api.ServiceAccount{} - serviceAccountObject.Name = "my-service-account" - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/serviceaccounts" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, serviceAccountObject)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdCreateServiceAccount(f, buf) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{serviceAccountObject.Name}) - expectedOutput := "serviceaccount/" + serviceAccountObject.Name + "\n" - if buf.String() != expectedOutput { - t.Errorf("expected output: %s, but got: %s", expectedOutput, buf.String()) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_test.go deleted file mode 100644 index 005b5faee..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/create_test.go +++ /dev/null @@ -1,230 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestExtraArgsFail(t *testing.T) { - initTestErrorHandler(t) - buf := bytes.NewBuffer([]byte{}) - - f, _, _ := NewAPIFactory() - c := NewCmdCreate(f, buf) - if ValidateArgs(c, []string{"rc"}) == nil { - t.Errorf("unexpected non-error") - } -} - -func TestCreateObject(t *testing.T) { - initTestErrorHandler(t) - _, _, rc := testData() - rc.Items[0].Name = "redis-master-controller" - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreate(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // uses the name from the file, not the response - if buf.String() != "replicationcontroller/redis-master-controller\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestCreateMultipleObject(t *testing.T) { - initTestErrorHandler(t) - _, svc, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/services" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &svc.Items[0])}, nil - case p == "/namespaces/test/replicationcontrollers" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreate(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // Names should come from the REST response, NOT the files - if buf.String() != "replicationcontroller/rc1\nservice/baz\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestCreateDirectory(t *testing.T) { - initTestErrorHandler(t) - _, _, rc := testData() - rc.Items[0].Name = "name" - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdCreate(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/name\nreplicationcontroller/name\nreplicationcontroller/name\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestPrintObjectSpecificMessage(t *testing.T) { - initTestErrorHandler(t) - tests := []struct { - obj runtime.Object - expectOutput bool - }{ - { - obj: &api.Service{}, - expectOutput: false, - }, - { - obj: &api.Pod{}, - expectOutput: false, - }, - { - obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeLoadBalancer}}, - expectOutput: false, - }, - { - obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeNodePort}}, - expectOutput: true, - }, - } - for _, test := range tests { - buff := &bytes.Buffer{} - printObjectSpecificMessage(test.obj, buff) - if test.expectOutput && buff.Len() == 0 { - t.Errorf("Expected output, saw none for %v", test.obj) - } - if !test.expectOutput && buff.Len() > 0 { - t.Errorf("Expected no output, saw %s for %v", buff.String(), test.obj) - } - } -} - -func TestMakePortsString(t *testing.T) { - initTestErrorHandler(t) - tests := []struct { - ports []api.ServicePort - useNodePort bool - expectedOutput string - }{ - {ports: nil, expectedOutput: ""}, - {ports: []api.ServicePort{}, expectedOutput: ""}, - {ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - }, - expectedOutput: "tcp:80", - }, - {ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - { - Port: 8080, - Protocol: "UDP", - }, - { - Port: 9000, - Protocol: "TCP", - }, - }, - expectedOutput: "tcp:80,udp:8080,tcp:9000", - }, - {ports: []api.ServicePort{ - { - Port: 80, - NodePort: 9090, - Protocol: "TCP", - }, - { - Port: 8080, - NodePort: 80, - Protocol: "UDP", - }, - }, - useNodePort: true, - expectedOutput: "tcp:9090,udp:80", - }, - } - for _, test := range tests { - output := makePortsString(test.ports, test.useNodePort) - if output != test.expectedOutput { - t.Errorf("expected: %s, saw: %s.", test.expectedOutput, output) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/delete.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/delete.go deleted file mode 100644 index 2982dee1e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/delete.go +++ /dev/null @@ -1,227 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "time" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" -) - -// DeleteOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type DeleteOptions struct { - Filenames []string - Recursive bool -} - -const ( - delete_long = `Delete resources by filenames, stdin, resources and names, or by resources and label selector. - -JSON and YAML formats are accepted. - -Only one type of the arguments may be specified: filenames, resources and names, or resources and label selector - -Note that the delete command does NOT do resource version checks, so if someone -submits an update to a resource right when you submit a delete, their update -will be lost along with the rest of the resource.` - delete_example = `# Delete a pod using the type and name specified in pod.json. -kubectl delete -f ./pod.json - -# Delete a pod based on the type and name in the JSON passed into stdin. -cat pod.json | kubectl delete -f - - -# Delete pods and services with same names "baz" and "foo" -kubectl delete pod,service baz foo - -# Delete pods and services with label name=myLabel. -kubectl delete pods,services -l name=myLabel - -# Delete a pod immediately (no graceful shutdown) -kubectl delete pod foo --now - -# Delete a pod with UID 1234-56-7890-234234-456456. -kubectl delete pod 1234-56-7890-234234-456456 - -# Delete all pods -kubectl delete pods --all` -) - -func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DeleteOptions{} - - // retrieve a list of handled resources from printer as valid args - validArgs, argAliases := []string{}, []string{} - p, err := f.Printer(nil, false, false, false, false, false, false, []string{}) - cmdutil.CheckErr(err) - if p != nil { - validArgs = p.HandledResources() - argAliases = kubectl.ResourceAliases(validArgs) - } - - cmd := &cobra.Command{ - Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])", - Short: "Delete resources by filenames, stdin, resources and names, or by resources and label selector.", - Long: delete_long, - Example: delete_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - err := RunDelete(f, out, cmd, args, options) - cmdutil.CheckErr(err) - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - usage := "Filename, directory, or URL to a file containing the resource to delete." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.") - cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.") - cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful delete. Defaults to \"true\" when --all is specified.") - cmd.Flags().Bool("cascade", true, "If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.") - cmd.Flags().Int("grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.") - cmd.Flags().Bool("now", false, "If true, resources are force terminated without graceful deletion (same as --grace-period=0).") - cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object") - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DeleteOptions) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - deleteAll := cmdutil.GetFlagBool(cmd, "all") - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - SelectorParam(cmdutil.GetFlagString(cmd, "selector")). - SelectAllParam(deleteAll). - ResourceTypeOrNameArgs(false, args...).RequireObject(false). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - ignoreNotFound := cmdutil.GetFlagBool(cmd, "ignore-not-found") - if deleteAll { - f := cmd.Flags().Lookup("ignore-not-found") - // The flag should never be missing - if f == nil { - return fmt.Errorf("missing --ignore-not-found flag") - } - // If the user didn't explicitly set the option, default to ignoring NotFound errors when used with --all - if !f.Changed { - ignoreNotFound = true - } - } - - gracePeriod := cmdutil.GetFlagInt(cmd, "grace-period") - if cmdutil.GetFlagBool(cmd, "now") { - if gracePeriod != -1 { - return fmt.Errorf("--now and --grace-period cannot be specified together") - } - gracePeriod = 0 - } - - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - // By default use a reaper to delete all related resources. - if cmdutil.GetFlagBool(cmd, "cascade") { - return ReapResult(r, f, out, cmdutil.GetFlagBool(cmd, "cascade"), ignoreNotFound, cmdutil.GetFlagDuration(cmd, "timeout"), gracePeriod, shortOutput, mapper) - } - return DeleteResult(r, out, ignoreNotFound, shortOutput, mapper) -} - -func ReapResult(r *resource.Result, f *cmdutil.Factory, out io.Writer, isDefaultDelete, ignoreNotFound bool, timeout time.Duration, gracePeriod int, shortOutput bool, mapper meta.RESTMapper) error { - found := 0 - if ignoreNotFound { - r = r.IgnoreErrors(errors.IsNotFound) - } - err := r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - found++ - reaper, err := f.Reaper(info.Mapping) - if err != nil { - // If there is no reaper for this resources and the user didn't explicitly ask for stop. - if kubectl.IsNoSuchReaperError(err) && isDefaultDelete { - return deleteResource(info, out, shortOutput, mapper) - } - return cmdutil.AddSourceToErr("reaping", info.Source, err) - } - var options *api.DeleteOptions - if gracePeriod >= 0 { - options = api.NewDeleteOptions(int64(gracePeriod)) - } - if err := reaper.Stop(info.Namespace, info.Name, timeout, options); err != nil { - return cmdutil.AddSourceToErr("stopping", info.Source, err) - } - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "deleted") - return nil - }) - if err != nil { - return err - } - if found == 0 { - fmt.Fprintf(out, "No resources found\n") - } - return nil -} - -func DeleteResult(r *resource.Result, out io.Writer, ignoreNotFound bool, shortOutput bool, mapper meta.RESTMapper) error { - found := 0 - if ignoreNotFound { - r = r.IgnoreErrors(errors.IsNotFound) - } - err := r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - found++ - return deleteResource(info, out, shortOutput, mapper) - }) - if err != nil { - return err - } - if found == 0 { - fmt.Fprintf(out, "No resources found\n") - } - return nil -} - -func deleteResource(info *resource.Info, out io.Writer, shortOutput bool, mapper meta.RESTMapper) error { - if err := resource.NewHelper(info.Client, info.Mapping).Delete(info.Namespace, info.Name); err != nil { - return cmdutil.AddSourceToErr("deleting", info.Source, err) - } - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "deleted") - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/delete_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/delete_test.go deleted file mode 100644 index 5e3cf3c99..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/delete_test.go +++ /dev/null @@ -1,449 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestDeleteObjectByTuple(t *testing.T) { - _, _, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - default: - // Ensures no GET is performed when deleting by name - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("namespace", "test") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{"replicationcontrollers/redis-master-controller"}) - - if buf.String() != "replicationcontroller/redis-master-controller\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteNamedObject(t *testing.T) { - _, _, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master-controller" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - default: - // Ensures no GET is performed when deleting by name - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("namespace", "test") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{"replicationcontrollers", "redis-master-controller"}) - - if buf.String() != "replicationcontroller/redis-master-controller\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteObject(t *testing.T) { - _, _, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // uses the name from the file, not the response - if buf.String() != "replicationcontroller/redis-master\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteObjectNotFound(t *testing.T) { - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": - return &http.Response{StatusCode: 404, Body: stringBody("")}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - options := &DeleteOptions{ - Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml"}, - } - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - err := RunDelete(f, buf, cmd, []string{}, options) - if err == nil || !errors.IsNotFound(err) { - t.Errorf("unexpected error: expected NotFound, got %v", err) - } -} - -func TestDeleteObjectIgnoreNotFound(t *testing.T) { - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": - return &http.Response{StatusCode: 404, Body: stringBody("")}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("ignore-not-found", "true") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteAllNotFound(t *testing.T) { - _, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - - // Add an item to the list which will result in a 404 on delete - svc.Items = append(svc.Items, api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - notFoundError := &errors.NewNotFound(api.Resource("services"), "foo").(*errors.StatusError).ErrStatus - - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/services" && m == "GET": - return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil - case p == "/namespaces/test/services/foo" && m == "DELETE": - return &http.Response{StatusCode: 404, Body: objBody(codec, notFoundError)}, nil - case p == "/namespaces/test/services/baz" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("all", "true") - cmd.Flags().Set("cascade", "false") - // Make sure we can explicitly choose to fail on NotFound errors, even with --all - cmd.Flags().Set("ignore-not-found", "false") - cmd.Flags().Set("output", "name") - - err := RunDelete(f, buf, cmd, []string{"services"}, &DeleteOptions{}) - if err == nil || !errors.IsNotFound(err) { - t.Errorf("unexpected error: expected NotFound, got %v", err) - } -} - -func TestDeleteAllIgnoreNotFound(t *testing.T) { - _, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - - // Add an item to the list which will result in a 404 on delete - svc.Items = append(svc.Items, api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - notFoundError := &errors.NewNotFound(api.Resource("services"), "foo").(*errors.StatusError).ErrStatus - - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/services" && m == "GET": - return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil - case p == "/namespaces/test/services/foo" && m == "DELETE": - return &http.Response{StatusCode: 404, Body: objBody(codec, notFoundError)}, nil - case p == "/namespaces/test/services/baz" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("all", "true") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{"services"}) - - if buf.String() != "service/baz\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteMultipleObject(t *testing.T) { - _, svc, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - case p == "/namespaces/test/services/frontend" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/redis-master\nservice/frontend\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) { - _, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": - return &http.Response{StatusCode: 404, Body: stringBody("")}, nil - case p == "/namespaces/test/services/frontend" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - options := &DeleteOptions{ - Filenames: []string{"../../../examples/guestbook/legacy/redis-master-controller.yaml", "../../../examples/guestbook/frontend-service.yaml"}, - } - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - err := RunDelete(f, buf, cmd, []string{}, options) - if err == nil || !errors.IsNotFound(err) { - t.Errorf("unexpected error: expected NotFound, got %v", err) - } - - if buf.String() != "service/frontend\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteMultipleResourcesWithTheSameName(t *testing.T) { - _, svc, rc := testData() - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/baz" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - case p == "/namespaces/test/replicationcontrollers/foo" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - case p == "/namespaces/test/services/baz" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - case p == "/namespaces/test/services/foo" && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - // Ensures no GET is performed when deleting by name - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("namespace", "test") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{"replicationcontrollers,services", "baz", "foo"}) - if buf.String() != "replicationcontroller/baz\nreplicationcontroller/foo\nservice/baz\nservice/foo\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteDirectory(t *testing.T) { - _, _, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/frontend\nreplicationcontroller/redis-master\nreplicationcontroller/redis-slave\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDeleteMultipleSelector(t *testing.T) { - pods, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/pods" && m == "GET": - if req.URL.Query().Get(unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String())) != "a=b" { - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - } - return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil - case p == "/namespaces/test/services" && m == "GET": - if req.URL.Query().Get(unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String())) != "a=b" { - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - } - return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil - case strings.HasPrefix(p, "/namespaces/test/pods/") && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - case strings.HasPrefix(p, "/namespaces/test/services/") && m == "DELETE": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDelete(f, buf) - cmd.Flags().Set("selector", "a=b") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{"pods,services"}) - - if buf.String() != "pod/foo\npod/bar\nservice/baz\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/describe.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/describe.go deleted file mode 100644 index e16c5756d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/describe.go +++ /dev/null @@ -1,189 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "strings" - - "github.com/spf13/cobra" - - apierrors "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - utilerrors "k8s.io/kubernetes/pkg/util/errors" -) - -// DescribeOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type DescribeOptions struct { - Filenames []string - Recursive bool -} - -const ( - describe_long = `Show details of a specific resource or group of resources. - -This command joins many API calls together to form a detailed description of a -given resource or group of resources. - -$ kubectl describe TYPE NAME_PREFIX - -will first check for an exact match on TYPE and NAME_PREFIX. If no such resource -exists, it will output details for every resource that has a name prefixed with NAME_PREFIX - -` + kubectl.PossibleResourceTypes - describe_example = `# Describe a node -kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal - -# Describe a pod -kubectl describe pods/nginx - -# Describe a pod identified by type and name in "pod.json" -kubectl describe -f pod.json - -# Describe all pods -kubectl describe pods - -# Describe pods by label name=myLabel -kubectl describe po -l name=myLabel - -# Describe all pods managed by the 'frontend' replication controller (rc-created pods -# get the name of the rc as a prefix in the pod the name). -kubectl describe pods frontend` -) - -func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DescribeOptions{} - describerSettings := &kubectl.DescriberSettings{} - - validArgs := kubectl.DescribableResources() - argAliases := kubectl.ResourceAliases(validArgs) - - cmd := &cobra.Command{ - Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)", - Short: "Show details of a specific resource or group of resources", - Long: describe_long, - Example: describe_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunDescribe(f, out, cmd, args, options, describerSettings) - cmdutil.CheckErr(err) - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - usage := "Filename, directory, or URL to a file containing the resource to describe" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") - cmd.Flags().BoolVar(&describerSettings.ShowEvents, "show-events", true, "If true, display events related to the described object.") - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DescribeOptions, describerSettings *kubectl.DescriberSettings) error { - selector := cmdutil.GetFlagString(cmd, "selector") - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - if len(args) == 0 && len(options.Filenames) == 0 { - fmt.Fprint(out, "You must specify the type of resource to describe. ", valid_resources) - return cmdutil.UsageError(cmd, "Required resource not specified.") - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - SelectorParam(selector). - ResourceTypeOrNameArgs(true, args...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - allErrs := []error{} - infos, err := r.Infos() - if err != nil { - if apierrors.IsNotFound(err) && len(args) == 2 { - return DescribeMatchingResources(mapper, typer, f, cmdNamespace, args[0], args[1], describerSettings, out, err) - } - allErrs = append(allErrs, err) - } - - for _, info := range infos { - mapping := info.ResourceMapping() - describer, err := f.Describer(mapping) - if err != nil { - allErrs = append(allErrs, err) - continue - } - s, err := describer.Describe(info.Namespace, info.Name, *describerSettings) - if err != nil { - allErrs = append(allErrs, err) - continue - } - fmt.Fprintf(out, "%s\n\n", s) - } - - return utilerrors.NewAggregate(allErrs) -} - -func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper, f *cmdutil.Factory, namespace, rsrc, prefix string, describerSettings *kubectl.DescriberSettings, out io.Writer, originalError error) error { - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(namespace).DefaultNamespace(). - ResourceTypeOrNameArgs(true, rsrc). - SingleResourceType(). - Flatten(). - Do() - mapping, err := r.ResourceMapping() - if err != nil { - return err - } - describer, err := f.Describer(mapping) - if err != nil { - return err - } - infos, err := r.Infos() - if err != nil { - return err - } - isFound := false - for ix := range infos { - info := infos[ix] - if strings.HasPrefix(info.Name, prefix) { - isFound = true - s, err := describer.Describe(info.Namespace, info.Name, *describerSettings) - if err != nil { - return err - } - fmt.Fprintf(out, "%s\n", s) - } - } - if !isFound { - return originalError - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/describe_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/describe_test.go deleted file mode 100644 index c8b9905ec..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/describe_test.go +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "fmt" - "net/http" - "testing" - - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. -func TestDescribeUnknownSchemaObject(t *testing.T) { - d := &testDescriber{Output: "test output"} - f, tf, codec := NewTestFactory() - tf.Describer = d - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &internalType{Name: "foo"})}, - } - tf.Namespace = "non-default" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDescribe(f, buf) - cmd.Run(cmd, []string{"type", "foo"}) - - if d.Name != "foo" || d.Namespace != "non-default" { - t.Errorf("unexpected describer: %#v", d) - } - - if buf.String() != fmt.Sprintf("%s\n\n", d.Output) { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDescribeObject(t *testing.T) { - _, _, rc := testData() - f, tf, codec := NewAPIFactory() - d := &testDescriber{Output: "test output"} - tf.Describer = d - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "GET": - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdDescribe(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Run(cmd, []string{}) - - if d.Name != "redis-master" || d.Namespace != "test" { - t.Errorf("unexpected describer: %#v", d) - } - - if buf.String() != fmt.Sprintf("%s\n\n", d.Output) { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDescribeListObjects(t *testing.T) { - pods, _, _ := testData() - f, tf, codec := NewAPIFactory() - d := &testDescriber{Output: "test output"} - tf.Describer = d - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, - } - - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(f, buf) - cmd.Run(cmd, []string{"pods"}) - if buf.String() != fmt.Sprintf("%s\n\n%s\n\n", d.Output, d.Output) { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestDescribeObjectShowEvents(t *testing.T) { - pods, _, _ := testData() - f, tf, codec := NewAPIFactory() - d := &testDescriber{Output: "test output"} - tf.Describer = d - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, - } - - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(f, buf) - cmd.Flags().Set("show-events", "true") - cmd.Run(cmd, []string{"pods"}) - if d.Settings.ShowEvents != true { - t.Errorf("ShowEvents = true expected, got ShowEvents = %v", d.Settings.ShowEvents) - } -} - -func TestDescribeObjectSkipEvents(t *testing.T) { - pods, _, _ := testData() - f, tf, codec := NewAPIFactory() - d := &testDescriber{Output: "test output"} - tf.Describer = d - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, - } - - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdDescribe(f, buf) - cmd.Flags().Set("show-events", "false") - cmd.Run(cmd, []string{"pods"}) - if d.Settings.ShowEvents != false { - t.Errorf("ShowEvents = false expected, got ShowEvents = %v", d.Settings.ShowEvents) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/drain.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/drain.go deleted file mode 100644 index 6be2cc4b9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/drain.go +++ /dev/null @@ -1,385 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "errors" - "fmt" - "io" - "reflect" - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/controller" - // "k8s.io/kubernetes/pkg/api/unversioned" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/fields" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/kubelet/types" - "k8s.io/kubernetes/pkg/runtime" -) - -type DrainOptions struct { - client *client.Client - factory *cmdutil.Factory - Force bool - GracePeriodSeconds int - IgnoreDaemonsets bool - mapper meta.RESTMapper - nodeInfo *resource.Info - out io.Writer - typer runtime.ObjectTyper -} - -const ( - cordon_long = `Mark node as unschedulable. -` - cordon_example = `# Mark node "foo" as unschedulable. -kubectl cordon foo -` -) - -func NewCmdCordon(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DrainOptions{factory: f, out: out} - - cmd := &cobra.Command{ - Use: "cordon NODE", - Short: "Mark node as unschedulable", - Long: cordon_long, - Example: cordon_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.SetupDrain(cmd, args)) - cmdutil.CheckErr(options.RunCordonOrUncordon(true)) - }, - } - return cmd -} - -const ( - uncordon_long = `Mark node as schedulable. -` - uncordon_example = `# Mark node "foo" as schedulable. -$ kubectl uncordon foo -` -) - -func NewCmdUncordon(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DrainOptions{factory: f, out: out} - - cmd := &cobra.Command{ - Use: "uncordon NODE", - Short: "Mark node as schedulable", - Long: uncordon_long, - Example: uncordon_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.SetupDrain(cmd, args)) - cmdutil.CheckErr(options.RunCordonOrUncordon(false)) - }, - } - return cmd -} - -const ( - drain_long = `Drain node in preparation for maintenance. - -The given node will be marked unschedulable to prevent new pods from arriving. -Then drain deletes all pods except mirror pods (which cannot be deleted through -the API server). If there are DaemonSet-managed pods, drain will not proceed -without --ignore-daemonsets, and regardless it will not delete any -DaemonSet-managed pods, because those pods would be immediately replaced by the -DaemonSet controller, which ignores unschedulable markings. If there are any -pods that are neither mirror pods nor managed--by ReplicationController, -ReplicaSet, DaemonSet or Job--, then drain will not delete any pods unless you -use --force. - -When you are ready to put the node back into service, use kubectl uncordon, which -will make the node schedulable again. -` - drain_example = `# Drain node "foo", even if there are pods not managed by a ReplicationController, ReplicaSet, Job, or DaemonSet on it. -$ kubectl drain foo --force - -# As above, but abort if there are pods not managed by a ReplicationController, ReplicaSet, Job, or DaemonSet, and use a grace period of 15 minutes. -$ kubectl drain foo --grace-period=900 -` -) - -func NewCmdDrain(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &DrainOptions{factory: f, out: out} - - cmd := &cobra.Command{ - Use: "drain NODE", - Short: "Drain node in preparation for maintenance", - Long: drain_long, - Example: drain_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.SetupDrain(cmd, args)) - cmdutil.CheckErr(options.RunDrain()) - }, - } - cmd.Flags().BoolVar(&options.Force, "force", false, "Continue even if there are pods not managed by a ReplicationController, ReplicaSet, Job, or DaemonSet.") - cmd.Flags().BoolVar(&options.IgnoreDaemonsets, "ignore-daemonsets", false, "Ignore DaemonSet-managed pods.") - cmd.Flags().IntVar(&options.GracePeriodSeconds, "grace-period", -1, "Period of time in seconds given to each pod to terminate gracefully. If negative, the default value specified in the pod will be used.") - return cmd -} - -// SetupDrain populates some fields from the factory, grabs command line -// arguments and looks up the node using Builder -func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { - var err error - if len(args) != 1 { - return cmdutil.UsageError(cmd, fmt.Sprintf("USAGE: %s [flags]", cmd.Use)) - } - - if o.client, err = o.factory.Client(); err != nil { - return err - } - - o.mapper, o.typer = o.factory.Object(false) - - cmdNamespace, _, err := o.factory.DefaultNamespace() - if err != nil { - return err - } - - r := o.factory.NewBuilder(cmdutil.GetIncludeThirdPartyAPIs(cmd)). - NamespaceParam(cmdNamespace).DefaultNamespace(). - ResourceNames("node", args[0]). - Do() - - if err = r.Err(); err != nil { - return err - } - - return r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - o.nodeInfo = info - return nil - }) -} - -// RunDrain runs the 'drain' command -func (o *DrainOptions) RunDrain() error { - if err := o.RunCordonOrUncordon(true); err != nil { - return err - } - - pods, err := o.GetPodsForDeletion() - if err != nil { - return err - } - - if err = o.deletePods(pods); err != nil { - return err - } - cmdutil.PrintSuccess(o.mapper, false, o.out, "node", o.nodeInfo.Name, "drained") - return nil -} - -// GetPodsForDeletion returns all the pods we're going to delete. If there are -// any unmanaged pods and the user didn't pass --force, we return that list in -// an error. -func (o *DrainOptions) GetPodsForDeletion() ([]api.Pod, error) { - pods := []api.Pod{} - podList, err := o.client.Pods(api.NamespaceAll).List(api.ListOptions{FieldSelector: fields.SelectorFromSet(fields.Set{"spec.nodeName": o.nodeInfo.Name})}) - if err != nil { - return pods, err - } - unreplicatedPodNames := []string{} - daemonSetPodNames := []string{} - - for _, pod := range podList.Items { - _, found := pod.ObjectMeta.Annotations[types.ConfigMirrorAnnotationKey] - if found { - // Skip mirror pod - continue - } - replicated := false - daemonset_pod := false - - creatorRef, found := pod.ObjectMeta.Annotations[controller.CreatedByAnnotation] - if found { - // Now verify that the specified creator actually exists. - var sr api.SerializedReference - if err := runtime.DecodeInto(o.factory.Decoder(true), []byte(creatorRef), &sr); err != nil { - return pods, err - } - if sr.Reference.Kind == "ReplicationController" { - rc, err := o.client.ReplicationControllers(sr.Reference.Namespace).Get(sr.Reference.Name) - // Assume the only reason for an error is because the RC is - // gone/missing, not for any other cause. TODO(mml): something more - // sophisticated than this - if err == nil && rc != nil { - replicated = true - } - } else if sr.Reference.Kind == "DaemonSet" { - ds, err := o.client.DaemonSets(sr.Reference.Namespace).Get(sr.Reference.Name) - - // Assume the only reason for an error is because the DaemonSet is - // gone/missing, not for any other cause. TODO(mml): something more - // sophisticated than this - if err == nil && ds != nil { - // Otherwise, treat daemonset-managed pods as unmanaged since - // DaemonSet Controller currently ignores the unschedulable bit. - // FIXME(mml): Add link to the issue concerning a proper way to drain - // daemonset pods, probably using taints. - daemonset_pod = true - } - } else if sr.Reference.Kind == "Job" { - job, err := o.client.ExtensionsClient.Jobs(sr.Reference.Namespace).Get(sr.Reference.Name) - - // Assume the only reason for an error is because the Job is - // gone/missing, not for any other cause. TODO(mml): something more - // sophisticated than this - if err == nil && job != nil { - replicated = true - } - } else if sr.Reference.Kind == "ReplicaSet" { - rs, err := o.client.ExtensionsClient.ReplicaSets(sr.Reference.Namespace).Get(sr.Reference.Name) - - // Assume the only reason for an error is because the RS is - // gone/missing, not for any other cause. TODO(mml): something more - // sophisticated than this - if err == nil && rs != nil { - replicated = true - } - } - } - - switch { - case daemonset_pod: - daemonSetPodNames = append(daemonSetPodNames, pod.Name) - case !replicated: - unreplicatedPodNames = append(unreplicatedPodNames, pod.Name) - if o.Force { - pods = append(pods, pod) - } - default: - pods = append(pods, pod) - } - } - - daemonSetErrors := !o.IgnoreDaemonsets && len(daemonSetPodNames) > 0 - unreplicatedErrors := !o.Force && len(unreplicatedPodNames) > 0 - - switch { - case daemonSetErrors && unreplicatedErrors: - return []api.Pod{}, errors.New(unmanagedMsg(unreplicatedPodNames, daemonSetPodNames, true)) - case daemonSetErrors && !unreplicatedErrors: - return []api.Pod{}, errors.New(unmanagedMsg([]string{}, daemonSetPodNames, true)) - case unreplicatedErrors && !daemonSetErrors: - return []api.Pod{}, errors.New(unmanagedMsg(unreplicatedPodNames, []string{}, true)) - } - - if len(unreplicatedPodNames) > 0 { - fmt.Fprintf(o.out, "WARNING: About to delete these %s\n", unmanagedMsg(unreplicatedPodNames, []string{}, false)) - } - if len(daemonSetPodNames) > 0 { - fmt.Fprintf(o.out, "WARNING: Skipping %s\n", unmanagedMsg([]string{}, daemonSetPodNames, false)) - } - - return pods, nil -} - -// Helper for generating errors or warnings about unmanaged pods. -func unmanagedMsg(unreplicatedNames []string, daemonSetNames []string, include_guidance bool) string { - msgs := []string{} - if len(unreplicatedNames) > 0 { - msg := fmt.Sprintf("pods not managed by ReplicationController, ReplicaSet, Job, or DaemonSet: %s", strings.Join(unreplicatedNames, ",")) - if include_guidance { - msg += " (use --force to override)" - } - msgs = append(msgs, msg) - } - if len(daemonSetNames) > 0 { - msg := fmt.Sprintf("DaemonSet-managed pods: %s", strings.Join(daemonSetNames, ",")) - if include_guidance { - msg += " (use --ignore-daemonsets to ignore)" - } - msgs = append(msgs, msg) - } - - return strings.Join(msgs, " and ") -} - -// deletePods deletes the pods on the api server -func (o *DrainOptions) deletePods(pods []api.Pod) error { - deleteOptions := api.DeleteOptions{} - if o.GracePeriodSeconds >= 0 { - gracePeriodSeconds := int64(o.GracePeriodSeconds) - deleteOptions.GracePeriodSeconds = &gracePeriodSeconds - } - - for _, pod := range pods { - err := o.client.Pods(pod.Namespace).Delete(pod.Name, &deleteOptions) - if err != nil { - return err - } - cmdutil.PrintSuccess(o.mapper, false, o.out, "pod", pod.Name, "deleted") - } - - return nil -} - -// RunCordonOrUncordon runs either Cordon or Uncordon. The desired value for -// "Unschedulable" is passed as the first arg. -func (o *DrainOptions) RunCordonOrUncordon(desired bool) error { - cmdNamespace, _, err := o.factory.DefaultNamespace() - if err != nil { - return err - } - - if o.nodeInfo.Mapping.GroupVersionKind.Kind == "Node" { - unsched := reflect.ValueOf(o.nodeInfo.Object).Elem().FieldByName("Spec").FieldByName("Unschedulable") - if unsched.Bool() == desired { - cmdutil.PrintSuccess(o.mapper, false, o.out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, already(desired)) - } else { - helper := resource.NewHelper(o.client, o.nodeInfo.Mapping) - unsched.SetBool(desired) - _, err := helper.Replace(cmdNamespace, o.nodeInfo.Name, true, o.nodeInfo.Object) - if err != nil { - return err - } - cmdutil.PrintSuccess(o.mapper, false, o.out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, changed(desired)) - } - } else { - cmdutil.PrintSuccess(o.mapper, false, o.out, o.nodeInfo.Mapping.Resource, o.nodeInfo.Name, "skipped") - } - - return nil -} - -// already() and changed() return suitable strings for {un,}cordoning - -func already(desired bool) string { - if desired { - return "already cordoned" - } - return "already uncordoned" -} - -func changed(desired bool) string { - if desired { - return "cordoned" - } - return "uncordoned" -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/drain_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/drain_test.go deleted file mode 100644 index e1f421bcd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/drain_test.go +++ /dev/null @@ -1,537 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "io" - "io/ioutil" - "net/http" - "net/url" - "os" - "reflect" - "strings" - "testing" - "time" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/conversion" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/runtime" -) - -var node *api.Node -var cordoned_node *api.Node - -func TestMain(m *testing.M) { - // Create a node. - node = &api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "node", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - }, - Spec: api.NodeSpec{ - ExternalID: "node", - }, - Status: api.NodeStatus{}, - } - clone, _ := conversion.NewCloner().DeepCopy(node) - - // A copy of the same node, but cordoned. - cordoned_node = clone.(*api.Node) - cordoned_node.Spec.Unschedulable = true - os.Exit(m.Run()) -} - -func TestCordon(t *testing.T) { - tests := []struct { - description string - node *api.Node - expected *api.Node - cmd func(*cmdutil.Factory, io.Writer) *cobra.Command - arg string - expectFatal bool - }{ - { - description: "node/node syntax", - node: cordoned_node, - expected: node, - cmd: NewCmdUncordon, - arg: "node/node", - expectFatal: false, - }, - { - description: "uncordon for real", - node: cordoned_node, - expected: node, - cmd: NewCmdUncordon, - arg: "node", - expectFatal: false, - }, - { - description: "uncordon does nothing", - node: node, - expected: node, - cmd: NewCmdUncordon, - arg: "node", - expectFatal: false, - }, - { - description: "cordon does nothing", - node: cordoned_node, - expected: cordoned_node, - cmd: NewCmdCordon, - arg: "node", - expectFatal: false, - }, - { - description: "cordon for real", - node: node, - expected: cordoned_node, - cmd: NewCmdCordon, - arg: "node", - expectFatal: false, - }, - { - description: "cordon missing node", - node: node, - expected: node, - cmd: NewCmdCordon, - arg: "bar", - expectFatal: true, - }, - { - description: "uncordon missing node", - node: node, - expected: node, - cmd: NewCmdUncordon, - arg: "bar", - expectFatal: true, - }, - } - - for _, test := range tests { - f, tf, codec := NewAPIFactory() - new_node := &api.Node{} - updated := false - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - m := &MyReq{req} - switch { - case m.isFor("GET", "/nodes/node"): - return &http.Response{StatusCode: 200, Body: objBody(codec, test.node)}, nil - case m.isFor("GET", "/nodes/bar"): - return &http.Response{StatusCode: 404, Body: stringBody("nope")}, nil - case m.isFor("PUT", "/nodes/node"): - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - defer req.Body.Close() - if err := runtime.DecodeInto(codec, data, new_node); err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, new_node.Spec) - } - updated = true - return &http.Response{StatusCode: 200, Body: objBody(codec, new_node)}, nil - default: - t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := test.cmd(f, buf) - - saw_fatal := false - func() { - defer func() { - // Recover from the panic below. - _ = recover() - // Restore cmdutil behavior - cmdutil.DefaultBehaviorOnFatal() - }() - cmdutil.BehaviorOnFatal(func(e string) { saw_fatal = true; panic(e) }) - cmd.SetArgs([]string{test.arg}) - cmd.Execute() - }() - - if test.expectFatal { - if !saw_fatal { - t.Fatalf("%s: unexpected non-error", test.description) - } - if updated { - t.Fatalf("%s: unexpcted update", test.description) - } - } - - if !test.expectFatal && saw_fatal { - t.Fatalf("%s: unexpected error", test.description) - } - if !reflect.DeepEqual(test.expected.Spec, test.node.Spec) && !updated { - t.Fatalf("%s: node never updated", test.description) - } - } -} - -func TestDrain(t *testing.T) { - labels := make(map[string]string) - labels["my_key"] = "my_value" - - rc := api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "rc", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - Labels: labels, - SelfLink: testapi.Default.SelfLink("replicationcontrollers", "rc"), - }, - Spec: api.ReplicationControllerSpec{ - Selector: labels, - }, - } - - rc_anno := make(map[string]string) - rc_anno[controller.CreatedByAnnotation] = refJson(t, &rc) - - rc_pod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - Labels: labels, - Annotations: rc_anno, - }, - Spec: api.PodSpec{ - NodeName: "node", - }, - } - - ds := extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "ds", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - SelfLink: "/apis/extensions/v1beta1/namespaces/default/daemonsets/ds", - }, - Spec: extensions.DaemonSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: labels}, - }, - } - - ds_anno := make(map[string]string) - ds_anno[controller.CreatedByAnnotation] = refJson(t, &ds) - - ds_pod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - Labels: labels, - Annotations: ds_anno, - }, - Spec: api.PodSpec{ - NodeName: "node", - }, - } - - job := batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "job", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - SelfLink: "/apis/extensions/v1beta1/namespaces/default/jobs/job", - }, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: labels}, - }, - } - - job_pod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - Labels: labels, - Annotations: map[string]string{controller.CreatedByAnnotation: refJson(t, &job)}, - }, - } - - rs := extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: "rs", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - Labels: labels, - SelfLink: testapi.Default.SelfLink("replicasets", "rs"), - }, - Spec: extensions.ReplicaSetSpec{ - Selector: &unversioned.LabelSelector{MatchLabels: labels}, - }, - } - - rs_anno := make(map[string]string) - rs_anno[controller.CreatedByAnnotation] = refJson(t, &rs) - - rs_pod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - Labels: labels, - Annotations: rs_anno, - }, - Spec: api.PodSpec{ - NodeName: "node", - }, - } - - naked_pod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "default", - CreationTimestamp: unversioned.Time{Time: time.Now()}, - Labels: labels, - }, - Spec: api.PodSpec{ - NodeName: "node", - }, - } - - tests := []struct { - description string - node *api.Node - expected *api.Node - pods []api.Pod - rcs []api.ReplicationController - replicaSets []extensions.ReplicaSet - args []string - expectFatal bool - expectDelete bool - }{ - { - description: "RC-managed pod", - node: node, - expected: cordoned_node, - pods: []api.Pod{rc_pod}, - rcs: []api.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, - }, - { - description: "DS-managed pod", - node: node, - expected: cordoned_node, - pods: []api.Pod{ds_pod}, - rcs: []api.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: true, - expectDelete: false, - }, - { - description: "DS-managed pod with --ignore-daemonsets", - node: node, - expected: cordoned_node, - pods: []api.Pod{ds_pod}, - rcs: []api.ReplicationController{rc}, - args: []string{"node", "--ignore-daemonsets"}, - expectFatal: false, - expectDelete: false, - }, - { - description: "Job-managed pod", - node: node, - expected: cordoned_node, - pods: []api.Pod{job_pod}, - rcs: []api.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, - }, - { - description: "RS-managed pod", - node: node, - expected: cordoned_node, - pods: []api.Pod{rs_pod}, - replicaSets: []extensions.ReplicaSet{rs}, - args: []string{"node"}, - expectFatal: false, - expectDelete: true, - }, - { - description: "naked pod", - node: node, - expected: cordoned_node, - pods: []api.Pod{naked_pod}, - rcs: []api.ReplicationController{}, - args: []string{"node"}, - expectFatal: true, - expectDelete: false, - }, - { - description: "naked pod with --force", - node: node, - expected: cordoned_node, - pods: []api.Pod{naked_pod}, - rcs: []api.ReplicationController{}, - args: []string{"node", "--force"}, - expectFatal: false, - expectDelete: true, - }, - { - description: "empty node", - node: node, - expected: cordoned_node, - pods: []api.Pod{}, - rcs: []api.ReplicationController{rc}, - args: []string{"node"}, - expectFatal: false, - expectDelete: false, - }, - } - - for _, test := range tests { - new_node := &api.Node{} - deleted := false - f, tf, codec := NewAPIFactory() - - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - m := &MyReq{req} - switch { - case m.isFor("GET", "/nodes/node"): - return &http.Response{StatusCode: 200, Body: objBody(codec, test.node)}, nil - case m.isFor("GET", "/namespaces/default/replicationcontrollers/rc"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &test.rcs[0])}, nil - case m.isFor("GET", "/namespaces/default/daemonsets/ds"): - return &http.Response{StatusCode: 200, Body: objBody(testapi.Extensions.Codec(), &ds)}, nil - case m.isFor("GET", "/namespaces/default/jobs/job"): - return &http.Response{StatusCode: 200, Body: objBody(testapi.Extensions.Codec(), &job)}, nil - case m.isFor("GET", "/namespaces/default/replicasets/rs"): - return &http.Response{StatusCode: 200, Body: objBody(testapi.Extensions.Codec(), &test.replicaSets[0])}, nil - case m.isFor("GET", "/pods"): - values, err := url.ParseQuery(req.URL.RawQuery) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - get_params := make(url.Values) - get_params["fieldSelector"] = []string{"spec.nodeName=node"} - if !reflect.DeepEqual(get_params, values) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, get_params, values) - } - return &http.Response{StatusCode: 200, Body: objBody(codec, &api.PodList{Items: test.pods})}, nil - case m.isFor("GET", "/replicationcontrollers"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &api.ReplicationControllerList{Items: test.rcs})}, nil - case m.isFor("PUT", "/nodes/node"): - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - defer req.Body.Close() - if err := runtime.DecodeInto(codec, data, new_node); err != nil { - t.Fatalf("%s: unexpected error: %v", test.description, err) - } - if !reflect.DeepEqual(test.expected.Spec, new_node.Spec) { - t.Fatalf("%s: expected:\n%v\nsaw:\n%v\n", test.description, test.expected.Spec, new_node.Spec) - } - return &http.Response{StatusCode: 200, Body: objBody(codec, new_node)}, nil - case m.isFor("DELETE", "/namespaces/default/pods/bar"): - deleted = true - return &http.Response{StatusCode: 204, Body: objBody(codec, &test.pods[0])}, nil - default: - t.Fatalf("%s: unexpected request: %v %#v\n%#v", test.description, req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdDrain(f, buf) - - saw_fatal := false - func() { - defer func() { - // Recover from the panic below. - _ = recover() - // Restore cmdutil behavior - cmdutil.DefaultBehaviorOnFatal() - }() - cmdutil.BehaviorOnFatal(func(e string) { saw_fatal = true; panic(e) }) - cmd.SetArgs(test.args) - cmd.Execute() - }() - - if test.expectFatal { - if !saw_fatal { - t.Fatalf("%s: unexpected non-error", test.description) - } - } - - if test.expectDelete { - if !deleted { - t.Fatalf("%s: pod never deleted", test.description) - } - } - if !test.expectDelete { - if deleted { - t.Fatalf("%s: unexpected delete", test.description) - } - } - } -} - -type MyReq struct { - Request *http.Request -} - -func (m *MyReq) isFor(method string, path string) bool { - req := m.Request - - return method == req.Method && (req.URL.Path == path || req.URL.Path == strings.Join([]string{"/api/v1", path}, "") || req.URL.Path == strings.Join([]string{"/apis/extensions/v1beta1", path}, "")) -} - -func refJson(t *testing.T, o runtime.Object) string { - ref, err := api.GetReference(o) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - _, _, codec := NewAPIFactory() - json, err := runtime.Encode(codec, &api.SerializedReference{Reference: *ref}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - return string(json) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/edit.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/edit.go deleted file mode 100644 index 78f613a86..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/edit.go +++ /dev/null @@ -1,496 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - "path/filepath" - gruntime "runtime" - "strings" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" - "k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/crlf" - "k8s.io/kubernetes/pkg/util/strategicpatch" - "k8s.io/kubernetes/pkg/util/yaml" - - "github.com/golang/glog" - "github.com/spf13/cobra" -) - -const ( - editLong = `Edit a resource from the default editor. - -The edit command allows you to directly edit any API resource you can retrieve via the -command line tools. It will open the editor defined by your KUBE_EDITOR, or EDITOR -environment variables, or fall back to 'vi' for Linux or 'notepad' for Windows. -You can edit multiple objects, although changes are applied one at a time. The command -accepts filenames as well as command line arguments, although the files you point to must -be previously saved versions of resources. - -The files to edit will be output in the default API version, or a version specified -by --output-version. The default format is YAML - if you would like to edit in JSON -pass -o json. The flag --windows-line-endings can be used to force Windows line endings, -otherwise the default for your operating system will be used. - -In the event an error occurs while updating, a temporary file will be created on disk -that contains your unapplied changes. The most common error when updating a resource -is another editor changing the resource on the server. When this occurs, you will have -to apply your changes to the newer version of the resource, or update your temporary -saved copy to include the latest resource version.` - - editExample = ` # Edit the service named 'docker-registry': - kubectl edit svc/docker-registry - - # Use an alternative editor - KUBE_EDITOR="nano" kubectl edit svc/docker-registry - - # Edit the service 'docker-registry' in JSON using the v1 API format: - kubectl edit svc/docker-registry --output-version=v1 -o json` -) - -// EditOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type EditOptions struct { - Filenames []string - Recursive bool -} - -var errExit = fmt.Errorf("exit directly") - -func NewCmdEdit(f *cmdutil.Factory, out, errOut io.Writer) *cobra.Command { - options := &EditOptions{} - - // retrieve a list of handled resources from printer as valid args - validArgs, argAliases := []string{}, []string{} - p, err := f.Printer(nil, false, false, false, false, false, false, []string{}) - cmdutil.CheckErr(err) - if p != nil { - validArgs = p.HandledResources() - argAliases = kubectl.ResourceAliases(validArgs) - } - - cmd := &cobra.Command{ - Use: "edit (RESOURCE/NAME | -f FILENAME)", - Short: "Edit a resource on the server", - Long: editLong, - Example: fmt.Sprintf(editExample), - Run: func(cmd *cobra.Command, args []string) { - err := RunEdit(f, out, errOut, cmd, args, options) - if err == errExit { - os.Exit(1) - } - cmdutil.CheckErr(err) - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - usage := "Filename, directory, or URL to file to use to edit the resource" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmd.Flags().StringP("output", "o", "yaml", "Output format. One of: yaml|json.") - cmd.Flags().String("output-version", "", "Output the formatted object with the given group version (for ex: 'extensions/v1beta1').") - cmd.Flags().Bool("windows-line-endings", gruntime.GOOS == "windows", "Use Windows line-endings (default Unix line-endings)") - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func RunEdit(f *cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *EditOptions) error { - var printer kubectl.ResourcePrinter - var ext string - switch format := cmdutil.GetFlagString(cmd, "output"); format { - case "json": - printer = &kubectl.JSONPrinter{} - ext = ".json" - case "yaml": - printer = &kubectl.YAMLPrinter{} - ext = ".yaml" - default: - return cmdutil.UsageError(cmd, "The flag 'output' must be one of yaml|json") - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - - // NB: we use `f.Decoder(false)` to get a plain deserializer for - // the resourceMapper, since it's used to read in edits and - // we don't want to convert into the internal version when - // reading in edits (this would cause us to potentially try to - // compare two different GroupVersions). - Decoder: f.Decoder(false), - } - - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - ResourceTypeOrNameArgs(true, args...). - Latest(). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - infos, err := r.Infos() - if err != nil { - return err - } - - clientConfig, err := f.ClientConfig() - if err != nil { - return err - } - - encoder := f.JSONEncoder() - defaultVersion, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) - if err != nil { - return err - } - objs, err := resource.AsVersionedObjects(infos, defaultVersion.String(), encoder) - if err != nil { - return err - } - - var ( - windowsLineEndings = cmdutil.GetFlagBool(cmd, "windows-line-endings") - edit = editor.NewDefaultEditor(f.EditorEnvs()) - results = editResults{} - original = []byte{} - edited = []byte{} - file string - ) - -outter: - for i := range objs { - obj := objs[i] - // some bookkeeping - results.header.flush() - containsError := false - - for { - // generate the file to edit - buf := &bytes.Buffer{} - var w io.Writer = buf - if windowsLineEndings { - w = crlf.NewCRLFWriter(w) - } - if err := results.header.writeTo(w); err != nil { - return preservedFile(err, results.file, errOut) - } - if !containsError { - if err := printer.PrintObj(obj, w); err != nil { - return preservedFile(err, results.file, errOut) - } - original = buf.Bytes() - } else { - // In case of an error, preserve the edited file. - // Remove the comments (header) from it since we already - // have included the latest header in the buffer above. - buf.Write(manualStrip(edited)) - } - - // launch the editor - editedDiff := edited - edited, file, err = edit.LaunchTempFile(fmt.Sprintf("%s-edit-", filepath.Base(os.Args[0])), ext, buf) - if err != nil { - return preservedFile(err, results.file, errOut) - } - if bytes.Equal(stripComments(editedDiff), stripComments(edited)) { - // Ugly hack right here. We will hit this either (1) when we try to - // save the same changes we tried to save in the previous iteration - // which means our changes are invalid or (2) when we exit the second - // time. The second case is more usual so we can probably live with it. - // TODO: A less hacky fix would be welcome :) - fmt.Fprintln(errOut, "Edit cancelled, no valid changes were saved.") - continue outter - } - - // cleanup any file from the previous pass - if len(results.file) > 0 { - os.Remove(results.file) - } - glog.V(4).Infof("User edited:\n%s", string(edited)) - - // Compare content without comments - if bytes.Equal(stripComments(original), stripComments(edited)) { - os.Remove(file) - fmt.Fprintln(errOut, "Edit cancelled, no changes made.") - continue outter - } - lines, err := hasLines(bytes.NewBuffer(edited)) - if err != nil { - return preservedFile(err, file, errOut) - } - if !lines { - os.Remove(file) - fmt.Fprintln(errOut, "Edit cancelled, saved file was empty.") - continue outter - } - - results = editResults{ - file: file, - } - - // parse the edited file - updates, err := resourceMapper.InfoForData(edited, "edited-file") - if err != nil { - // syntax error - containsError = true - results.header.reasons = append(results.header.reasons, editReason{head: fmt.Sprintf("The edited file had a syntax error: %v", err)}) - continue - } - // not a syntax error as it turns out... - containsError = false - - // put configuration annotation in "updates" - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), updates, encoder); err != nil { - return preservedFile(err, file, errOut) - } - if cmdutil.ShouldRecord(cmd, updates) { - err = cmdutil.RecordChangeCause(updates.Object, f.Command()) - if err != nil { - return err - } - } - editedCopy := edited - if editedCopy, err = runtime.Encode(encoder, updates.Object); err != nil { - return preservedFile(err, file, errOut) - } - - visitor := resource.NewFlattenListVisitor(updates, resourceMapper) - - // need to make sure the original namespace wasn't changed while editing - if err = visitor.Visit(resource.RequireNamespace(cmdNamespace)); err != nil { - return preservedFile(err, file, errOut) - } - - // use strategic merge to create a patch - originalJS, err := yaml.ToJSON(original) - if err != nil { - return preservedFile(err, file, errOut) - } - editedJS, err := yaml.ToJSON(editedCopy) - if err != nil { - return preservedFile(err, file, errOut) - } - patch, err := strategicpatch.CreateStrategicMergePatch(originalJS, editedJS, obj) - // TODO: change all jsonmerge to strategicpatch - // for checking preconditions - preconditions := []jsonmerge.PreconditionFunc{} - if err != nil { - glog.V(4).Infof("Unable to calculate diff, no merge is possible: %v", err) - return preservedFile(err, file, errOut) - } else { - preconditions = append(preconditions, jsonmerge.RequireKeyUnchanged("apiVersion")) - preconditions = append(preconditions, jsonmerge.RequireKeyUnchanged("kind")) - preconditions = append(preconditions, jsonmerge.RequireMetadataKeyUnchanged("name")) - results.version = defaultVersion - } - - if hold, msg := jsonmerge.TestPreconditionsHold(patch, preconditions); !hold { - fmt.Fprintf(errOut, "error: %s\n", msg) - return preservedFile(nil, file, errOut) - } - - errorMsg := "" - err = visitor.Visit(func(info *resource.Info, err error) error { - patched, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) - if err != nil { - errorMsg = results.addError(err, info) - return err - } - info.Refresh(patched, true) - cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, "edited") - return nil - }) - if err == nil { - os.Remove(file) - continue outter - } - // Handle all possible errors - // - // 1. retryable: propose kubectl replace -f - // 2. notfound: indicate the location of the saved configuration of the deleted resource - // 3. invalid: retry those on the spot by looping ie. reloading the editor - if results.retryable > 0 { - fmt.Fprintln(errOut, errorMsg) - fmt.Fprintf(errOut, "You can run `%s replace -f %s` to try this update again.\n", filepath.Base(os.Args[0]), file) - continue outter - } - if results.notfound > 0 { - fmt.Fprintln(errOut, errorMsg) - fmt.Fprintf(errOut, "The edits you made on deleted resources have been saved to %q\n", file) - continue outter - } - // validation error - containsError = true - } - } - return nil -} - -// editReason preserves a message about the reason this file must be edited again -type editReason struct { - head string - other []string -} - -// editHeader includes a list of reasons the edit must be retried -type editHeader struct { - reasons []editReason -} - -// writeTo outputs the current header information into a stream -func (h *editHeader) writeTo(w io.Writer) error { - fmt.Fprint(w, `# Please edit the object below. Lines beginning with a '#' will be ignored, -# and an empty file will abort the edit. If an error occurs while saving this file will be -# reopened with the relevant failures. -# -`) - for _, r := range h.reasons { - if len(r.other) > 0 { - fmt.Fprintf(w, "# %s:\n", r.head) - } else { - fmt.Fprintf(w, "# %s\n", r.head) - } - for _, o := range r.other { - fmt.Fprintf(w, "# * %s\n", o) - } - fmt.Fprintln(w, "#") - } - return nil -} - -func (h *editHeader) flush() { - h.reasons = []editReason{} -} - -// editResults capture the result of an update -type editResults struct { - header editHeader - retryable int - notfound int - edit []*resource.Info - file string - - version unversioned.GroupVersion -} - -func (r *editResults) addError(err error, info *resource.Info) string { - switch { - case errors.IsInvalid(err): - r.edit = append(r.edit, info) - reason := editReason{ - head: fmt.Sprintf("%s %q was not valid", info.Mapping.Resource, info.Name), - } - if err, ok := err.(errors.APIStatus); ok { - if details := err.Status().Details; details != nil { - for _, cause := range details.Causes { - reason.other = append(reason.other, fmt.Sprintf("%s: %s", cause.Field, cause.Message)) - } - } - } - r.header.reasons = append(r.header.reasons, reason) - return fmt.Sprintf("error: %s %q is invalid", info.Mapping.Resource, info.Name) - case errors.IsNotFound(err): - r.notfound++ - return fmt.Sprintf("error: %s %q could not be found on the server", info.Mapping.Resource, info.Name) - default: - r.retryable++ - return fmt.Sprintf("error: %s %q could not be patched: %v", info.Mapping.Resource, info.Name, err) - } -} - -// preservedFile writes out a message about the provided file if it exists to the -// provided output stream when an error happens. Used to notify the user where -// their updates were preserved. -func preservedFile(err error, path string, out io.Writer) error { - if len(path) > 0 { - if _, err := os.Stat(path); !os.IsNotExist(err) { - fmt.Fprintf(out, "A copy of your changes has been stored to %q\n", path) - } - } - return err -} - -// hasLines returns true if any line in the provided stream is non empty - has non-whitespace -// characters, or the first non-whitespace character is a '#' indicating a comment. Returns -// any errors encountered reading the stream. -func hasLines(r io.Reader) (bool, error) { - // TODO: if any files we read have > 64KB lines, we'll need to switch to bytes.ReadLine - // TODO: probably going to be secrets - s := bufio.NewScanner(r) - for s.Scan() { - if line := strings.TrimSpace(s.Text()); len(line) > 0 && line[0] != '#' { - return true, nil - } - } - if err := s.Err(); err != nil && err != io.EOF { - return false, err - } - return false, nil -} - -// stripComments will transform a YAML file into JSON, thus dropping any comments -// in it. Note that if the given file has a syntax error, the transformation will -// fail and we will manually drop all comments from the file. -func stripComments(file []byte) []byte { - stripped := file - stripped, err := yaml.ToJSON(stripped) - if err != nil { - stripped = manualStrip(file) - } - return stripped -} - -// manualStrip is used for dropping comments from a YAML file -func manualStrip(file []byte) []byte { - stripped := []byte{} - lines := bytes.Split(file, []byte("\n")) - for i, line := range lines { - if bytes.HasPrefix(bytes.TrimSpace(line), []byte("#")) { - continue - } - stripped = append(stripped, line...) - if i < len(lines)-1 { - stripped = append(stripped, '\n') - } - } - return stripped -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/exec.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/exec.go deleted file mode 100644 index e59925873..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/exec.go +++ /dev/null @@ -1,241 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "net/url" - "os" - "os/signal" - "syscall" - - "github.com/docker/docker/pkg/term" - "github.com/golang/glog" - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/remotecommand" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand" -) - -const ( - exec_example = `# Get output from running 'date' from pod 123456-7890, using the first container by default -kubectl exec 123456-7890 date - -# Get output from running 'date' in ruby-container from pod 123456-7890 -kubectl exec 123456-7890 -c ruby-container date - -# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod 123456-7890 -# and sends stdout/stderr from 'bash' back to the client -kubectl exec 123456-7890 -c ruby-container -i -t -- bash -il` -) - -func NewCmdExec(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command { - options := &ExecOptions{ - In: cmdIn, - Out: cmdOut, - Err: cmdErr, - - Executor: &DefaultRemoteExecutor{}, - } - cmd := &cobra.Command{ - Use: "exec POD [-c CONTAINER] -- COMMAND [args...]", - Short: "Execute a command in a container.", - Long: "Execute a command in a container.", - Example: exec_example, - Run: func(cmd *cobra.Command, args []string) { - argsLenAtDash := cmd.ArgsLenAtDash() - cmdutil.CheckErr(options.Complete(f, cmd, args, argsLenAtDash)) - cmdutil.CheckErr(options.Validate()) - cmdutil.CheckErr(options.Run()) - }, - } - cmd.Flags().StringVarP(&options.PodName, "pod", "p", "", "Pod name") - // TODO support UID - cmd.Flags().StringVarP(&options.ContainerName, "container", "c", "", "Container name. If omitted, the first container in the pod will be chosen") - cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", false, "Pass stdin to the container") - cmd.Flags().BoolVarP(&options.TTY, "tty", "t", false, "Stdin is a TTY") - return cmd -} - -// RemoteExecutor defines the interface accepted by the Exec command - provided for test stubbing -type RemoteExecutor interface { - Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error -} - -// DefaultRemoteExecutor is the standard implementation of remote command execution -type DefaultRemoteExecutor struct{} - -func (*DefaultRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { - exec, err := remotecommand.NewExecutor(config, method, url) - if err != nil { - return err - } - return exec.Stream(remotecommandserver.SupportedStreamingProtocols, stdin, stdout, stderr, tty) -} - -// ExecOptions declare the arguments accepted by the Exec command -type ExecOptions struct { - Namespace string - PodName string - ContainerName string - Stdin bool - TTY bool - Command []string - - In io.Reader - Out io.Writer - Err io.Writer - - Executor RemoteExecutor - Client *client.Client - Config *restclient.Config -} - -// Complete verifies command line arguments and loads data from the command environment -func (p *ExecOptions) Complete(f *cmdutil.Factory, cmd *cobra.Command, argsIn []string, argsLenAtDash int) error { - // Let kubectl exec follow rules for `--`, see #13004 issue - if len(p.PodName) == 0 && (len(argsIn) == 0 || argsLenAtDash == 0) { - return cmdutil.UsageError(cmd, "POD is required for exec") - } - if len(p.PodName) != 0 { - printDeprecationWarning("exec POD", "-p POD") - if len(argsIn) < 1 { - return cmdutil.UsageError(cmd, "COMMAND is required for exec") - } - p.Command = argsIn - } else { - p.PodName = argsIn[0] - p.Command = argsIn[1:] - if len(p.Command) < 1 { - return cmdutil.UsageError(cmd, "COMMAND is required for exec") - } - } - - namespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } - p.Namespace = namespace - - config, err := f.ClientConfig() - if err != nil { - return err - } - p.Config = config - - client, err := f.Client() - if err != nil { - return err - } - p.Client = client - - return nil -} - -// Validate checks that the provided exec options are specified. -func (p *ExecOptions) Validate() error { - if len(p.PodName) == 0 { - return fmt.Errorf("pod name must be specified") - } - if len(p.Command) == 0 { - return fmt.Errorf("you must specify at least one command for the container") - } - if p.Out == nil || p.Err == nil { - return fmt.Errorf("both output and error output must be provided") - } - if p.Executor == nil || p.Client == nil || p.Config == nil { - return fmt.Errorf("client, client config, and executor must be provided") - } - return nil -} - -// Run executes a validated remote execution against a pod. -func (p *ExecOptions) Run() error { - pod, err := p.Client.Pods(p.Namespace).Get(p.PodName) - if err != nil { - return err - } - - if pod.Status.Phase != api.PodRunning { - return fmt.Errorf("pod %s is not running and cannot execute commands; current phase is %s", p.PodName, pod.Status.Phase) - } - - containerName := p.ContainerName - if len(containerName) == 0 { - glog.V(4).Infof("defaulting container name to %s", pod.Spec.Containers[0].Name) - containerName = pod.Spec.Containers[0].Name - } - - // TODO: refactor with terminal helpers from the edit utility once that is merged - var stdin io.Reader - tty := p.TTY - if p.Stdin { - stdin = p.In - if tty { - if file, ok := stdin.(*os.File); ok { - inFd := file.Fd() - if term.IsTerminal(inFd) { - oldState, err := term.SetRawTerminal(inFd) - if err != nil { - glog.Fatal(err) - } - // this handles a clean exit, where the command finished - defer term.RestoreTerminal(inFd, oldState) - - // SIGINT is handled by term.SetRawTerminal (it runs a goroutine that listens - // for SIGINT and restores the terminal before exiting) - - // this handles SIGTERM - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGTERM) - go func() { - <-sigChan - term.RestoreTerminal(inFd, oldState) - os.Exit(0) - }() - } else { - fmt.Fprintln(p.Err, "STDIN is not a terminal") - } - } else { - tty = false - fmt.Fprintln(p.Err, "Unable to use a TTY - input is not the right kind of file") - } - } - } - - // TODO: consider abstracting into a client invocation or client helper - req := p.Client.RESTClient.Post(). - Resource("pods"). - Name(pod.Name). - Namespace(pod.Namespace). - SubResource("exec"). - Param("container", containerName) - req.VersionedParams(&api.PodExecOptions{ - Container: containerName, - Command: p.Command, - Stdin: stdin != nil, - Stdout: p.Out != nil, - Stderr: p.Err != nil, - TTY: tty, - }, api.ParameterCodec) - - return p.Executor.Execute("POST", req.URL(), p.Config, stdin, p.Out, p.Err, tty) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/exec_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/exec_test.go deleted file mode 100644 index 001f59a47..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/exec_test.go +++ /dev/null @@ -1,258 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "fmt" - "io" - "net/http" - "net/url" - "reflect" - "testing" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -type fakeRemoteExecutor struct { - method string - url *url.URL - execErr error -} - -func (f *fakeRemoteExecutor) Execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { - f.method = method - f.url = url - return f.execErr -} - -func TestPodAndContainer(t *testing.T) { - tests := []struct { - args []string - argsLenAtDash int - p *ExecOptions - name string - expectError bool - expectedPod string - expectedContainer string - expectedArgs []string - }{ - { - p: &ExecOptions{}, - argsLenAtDash: -1, - expectError: true, - name: "empty", - }, - { - p: &ExecOptions{PodName: "foo"}, - argsLenAtDash: -1, - expectError: true, - name: "no cmd", - }, - { - p: &ExecOptions{PodName: "foo", ContainerName: "bar"}, - argsLenAtDash: -1, - expectError: true, - name: "no cmd, w/ container", - }, - { - p: &ExecOptions{PodName: "foo"}, - args: []string{"cmd"}, - argsLenAtDash: -1, - expectedPod: "foo", - expectedArgs: []string{"cmd"}, - name: "pod in flags", - }, - { - p: &ExecOptions{}, - args: []string{"foo", "cmd"}, - argsLenAtDash: 0, - expectError: true, - name: "no pod, pod name is behind dash", - }, - { - p: &ExecOptions{}, - args: []string{"foo"}, - argsLenAtDash: -1, - expectError: true, - name: "no cmd, w/o flags", - }, - { - p: &ExecOptions{}, - args: []string{"foo", "cmd"}, - argsLenAtDash: -1, - expectedPod: "foo", - expectedArgs: []string{"cmd"}, - name: "cmd, w/o flags", - }, - { - p: &ExecOptions{}, - args: []string{"foo", "cmd"}, - argsLenAtDash: 1, - expectedPod: "foo", - expectedArgs: []string{"cmd"}, - name: "cmd, cmd is behind dash", - }, - { - p: &ExecOptions{ContainerName: "bar"}, - args: []string{"foo", "cmd"}, - argsLenAtDash: -1, - expectedPod: "foo", - expectedContainer: "bar", - expectedArgs: []string{"cmd"}, - name: "cmd, container in flag", - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { return nil, nil }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{} - - cmd := &cobra.Command{} - options := test.p - err := options.Complete(f, cmd, test.args, test.argsLenAtDash) - if test.expectError && err == nil { - t.Errorf("unexpected non-error (%s)", test.name) - } - if !test.expectError && err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.name) - } - if err != nil { - continue - } - if options.PodName != test.expectedPod { - t.Errorf("expected: %s, got: %s (%s)", test.expectedPod, options.PodName, test.name) - } - if options.ContainerName != test.expectedContainer { - t.Errorf("expected: %s, got: %s (%s)", test.expectedContainer, options.ContainerName, test.name) - } - if !reflect.DeepEqual(test.expectedArgs, options.Command) { - t.Errorf("expected: %v, got %v (%s)", test.expectedArgs, options.Command, test.name) - } - } -} - -func TestExec(t *testing.T) { - version := testapi.Default.GroupVersion().Version - tests := []struct { - name, version, podPath, execPath, container string - pod *api.Pod - execErr bool - }{ - { - name: "pod exec", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", - pod: execPod(), - }, - { - name: "pod exec error", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - execPath: "/api/" + version + "/namespaces/test/pods/foo/exec", - pod: execPod(), - execErr: true, - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: test.version}}} - bufOut := bytes.NewBuffer([]byte{}) - bufErr := bytes.NewBuffer([]byte{}) - bufIn := bytes.NewBuffer([]byte{}) - ex := &fakeRemoteExecutor{} - if test.execErr { - ex.execErr = fmt.Errorf("exec error") - } - params := &ExecOptions{ - PodName: "foo", - ContainerName: "bar", - In: bufIn, - Out: bufOut, - Err: bufErr, - Executor: ex, - } - cmd := &cobra.Command{} - args := []string{"test", "command"} - if err := params.Complete(f, cmd, args, -1); err != nil { - t.Fatal(err) - } - err := params.Run() - if test.execErr && err != ex.execErr { - t.Errorf("%s: Unexpected exec error: %v", test.name, err) - continue - } - if !test.execErr && err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - continue - } - if test.execErr { - continue - } - if ex.url.Path != test.execPath { - t.Errorf("%s: Did not get expected path for exec request", test.name) - continue - } - if ex.method != "POST" { - t.Errorf("%s: Did not get method for exec request: %s", test.name, ex.method) - } - } -} - -func execPod() *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{ - { - Name: "bar", - }, - }, - }, - Status: api.PodStatus{ - Phase: api.PodRunning, - }, - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/explain.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/explain.go deleted file mode 100644 index ce959e394..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/explain.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -const ( - explainExamples = `# Get the documentation of the resource and its fields -kubectl explain pods - -# Get the documentation of a specific field of a resource -kubectl explain pods.spec.containers` - - explainLong = `Documentation of resources. - -` + kubectl.PossibleResourceTypes -) - -// NewCmdExplain returns a cobra command for swagger docs -func NewCmdExplain(f *cmdutil.Factory, out io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "explain RESOURCE", - Short: "Documentation of resources.", - Long: explainLong, - Example: explainExamples, - Run: func(cmd *cobra.Command, args []string) { - err := RunExplain(f, out, cmd, args) - cmdutil.CheckErr(err) - }, - } - cmd.Flags().Bool("recursive", false, "Print the fields of fields (Currently only 1 level deep)") - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -// RunExplain executes the appropriate steps to print a model's documentation -func RunExplain(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return cmdutil.UsageError(cmd, "We accept only this format: explain RESOURCE") - } - - recursive := cmdutil.GetFlagBool(cmd, "recursive") - apiVersionString := cmdutil.GetFlagString(cmd, "api-version") - apiVersion := unversioned.GroupVersion{} - - mapper, _ := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - // TODO: After we figured out the new syntax to separate group and resource, allow - // the users to use it in explain (kubectl explain ). - // Refer to issue #16039 for why we do this. Refer to PR #15808 that used "/" syntax. - inModel, fieldsPath, err := kubectl.SplitAndParseResourceRequest(args[0], mapper) - if err != nil { - return err - } - - // TODO: We should deduce the group for a resource by discovering the supported resources at server. - fullySpecifiedGVR, groupResource := unversioned.ParseResourceArg(inModel) - gvk := unversioned.GroupVersionKind{} - if fullySpecifiedGVR != nil { - gvk, _ = mapper.KindFor(*fullySpecifiedGVR) - } - if gvk.IsEmpty() { - gvk, err = mapper.KindFor(groupResource.WithVersion("")) - if err != nil { - return err - } - } - - if len(apiVersionString) == 0 { - groupMeta, err := registered.Group(gvk.Group) - if err != nil { - return err - } - apiVersion = groupMeta.GroupVersion - - } else { - apiVersion, err = unversioned.ParseGroupVersion(apiVersionString) - if err != nil { - return nil - } - } - - schema, err := f.SwaggerSchema(apiVersion.WithKind(gvk.Kind)) - if err != nil { - return err - } - - return kubectl.PrintModelDescription(inModel, fieldsPath, out, schema, recursive) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/expose.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/expose.go deleted file mode 100644 index 068a624fc..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/expose.go +++ /dev/null @@ -1,271 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "regexp" - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/validation" -) - -// ExposeOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ExposeOptions struct { - Filenames []string - Recursive bool -} - -const ( - expose_resources = ` - pod (po), service (svc), replicationcontroller (rc), - deployment, replicaset (rs) -` - - expose_long = `Expose a resource as a new Kubernetes service. - -Looks up a deployment, service, replica set, replication controller or pod by name and uses the selector -for that resource as the selector for a new service on the specified port. A deployment or replica set -will be exposed as a service only if its selector is convertible to a selector that service supports, -i.e. when the selector contains only the matchLabels component. Note that if no port is specified via ---port and the exposed resource has multiple ports, all will be re-used by the new service. Also if no -labels are specified, the new service will re-use the labels from the resource it exposes. - -Possible resources include (case insensitive):` + expose_resources - - expose_example = `# Create a service for a replicated nginx, which serves on port 80 and connects to the containers on port 8000. -kubectl expose rc nginx --port=80 --target-port=8000 - -# Create a service for a replication controller identified by type and name specified in "nginx-controller.yaml", which serves on port 80 and connects to the containers on port 8000. -kubectl expose -f nginx-controller.yaml --port=80 --target-port=8000 - -# Create a service for a pod valid-pod, which serves on port 444 with the name "frontend" -kubectl expose pod valid-pod --port=444 --name=frontend - -# Create a second service based on the above service, exposing the container port 8443 as port 443 with the name "nginx-https" -kubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https - -# Create a service for a replicated streaming application on port 4100 balancing UDP traffic and named 'video-stream'. -kubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream - -# Create a service for a replicated nginx using replica set, which serves on port 80 and connects to the containers on port 8000. -kubectl expose rs nginx --port=80 --target-port=8000 - -# Create a service for an nginx deployment, which serves on port 80 and connects to the containers on port 8000. -kubectl expose deployment nginx --port=80 --target-port=8000` -) - -func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ExposeOptions{} - - validArgs, argAliases := []string{}, []string{} - resources := regexp.MustCompile(`\s*,`).Split(expose_resources, -1) - for _, r := range resources { - validArgs = append(validArgs, strings.Fields(r)[0]) - argAliases = kubectl.ResourceAliases(validArgs) - } - - cmd := &cobra.Command{ - Use: "expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP] [--target-port=number-or-name] [--name=name] [--external-ip=external-ip-of-service] [--type=type]", - Short: "Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service", - Long: expose_long, - Example: expose_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunExpose(f, out, cmd, args, options) - cmdutil.CheckErr(err) - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().String("generator", "service/v2", "The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.") - cmd.Flags().String("protocol", "TCP", "The network protocol for the service to be created. Default is 'tcp'.") - cmd.Flags().String("port", "", "The port that the service should serve on. Copied from the resource being exposed, if unspecified") - cmd.Flags().String("type", "", "Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.") - // TODO: remove create-external-load-balancer in code on or after Aug 25, 2016. - cmd.Flags().Bool("create-external-load-balancer", false, "If true, create an external load balancer for this service (trumped by --type). Implementation is cloud provider dependent. Default is 'false'.") - cmd.Flags().MarkDeprecated("create-external-load-balancer", "use --type=\"LoadBalancer\" instead") - cmd.Flags().String("load-balancer-ip", "", "IP to assign to to the Load Balancer. If empty, an ephemeral IP will be created and used (cloud-provider specific).") - cmd.Flags().String("selector", "", "A label selector to use for this service. Only equality-based selector requirements are supported. If empty (the default) infer the selector from the replication controller or replica set.") - cmd.Flags().StringP("labels", "l", "", "Labels to apply to the service created by this call.") - cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without creating it.") - cmd.Flags().String("container-port", "", "Synonym for --target-port") - cmd.Flags().MarkDeprecated("container-port", "--container-port will be removed in the future, please use --target-port instead") - cmd.Flags().String("target-port", "", "Name or number for the port on the container that the service should direct traffic to. Optional.") - cmd.Flags().String("external-ip", "", "Additional external IP address (not managed by Kubernetes) to accept for the service. If this IP is routed to a node, the service can be accessed by this IP in addition to its generated service IP.") - cmd.Flags().String("overrides", "", "An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.") - cmd.Flags().String("name", "", "The name for the newly created object.") - cmd.Flags().String("session-affinity", "", "If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'") - - usage := "Filename, directory, or URL to a file identifying the resource to expose a service" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - return cmd -} - -func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *ExposeOptions) error { - namespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - mapper, typer := f.Object(false) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - ResourceTypeOrNameArgs(false, args...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - // Get the generator, setup and validate all required parameters - generatorName := cmdutil.GetFlagString(cmd, "generator") - generators := f.Generators("expose") - generator, found := generators[generatorName] - if !found { - return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) - } - names := generator.ParamNames() - - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - mapping := info.ResourceMapping() - if err := f.CanBeExposed(mapping.GroupVersionKind.GroupKind()); err != nil { - return err - } - - params := kubectl.MakeParams(cmd, names) - name := info.Name - if len(name) > validation.DNS952LabelMaxLength { - name = name[:validation.DNS952LabelMaxLength] - } - params["default-name"] = name - - // For objects that need a pod selector, derive it from the exposed object in case a user - // didn't explicitly specify one via --selector - if s, found := params["selector"]; found && kubectl.IsZero(s) { - s, err := f.MapBasedSelectorForObject(info.Object) - if err != nil { - return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't retrieve selectors via --selector flag or introspection: %s", err)) - } - params["selector"] = s - } - - // For objects that need a port, derive it from the exposed object in case a user - // didn't explicitly specify one via --port - if port, found := params["port"]; found && kubectl.IsZero(port) { - ports, err := f.PortsForObject(info.Object) - if err != nil { - return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find port via --port flag or introspection: %s", err)) - } - switch len(ports) { - case 0: - return cmdutil.UsageError(cmd, "couldn't find port via --port flag or introspection") - case 1: - params["port"] = ports[0] - default: - params["ports"] = strings.Join(ports, ",") - } - } - if kubectl.IsZero(params["labels"]) { - labels, err := f.LabelsForObject(info.Object) - if err != nil { - return err - } - params["labels"] = kubectl.MakeLabels(labels) - } - if err = kubectl.ValidateParams(names, params); err != nil { - return err - } - // Check for invalid flags used against the present generator. - if err := kubectl.EnsureFlagsValid(cmd, generators, generatorName); err != nil { - return err - } - - // Generate new object - object, err := generator.Generate(params) - if err != nil { - return err - } - - if inline := cmdutil.GetFlagString(cmd, "overrides"); len(inline) > 0 { - codec := runtime.NewCodec(f.JSONEncoder(), f.Decoder(true)) - object, err = cmdutil.Merge(codec, object, inline, mapping.GroupVersionKind.Kind) - if err != nil { - return err - } - } - - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - Decoder: f.Decoder(true), - } - info, err = resourceMapper.InfoForObject(object, nil) - if err != nil { - return err - } - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(object, f.Command()); err != nil { - return err - } - } - info.Refresh(object, true) - // TODO: extract this flag to a central location, when such a location exists. - if cmdutil.GetFlagBool(cmd, "dry-run") { - return f.PrintObject(cmd, mapper, object, out) - } - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil { - return err - } - - // Serialize the object with the annotation applied. - object, err = resource.NewHelper(info.Client, info.Mapping).Create(namespace, false, object) - if err != nil { - return err - } - - if len(cmdutil.GetFlagString(cmd, "output")) > 0 { - return f.PrintObject(cmd, mapper, object, out) - } - - cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, "exposed") - return nil - }) - if err != nil { - return err - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/expose_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/expose_test.go deleted file mode 100644 index 6bad24357..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/expose_test.go +++ /dev/null @@ -1,351 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func TestRunExposeService(t *testing.T) { - tests := []struct { - name string - args []string - ns string - calls map[string]string - input runtime.Object - flags map[string]string - output runtime.Object - expected string - status int - }{ - { - name: "expose-service-from-service-no-selector-defined", - args: []string{"service", "baz"}, - ns: "test", - calls: map[string]string{ - "GET": "/namespaces/test/services/baz", - "POST": "/namespaces/test/services", - }, - input: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"app": "go"}, - }, - }, - flags: map[string]string{"protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "", Labels: map[string]string{"svc": "test"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolUDP, - Port: 14, - TargetPort: intstr.FromInt(14), - }, - }, - Selector: map[string]string{"app": "go"}, - }, - }, - expected: "service \"foo\" exposed", - status: 200, - }, - { - name: "expose-service-from-service", - args: []string{"service", "baz"}, - ns: "test", - calls: map[string]string{ - "GET": "/namespaces/test/services/baz", - "POST": "/namespaces/test/services", - }, - input: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"app": "go"}, - }, - }, - flags: map[string]string{"selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "", Labels: map[string]string{"svc": "test"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolUDP, - Port: 14, - TargetPort: intstr.FromInt(14), - }, - }, - Selector: map[string]string{"func": "stream"}, - }, - }, - expected: "service \"foo\" exposed", - status: 200, - }, - { - name: "no-name-passed-from-the-cli", - args: []string{"service", "mayor"}, - ns: "default", - calls: map[string]string{ - "GET": "/namespaces/default/services/mayor", - "POST": "/namespaces/default/services", - }, - input: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "mayor", Namespace: "default", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"run": "this"}, - }, - }, - // No --name flag specified below. Service will use the rc's name passed via the 'default-name' parameter - flags: map[string]string{"selector": "run=this", "port": "80", "labels": "runas=amayor"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "mayor", Namespace: "", Labels: map[string]string{"runas": "amayor"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolTCP, - Port: 80, - TargetPort: intstr.FromInt(80), - }, - }, - Selector: map[string]string{"run": "this"}, - }, - }, - expected: "service \"mayor\" exposed", - status: 200, - }, - { - name: "expose-service", - args: []string{"service", "baz"}, - ns: "test", - calls: map[string]string{ - "GET": "/namespaces/test/services/baz", - "POST": "/namespaces/test/services", - }, - input: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"app": "go"}, - }, - }, - flags: map[string]string{"selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test", "type": "LoadBalancer", "dry-run": "true"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "", Labels: map[string]string{"svc": "test"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolUDP, - Port: 14, - TargetPort: intstr.FromInt(14), - }, - }, - Selector: map[string]string{"func": "stream"}, - Type: api.ServiceTypeLoadBalancer, - }, - }, - status: 200, - }, - { - name: "expose-affinity-service", - args: []string{"service", "baz"}, - ns: "test", - calls: map[string]string{ - "GET": "/namespaces/test/services/baz", - "POST": "/namespaces/test/services", - }, - input: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"app": "go"}, - }, - }, - flags: map[string]string{"selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test", "type": "LoadBalancer", "session-affinity": "ClientIP", "dry-run": "true"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "", Labels: map[string]string{"svc": "test"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolUDP, - Port: 14, - TargetPort: intstr.FromInt(14), - }, - }, - Selector: map[string]string{"func": "stream"}, - Type: api.ServiceTypeLoadBalancer, - SessionAffinity: api.ServiceAffinityClientIP, - }, - }, - status: 200, - }, - { - name: "expose-from-file", - args: []string{}, - ns: "test", - calls: map[string]string{ - "GET": "/namespaces/test/services/redis-master", - "POST": "/namespaces/test/services", - }, - input: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "redis-master", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"app": "go"}, - }, - }, - flags: map[string]string{"filename": "../../../examples/guestbook/redis-master-service.yaml", "selector": "func=stream", "protocol": "UDP", "port": "14", "name": "foo", "labels": "svc=test", "dry-run": "true"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Labels: map[string]string{"svc": "test"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolUDP, - Port: 14, - TargetPort: intstr.FromInt(14), - }, - }, - Selector: map[string]string{"func": "stream"}, - }, - }, - status: 200, - }, - { - name: "truncate-name", - args: []string{"pod", "a-name-that-is-toooo-big-for-a-service"}, - ns: "test", - calls: map[string]string{ - "GET": "/namespaces/test/pods/a-name-that-is-toooo-big-for-a-service", - "POST": "/namespaces/test/services", - }, - input: &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - }, - flags: map[string]string{"selector": "svc=frompod", "port": "90", "labels": "svc=frompod", "generator": "service/v2"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "a-name-that-is-toooo-big", Namespace: "", Labels: map[string]string{"svc": "frompod"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolTCP, - Port: 90, - TargetPort: intstr.FromInt(90), - }, - }, - Selector: map[string]string{"svc": "frompod"}, - }, - }, - expected: "service \"a-name-that-is-toooo-big\" exposed", - status: 200, - }, - { - name: "expose-multiport-object", - args: []string{"service", "foo"}, - ns: "test", - calls: map[string]string{ - "GET": "/namespaces/test/services/foo", - "POST": "/namespaces/test/services", - }, - input: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "", Labels: map[string]string{"svc": "multiport"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolTCP, - Port: 80, - TargetPort: intstr.FromInt(80), - }, - { - Protocol: api.ProtocolTCP, - Port: 443, - TargetPort: intstr.FromInt(443), - }, - }, - }, - }, - flags: map[string]string{"selector": "svc=fromfoo", "generator": "service/v2", "name": "fromfoo", "dry-run": "true"}, - output: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "fromfoo", Namespace: "", Labels: map[string]string{"svc": "multiport"}}, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Name: "port-1", - Protocol: api.ProtocolTCP, - Port: 80, - TargetPort: intstr.FromInt(80), - }, - { - Name: "port-2", - Protocol: api.ProtocolTCP, - Port: 443, - TargetPort: intstr.FromInt(443), - }, - }, - Selector: map[string]string{"svc": "fromfoo"}, - }, - }, - status: 200, - }, - } - - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Printer = &kubectl.JSONPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.calls[m] && m == "GET": - return &http.Response{StatusCode: test.status, Body: objBody(codec, test.input)}, nil - case p == test.calls[m] && m == "POST": - return &http.Response{StatusCode: test.status, Body: objBody(codec, test.output)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = test.ns - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdExposeService(f, buf) - cmd.SetOutput(buf) - for flag, value := range test.flags { - cmd.Flags().Set(flag, value) - } - cmd.Run(cmd, test.args) - - out := buf.String() - if _, ok := test.flags["dry-run"]; ok { - buf.Reset() - if err := tf.Printer.PrintObj(test.output, buf); err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - continue - } - - test.expected = buf.String() - } - - if !strings.Contains(out, test.expected) { - t.Errorf("%s: Unexpected output! Expected\n%s\ngot\n%s", test.name, test.expected, out) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/get.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/get.go deleted file mode 100644 index 286cdf277..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/get.go +++ /dev/null @@ -1,325 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - utilerrors "k8s.io/kubernetes/pkg/util/errors" - "k8s.io/kubernetes/pkg/watch" -) - -// GetOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type GetOptions struct { - Filenames []string - Recursive bool -} - -const ( - get_long = `Display one or many resources. - -` + kubectl.PossibleResourceTypes + ` - -By specifying the output as 'template' and providing a Go template as the value -of the --template flag, you can filter the attributes of the fetched resource(s).` - get_example = `# List all pods in ps output format. -kubectl get pods - -# List all pods in ps output format with more information (such as node name). -kubectl get pods -o wide - -# List a single replication controller with specified NAME in ps output format. -kubectl get replicationcontroller web - -# List a single pod in JSON output format. -kubectl get -o json pod web-pod-13je7 - -# List a pod identified by type and name specified in "pod.yaml" in JSON output format. -kubectl get -f pod.yaml -o json - -# Return only the phase value of the specified pod. -kubectl get -o template pod/web-pod-13je7 --template={{.status.phase}} - -# List all replication controllers and services together in ps output format. -kubectl get rc,services - -# List one or more resources by their type and names. -kubectl get rc/web service/frontend pods/web-pod-13je7` -) - -// NewCmdGet creates a command object for the generic "get" action, which -// retrieves one or more resources from a server. -func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &GetOptions{} - - // retrieve a list of handled resources from printer as valid args - validArgs, argAliases := []string{}, []string{} - p, err := f.Printer(nil, false, false, false, false, false, false, []string{}) - cmdutil.CheckErr(err) - if p != nil { - validArgs = p.HandledResources() - argAliases = kubectl.ResourceAliases(validArgs) - } - - cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|wide|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE [NAME | -l label] | TYPE/NAME ...) [flags]", - Short: "Display one or many resources", - Long: get_long, - Example: get_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunGet(f, out, cmd, args, options) - cmdutil.CheckErr(err) - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") - cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.") - cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.") - cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") - cmd.Flags().StringSliceP("label-columns", "L", []string{}, "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag statements like -L label1 -L label2...") - cmd.Flags().Bool("export", false, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.") - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -// RunGet implements the generic Get command -// TODO: convert all direct flag accessors to a struct and pass that instead of cmd -func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *GetOptions) error { - selector := cmdutil.GetFlagString(cmd, "selector") - allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - if allNamespaces { - enforceNamespace = false - } - - if len(args) == 0 && len(options.Filenames) == 0 { - fmt.Fprint(out, "You must specify the type of resource to get. ", valid_resources) - return cmdutil.UsageError(cmd, "Required resource not specified.") - } - - // always show resources when getting by name or filename - argsHasNames, err := resource.HasNames(args) - if err != nil { - return err - } - if len(options.Filenames) > 0 || argsHasNames { - cmd.Flag("show-all").Value.Set("true") - } - export := cmdutil.GetFlagBool(cmd, "export") - - // handle watch separately since we cannot watch multiple resource types - isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only") - if isWatch || isWatchOnly { - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - SelectorParam(selector). - ExportParam(export). - ResourceTypeOrNameArgs(true, args...). - SingleResourceType(). - Latest(). - Do() - err := r.Err() - if err != nil { - return err - } - infos, err := r.Infos() - if err != nil { - return err - } - if len(infos) != 1 { - return fmt.Errorf("watch is only supported on individual resources and resource collections - %d resources were found", len(infos)) - } - info := infos[0] - mapping := info.ResourceMapping() - printer, err := f.PrinterForMapping(cmd, mapping, allNamespaces) - if err != nil { - return err - } - - obj, err := r.Object() - if err != nil { - return err - } - rv, err := mapping.MetadataAccessor.ResourceVersion(obj) - if err != nil { - return err - } - - // print the current object - if !isWatchOnly { - if err := printer.PrintObj(obj, out); err != nil { - return fmt.Errorf("unable to output the provided object: %v", err) - } - } - - // print watched changes - w, err := r.Watch(rv) - if err != nil { - return err - } - - kubectl.WatchLoop(w, func(e watch.Event) error { - return printer.PrintObj(e.Object, out) - }) - return nil - } - - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - SelectorParam(selector). - ExportParam(export). - ResourceTypeOrNameArgs(true, args...). - ContinueOnError(). - Latest(). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - printer, generic, err := cmdutil.PrinterForCommand(cmd) - if err != nil { - return err - } - - infos := []*resource.Info{} - allErrs := []error{} - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - infos = append(infos, info) - return nil - }) - if err != nil { - allErrs = append(allErrs, err) - } - - if generic { - clientConfig, err := f.ClientConfig() - if err != nil { - return err - } - - singular := false - r.IntoSingular(&singular) - - // the outermost object will be converted to the output-version, but inner - // objects can use their mappings - version, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) - if err != nil { - return err - } - obj, err := resource.AsVersionedObject(infos, !singular, version.String(), f.JSONEncoder()) - if err != nil { - return err - } - - return printer.PrintObj(obj, out) - } - - objs := make([]runtime.Object, len(infos)) - for ix := range infos { - objs[ix] = infos[ix].Object - } - - sorting, err := cmd.Flags().GetString("sort-by") - var sorter *kubectl.RuntimeSort - if err == nil && len(sorting) > 0 && len(objs) > 1 { - clientConfig, err := f.ClientConfig() - if err != nil { - return err - } - - version, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) - if err != nil { - return err - } - - for ix := range infos { - objs[ix], err = infos[ix].Mapping.ConvertToVersion(infos[ix].Object, version.String()) - if err != nil { - allErrs = append(allErrs, err) - continue - } - } - - // TODO: questionable - if sorter, err = kubectl.SortObjects(f.Decoder(true), objs, sorting); err != nil { - return err - } - } - - // use the default printer for each object - printer = nil - var lastMapping *meta.RESTMapping - w := kubectl.GetNewTabWriter(out) - defer w.Flush() - - for ix := range objs { - var mapping *meta.RESTMapping - var original runtime.Object - if sorter != nil { - mapping = infos[sorter.OriginalPosition(ix)].Mapping - original = infos[sorter.OriginalPosition(ix)].Object - } else { - mapping = infos[ix].Mapping - original = infos[ix].Object - } - if printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource { - printer, err = f.PrinterForMapping(cmd, mapping, allNamespaces) - if err != nil { - allErrs = append(allErrs, err) - continue - } - lastMapping = mapping - } - if _, found := printer.(*kubectl.HumanReadablePrinter); found { - if err := printer.PrintObj(original, w); err != nil { - allErrs = append(allErrs, err) - } - continue - } - if err := printer.PrintObj(original, w); err != nil { - allErrs = append(allErrs, err) - continue - } - } - return utilerrors.NewAggregate(allErrs) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/get_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/get_test.go deleted file mode 100644 index 8b0981233..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/get_test.go +++ /dev/null @@ -1,869 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - encjson "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/json" - "k8s.io/kubernetes/pkg/runtime/serializer/streaming" - "k8s.io/kubernetes/pkg/util/diff" - "k8s.io/kubernetes/pkg/watch" - "k8s.io/kubernetes/pkg/watch/versioned" -) - -func testData() (*api.PodList, *api.ServiceList, *api.ReplicationControllerList) { - pods := &api.PodList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "15", - }, - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - svc := &api.ServiceList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "16", - }, - Items: []api.Service{ - { - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - SessionAffinity: "None", - Type: api.ServiceTypeClusterIP, - }, - }, - }, - } - rc := &api.ReplicationControllerList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "17", - }, - Items: []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{Name: "rc1", Namespace: "test", ResourceVersion: "18"}, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - }, - }, - }, - } - return pods, svc, rc -} - -func testComponentStatusData() *api.ComponentStatusList { - good := api.ComponentStatus{ - Conditions: []api.ComponentCondition{ - {Type: api.ComponentHealthy, Status: api.ConditionTrue, Message: "ok"}, - }, - ObjectMeta: api.ObjectMeta{Name: "servergood"}, - } - - bad := api.ComponentStatus{ - Conditions: []api.ComponentCondition{ - {Type: api.ComponentHealthy, Status: api.ConditionFalse, Message: "", Error: "bad status: 500"}, - }, - ObjectMeta: api.ObjectMeta{Name: "serverbad"}, - } - - unknown := api.ComponentStatus{ - Conditions: []api.ComponentCondition{ - {Type: api.ComponentHealthy, Status: api.ConditionUnknown, Message: "", Error: "fizzbuzz error"}, - }, - ObjectMeta: api.ObjectMeta{Name: "serverunknown"}, - } - - return &api.ComponentStatusList{ - Items: []api.ComponentStatus{good, bad, unknown}, - } -} - -// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. -func TestGetUnknownSchemaObject(t *testing.T) { - f, tf, codec := NewTestFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &internalType{Name: "foo"})}, - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"type", "foo"}) - - expected := &internalType{Name: "foo"} - actual := tf.Printer.(*testPrinter).Objects[0] - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v", actual) - } - if buf.String() != fmt.Sprintf("%#v", expected) { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. -// Because api.List is part of the Kube API, resource.Builder has to perform a conversion on -// api.Scheme, which may not have access to all objects, and not all objects are at the same -// internal versioning scheme. This test verifies that two isolated schemes (Test, and api.Scheme) -// can be conjoined into a single output object. -// -// The expected behavior of the `kubectl get` command is: -// 1. objects using unrecognized schemes will always be returned using that scheme/version, "unlikelyversion" in this test; -// 2. if the specified output-version is a recognized, valid Scheme, then the list should use that scheme, and otherwise it will default to the client version, testapi.Default.GroupVersion().String() in this test; -// 3a. if the specified output-version is a recognized, valid Scheme, in which the requested object (replicationcontroller) can be represented, then the object should be returned using that version; -// 3b. otherwise if the specified output-version is unrecognized, but the requested object (replicationcontroller) is recognized by the client's codec, then it will be converted to the client version, testapi.Default.GroupVersion().String() in this test. -func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { - testCases := map[string]struct { - outputVersion string - listVersion string - testtypeVersion string - rcVersion string - }{ - "handles specific version": { - outputVersion: testapi.Default.GroupVersion().String(), - listVersion: testapi.Default.GroupVersion().String(), - testtypeVersion: unlikelyGV.String(), - rcVersion: testapi.Default.GroupVersion().String(), - }, - "handles second specific version": { - outputVersion: "unlikely.group/unlikelyversion", - listVersion: testapi.Default.GroupVersion().String(), - testtypeVersion: unlikelyGV.String(), - rcVersion: testapi.Default.GroupVersion().String(), // see expected behavior 3b - }, - "handles common version": { - outputVersion: testapi.Default.GroupVersion().String(), - listVersion: testapi.Default.GroupVersion().String(), - testtypeVersion: unlikelyGV.String(), - rcVersion: testapi.Default.GroupVersion().String(), - }, - } - for k, test := range testCases { - apiCodec := testapi.Default.Codec() - regularClient := &fake.RESTClient{ - Codec: apiCodec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - return &http.Response{StatusCode: 200, Body: objBody(apiCodec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}})}, nil - }), - } - - f, tf, codec := NewMixedFactory(regularClient) - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - return &http.Response{StatusCode: 200, Body: objBody(codec, &internalType{Name: "foo"})}, nil - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("output", "json") - - cmd.Flags().Set("output-version", test.outputVersion) - err := RunGet(f, buf, cmd, []string{"type/foo", "replicationcontrollers/foo"}, &GetOptions{}) - if err != nil { - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - out := make(map[string]interface{}) - if err := encjson.Unmarshal(buf.Bytes(), &out); err != nil { - t.Errorf("%s: unexpected error: %v\n%s", k, err, buf.String()) - continue - } - if out["apiVersion"] != test.listVersion { - t.Errorf("%s: unexpected list: %#v", k, out) - } - arr := out["items"].([]interface{}) - if arr[0].(map[string]interface{})["apiVersion"] != test.testtypeVersion { - t.Errorf("%s: unexpected list: %#v", k, out) - } - if arr[1].(map[string]interface{})["apiVersion"] != test.rcVersion { - t.Errorf("%s: unexpected list: %#v", k, out) - } - } -} - -// Verifies that schemas that are not in the master tree of Kubernetes can be retrieved via Get. -func TestGetSchemaObject(t *testing.T) { - f, tf, _ := NewTestFactory() - tf.Mapper = testapi.Default.RESTMapper() - tf.Typer = api.Scheme - codec := testapi.Default.Codec() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}})}, - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}} - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.Run(cmd, []string{"replicationcontrollers", "foo"}) - - if !strings.Contains(buf.String(), "\"foo\"") { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestGetObjects(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"pods", "foo"}) - - expected := []runtime.Object{&pods.Items[0]} - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v", actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestGetSortedObjects(t *testing.T) { - pods := &api.PodList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "15", - }, - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{Name: "c", Namespace: "test", ResourceVersion: "10"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "b", Namespace: "test", ResourceVersion: "11"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "a", Namespace: "test", ResourceVersion: "9"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - // sorting with metedata.name - cmd.Flags().Set("sort-by", ".metadata.name") - cmd.Run(cmd, []string{"pods"}) - - // expect sorted: a,b,c - expected := []runtime.Object{&pods.Items[2], &pods.Items[1], &pods.Items[0]} - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v", actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } - -} - -func TestGetObjectsIdentifiedByFile(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("filename", "../../../examples/cassandra/cassandra-controller.yaml") - cmd.Run(cmd, []string{}) - - expected := []runtime.Object{&pods.Items[0]} - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v", actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestGetListObjects(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"pods"}) - - expected, err := extractResourceList([]runtime.Object{pods}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: expected %#v, got %#v", expected, actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func extractResourceList(objs []runtime.Object) ([]runtime.Object, error) { - finalObjs := []runtime.Object{} - for _, obj := range objs { - items, err := meta.ExtractList(obj) - if err != nil { - return nil, err - } - for _, item := range items { - finalObjs = append(finalObjs, item) - } - } - return finalObjs, nil -} - -func TestGetAllListObjects(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Flags().Set("show-all", "true") - cmd.Run(cmd, []string{"pods"}) - - expected, err := extractResourceList([]runtime.Object{pods}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v %#v", expected, actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestGetListComponentStatus(t *testing.T) { - statuses := testComponentStatusData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, statuses)}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"componentstatuses"}) - - expected, err := extractResourceList([]runtime.Object{statuses}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: expected %#v, got %#v", expected, actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestGetMultipleTypeObjects(t *testing.T) { - pods, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil - case "/namespaces/test/services": - return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"pods,services"}) - - expected, err := extractResourceList([]runtime.Object{pods, svc}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v", actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestGetMultipleTypeObjectsAsList(t *testing.T) { - pods, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil - case "/namespaces/test/services": - return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - cmd.Flags().Set("output", "json") - cmd.Run(cmd, []string{"pods,services"}) - - if tf.Printer.(*testPrinter).Objects != nil { - t.Errorf("unexpected print to default printer") - } - - out, err := runtime.Decode(codec, buf.Bytes()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - list, err := meta.ExtractList(out) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if errs := runtime.DecodeList(list, codec); len(errs) > 0 { - t.Fatalf("unexpected error: %v", errs) - } - if err := meta.SetList(out, list); err != nil { - t.Fatalf("unexpected error: %v", err) - } - - expected := &api.List{ - Items: []runtime.Object{ - &pods.Items[0], - &pods.Items[1], - &svc.Items[0], - }, - } - if !reflect.DeepEqual(expected, out) { - t.Errorf("unexpected output: %#v", out) - } -} - -func TestGetMultipleTypeObjectsWithSelector(t *testing.T) { - pods, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.URL.Query().Get(unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String())) != "a=b" { - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - } - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil - case "/namespaces/test/services": - return &http.Response{StatusCode: 200, Body: objBody(codec, svc)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - cmd.Flags().Set("selector", "a=b") - cmd.Run(cmd, []string{"pods,services"}) - - expected, err := extractResourceList([]runtime.Object{pods, svc}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v", actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) { - _, svc, _ := testData() - node := &api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.NodeSpec{ - ExternalID: "ext", - }, - } - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/nodes/foo": - return &http.Response{StatusCode: 200, Body: objBody(codec, node)}, nil - case "/namespaces/test/services/bar": - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - cmd.Run(cmd, []string{"services/bar", "node/foo"}) - - expected := []runtime.Object{&svc.Items[0], node} - actual := tf.Printer.(*testPrinter).Objects - if !api.Semantic.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %s", diff.ObjectDiff(expected, actual)) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestGetByNameForcesFlag(t *testing.T) { - pods, _, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Resp: &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - cmd.Run(cmd, []string{"pods", "foo"}) - - showAllFlag, _ := cmd.Flags().GetBool("show-all") - if !showAllFlag { - t.Errorf("expected showAll to be true when getting resource by name") - } -} - -func watchTestData() ([]api.Pod, []watch.Event) { - pods := []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "test", - ResourceVersion: "10", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - } - events := []watch.Event{ - { - Type: watch.Modified, - Object: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "test", - ResourceVersion: "11", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - { - Type: watch.Deleted, - Object: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "test", - ResourceVersion: "12", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - return pods, events -} - -func TestWatchSelector(t *testing.T) { - pods, events := watchTestData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.URL.Query().Get(unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String())) != "a=b" { - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - } - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Body: objBody(codec, &api.PodList{Items: pods})}, nil - case "/watch/namespaces/test/pods": - return &http.Response{StatusCode: 200, Body: watchBody(codec, events)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch", "true") - cmd.Flags().Set("selector", "a=b") - cmd.Run(cmd, []string{"pods"}) - - expected := []runtime.Object{&api.PodList{Items: pods}, events[0].Object, events[1].Object} - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object:\nExpected: %#v\n\nGot: %#v\n\n", expected[0], actual[0]) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestWatchResource(t *testing.T) { - pods, events := watchTestData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods[0])}, nil - case "/watch/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: watchBody(codec, events)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch", "true") - cmd.Run(cmd, []string{"pods", "foo"}) - - expected := []runtime.Object{&pods[0], events[0].Object, events[1].Object} - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object:\nExpected: %#v\n\nGot: %#v\n\n", expected, actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestWatchResourceIdentifiedByFile(t *testing.T) { - pods, events := watchTestData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/replicationcontrollers/cassandra": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods[0])}, nil - case "/watch/namespaces/test/replicationcontrollers/cassandra": - return &http.Response{StatusCode: 200, Body: watchBody(codec, events)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch", "true") - cmd.Flags().Set("filename", "../../../examples/cassandra/cassandra-controller.yaml") - cmd.Run(cmd, []string{}) - - expected := []runtime.Object{&pods[0], events[0].Object, events[1].Object} - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("expected object: %#v unexpected object: %#v", expected, actual) - } - - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func TestWatchOnlyResource(t *testing.T) { - pods, events := watchTestData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods[0])}, nil - case "/watch/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: watchBody(codec, events)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdGet(f, buf) - cmd.SetOutput(buf) - - cmd.Flags().Set("watch-only", "true") - cmd.Run(cmd, []string{"pods", "foo"}) - - expected := []runtime.Object{events[0].Object, events[1].Object} - actual := tf.Printer.(*testPrinter).Objects - if !reflect.DeepEqual(expected, actual) { - t.Errorf("unexpected object: %#v", actual) - } - if len(buf.String()) == 0 { - t.Errorf("unexpected empty output") - } -} - -func watchBody(codec runtime.Codec, events []watch.Event) io.ReadCloser { - buf := bytes.NewBuffer([]byte{}) - enc := versioned.NewEncoder(streaming.NewEncoder(buf, codec), codec) - for i := range events { - enc.Encode(&events[i]) - } - return json.Framer.NewFrameReader(ioutil.NopCloser(buf)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/label.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/label.go deleted file mode 100644 index b6a28d088..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/label.go +++ /dev/null @@ -1,312 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "encoding/json" - "fmt" - "io" - "reflect" - "strings" - - "github.com/golang/glog" - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - utilerrors "k8s.io/kubernetes/pkg/util/errors" - "k8s.io/kubernetes/pkg/util/strategicpatch" - "k8s.io/kubernetes/pkg/util/validation" -) - -// LabelOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type LabelOptions struct { - Filenames []string - Recursive bool -} - -const ( - label_long = `Update the labels on a resource. - -A label must begin with a letter or number, and may contain letters, numbers, hyphens, dots, and underscores, up to %[1]d characters. -If --overwrite is true, then existing labels can be overwritten, otherwise attempting to overwrite a label will result in an error. -If --resource-version is specified, then updates will use this resource version, otherwise the existing resource-version will be used.` - label_example = `# Update pod 'foo' with the label 'unhealthy' and the value 'true'. -kubectl label pods foo unhealthy=true - -# Update pod 'foo' with the label 'status' and the value 'unhealthy', overwriting any existing value. -kubectl label --overwrite pods foo status=unhealthy - -# Update all pods in the namespace -kubectl label pods --all status=unhealthy - -# Update a pod identified by the type and name in "pod.json" -kubectl label -f pod.json status=unhealthy - -# Update pod 'foo' only if the resource is unchanged from version 1. -kubectl label pods foo status=unhealthy --resource-version=1 - -# Update pod 'foo' by removing a label named 'bar' if it exists. -# Does not require the --overwrite flag. -kubectl label pods foo bar-` -) - -func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &LabelOptions{} - - // retrieve a list of handled resources from printer as valid args - validArgs, argAliases := []string{}, []string{} - p, err := f.Printer(nil, false, false, false, false, false, false, []string{}) - cmdutil.CheckErr(err) - if p != nil { - validArgs = p.HandledResources() - argAliases = kubectl.ResourceAliases(validArgs) - } - - cmd := &cobra.Command{ - Use: "label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]", - Short: "Update the labels on a resource", - Long: fmt.Sprintf(label_long, validation.LabelValueMaxLength), - Example: label_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunLabel(f, out, cmd, args, options) - cmdutil.CheckErr(err) - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - cmdutil.AddPrinterFlags(cmd) - cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.") - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") - cmd.Flags().Bool("all", false, "select all resources in the namespace of the specified resource types") - cmd.Flags().String("resource-version", "", "If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") - usage := "Filename, directory, or URL to a file identifying the resource to update the labels" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.") - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - - return cmd -} - -func validateNoOverwrites(accessor meta.Object, labels map[string]string) error { - allErrs := []error{} - for key := range labels { - if value, found := accessor.GetLabels()[key]; found { - allErrs = append(allErrs, fmt.Errorf("'%s' already has a value (%s), and --overwrite is false", key, value)) - } - } - return utilerrors.NewAggregate(allErrs) -} - -func parseLabels(spec []string) (map[string]string, []string, error) { - labels := map[string]string{} - var remove []string - for _, labelSpec := range spec { - if strings.Index(labelSpec, "=") != -1 { - parts := strings.Split(labelSpec, "=") - if len(parts) != 2 || len(parts[1]) == 0 || !validation.IsValidLabelValue(parts[1]) { - return nil, nil, fmt.Errorf("invalid label spec: %v", labelSpec) - } - labels[parts[0]] = parts[1] - } else if strings.HasSuffix(labelSpec, "-") { - remove = append(remove, labelSpec[:len(labelSpec)-1]) - } else { - return nil, nil, fmt.Errorf("unknown label spec: %v", labelSpec) - } - } - for _, removeLabel := range remove { - if _, found := labels[removeLabel]; found { - return nil, nil, fmt.Errorf("can not both modify and remove a label in the same command") - } - } - return labels, remove, nil -} - -func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, labels map[string]string, remove []string) error { - accessor, err := meta.Accessor(obj) - if err != nil { - return err - } - if !overwrite { - if err := validateNoOverwrites(accessor, labels); err != nil { - return err - } - } - - objLabels := accessor.GetLabels() - if objLabels == nil { - objLabels = make(map[string]string) - } - - for key, value := range labels { - objLabels[key] = value - } - for _, label := range remove { - delete(objLabels, label) - } - accessor.SetLabels(objLabels) - - if len(resourceVersion) != 0 { - accessor.SetResourceVersion(resourceVersion) - } - return nil -} - -func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *LabelOptions) error { - resources, labelArgs := []string{}, []string{} - first := true - for _, s := range args { - isLabel := strings.Contains(s, "=") || strings.HasSuffix(s, "-") - switch { - case first && isLabel: - first = false - fallthrough - case !first && isLabel: - labelArgs = append(labelArgs, s) - case first && !isLabel: - resources = append(resources, s) - case !first && !isLabel: - return cmdutil.UsageError(cmd, "all resources must be specified before label changes: %s", s) - } - } - if len(resources) < 1 && len(options.Filenames) == 0 { - return cmdutil.UsageError(cmd, "one or more resources must be specified as or /") - } - if len(labelArgs) < 1 { - return cmdutil.UsageError(cmd, "at least one label update is required") - } - - selector := cmdutil.GetFlagString(cmd, "selector") - all := cmdutil.GetFlagBool(cmd, "all") - overwrite := cmdutil.GetFlagBool(cmd, "overwrite") - resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - lbls, remove, err := parseLabels(labelArgs) - if err != nil { - return cmdutil.UsageError(cmd, err.Error()) - } - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - SelectorParam(selector). - ResourceTypeOrNameArgs(all, resources...). - Flatten(). - Latest() - - one := false - r := b.Do().IntoSingular(&one) - if err := r.Err(); err != nil { - return err - } - - // only apply resource version locking on a single resource - if !one && len(resourceVersion) > 0 { - return cmdutil.UsageError(cmd, "--resource-version may only be used with a single resource") - } - - // TODO: support bulk generic output a la Get - return r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - var outputObj runtime.Object - dataChangeMsg := "not labeled" - if cmdutil.GetFlagBool(cmd, "dry-run") { - err = labelFunc(info.Object, overwrite, resourceVersion, lbls, remove) - if err != nil { - return err - } - outputObj = info.Object - } else { - obj, err := info.Mapping.ConvertToVersion(info.Object, info.Mapping.GroupVersionKind.GroupVersion().String()) - if err != nil { - return err - } - name, namespace := info.Name, info.Namespace - oldData, err := json.Marshal(obj) - if err != nil { - return err - } - accessor, err := meta.Accessor(obj) - if err != nil { - return err - } - for _, label := range remove { - if _, ok := accessor.GetLabels()[label]; !ok { - fmt.Fprintf(out, "label %q not found.\n", label) - } - } - - if err := labelFunc(obj, overwrite, resourceVersion, lbls, remove); err != nil { - return err - } - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(obj, f.Command()); err != nil { - return err - } - } - newData, err := json.Marshal(obj) - if err != nil { - return err - } - if !reflect.DeepEqual(oldData, newData) { - dataChangeMsg = "labeled" - } - patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, obj) - createdPatch := err == nil - if err != nil { - glog.V(2).Infof("couldn't compute patch: %v", err) - } - - mapping := info.ResourceMapping() - client, err := f.ClientForMapping(mapping) - if err != nil { - return err - } - helper := resource.NewHelper(client, mapping) - - if createdPatch { - outputObj, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) - } else { - outputObj, err = helper.Replace(namespace, name, false, obj) - } - if err != nil { - return err - } - } - outputFormat := cmdutil.GetFlagString(cmd, "output") - if outputFormat != "" { - return f.PrintObject(cmd, mapper, outputObj, out) - } - cmdutil.PrintSuccess(mapper, false, out, info.Mapping.Resource, info.Name, dataChangeMsg) - return nil - }) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/label_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/label_test.go deleted file mode 100644 index 5c5f4d24f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/label_test.go +++ /dev/null @@ -1,418 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestValidateLabels(t *testing.T) { - tests := []struct { - meta *api.ObjectMeta - labels map[string]string - expectErr bool - test string - }{ - { - meta: &api.ObjectMeta{ - Labels: map[string]string{ - "a": "b", - "c": "d", - }, - }, - labels: map[string]string{ - "a": "c", - "d": "b", - }, - test: "one shared", - expectErr: true, - }, - { - meta: &api.ObjectMeta{ - Labels: map[string]string{ - "a": "b", - "c": "d", - }, - }, - labels: map[string]string{ - "b": "d", - "c": "a", - }, - test: "second shared", - expectErr: true, - }, - { - meta: &api.ObjectMeta{ - Labels: map[string]string{ - "a": "b", - "c": "d", - }, - }, - labels: map[string]string{ - "b": "a", - "d": "c", - }, - test: "no overlap", - }, - { - meta: &api.ObjectMeta{}, - labels: map[string]string{ - "b": "a", - "d": "c", - }, - test: "no labels", - }, - } - for _, test := range tests { - err := validateNoOverwrites(test.meta, test.labels) - if test.expectErr && err == nil { - t.Errorf("%s: unexpected non-error", test.test) - } - if !test.expectErr && err != nil { - t.Errorf("%s: unexpected error: %v", test.test, err) - } - } -} - -func TestParseLabels(t *testing.T) { - tests := []struct { - labels []string - expected map[string]string - expectedRemove []string - expectErr bool - }{ - { - labels: []string{"a=b", "c=d"}, - expected: map[string]string{"a": "b", "c": "d"}, - }, - { - labels: []string{}, - expected: map[string]string{}, - }, - { - labels: []string{"a=b", "c=d", "e-"}, - expected: map[string]string{"a": "b", "c": "d"}, - expectedRemove: []string{"e"}, - }, - { - labels: []string{"ab", "c=d"}, - expectErr: true, - }, - { - labels: []string{"a=b", "c=d", "a-"}, - expectErr: true, - }, - { - labels: []string{"a="}, - expectErr: true, - }, - { - labels: []string{"a=%^$"}, - expectErr: true, - }, - } - for _, test := range tests { - labels, remove, err := parseLabels(test.labels) - if test.expectErr && err == nil { - t.Errorf("unexpected non-error: %v", test) - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v %v", err, test) - } - if !reflect.DeepEqual(labels, test.expected) { - t.Errorf("expected: %v, got %v", test.expected, labels) - } - if !reflect.DeepEqual(remove, test.expectedRemove) { - t.Errorf("expected: %v, got %v", test.expectedRemove, remove) - } - } -} - -func TestLabelFunc(t *testing.T) { - tests := []struct { - obj runtime.Object - overwrite bool - version string - labels map[string]string - remove []string - expected runtime.Object - expectErr bool - }{ - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b"}, - }, - }, - labels: map[string]string{"a": "b"}, - expectErr: true, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b"}, - }, - }, - labels: map[string]string{"a": "c"}, - overwrite: true, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "c"}, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b"}, - }, - }, - labels: map[string]string{"c": "d"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b", "c": "d"}, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b"}, - }, - }, - labels: map[string]string{"c": "d"}, - version: "2", - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b", "c": "d"}, - ResourceVersion: "2", - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b"}, - }, - }, - labels: map[string]string{}, - remove: []string{"a"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{}, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b", "c": "d"}, - }, - }, - labels: map[string]string{"e": "f"}, - remove: []string{"a"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "c": "d", - "e": "f", - }, - }, - }, - }, - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{}, - }, - labels: map[string]string{"a": "b"}, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"a": "b"}, - }, - }, - }, - } - for _, test := range tests { - err := labelFunc(test.obj, test.overwrite, test.version, test.labels, test.remove) - if test.expectErr { - if err == nil { - t.Errorf("unexpected non-error: %v", test) - } - continue - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v %v", err, test) - } - if !reflect.DeepEqual(test.obj, test.expected) { - t.Errorf("expected: %v, got %v", test.expected, test.obj) - } - } -} - -func TestLabelErrors(t *testing.T) { - testCases := map[string]struct { - args []string - flags map[string]string - errFn func(error) bool - }{ - "no args": { - args: []string{}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "one or more resources must be specified") }, - }, - "not enough labels": { - args: []string{"pods"}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "at least one label update is required") }, - }, - "no resources": { - args: []string{"pods-"}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "one or more resources must be specified") }, - }, - "no resources 2": { - args: []string{"pods=bar"}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "one or more resources must be specified") }, - }, - } - - for k, testCase := range testCases { - f, tf, _ := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(f, buf) - cmd.SetOutput(buf) - - for k, v := range testCase.flags { - cmd.Flags().Set(k, v) - } - err := RunLabel(f, buf, cmd, testCase.args, &LabelOptions{}) - if !testCase.errFn(err) { - t.Errorf("%s: unexpected error: %v", k, err) - continue - } - if tf.Printer.(*testPrinter).Objects != nil { - t.Errorf("unexpected print to default printer") - } - if buf.Len() > 0 { - t.Errorf("buffer should be empty: %s", string(buf.Bytes())) - } - } -} - -func TestLabelForResourceFromFile(t *testing.T) { - pods, _, _ := testData() - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.Method { - case "GET": - switch req.URL.Path { - case "/namespaces/test/replicationcontrollers/cassandra": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - case "PATCH": - switch req.URL.Path { - case "/namespaces/test/replicationcontrollers/cassandra": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - default: - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(f, buf) - options := &LabelOptions{ - Filenames: []string{"../../../examples/cassandra/cassandra-controller.yaml"}, - } - - err := RunLabel(f, buf, cmd, []string{"a=b"}, options) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !strings.Contains(buf.String(), "labeled") { - t.Errorf("did not set labels: %s", buf.String()) - } -} - -func TestLabelMultipleObjects(t *testing.T) { - pods, _, _ := testData() - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch req.Method { - case "GET": - switch req.URL.Path { - case "/namespaces/test/pods": - return &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - case "PATCH": - switch req.URL.Path { - case "/namespaces/test/pods/foo": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[0])}, nil - case "/namespaces/test/pods/bar": - return &http.Response{StatusCode: 200, Body: objBody(codec, &pods.Items[1])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - default: - t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - - buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdLabel(f, buf) - cmd.Flags().Set("all", "true") - - if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}, &LabelOptions{}); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if strings.Count(buf.String(), "labeled") != len(pods.Items) { - t.Errorf("not all labels are set: %s", buf.String()) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go deleted file mode 100644 index b79d8c07d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/logs.go +++ /dev/null @@ -1,208 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "errors" - "io" - "math" - "os" - "time" - - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/client/restclient" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" -) - -const ( - logs_example = `# Return snapshot logs from pod nginx with only one container -kubectl logs nginx - -# Return snapshot of previous terminated ruby container logs from pod web-1 -kubectl logs -p -c ruby web-1 - -# Begin streaming the logs of the ruby container in pod web-1 -kubectl logs -f -c ruby web-1 - -# Display only the most recent 20 lines of output in pod nginx -kubectl logs --tail=20 nginx - -# Show all logs from pod nginx written in the last hour -kubectl logs --since=1h nginx` -) - -type LogsOptions struct { - Namespace string - ResourceArg string - Options runtime.Object - - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - ClientMapper resource.ClientMapper - Decoder runtime.Decoder - - Object runtime.Object - LogsForObject func(object, options runtime.Object) (*restclient.Request, error) - - Out io.Writer -} - -// NewCmdLog creates a new pod logs command -func NewCmdLogs(f *cmdutil.Factory, out io.Writer) *cobra.Command { - o := &LogsOptions{} - cmd := &cobra.Command{ - Use: "logs [-f] [-p] POD [-c CONTAINER]", - Short: "Print the logs for a container in a pod.", - Long: "Print the logs for a container in a pod. If the pod has only one container, the container name is optional.", - Example: logs_example, - PreRun: func(cmd *cobra.Command, args []string) { - if len(os.Args) > 1 && os.Args[1] == "log" { - printDeprecationWarning("logs", "log") - } - }, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(o.Complete(f, out, cmd, args)) - if err := o.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) - } - _, err := o.RunLogs() - cmdutil.CheckErr(err) - }, - Aliases: []string{"log"}, - } - cmd.Flags().BoolP("follow", "f", false, "Specify if the logs should be streamed.") - cmd.Flags().Bool("timestamps", false, "Include timestamps on each line in the log output") - cmd.Flags().Int64("limit-bytes", 0, "Maximum bytes of logs to return. Defaults to no limit.") - cmd.Flags().BoolP("previous", "p", false, "If true, print the logs for the previous instance of the container in a pod if it exists.") - cmd.Flags().Int64("tail", -1, "Lines of recent log file to display. Defaults to -1, showing all log lines.") - cmd.Flags().String("since-time", "", "Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.") - cmd.Flags().Duration("since", 0, "Only return logs newer than a relative duration like 5s, 2m, or 3h. Defaults to all logs. Only one of since-time / since may be used.") - cmd.Flags().StringP("container", "c", "", "Print the logs of this container") - - cmd.Flags().Bool("interactive", false, "If true, prompt the user for input when required.") - cmd.Flags().MarkDeprecated("interactive", "This flag is no longer respected and there is no replacement.") - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func (o *LogsOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error { - containerName := cmdutil.GetFlagString(cmd, "container") - switch len(args) { - case 0: - return cmdutil.UsageError(cmd, "POD is required for logs") - case 1: - o.ResourceArg = args[0] - case 2: - if cmd.Flag("container").Changed { - return cmdutil.UsageError(cmd, "only one of -c, [CONTAINER] arg is allowed") - } - o.ResourceArg = args[0] - containerName = args[1] - default: - return cmdutil.UsageError(cmd, "logs POD [-c CONTAINER]") - } - var err error - o.Namespace, _, err = f.DefaultNamespace() - if err != nil { - return err - } - - logOptions := &api.PodLogOptions{ - Container: containerName, - Follow: cmdutil.GetFlagBool(cmd, "follow"), - Previous: cmdutil.GetFlagBool(cmd, "previous"), - Timestamps: cmdutil.GetFlagBool(cmd, "timestamps"), - } - if sinceTime := cmdutil.GetFlagString(cmd, "since-time"); len(sinceTime) > 0 { - t, err := api.ParseRFC3339(sinceTime, unversioned.Now) - if err != nil { - return err - } - logOptions.SinceTime = &t - } - if limit := cmdutil.GetFlagInt64(cmd, "limit-bytes"); limit != 0 { - logOptions.LimitBytes = &limit - } - if tail := cmdutil.GetFlagInt64(cmd, "tail"); tail != -1 { - logOptions.TailLines = &tail - } - if sinceSeconds := cmdutil.GetFlagDuration(cmd, "since"); sinceSeconds != 0 { - // round up to the nearest second - sec := int64(math.Ceil(float64(sinceSeconds) / float64(time.Second))) - logOptions.SinceSeconds = &sec - } - o.Options = logOptions - o.LogsForObject = f.LogsForObject - o.ClientMapper = resource.ClientMapperFunc(f.ClientForMapping) - o.Out = out - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - decoder := f.Decoder(true) - if o.Object == nil { - infos, err := resource.NewBuilder(mapper, typer, o.ClientMapper, decoder). - NamespaceParam(o.Namespace).DefaultNamespace(). - ResourceNames("pods", o.ResourceArg). - SingleResourceType(). - Do().Infos() - if err != nil { - return err - } - if len(infos) != 1 { - return errors.New("expected a resource") - } - o.Object = infos[0].Object - } - - return nil -} - -func (o LogsOptions) Validate() error { - if len(o.ResourceArg) == 0 { - return errors.New("a pod must be specified") - } - logsOptions, ok := o.Options.(*api.PodLogOptions) - if !ok { - return errors.New("unexpected logs options object") - } - if errs := validation.ValidatePodLogOptions(logsOptions); len(errs) > 0 { - return errs.ToAggregate() - } - - return nil -} - -// RunLogs retrieves a pod log -func (o LogsOptions) RunLogs() (int64, error) { - req, err := o.LogsForObject(o.Object, o.Options) - if err != nil { - return 0, err - } - - readCloser, err := req.Stream() - if err != nil { - return 0, err - } - defer readCloser.Close() - - return io.Copy(o.Out, readCloser) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/logs_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/logs_test.go deleted file mode 100644 index 9f1205f71..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/logs_test.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "io/ioutil" - "net/http" - "os" - "strings" - "testing" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestLog(t *testing.T) { - tests := []struct { - name, version, podPath, logPath, container string - pod *api.Pod - }{ - { - name: "v1 - pod log", - version: "v1", - podPath: "/namespaces/test/pods/foo", - logPath: "/api/v1/namespaces/test/pods/foo/log", - pod: testPod(), - }, - } - for _, test := range tests { - logContent := "test log content" - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Body: body}, nil - case p == test.logPath && m == "GET": - body := ioutil.NopCloser(bytes.NewBufferString(logContent)) - return &http.Response{StatusCode: 200, Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: test.version}}} - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdLogs(f, buf) - cmd.Flags().Set("namespace", "test") - cmd.Run(cmd, []string{"foo"}) - - if buf.String() != logContent { - t.Errorf("%s: did not get expected log content. Got: %s", test.name, buf.String()) - } - } -} - -func testPod() *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - Containers: []api.Container{ - { - Name: "bar", - }, - }, - }, - } -} - -func TestValidateLogFlags(t *testing.T) { - f, _, _ := NewAPIFactory() - - tests := []struct { - name string - flags map[string]string - expected string - }{ - { - name: "since & since-time", - flags: map[string]string{"since": "1h", "since-time": "2006-01-02T15:04:05Z"}, - expected: "at most one of `sinceTime` or `sinceSeconds` may be specified", - }, - { - name: "negative limit-bytes", - flags: map[string]string{"limit-bytes": "-100"}, - expected: "must be greater than 0", - }, - { - name: "negative tail", - flags: map[string]string{"tail": "-100"}, - expected: "must be greater than or equal to 0", - }, - } - for _, test := range tests { - cmd := NewCmdLogs(f, bytes.NewBuffer([]byte{})) - out := "" - for flag, value := range test.flags { - cmd.Flags().Set(flag, value) - } - // checkErr breaks tests in case of errors, plus we just - // need to check errors returned by the command validation - o := &LogsOptions{} - cmd.Run = func(cmd *cobra.Command, args []string) { - o.Complete(f, os.Stdout, cmd, args) - out = o.Validate().Error() - } - cmd.Run(cmd, []string{"foo"}) - - if !strings.Contains(out, test.expected) { - t.Errorf("%s: expected to find:\n\t%s\nfound:\n\t%s\n", test.name, test.expected, out) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/namespace.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/namespace.go deleted file mode 100644 index e50e4c078..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/namespace.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -// TODO remove once people have been given enough time to notice -func NewCmdNamespace(out io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "namespace [namespace]", - Short: "SUPERSEDED: Set and view the current Kubernetes namespace", - Long: `SUPERSEDED: Set and view the current Kubernetes namespace scope for command line requests. - -namespace has been superseded by the context.namespace field of .kubeconfig files. See 'kubectl config set-context --help' for more details. -`, - Run: func(cmd *cobra.Command, args []string) { - util.CheckErr(fmt.Errorf("namespace has been superseded by the context.namespace field of .kubeconfig files. See 'kubectl config set-context --help' for more details.")) - }, - } - return cmd -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/patch.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/patch.go deleted file mode 100644 index 6f892133c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/patch.go +++ /dev/null @@ -1,177 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "strings" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/yaml" -) - -var patchTypes = map[string]api.PatchType{"json": api.JSONPatchType, "merge": api.MergePatchType, "strategic": api.StrategicMergePatchType} - -// PatchOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type PatchOptions struct { - Filenames []string - Recursive bool -} - -const ( - patch_long = `Update field(s) of a resource using strategic merge patch - -JSON and YAML formats are accepted. - -Please refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.` - patch_example = ` -# Partially update a node using strategic merge patch -kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}' - -# Partially update a node identified by the type and name specified in "node.json" using strategic merge patch -kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}' - -# Update a container's image; spec.containers[*].name is required because it's a merge key -kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}' - -# Update a container's image using a json patch with positional arrays -kubectl patch pod valid-pod -type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'` -) - -func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &PatchOptions{} - - // retrieve a list of handled resources from printer as valid args - validArgs, argAliases := []string{}, []string{} - p, err := f.Printer(nil, false, false, false, false, false, false, []string{}) - cmdutil.CheckErr(err) - if p != nil { - validArgs = p.HandledResources() - argAliases = kubectl.ResourceAliases(validArgs) - } - - cmd := &cobra.Command{ - Use: "patch (-f FILENAME | TYPE NAME) -p PATCH", - Short: "Update field(s) of a resource using strategic merge patch.", - Long: patch_long, - Example: patch_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - err := RunPatch(f, out, cmd, args, shortOutput, options) - cmdutil.CheckErr(err) - }, - ValidArgs: validArgs, - ArgAliases: argAliases, - } - cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.") - cmd.MarkFlagRequired("patch") - cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List())) - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - - usage := "Filename, directory, or URL to a file identifying the resource to update" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - return cmd -} - -func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *PatchOptions) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - patchType := api.StrategicMergePatchType - patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type")) - if len(patchTypeString) != 0 { - ok := false - patchType, ok = patchTypes[patchTypeString] - if !ok { - return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString)) - } - } - - patch := cmdutil.GetFlagString(cmd, "patch") - if len(patch) == 0 { - return cmdutil.UsageError(cmd, "Must specify -p to patch") - } - patchBytes, err := yaml.ToJSON([]byte(patch)) - if err != nil { - return fmt.Errorf("unable to parse %q: %v", patch, err) - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - ResourceTypeOrNameArgs(false, args...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - count := 0 - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - name, namespace := info.Name, info.Namespace - mapping := info.ResourceMapping() - client, err := f.ClientForMapping(mapping) - if err != nil { - return err - } - - helper := resource.NewHelper(client, mapping) - patchedObject, err := helper.Patch(namespace, name, patchType, patchBytes) - if err != nil { - return err - } - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(patchedObject, f.Command()); err == nil { - // don't return an error on failure. The patch itself succeeded, its only the hint for that change that failed - // don't bother checking for failures of this replace, because a failure to indicate the hint doesn't fail the command - // also, don't force the replacement. If the replacement fails on a resourceVersion conflict, then it means this - // record hint is likely to be invalid anyway, so avoid the bad hint - resource.NewHelper(client, mapping).Replace(namespace, name, false, patchedObject) - } - } - count++ - cmdutil.PrintSuccess(mapper, shortOutput, out, "", name, "patched") - return nil - }) - if err != nil { - return err - } - if count == 0 { - return fmt.Errorf("no objects passed to patch") - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/patch_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/patch_test.go deleted file mode 100644 index fd22dcaf4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/patch_test.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "testing" - - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestPatchObject(t *testing.T) { - _, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdPatch(f, buf) - cmd.Flags().Set("namespace", "test") - cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`) - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{"services/frontend"}) - - // uses the name from the file, not the response - if buf.String() != "frontend\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestPatchObjectFromFile(t *testing.T) { - _, svc, _ := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/services/frontend" && (m == "PATCH" || m == "GET"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdPatch(f, buf) - cmd.Flags().Set("namespace", "test") - cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`) - cmd.Flags().Set("output", "name") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") - cmd.Run(cmd, []string{}) - - // uses the name from the file, not the response - if buf.String() != "frontend\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/portforward.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/portforward.go deleted file mode 100644 index 3d705466f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/portforward.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "io" - "net/url" - "os" - "os/signal" - - "github.com/golang/glog" - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/portforward" - "k8s.io/kubernetes/pkg/client/unversioned/remotecommand" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -const ( - portforward_example = ` -# Listen on ports 5000 and 6000 locally, forwarding data to/from ports 5000 and 6000 in the pod -kubectl port-forward mypod 5000 6000 - -# Listen on port 8888 locally, forwarding to 5000 in the pod -kubectl port-forward mypod 8888:5000 - -# Listen on a random port locally, forwarding to 5000 in the pod -kubectl port-forward mypod :5000 - -# Listen on a random port locally, forwarding to 5000 in the pod -kubectl port-forward mypod 0:5000` -) - -func NewCmdPortForward(f *cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "port-forward POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]", - Short: "Forward one or more local ports to a pod.", - Long: "Forward one or more local ports to a pod.", - Example: portforward_example, - Run: func(cmd *cobra.Command, args []string) { - pf := &defaultPortForwarder{ - cmdOut: cmdOut, - cmdErr: cmdErr, - } - err := RunPortForward(f, cmd, args, pf) - cmdutil.CheckErr(err) - }, - } - cmd.Flags().StringP("pod", "p", "", "Pod name") - // TODO support UID - return cmd -} - -type portForwarder interface { - ForwardPorts(method string, url *url.URL, config *restclient.Config, ports []string, stopChan <-chan struct{}) error -} - -type defaultPortForwarder struct { - cmdOut, cmdErr io.Writer -} - -func (f *defaultPortForwarder) ForwardPorts(method string, url *url.URL, config *restclient.Config, ports []string, stopChan <-chan struct{}) error { - dialer, err := remotecommand.NewExecutor(config, method, url) - if err != nil { - return err - } - fw, err := portforward.New(dialer, ports, stopChan, f.cmdOut, f.cmdErr) - if err != nil { - return err - } - return fw.ForwardPorts() -} - -func RunPortForward(f *cmdutil.Factory, cmd *cobra.Command, args []string, fw portForwarder) error { - podName := cmdutil.GetFlagString(cmd, "pod") - if len(podName) == 0 && len(args) == 0 { - return cmdutil.UsageError(cmd, "POD is required for port-forward") - } - - if len(podName) != 0 { - printDeprecationWarning("port-forward POD", "-p POD") - } else { - podName = args[0] - args = args[1:] - } - - if len(args) < 1 { - return cmdutil.UsageError(cmd, "at least 1 PORT is required for port-forward") - } - - namespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } - - client, err := f.Client() - if err != nil { - return err - } - - pod, err := client.Pods(namespace).Get(podName) - if err != nil { - return err - } - - if pod.Status.Phase != api.PodRunning { - glog.Fatalf("Unable to execute command because pod is not running. Current status=%v", pod.Status.Phase) - } - - config, err := f.ClientConfig() - if err != nil { - return err - } - - signals := make(chan os.Signal, 1) - signal.Notify(signals, os.Interrupt) - defer signal.Stop(signals) - - stopCh := make(chan struct{}, 1) - go func() { - <-signals - close(stopCh) - }() - - req := client.RESTClient.Post(). - Resource("pods"). - Namespace(namespace). - Name(pod.Name). - SubResource("portforward") - - return fw.ForwardPorts("POST", req.URL(), config, args, stopCh) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/portforward_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/portforward_test.go deleted file mode 100644 index d88ab90f4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/portforward_test.go +++ /dev/null @@ -1,176 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "net/http" - "net/url" - "testing" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -type fakePortForwarder struct { - method string - url *url.URL - pfErr error -} - -func (f *fakePortForwarder) ForwardPorts(method string, url *url.URL, config *restclient.Config, ports []string, stopChan <-chan struct{}) error { - f.method = method - f.url = url - return f.pfErr -} - -func TestPortForward(t *testing.T) { - version := testapi.Default.GroupVersion().Version - - tests := []struct { - name, version, podPath, pfPath, container string - pod *api.Pod - pfErr bool - }{ - { - name: "pod portforward", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - pfPath: "/api/" + version + "/namespaces/test/pods/foo/portforward", - pod: execPod(), - }, - { - name: "pod portforward error", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - pfPath: "/api/" + version + "/namespaces/test/pods/foo/portforward", - pod: execPod(), - pfErr: true, - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: test.version}}} - ff := &fakePortForwarder{} - if test.pfErr { - ff.pfErr = fmt.Errorf("pf error") - } - cmd := &cobra.Command{} - cmd.Flags().StringP("pod", "p", "", "Pod name") - err := RunPortForward(f, cmd, []string{"foo", ":5000", ":1000"}, ff) - - if test.pfErr && err != ff.pfErr { - t.Errorf("%s: Unexpected exec error: %v", test.name, err) - } - if !test.pfErr && err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - } - if test.pfErr { - continue - } - - if ff.url.Path != test.pfPath { - t.Errorf("%s: Did not get expected path for portforward request", test.name) - } - if ff.method != "POST" { - t.Errorf("%s: Did not get method for attach request: %s", test.name, ff.method) - } - - } -} - -func TestPortForwardWithPFlag(t *testing.T) { - version := testapi.Default.GroupVersion().Version - - tests := []struct { - name, version, podPath, pfPath, container string - pod *api.Pod - pfErr bool - }{ - { - name: "pod portforward", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - pfPath: "/api/" + version + "/namespaces/test/pods/foo/portforward", - pod: execPod(), - }, - { - name: "pod portforward error", - version: version, - podPath: "/api/" + version + "/namespaces/test/pods/foo", - pfPath: "/api/" + version + "/namespaces/test/pods/foo/portforward", - pod: execPod(), - pfErr: true, - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == test.podPath && m == "GET": - body := objBody(codec, test.pod) - return &http.Response{StatusCode: 200, Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %#v\n%#v", test.name, req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: test.version}}} - ff := &fakePortForwarder{} - if test.pfErr { - ff.pfErr = fmt.Errorf("pf error") - } - cmd := &cobra.Command{} - podPtr := cmd.Flags().StringP("pod", "p", "", "Pod name") - *podPtr = "foo" - err := RunPortForward(f, cmd, []string{":5000", ":1000"}, ff) - if test.pfErr && err != ff.pfErr { - t.Errorf("%s: Unexpected exec error: %v", test.name, err) - } - if !test.pfErr && ff.url.Path != test.pfPath { - t.Errorf("%s: Did not get expected path for portforward request", test.name) - } - if !test.pfErr && err != nil { - t.Errorf("%s: Unexpected error: %v", test.name, err) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/proxy.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/proxy.go deleted file mode 100644 index 77330af76..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/proxy.go +++ /dev/null @@ -1,137 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "errors" - "fmt" - "io" - "net" - "strings" - - "github.com/golang/glog" - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -const ( - default_port = 8001 - proxy_example = `# Run a proxy to kubernetes apiserver on port 8011, serving static content from ./local/www/ -kubectl proxy --port=8011 --www=./local/www/ - -# Run a proxy to kubernetes apiserver on an arbitrary local port. -# The chosen port for the server will be output to stdout. -kubectl proxy --port=0 - -# Run a proxy to kubernetes apiserver, changing the api prefix to k8s-api -# This makes e.g. the pods api available at localhost:8011/k8s-api/v1/pods/ -kubectl proxy --api-prefix=/k8s-api` -) - -func NewCmdProxy(f *cmdutil.Factory, out io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix]", - Short: "Run a proxy to the Kubernetes API server", - Long: `To proxy all of the kubernetes api and nothing else, use: - -kubectl proxy --api-prefix=/ - -To proxy only part of the kubernetes api and also some static files: - -kubectl proxy --www=/my/files --www-prefix=/static/ --api-prefix=/api/ - -The above lets you 'curl localhost:8001/api/v1/pods'. - -To proxy the entire kubernetes api at a different root, use: - -kubectl proxy --api-prefix=/custom/ - -The above lets you 'curl localhost:8001/custom/api/v1/pods' -`, - Example: proxy_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunProxy(f, out, cmd) - cmdutil.CheckErr(err) - }, - } - cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the specified prefix.") - cmd.Flags().StringP("www-prefix", "P", "/static/", "Prefix to serve static files under, if static file directory is specified.") - cmd.Flags().StringP("api-prefix", "", "/", "Prefix to serve the proxied API under.") - cmd.Flags().String("accept-paths", kubectl.DefaultPathAcceptRE, "Regular expression for paths that the proxy should accept.") - cmd.Flags().String("reject-paths", kubectl.DefaultPathRejectRE, "Regular expression for paths that the proxy should reject.") - cmd.Flags().String("accept-hosts", kubectl.DefaultHostAcceptRE, "Regular expression for hosts that the proxy should accept.") - cmd.Flags().String("reject-methods", kubectl.DefaultMethodRejectRE, "Regular expression for HTTP methods that the proxy should reject.") - cmd.Flags().IntP("port", "p", default_port, "The port on which to run the proxy. Set to 0 to pick a random port.") - cmd.Flags().StringP("address", "", "127.0.0.1", "The IP address on which to serve on.") - cmd.Flags().Bool("disable-filter", false, "If true, disable request filtering in the proxy. This is dangerous, and can leave you vulnerable to XSRF attacks, when used with an accessible port.") - cmd.Flags().StringP("unix-socket", "u", "", "Unix socket on which to run the proxy.") - return cmd -} - -func RunProxy(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { - path := cmdutil.GetFlagString(cmd, "unix-socket") - port := cmdutil.GetFlagInt(cmd, "port") - address := cmdutil.GetFlagString(cmd, "address") - - if port != default_port && path != "" { - return errors.New("Don't specify both --unix-socket and --port") - } - - clientConfig, err := f.ClientConfig() - if err != nil { - return err - } - - staticPrefix := cmdutil.GetFlagString(cmd, "www-prefix") - if !strings.HasSuffix(staticPrefix, "/") { - staticPrefix += "/" - } - - apiProxyPrefix := cmdutil.GetFlagString(cmd, "api-prefix") - if !strings.HasSuffix(apiProxyPrefix, "/") { - apiProxyPrefix += "/" - } - filter := &kubectl.FilterServer{ - AcceptPaths: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "accept-paths")), - RejectPaths: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "reject-paths")), - AcceptHosts: kubectl.MakeRegexpArrayOrDie(cmdutil.GetFlagString(cmd, "accept-hosts")), - } - if cmdutil.GetFlagBool(cmd, "disable-filter") { - if path == "" { - glog.Warning("Request filter disabled, your proxy is vulnerable to XSRF attacks, please be cautious") - } - filter = nil - } - - server, err := kubectl.NewProxyServer(cmdutil.GetFlagString(cmd, "www"), apiProxyPrefix, staticPrefix, filter, clientConfig) - - // Separate listening from serving so we can report the bound port - // when it is chosen by os (eg: port == 0) - var l net.Listener - if path == "" { - l, err = server.Listen(address, port) - } else { - l, err = server.ListenUnix(path) - } - if err != nil { - glog.Fatal(err) - } - fmt.Fprintf(out, "Starting to serve on %s", l.Addr().String()) - glog.Fatal(server.ServeOnListener(l)) - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/replace.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/replace.go deleted file mode 100644 index e7157ebb3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/replace.go +++ /dev/null @@ -1,258 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - - "github.com/spf13/cobra" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" -) - -// ReplaceOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ReplaceOptions struct { - Filenames []string - Recursive bool -} - -const ( - replace_long = `Replace a resource by filename or stdin. - -JSON and YAML formats are accepted. If replacing an existing resource, the -complete resource spec must be provided. This can be obtained by -$ kubectl get TYPE NAME -o yaml - -Please refer to the models in https://htmlpreview.github.io/?https://github.com/kubernetes/kubernetes/blob/HEAD/docs/api-reference/v1/definitions.html to find if a field is mutable.` - replace_example = `# Replace a pod using the data in pod.json. -kubectl replace -f ./pod.json - -# Replace a pod based on the JSON passed into stdin. -cat pod.json | kubectl replace -f - - -# Update a single-container pod's image version (tag) to v4 -kubectl get pod mypod -o yaml | sed 's/\(image: myimage\):.*$/\1:v4/' | kubectl replace -f - - -# Force replace, delete and then re-create the resource -kubectl replace --force -f ./pod.json` -) - -func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ReplaceOptions{} - - cmd := &cobra.Command{ - Use: "replace -f FILENAME", - // update is deprecated. - Aliases: []string{"update"}, - Short: "Replace a resource by filename or stdin.", - Long: replace_long, - Example: replace_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - err := RunReplace(f, out, cmd, args, options) - cmdutil.CheckErr(err) - }, - } - usage := "Filename, directory, or URL to file to use to replace the resource." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmd.MarkFlagRequired("filename") - cmd.Flags().Bool("force", false, "Delete and re-create the specified resource") - cmd.Flags().Bool("cascade", false, "Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController).") - cmd.Flags().Int("grace-period", -1, "Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.") - cmd.Flags().Duration("timeout", 0, "Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object") - cmdutil.AddValidateFlags(cmd) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - - return cmd -} - -func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *ReplaceOptions) error { - if len(os.Args) > 1 && os.Args[1] == "update" { - printDeprecationWarning("replace", "update") - } - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) - if err != nil { - return err - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - force := cmdutil.GetFlagBool(cmd, "force") - if len(options.Filenames) == 0 { - return cmdutil.UsageError(cmd, "Must specify --filename to replace") - } - - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - if force { - return forceReplace(f, out, cmd, args, shortOutput, options) - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - Schema(schema). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - return r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil { - return cmdutil.AddSourceToErr("replacing", info.Source, err) - } - - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { - return cmdutil.AddSourceToErr("replacing", info.Source, err) - } - } - - // Serialize the object with the annotation applied. - obj, err := resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, true, info.Object) - if err != nil { - return cmdutil.AddSourceToErr("replacing", info.Source, err) - } - - info.Refresh(obj, true) - printObjectSpecificMessage(obj, out) - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced") - return nil - }) -} - -func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *ReplaceOptions) error { - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) - if err != nil { - return err - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - for i, filename := range options.Filenames { - if filename == "-" { - tempDir, err := ioutil.TempDir("", "kubectl_replace_") - if err != nil { - return err - } - defer os.RemoveAll(tempDir) - tempFilename := filepath.Join(tempDir, "resource.stdin") - err = cmdutil.DumpReaderToFile(os.Stdin, tempFilename) - if err != nil { - return err - } - options.Filenames[i] = tempFilename - } - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - ResourceTypeOrNameArgs(false, args...).RequireObject(false). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - //Replace will create a resource if it doesn't exist already, so ignore not found error - ignoreNotFound := true - // By default use a reaper to delete all related resources. - if cmdutil.GetFlagBool(cmd, "cascade") { - glog.Warningf("\"cascade\" is set, kubectl will delete and re-create all resources managed by this resource (e.g. Pods created by a ReplicationController). Consider using \"kubectl rolling-update\" if you want to update a ReplicationController together with its Pods.") - err = ReapResult(r, f, out, cmdutil.GetFlagBool(cmd, "cascade"), ignoreNotFound, cmdutil.GetFlagDuration(cmd, "timeout"), cmdutil.GetFlagInt(cmd, "grace-period"), shortOutput, mapper) - } else { - err = DeleteResult(r, out, ignoreNotFound, shortOutput, mapper) - } - if err != nil { - return err - } - - r = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - Schema(schema). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - count := 0 - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil { - return err - } - - if cmdutil.ShouldRecord(cmd, info) { - if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil { - return cmdutil.AddSourceToErr("replacing", info.Source, err) - } - } - - obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object) - if err != nil { - return err - } - - count++ - info.Refresh(obj, true) - printObjectSpecificMessage(obj, out) - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced") - return nil - }) - if err != nil { - return err - } - if count == 0 { - return fmt.Errorf("no objects passed to replace") - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/replace_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/replace_test.go deleted file mode 100644 index e511f92b8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/replace_test.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "net/http" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/client/unversioned/fake" -) - -func TestReplaceObject(t *testing.T) { - _, _, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == "GET" || m == "PUT" || m == "DELETE"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - case p == "/namespaces/test/replicationcontrollers" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdReplace(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - // uses the name from the file, not the response - if buf.String() != "replicationcontroller/rc1\n" { - t.Errorf("unexpected output: %s", buf.String()) - } - - buf.Reset() - cmd.Flags().Set("force", "true") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/redis-master\nreplicationcontroller/rc1\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestReplaceMultipleObject(t *testing.T) { - _, svc, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == "GET" || m == "PUT" || m == "DELETE"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - case p == "/namespaces/test/replicationcontrollers" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - case p == "/namespaces/test/services/frontend" && (m == "GET" || m == "PUT" || m == "DELETE"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &svc.Items[0])}, nil - case p == "/namespaces/test/services" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &svc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdReplace(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/rc1\nservice/baz\n" { - t.Errorf("unexpected output: %s", buf.String()) - } - - buf.Reset() - cmd.Flags().Set("force", "true") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/redis-master\nservice/frontend\nreplicationcontroller/rc1\nservice/baz\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestReplaceDirectory(t *testing.T) { - _, _, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && (m == "GET" || m == "PUT" || m == "DELETE"): - return &http.Response{StatusCode: 200, Body: objBody(codec, &rc.Items[0])}, nil - case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers") && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdReplace(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy") - cmd.Flags().Set("namespace", "test") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/rc1\nreplicationcontroller/rc1\nreplicationcontroller/rc1\n" { - t.Errorf("unexpected output: %s", buf.String()) - } - - buf.Reset() - cmd.Flags().Set("force", "true") - cmd.Flags().Set("cascade", "false") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/frontend\nreplicationcontroller/redis-master\nreplicationcontroller/redis-slave\n"+ - "replicationcontroller/rc1\nreplicationcontroller/rc1\nreplicationcontroller/rc1\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} - -func TestForceReplaceObjectNotFound(t *testing.T) { - _, _, rc := testData() - - f, tf, codec := NewAPIFactory() - tf.Printer = &testPrinter{} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == "/namespaces/test/replicationcontrollers/redis-master" && m == "DELETE": - return &http.Response{StatusCode: 404, Body: stringBody("")}, nil - case p == "/namespaces/test/replicationcontrollers" && m == "POST": - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - tf.Namespace = "test" - buf := bytes.NewBuffer([]byte{}) - - cmd := NewCmdReplace(f, buf) - cmd.Flags().Set("filename", "../../../examples/guestbook/legacy/redis-master-controller.yaml") - cmd.Flags().Set("force", "true") - cmd.Flags().Set("cascade", "false") - cmd.Flags().Set("output", "name") - cmd.Run(cmd, []string{}) - - if buf.String() != "replicationcontroller/rc1\n" { - t.Errorf("unexpected output: %s", buf.String()) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate.go deleted file mode 100644 index 8f745e06d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate.go +++ /dev/null @@ -1,410 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "fmt" - "io" - "os" - "time" - - "github.com/golang/glog" - - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/util/intstr" -) - -// RollingUpdateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type RollingUpdateOptions struct { - Filenames []string -} - -const ( - rollingUpdate_long = `Perform a rolling update of the given ReplicationController. - -Replaces the specified replication controller with a new replication controller by updating one pod at a time to use the -new PodTemplate. The new-controller.json must specify the same namespace as the -existing replication controller and overwrite at least one (common) label in its replicaSelector.` - rollingUpdate_example = `# Update pods of frontend-v1 using new replication controller data in frontend-v2.json. -kubectl rolling-update frontend-v1 -f frontend-v2.json - -# Update pods of frontend-v1 using JSON data passed into stdin. -cat frontend-v2.json | kubectl rolling-update frontend-v1 -f - - -# Update the pods of frontend-v1 to frontend-v2 by just changing the image, and switching the -# name of the replication controller. -kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2 - -# Update the pods of frontend by just changing the image, and keeping the old name. -kubectl rolling-update frontend --image=image:v2 - -# Abort and reverse an existing rollout in progress (from frontend-v1 to frontend-v2). -kubectl rolling-update frontend-v1 frontend-v2 --rollback -` -) - -var ( - updatePeriod, _ = time.ParseDuration("1m0s") - timeout, _ = time.ParseDuration("5m0s") - pollInterval, _ = time.ParseDuration("3s") -) - -func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &RollingUpdateOptions{} - - cmd := &cobra.Command{ - Use: "rolling-update OLD_CONTROLLER_NAME ([NEW_CONTROLLER_NAME] --image=NEW_CONTAINER_IMAGE | -f NEW_CONTROLLER_SPEC)", - // rollingupdate is deprecated. - Aliases: []string{"rollingupdate"}, - Short: "Perform a rolling update of the given ReplicationController.", - Long: rollingUpdate_long, - Example: rollingUpdate_example, - Run: func(cmd *cobra.Command, args []string) { - err := RunRollingUpdate(f, out, cmd, args, options) - cmdutil.CheckErr(err) - }, - } - cmd.Flags().Duration("update-period", updatePeriod, `Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) - cmd.Flags().Duration("poll-interval", pollInterval, `Time delay between polling for replication controller status after the update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) - cmd.Flags().Duration("timeout", timeout, `Max time to wait for a replication controller to update before giving up. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`) - usage := "Filename or URL to file to use to create the new replication controller." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmd.MarkFlagRequired("filename") - cmd.Flags().String("image", "", "Image to use for upgrading the replication controller. Must be distinct from the existing image (either new image or new image tag). Can not be used with --filename/-f") - cmd.MarkFlagRequired("image") - cmd.Flags().String("deployment-label-key", "deployment", "The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise") - cmd.Flags().String("container", "", "Container name which will have its image upgraded. Only relevant when --image is specified, ignored otherwise. Required when using --image on a multi-container pod") - cmd.Flags().String("image-pull-policy", "", "Explicit policy for when to pull container images. Required when --image is same as existing image, ignored otherwise.") - cmd.Flags().Bool("dry-run", false, "If true, print out the changes that would be made, but don't actually make them.") - cmd.Flags().Bool("rollback", false, "If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout") - cmdutil.AddValidateFlags(cmd) - cmdutil.AddPrinterFlags(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - - return cmd -} - -func validateArguments(cmd *cobra.Command, filenames, args []string) error { - deploymentKey := cmdutil.GetFlagString(cmd, "deployment-label-key") - image := cmdutil.GetFlagString(cmd, "image") - rollback := cmdutil.GetFlagBool(cmd, "rollback") - - if len(deploymentKey) == 0 { - return cmdutil.UsageError(cmd, "--deployment-label-key can not be empty") - } - if len(filenames) > 1 { - return cmdutil.UsageError(cmd, "May only specify a single filename for new controller") - } - - if !rollback { - if len(filenames) == 0 && len(image) == 0 { - return cmdutil.UsageError(cmd, "Must specify --filename or --image for new controller") - } - if len(filenames) != 0 && len(image) != 0 { - return cmdutil.UsageError(cmd, "--filename and --image can not both be specified") - } - } else { - if len(filenames) != 0 || len(image) != 0 { - return cmdutil.UsageError(cmd, "Don't specify --filename or --image on rollback") - } - } - - if len(args) < 1 { - return cmdutil.UsageError(cmd, "Must specify the controller to update") - } - - return nil -} - -func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *RollingUpdateOptions) error { - if len(os.Args) > 1 && os.Args[1] == "rollingupdate" { - printDeprecationWarning("rolling-update", "rollingupdate") - } - err := validateArguments(cmd, options.Filenames, args) - if err != nil { - return err - } - - deploymentKey := cmdutil.GetFlagString(cmd, "deployment-label-key") - filename := "" - image := cmdutil.GetFlagString(cmd, "image") - pullPolicy := cmdutil.GetFlagString(cmd, "image-pull-policy") - oldName := args[0] - rollback := cmdutil.GetFlagBool(cmd, "rollback") - period := cmdutil.GetFlagDuration(cmd, "update-period") - interval := cmdutil.GetFlagDuration(cmd, "poll-interval") - timeout := cmdutil.GetFlagDuration(cmd, "timeout") - dryrun := cmdutil.GetFlagBool(cmd, "dry-run") - outputFormat := cmdutil.GetFlagString(cmd, "output") - container := cmdutil.GetFlagString(cmd, "container") - - if len(options.Filenames) > 0 { - filename = options.Filenames[0] - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - client, err := f.Client() - if err != nil { - return err - } - - var newRc *api.ReplicationController - // fetch rc - oldRc, err := client.ReplicationControllers(cmdNamespace).Get(oldName) - if err != nil { - if !errors.IsNotFound(err) || len(image) == 0 || len(args) > 1 { - return err - } - // We're in the middle of a rename, look for an RC with a source annotation of oldName - newRc, err := kubectl.FindSourceController(client, cmdNamespace, oldName) - if err != nil { - return err - } - return kubectl.Rename(client, newRc, oldName) - } - - var keepOldName bool - var replicasDefaulted bool - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - - if len(filename) != 0 { - schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"), cmdutil.GetFlagString(cmd, "schema-cache-dir")) - if err != nil { - return err - } - - request := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - Schema(schema). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, false, filename). - Do() - obj, err := request.Object() - if err != nil { - return err - } - var ok bool - // Handle filename input from stdin. The resource builder always returns an api.List - // when creating resource(s) from a stream. - if list, ok := obj.(*api.List); ok { - if len(list.Items) > 1 { - return cmdutil.UsageError(cmd, "%s specifies multiple items", filename) - } - obj = list.Items[0] - } - newRc, ok = obj.(*api.ReplicationController) - if !ok { - if gvk, err := typer.ObjectKind(obj); err == nil { - return cmdutil.UsageError(cmd, "%s contains a %v not a ReplicationController", filename, gvk) - } - glog.V(4).Infof("Object %#v is not a ReplicationController", obj) - return cmdutil.UsageError(cmd, "%s does not specify a valid ReplicationController", filename) - } - infos, err := request.Infos() - if err != nil || len(infos) != 1 { - glog.V(2).Infof("was not able to recover adequate information to discover if .spec.replicas was defaulted") - } else { - replicasDefaulted = isReplicasDefaulted(infos[0]) - } - } - // If the --image option is specified, we need to create a new rc with at least one different selector - // than the old rc. This selector is the hash of the rc, with a suffix to provide uniqueness for - // same-image updates. - if len(image) != 0 { - codec := api.Codecs.LegacyCodec(client.APIVersion()) - keepOldName = len(args) == 1 - newName := findNewName(args, oldRc) - if newRc, err = kubectl.LoadExistingNextReplicationController(client, cmdNamespace, newName); err != nil { - return err - } - if newRc != nil { - if inProgressImage := newRc.Spec.Template.Spec.Containers[0].Image; inProgressImage != image { - return cmdutil.UsageError(cmd, "Found existing in-progress update to image (%s).\nEither continue in-progress update with --image=%s or rollback with --rollback", inProgressImage, inProgressImage) - } - fmt.Fprintf(out, "Found existing update in progress (%s), resuming.\n", newRc.Name) - } else { - config := &kubectl.NewControllerConfig{ - Namespace: cmdNamespace, - OldName: oldName, - NewName: newName, - Image: image, - Container: container, - DeploymentKey: deploymentKey, - } - if oldRc.Spec.Template.Spec.Containers[0].Image == image { - if len(pullPolicy) == 0 { - return cmdutil.UsageError(cmd, "--image-pull-policy (Always|Never|IfNotPresent) must be provided when --image is the same as existing container image") - } - config.PullPolicy = api.PullPolicy(pullPolicy) - } - newRc, err = kubectl.CreateNewControllerFromCurrentController(client, codec, config) - if err != nil { - return err - } - } - // Update the existing replication controller with pointers to the 'next' controller - // and adding the label if necessary to distinguish it from the 'next' controller. - oldHash, err := api.HashObject(oldRc, codec) - if err != nil { - return err - } - // If new image is same as old, the hash may not be distinct, so add a suffix. - oldHash += "-orig" - oldRc, err = kubectl.UpdateExistingReplicationController(client, oldRc, cmdNamespace, newRc.Name, deploymentKey, oldHash, out) - if err != nil { - return err - } - } - - if rollback { - keepOldName = len(args) == 1 - newName := findNewName(args, oldRc) - if newRc, err = kubectl.LoadExistingNextReplicationController(client, cmdNamespace, newName); err != nil { - return err - } - - if newRc == nil { - return cmdutil.UsageError(cmd, "Could not find %s to rollback.\n", newName) - } - } - - if oldName == newRc.Name { - return cmdutil.UsageError(cmd, "%s cannot have the same name as the existing ReplicationController %s", - filename, oldName) - } - - updater := kubectl.NewRollingUpdater(newRc.Namespace, client) - - // To successfully pull off a rolling update the new and old rc have to differ - // by at least one selector. Every new pod should have the selector and every - // old pod should not have the selector. - var hasLabel bool - for key, oldValue := range oldRc.Spec.Selector { - if newValue, ok := newRc.Spec.Selector[key]; ok && newValue != oldValue { - hasLabel = true - break - } - } - if !hasLabel { - return cmdutil.UsageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s", - filename, oldName) - } - // TODO: handle scales during rolling update - if replicasDefaulted { - newRc.Spec.Replicas = oldRc.Spec.Replicas - } - if dryrun { - oldRcData := &bytes.Buffer{} - newRcData := &bytes.Buffer{} - if outputFormat == "" { - oldRcData.WriteString(oldRc.Name) - newRcData.WriteString(newRc.Name) - } else { - if err := f.PrintObject(cmd, mapper, oldRc, oldRcData); err != nil { - return err - } - if err := f.PrintObject(cmd, mapper, newRc, newRcData); err != nil { - return err - } - } - fmt.Fprintf(out, "Rolling from:\n%s\nTo:\n%s\n", string(oldRcData.Bytes()), string(newRcData.Bytes())) - return nil - } - updateCleanupPolicy := kubectl.DeleteRollingUpdateCleanupPolicy - if keepOldName { - updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy - } - config := &kubectl.RollingUpdaterConfig{ - Out: out, - OldRc: oldRc, - NewRc: newRc, - UpdatePeriod: period, - Interval: interval, - Timeout: timeout, - CleanupPolicy: updateCleanupPolicy, - MaxUnavailable: intstr.FromInt(0), - MaxSurge: intstr.FromInt(1), - } - if rollback { - err = kubectl.AbortRollingUpdate(config) - if err != nil { - return err - } - client.ReplicationControllers(config.NewRc.Namespace).Update(config.NewRc) - } - err = updater.Update(config) - if err != nil { - return err - } - - message := "rolling updated" - if keepOldName { - newRc.Name = oldName - } else { - message = fmt.Sprintf("rolling updated to %q", newRc.Name) - } - newRc, err = client.ReplicationControllers(cmdNamespace).Get(newRc.Name) - if err != nil { - return err - } - if outputFormat != "" { - return f.PrintObject(cmd, mapper, newRc, out) - } - kind, err := api.Scheme.ObjectKind(newRc) - if err != nil { - return err - } - _, res := meta.KindToResource(kind) - cmdutil.PrintSuccess(mapper, false, out, res.Resource, oldName, message) - return nil -} - -func findNewName(args []string, oldRc *api.ReplicationController) string { - if len(args) >= 2 { - return args[1] - } - if oldRc != nil { - newName, _ := kubectl.GetNextControllerAnnotation(oldRc) - return newName - } - return "" -} - -func isReplicasDefaulted(info *resource.Info) bool { - if info == nil || info.VersionedObject == nil { - // was unable to recover versioned info - return false - } - switch t := info.VersionedObject.(type) { - case *v1.ReplicationController: - return t.Spec.Replicas == nil - } - return false -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate_test.go deleted file mode 100644 index bf2204b27..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollingupdate_test.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "testing" -) - -func TestValidateArgs(t *testing.T) { - f, _, _ := NewAPIFactory() - - tests := []struct { - flags map[string]string - filenames []string - args []string - expectErr bool - testName string - }{ - { - expectErr: true, - testName: "nothing", - }, - { - flags: map[string]string{}, - args: []string{"foo"}, - expectErr: true, - testName: "no file, no image", - }, - { - filenames: []string{"bar.yaml"}, - args: []string{"foo"}, - testName: "valid file example", - }, - { - flags: map[string]string{ - "image": "foo:v2", - }, - args: []string{"foo"}, - testName: "missing second image name", - }, - { - flags: map[string]string{ - "image": "foo:v2", - }, - args: []string{"foo", "foo-v2"}, - testName: "valid image example", - }, - { - flags: map[string]string{ - "image": "foo:v2", - }, - filenames: []string{"bar.yaml"}, - args: []string{"foo", "foo-v2"}, - expectErr: true, - testName: "both filename and image example", - }, - } - for _, test := range tests { - out := &bytes.Buffer{} - cmd := NewCmdRollingUpdate(f, out) - - if test.flags != nil { - for key, val := range test.flags { - cmd.Flags().Set(key, val) - } - } - err := validateArguments(cmd, test.filenames, test.args) - if err != nil && !test.expectErr { - t.Errorf("unexpected error: %v (%s)", err, test.testName) - } - if err == nil && test.expectErr { - t.Errorf("unexpected non-error (%s)", test.testName) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout.go deleted file mode 100644 index 93e9f2362..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 rollout - -import ( - "io" - - "github.com/spf13/cobra" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -const ( - rollout_long = `Manages a deployment using subcommands like "kubectl rollout undo deployment/abc"` - rollout_example = `# Rollback to the previous deployment -kubectl rollout undo deployment/abc` - rollout_valid_resources = `Valid resource types include: - * deployments -` -) - -func NewCmdRollout(f *cmdutil.Factory, out io.Writer) *cobra.Command { - - cmd := &cobra.Command{ - Use: "rollout SUBCOMMAND", - Short: "rollout manages a deployment", - Long: rollout_long, - Example: rollout_example, - Run: func(cmd *cobra.Command, args []string) { - cmd.Help() - }, - } - // subcommands - cmd.AddCommand(NewCmdRolloutHistory(f, out)) - cmd.AddCommand(NewCmdRolloutPause(f, out)) - cmd.AddCommand(NewCmdRolloutResume(f, out)) - cmd.AddCommand(NewCmdRolloutUndo(f, out)) - - return cmd -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_history.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_history.go deleted file mode 100644 index 09fddde63..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_history.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 rollout - -import ( - "fmt" - "io" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/util/errors" - - "github.com/spf13/cobra" -) - -// HistoryOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type HistoryOptions struct { - Filenames []string - Recursive bool -} - -const ( - history_long = `View previous rollout revisions and configurations.` - history_example = `# View the rollout history of a deployment -kubectl rollout history deployment/abc - -# View the details of deployment revision 3 -kubectl rollout history deployment/abc --revision=3` -) - -func NewCmdRolloutHistory(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &HistoryOptions{} - - cmd := &cobra.Command{ - Use: "history (TYPE NAME | TYPE/NAME) [flags]", - Short: "view rollout history", - Long: history_long, - Example: history_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(RunHistory(f, cmd, out, args, options)) - }, - } - - cmd.Flags().Int64("revision", 0, "See the details, including podTemplate of the revision specified") - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - return cmd -} - -func RunHistory(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *HistoryOptions) error { - if len(args) == 0 && len(options.Filenames) == 0 { - return cmdutil.UsageError(cmd, "Required resource not specified.") - } - revisionDetail := cmdutil.GetFlagInt64(cmd, "revision") - - mapper, typer := f.Object(false) - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - infos, err := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - ResourceTypeOrNameArgs(true, args...). - Latest(). - Flatten(). - Do(). - Infos() - if err != nil { - return err - } - - errs := []error{} - for _, info := range infos { - mapping := info.ResourceMapping() - historyViewer, err := f.HistoryViewer(mapping) - if err != nil { - errs = append(errs, err) - continue - } - historyInfo, err := historyViewer.History(info.Namespace, info.Name) - if err != nil { - errs = append(errs, err) - continue - } - - if revisionDetail > 0 { - // Print details of a specific revision - template, ok := historyInfo.RevisionToTemplate[revisionDetail] - if !ok { - return fmt.Errorf("unable to find revision %d of %s %q", revisionDetail, mapping.Resource, info.Name) - } - fmt.Fprintf(out, "%s %q revision %d\n", mapping.Resource, info.Name, revisionDetail) - kubectl.DescribePodTemplate(template, out) - } else { - // Print all revisions - formattedOutput, printErr := kubectl.PrintRolloutHistory(historyInfo, mapping.Resource, info.Name) - if printErr != nil { - errs = append(errs, printErr) - continue - } - fmt.Fprintf(out, "%s\n", formattedOutput) - } - } - - return errors.NewAggregate(errs) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause.go deleted file mode 100644 index 5eed89fde..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_pause.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 rollout - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" -) - -// PauseConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type PauseConfig struct { - PauseObject func(object runtime.Object) (bool, error) - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - Info *resource.Info - - Out io.Writer - Filenames []string - Recursive bool -} - -const ( - pause_long = `Mark the provided resource as paused - -Paused resources will not be reconciled by a controller. -Use \"kubectl rollout resume\" to resume a paused resource. -Currently only deployments support being paused.` - - pause_example = `# Mark the nginx deployment as paused. Any current state of -# the deployment will continue its function, new updates to the deployment will not -# have an effect as long as the deployment is paused. -kubectl rollout pause deployment/nginx` -) - -func NewCmdRolloutPause(f *cmdutil.Factory, out io.Writer) *cobra.Command { - opts := &PauseConfig{} - - cmd := &cobra.Command{ - Use: "pause RESOURCE", - Short: "Mark the provided resource as paused", - Long: pause_long, - Example: pause_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(opts.CompletePause(f, cmd, out, args)) - cmdutil.CheckErr(opts.RunPause()) - }, - } - - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &opts.Recursive) - return cmd -} - -func (o *PauseConfig) CompletePause(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && len(o.Filenames) == 0 { - return cmdutil.UsageError(cmd, cmd.Use) - } - - o.Mapper, o.Typer = f.Object(false) - o.PauseObject = f.PauseObject - o.Out = out - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - infos, err := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). - ResourceTypeOrNameArgs(true, args...). - SingleResourceType(). - Latest(). - Do().Infos() - if err != nil { - return err - } - if len(infos) != 1 { - return fmt.Errorf("rollout pause is only supported on individual resources - %d resources were found", len(infos)) - } - o.Info = infos[0] - return nil -} - -func (o PauseConfig) RunPause() error { - isAlreadyPaused, err := o.PauseObject(o.Info.Object) - if err != nil { - return err - } - if isAlreadyPaused { - cmdutil.PrintSuccess(o.Mapper, false, o.Out, o.Info.Mapping.Resource, o.Info.Name, "already paused") - return nil - } - cmdutil.PrintSuccess(o.Mapper, false, o.Out, o.Info.Mapping.Resource, o.Info.Name, "paused") - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_resume.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_resume.go deleted file mode 100644 index cbdfc0dc3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_resume.go +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 rollout - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" -) - -// ResumeConfig is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ResumeConfig struct { - ResumeObject func(object runtime.Object) (bool, error) - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - Info *resource.Info - - Out io.Writer - Filenames []string - Recursive bool -} - -const ( - resume_long = `Resume a paused resource - -Paused resources will not be reconciled by a controller. By resuming a -resource, we allow it to be reconciled again. -Currently only deployments support being resumed.` - - resume_example = `# Resume an already paused deployment -kubectl rollout resume deployment/nginx` -) - -func NewCmdRolloutResume(f *cmdutil.Factory, out io.Writer) *cobra.Command { - opts := &ResumeConfig{} - - cmd := &cobra.Command{ - Use: "resume RESOURCE", - Short: "Resume a paused resource", - Long: resume_long, - Example: resume_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(opts.CompleteResume(f, cmd, out, args)) - cmdutil.CheckErr(opts.RunResume()) - }, - } - - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &opts.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &opts.Recursive) - return cmd -} - -func (o *ResumeConfig) CompleteResume(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && len(o.Filenames) == 0 { - return cmdutil.UsageError(cmd, cmd.Use) - } - - o.Mapper, o.Typer = f.Object(false) - o.ResumeObject = f.ResumeObject - o.Out = out - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - infos, err := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). - ResourceTypeOrNameArgs(true, args...). - SingleResourceType(). - Latest(). - Do().Infos() - if err != nil { - return err - } - if len(infos) != 1 { - return fmt.Errorf("rollout resume is only supported on individual resources - %d resources were found", len(infos)) - } - o.Info = infos[0] - return nil -} - -func (o ResumeConfig) RunResume() error { - isAlreadyResumed, err := o.ResumeObject(o.Info.Object) - if err != nil { - return err - } - if isAlreadyResumed { - cmdutil.PrintSuccess(o.Mapper, false, o.Out, o.Info.Mapping.Resource, o.Info.Name, "already resumed") - return nil - } - cmdutil.PrintSuccess(o.Mapper, false, o.Out, o.Info.Mapping.Resource, o.Info.Name, "resumed") - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_undo.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_undo.go deleted file mode 100644 index b70b003d8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/rollout/rollout_undo.go +++ /dev/null @@ -1,117 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 rollout - -import ( - "fmt" - "io" - - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" - - "github.com/spf13/cobra" -) - -// UndoOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type UndoOptions struct { - Rollbacker kubectl.Rollbacker - Mapper meta.RESTMapper - Typer runtime.ObjectTyper - Info *resource.Info - ToRevision int64 - - Out io.Writer - Filenames []string - Recursive bool -} - -const ( - undo_long = `Rollback to a previous rollout.` - undo_example = `# Rollback to the previous deployment -kubectl rollout undo deployment/abc - -# Rollback to deployment revision 3 -kubectl rollout undo deployment/abc --to-revision=3` -) - -func NewCmdRolloutUndo(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &UndoOptions{} - - cmd := &cobra.Command{ - Use: "undo (TYPE NAME | TYPE/NAME) [flags]", - Short: "undoes a previous rollout", - Long: undo_long, - Example: undo_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(options.CompleteUndo(f, cmd, out, args)) - cmdutil.CheckErr(options.RunUndo()) - }, - } - - cmd.Flags().Int64("to-revision", 0, "The revision to rollback to. Default to 0 (last revision).") - usage := "Filename, directory, or URL to a file identifying the resource to get from a server." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - return cmd -} - -func (o *UndoOptions) CompleteUndo(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && len(o.Filenames) == 0 { - return cmdutil.UsageError(cmd, "Required resource not specified.") - } - - o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision") - o.Mapper, o.Typer = f.Object(false) - o.Out = out - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - infos, err := resource.NewBuilder(o.Mapper, o.Typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, o.Recursive, o.Filenames...). - ResourceTypeOrNameArgs(true, args...). - Latest(). - Flatten(). - Do(). - Infos() - if err != nil { - return err - } - - if len(infos) != 1 { - return fmt.Errorf("rollout undo is only supported on individual resources - %d resources were found", len(infos)) - } - o.Info = infos[0] - o.Rollbacker, err = f.Rollbacker(o.Info.ResourceMapping()) - return err -} - -func (o *UndoOptions) RunUndo() error { - result, err := o.Rollbacker.Rollback(o.Info.Namespace, o.Info.Name, nil, o.ToRevision, o.Info.Object) - if err != nil { - return err - } - cmdutil.PrintSuccess(o.Mapper, false, o.Out, o.Info.Mapping.Resource, o.Info.Name, result) - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/run.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/run.go deleted file mode 100644 index d1b8e4f2d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/run.go +++ /dev/null @@ -1,500 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "os" - "time" - - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" - batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1" - "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/runtime" -) - -const ( - run_long = `Create and run a particular image, possibly replicated. -Creates a deployment or job to manage the created container(s).` - run_example = `# Start a single instance of nginx. -kubectl run nginx --image=nginx - -# Start a single instance of hazelcast and let the container expose port 5701 . -kubectl run hazelcast --image=hazelcast --port=5701 - -# Start a single instance of hazelcast and set environment variables "DNS_DOMAIN=cluster" and "POD_NAMESPACE=default" in the container. -kubectl run hazelcast --image=hazelcast --env="DNS_DOMAIN=cluster" --env="POD_NAMESPACE=default" - -# Start a replicated instance of nginx. -kubectl run nginx --image=nginx --replicas=5 - -# Dry run. Print the corresponding API objects without creating them. -kubectl run nginx --image=nginx --dry-run - -# Start a single instance of nginx, but overload the spec of the deployment with a partial set of values parsed from JSON. -kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { ... } }' - -# Start a single instance of busybox and keep it in the foreground, don't restart it if it exits. -kubectl run -i -t busybox --image=busybox --restart=Never - -# Start the nginx container using the default command, but use custom arguments (arg1 .. argN) for that command. -kubectl run nginx --image=nginx -- ... - -# Start the nginx container using a different command and custom arguments. -kubectl run nginx --image=nginx --command -- ... - -# Start the perl container to compute π to 2000 places and print it out. -kubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(2000)'` -) - -func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "run NAME --image=image [--env=\"key=value\"] [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json] [--command] -- [COMMAND] [args...]", - // run-container is deprecated - Aliases: []string{"run-container"}, - Short: "Run a particular image on the cluster.", - Long: run_long, - Example: run_example, - Run: func(cmd *cobra.Command, args []string) { - argsLenAtDash := cmd.ArgsLenAtDash() - err := Run(f, cmdIn, cmdOut, cmdErr, cmd, args, argsLenAtDash) - cmdutil.CheckErr(err) - }, - } - cmdutil.AddPrinterFlags(cmd) - addRunFlags(cmd) - cmdutil.AddApplyAnnotationFlags(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func addRunFlags(cmd *cobra.Command) { - cmd.Flags().String("generator", "", "The name of the API generator to use. Default is 'deployment/v1beta1' if --restart=Always, otherwise the default is 'job/v1'. This will happen only for cluster version at least 1.2, for olders we will fallback to 'run/v1' for --restart=Always, 'run-pod/v1' for others.") - cmd.Flags().String("image", "", "The image for the container to run.") - cmd.MarkFlagRequired("image") - cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.") - cmd.Flags().Bool("rm", false, "If true, delete resources created in this command for attached containers.") - cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.") - cmd.Flags().String("overrides", "", "An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.") - cmd.Flags().StringSlice("env", []string{}, "Environment variables to set in the container") - cmd.Flags().Int("port", -1, "The port that this container exposes. If --expose is true, this is also the port used by the service that is created.") - cmd.Flags().Int("hostport", -1, "The host port mapping for the container port. To demonstrate a single-machine container.") - cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s).") - cmd.Flags().BoolP("stdin", "i", false, "Keep stdin open on the container(s) in the pod, even if nothing is attached.") - cmd.Flags().BoolP("tty", "t", false, "Allocated a TTY for each container in the pod.") - cmd.Flags().Bool("attach", false, "If true, wait for the Pod to start running, and then attach to the Pod as if 'kubectl attach ...' were called. Default false, unless '-i/--interactive' is set, in which case the default is true.") - cmd.Flags().Bool("leave-stdin-open", false, "If the pod is started in interactive mode or with stdin, leave stdin open after the first attach completes. By default, stdin will be closed after the first attach completes.") - cmd.Flags().String("restart", "Always", "The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a deployment is created for this pod, if set to OnFailure or Never, a job is created for this pod and --replicas must be 1. Default 'Always'") - cmd.Flags().Bool("command", false, "If true and extra arguments are present, use them as the 'command' field in the container, rather than the 'args' field which is the default.") - cmd.Flags().String("requests", "", "The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'. Note that server side components may assign requests depending on the server configuration, such as limit ranges.") - cmd.Flags().String("limits", "", "The resource requirement limits for this container. For example, 'cpu=200m,memory=512Mi'. Note that server side components may assign limits depending on the server configuration, such as limit ranges.") - cmd.Flags().Bool("expose", false, "If true, a public, external service is created for the container(s) which are run") - cmd.Flags().String("service-generator", "service/v2", "The name of the generator to use for creating a service. Only used if --expose is true") - cmd.Flags().String("service-overrides", "", "An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.") -} - -func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string, argsLenAtDash int) error { - if len(os.Args) > 1 && os.Args[1] == "run-container" { - printDeprecationWarning("run", "run-container") - } - - // Let kubectl run follow rules for `--`, see #13004 issue - if len(args) == 0 || argsLenAtDash == 0 { - return cmdutil.UsageError(cmd, "NAME is required for run") - } - - interactive := cmdutil.GetFlagBool(cmd, "stdin") - tty := cmdutil.GetFlagBool(cmd, "tty") - if tty && !interactive { - return cmdutil.UsageError(cmd, "-i/--stdin is required for containers with -t/--tty=true") - } - replicas := cmdutil.GetFlagInt(cmd, "replicas") - if interactive && replicas != 1 { - return cmdutil.UsageError(cmd, fmt.Sprintf("-i/--stdin requires that replicas is 1, found %d", replicas)) - } - - namespace, _, err := f.DefaultNamespace() - if err != nil { - return err - } - restartPolicy, err := getRestartPolicy(cmd, interactive) - if err != nil { - return err - } - if restartPolicy != api.RestartPolicyAlways && replicas != 1 { - return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas)) - } - - generatorName := cmdutil.GetFlagString(cmd, "generator") - if len(generatorName) == 0 { - client, err := f.Client() - if err != nil { - return err - } - resourcesList, err := client.Discovery().ServerResources() - if err != nil { - // this cover the cases where old servers do not expose discovery - resourcesList = nil - } - if restartPolicy == api.RestartPolicyAlways { - if contains(resourcesList, v1beta1.SchemeGroupVersion.WithResource("deployments")) { - generatorName = "deployment/v1beta1" - } else { - generatorName = "run/v1" - } - } else { - if contains(resourcesList, batchv1.SchemeGroupVersion.WithResource("jobs")) { - generatorName = "job/v1" - } else if contains(resourcesList, v1beta1.SchemeGroupVersion.WithResource("jobs")) { - generatorName = "job/v1beta1" - } else { - generatorName = "run-pod/v1" - } - } - } - generators := f.Generators("run") - generator, found := generators[generatorName] - if !found { - return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) - } - names := generator.ParamNames() - params := kubectl.MakeParams(cmd, names) - params["name"] = args[0] - if len(args) > 1 { - params["args"] = args[1:] - } - - params["env"] = cmdutil.GetFlagStringSlice(cmd, "env") - - obj, _, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) - if err != nil { - return err - } - - if cmdutil.GetFlagBool(cmd, "expose") { - serviceGenerator := cmdutil.GetFlagString(cmd, "service-generator") - if len(serviceGenerator) == 0 { - return cmdutil.UsageError(cmd, fmt.Sprintf("No service generator specified")) - } - if err := generateService(f, cmd, args, serviceGenerator, params, namespace, cmdOut); err != nil { - return err - } - } - - attachFlag := cmd.Flags().Lookup("attach") - attach := cmdutil.GetFlagBool(cmd, "attach") - - if !attachFlag.Changed && interactive { - attach = true - } - - remove := cmdutil.GetFlagBool(cmd, "rm") - if !attach && remove { - return cmdutil.UsageError(cmd, "--rm should only be used for attached containers") - } - - if attach { - opts := &AttachOptions{ - In: cmdIn, - Out: cmdOut, - Err: cmdErr, - Stdin: interactive, - TTY: tty, - - Attach: &DefaultRemoteAttach{}, - } - config, err := f.ClientConfig() - if err != nil { - return err - } - opts.Config = config - - client, err := f.Client() - if err != nil { - return err - } - opts.Client = client - - attachablePod, err := f.AttachablePodForObject(obj) - if err != nil { - return err - } - err = handleAttachPod(f, client, attachablePod, opts) - if err != nil { - return err - } - - if remove { - namespace, err = mapping.MetadataAccessor.Namespace(obj) - if err != nil { - return err - } - var name string - name, err = mapping.MetadataAccessor.Name(obj) - if err != nil { - return err - } - _, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(namespace).DefaultNamespace(). - ResourceNames(mapping.Resource, name). - Flatten(). - Do() - return ReapResult(r, f, cmdOut, true, true, 0, -1, false, mapper) - } - return nil - } - - outputFormat := cmdutil.GetFlagString(cmd, "output") - if outputFormat != "" { - return f.PrintObject(cmd, mapper, obj, cmdOut) - } - cmdutil.PrintSuccess(mapper, false, cmdOut, mapping.Resource, args[0], "created") - return nil -} - -// TODO turn this into reusable method checking available resources -func contains(resourcesList map[string]*unversioned.APIResourceList, resource unversioned.GroupVersionResource) bool { - if resourcesList == nil { - return false - } - resourcesGroup, ok := resourcesList[resource.GroupVersion().String()] - if !ok { - return false - } - for _, item := range resourcesGroup.APIResources { - if resource.Resource == item.Name { - return true - } - } - return false -} - -func waitForPodRunning(c *client.Client, pod *api.Pod, out io.Writer) (status api.PodPhase, err error) { - for { - pod, err := c.Pods(pod.Namespace).Get(pod.Name) - if err != nil { - return api.PodUnknown, err - } - ready := false - if pod.Status.Phase == api.PodRunning { - ready = true - for _, status := range pod.Status.ContainerStatuses { - if !status.Ready { - ready = false - break - } - } - if ready { - return api.PodRunning, nil - } - } - if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed { - return pod.Status.Phase, nil - } - fmt.Fprintf(out, "Waiting for pod %s/%s to be running, status is %s, pod ready: %v\n", pod.Namespace, pod.Name, pod.Status.Phase, ready) - time.Sleep(2 * time.Second) - continue - } -} - -func handleAttachPod(f *cmdutil.Factory, c *client.Client, pod *api.Pod, opts *AttachOptions) error { - status, err := waitForPodRunning(c, pod, opts.Out) - if err != nil { - return err - } - if status == api.PodSucceeded || status == api.PodFailed { - req, err := f.LogsForObject(pod, &api.PodLogOptions{Container: opts.GetContainerName(pod)}) - if err != nil { - return err - } - readCloser, err := req.Stream() - if err != nil { - return err - } - defer readCloser.Close() - _, err = io.Copy(opts.Out, readCloser) - return err - } - opts.Client = c - opts.PodName = pod.Name - opts.Namespace = pod.Namespace - opts.CommandName = "kubectl attach" - if err := opts.Run(); err != nil { - fmt.Fprintf(opts.Out, "Error attaching, falling back to logs: %v\n", err) - req, err := f.LogsForObject(pod, &api.PodLogOptions{Container: opts.GetContainerName(pod)}) - if err != nil { - return err - } - readCloser, err := req.Stream() - if err != nil { - return err - } - defer readCloser.Close() - _, err = io.Copy(opts.Out, readCloser) - return err - } - return nil -} - -func getRestartPolicy(cmd *cobra.Command, interactive bool) (api.RestartPolicy, error) { - restart := cmdutil.GetFlagString(cmd, "restart") - if len(restart) == 0 { - if interactive { - return api.RestartPolicyOnFailure, nil - } else { - return api.RestartPolicyAlways, nil - } - } - switch api.RestartPolicy(restart) { - case api.RestartPolicyAlways: - return api.RestartPolicyAlways, nil - case api.RestartPolicyOnFailure: - return api.RestartPolicyOnFailure, nil - case api.RestartPolicyNever: - return api.RestartPolicyNever, nil - default: - return "", cmdutil.UsageError(cmd, fmt.Sprintf("invalid restart policy: %s", restart)) - } -} - -func generateService(f *cmdutil.Factory, cmd *cobra.Command, args []string, serviceGenerator string, paramsIn map[string]interface{}, namespace string, out io.Writer) error { - generators := f.Generators("expose") - generator, found := generators[serviceGenerator] - if !found { - return fmt.Errorf("missing service generator: %s", serviceGenerator) - } - names := generator.ParamNames() - - port := cmdutil.GetFlagInt(cmd, "port") - if port < 1 { - return fmt.Errorf("--port must be a positive integer when exposing a service") - } - - params := map[string]interface{}{} - for key, value := range paramsIn { - _, isString := value.(string) - if isString { - params[key] = value - } - } - - name, found := params["name"] - if !found || len(name.(string)) == 0 { - return fmt.Errorf("name is a required parameter") - } - selector, found := params["labels"] - if !found || len(selector.(string)) == 0 { - selector = fmt.Sprintf("run=%s", name.(string)) - } - params["selector"] = selector - - if defaultName, found := params["default-name"]; !found || len(defaultName.(string)) == 0 { - params["default-name"] = name - } - - obj, _, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "service-overrides"), namespace) - if err != nil { - return err - } - - if cmdutil.GetFlagString(cmd, "output") != "" { - return f.PrintObject(cmd, mapper, obj, out) - } - cmdutil.PrintSuccess(mapper, false, out, mapping.Resource, args[0], "created") - - return nil -} - -func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kubectl.Generator, names []kubectl.GeneratorParam, params map[string]interface{}, overrides, namespace string) (runtime.Object, string, meta.RESTMapper, *meta.RESTMapping, error) { - err := kubectl.ValidateParams(names, params) - if err != nil { - return nil, "", nil, nil, err - } - - // TODO: Validate flag usage against selected generator. More tricky since --expose was added. - obj, err := generator.Generate(params) - if err != nil { - return nil, "", nil, nil, err - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - groupVersionKind, err := typer.ObjectKind(obj) - if err != nil { - return nil, "", nil, nil, err - } - - if len(overrides) > 0 { - codec := runtime.NewCodec(f.JSONEncoder(), f.Decoder(true)) - obj, err = cmdutil.Merge(codec, obj, overrides, groupVersionKind.Kind) - if err != nil { - return nil, "", nil, nil, err - } - } - - mapping, err := mapper.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version) - if err != nil { - return nil, "", nil, nil, err - } - client, err := f.ClientForMapping(mapping) - if err != nil { - return nil, "", nil, nil, err - } - - annotations, err := mapping.MetadataAccessor.Annotations(obj) - if err != nil { - return nil, "", nil, nil, err - } - if cmdutil.GetRecordFlag(cmd) || len(annotations[kubectl.ChangeCauseAnnotation]) > 0 { - if err := cmdutil.RecordChangeCause(obj, f.Command()); err != nil { - return nil, "", nil, nil, err - } - } - // TODO: extract this flag to a central location, when such a location exists. - if !cmdutil.GetFlagBool(cmd, "dry-run") { - resourceMapper := &resource.Mapper{ - ObjectTyper: typer, - RESTMapper: mapper, - ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), - Decoder: f.Decoder(true), - } - info, err := resourceMapper.InfoForObject(obj, nil) - if err != nil { - return nil, "", nil, nil, err - } - - if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info, f.JSONEncoder()); err != nil { - return nil, "", nil, nil, err - } - - obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object) - if err != nil { - return nil, "", nil, nil, err - } - } - return obj, groupVersionKind.Kind, mapper, mapping, err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/run_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/run_test.go deleted file mode 100644 index 1894deca8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/run_test.go +++ /dev/null @@ -1,332 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "bytes" - "fmt" - "io/ioutil" - "net/http" - "os" - "reflect" - "testing" - - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/client/restclient" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func TestGetRestartPolicy(t *testing.T) { - tests := []struct { - input string - interactive bool - expected api.RestartPolicy - expectErr bool - }{ - { - input: "", - expected: api.RestartPolicyAlways, - }, - { - input: "", - interactive: true, - expected: api.RestartPolicyOnFailure, - }, - { - input: string(api.RestartPolicyAlways), - interactive: true, - expected: api.RestartPolicyAlways, - }, - { - input: string(api.RestartPolicyNever), - interactive: true, - expected: api.RestartPolicyNever, - }, - { - input: string(api.RestartPolicyAlways), - expected: api.RestartPolicyAlways, - }, - { - input: string(api.RestartPolicyNever), - expected: api.RestartPolicyNever, - }, - { - input: "foo", - expectErr: true, - }, - } - for _, test := range tests { - cmd := &cobra.Command{} - cmd.Flags().String("restart", "", "dummy restart flag") - cmd.Flags().Lookup("restart").Value.Set(test.input) - policy, err := getRestartPolicy(cmd, test.interactive) - if test.expectErr && err == nil { - t.Error("unexpected non-error") - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if !test.expectErr && policy != test.expected { - t.Errorf("expected: %s, saw: %s (%s:%v)", test.expected, policy, test.input, test.interactive) - } - } -} - -func TestGetEnv(t *testing.T) { - test := struct { - input []string - expected []string - }{ - input: []string{"a=b", "c=d"}, - expected: []string{"a=b", "c=d"}, - } - cmd := &cobra.Command{} - cmd.Flags().StringSlice("env", test.input, "") - - envStrings := cmdutil.GetFlagStringSlice(cmd, "env") - if len(envStrings) != 2 || !reflect.DeepEqual(envStrings, test.expected) { - t.Errorf("expected: %s, saw: %s", test.expected, envStrings) - } -} - -func TestRunArgsFollowDashRules(t *testing.T) { - _, _, rc := testData() - - tests := []struct { - args []string - argsLenAtDash int - expectError bool - name string - }{ - { - args: []string{}, - argsLenAtDash: -1, - expectError: true, - name: "empty", - }, - { - args: []string{"foo"}, - argsLenAtDash: -1, - expectError: false, - name: "no cmd", - }, - { - args: []string{"foo", "sleep"}, - argsLenAtDash: -1, - expectError: false, - name: "cmd no dash", - }, - { - args: []string{"foo", "sleep"}, - argsLenAtDash: 1, - expectError: false, - name: "cmd has dash", - }, - { - args: []string{"foo", "sleep"}, - argsLenAtDash: 0, - expectError: true, - name: "no name", - }, - } - for _, test := range tests { - f, tf, codec := NewAPIFactory() - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - return &http.Response{StatusCode: 201, Body: objBody(codec, &rc.Items[0])}, nil - }), - } - tf.Namespace = "test" - tf.ClientConfig = &restclient.Config{} - cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) - cmd.Flags().Set("image", "nginx") - cmd.Flags().Set("generator", "run/v1") - err := Run(f, os.Stdin, os.Stdout, os.Stderr, cmd, test.args, test.argsLenAtDash) - if test.expectError && err == nil { - t.Errorf("unexpected non-error (%s)", test.name) - } - if !test.expectError && err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.name) - } - } -} - -func TestGenerateService(t *testing.T) { - - tests := []struct { - port string - args []string - serviceGenerator string - params map[string]interface{} - expectErr bool - name string - service api.Service - expectPOST bool - }{ - { - port: "80", - args: []string{"foo"}, - serviceGenerator: "service/v2", - params: map[string]interface{}{ - "name": "foo", - }, - expectErr: false, - name: "basic", - service: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - TargetPort: intstr.FromInt(80), - }, - }, - Selector: map[string]string{ - "run": "foo", - }, - Type: api.ServiceTypeClusterIP, - SessionAffinity: api.ServiceAffinityNone, - }, - }, - expectPOST: true, - }, - { - port: "80", - args: []string{"foo"}, - serviceGenerator: "service/v2", - params: map[string]interface{}{ - "name": "foo", - "labels": "app=bar", - }, - expectErr: false, - name: "custom labels", - service: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"app": "bar"}, - }, - Spec: api.ServiceSpec{ - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - TargetPort: intstr.FromInt(80), - }, - }, - Selector: map[string]string{ - "app": "bar", - }, - Type: api.ServiceTypeClusterIP, - SessionAffinity: api.ServiceAffinityNone, - }, - }, - expectPOST: true, - }, - { - expectErr: true, - name: "missing port", - expectPOST: false, - }, - { - port: "80", - args: []string{"foo"}, - serviceGenerator: "service/v2", - params: map[string]interface{}{ - "name": "foo", - }, - expectErr: false, - name: "dry-run", - expectPOST: false, - }, - } - for _, test := range tests { - sawPOST := false - f, tf, codec := NewAPIFactory() - tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - tf.Client = &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case test.expectPOST && m == "POST" && p == "/namespaces/namespace/services": - sawPOST = true - body := objBody(codec, &test.service) - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } - defer req.Body.Close() - svc := &api.Service{} - if err := runtime.DecodeInto(codec, data, svc); err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } - // Copy things that are defaulted by the system - test.service.Annotations = svc.Annotations - - if !reflect.DeepEqual(&test.service, svc) { - t.Errorf("expected:\n%v\nsaw:\n%v\n", &test.service, svc) - } - return &http.Response{StatusCode: 200, Body: body}, nil - default: - // Ensures no GET is performed when deleting by name - t.Errorf("%s: unexpected request: %s %#v\n%#v", test.name, req.Method, req.URL, req) - return nil, fmt.Errorf("unexpected request") - } - }), - } - cmd := &cobra.Command{} - cmd.Flags().String("output", "", "") - cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "") - cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation.") - cmdutil.AddInclude3rdPartyFlags(cmd) - addRunFlags(cmd) - - if !test.expectPOST { - cmd.Flags().Set("dry-run", "true") - } - - if len(test.port) > 0 { - cmd.Flags().Set("port", test.port) - test.params["port"] = test.port - } - - buff := &bytes.Buffer{} - err := generateService(f, cmd, test.args, test.serviceGenerator, test.params, "namespace", buff) - if test.expectErr { - if err == nil { - t.Error("unexpected non-error") - } - continue - } - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectPOST != sawPOST { - t.Errorf("expectPost: %v, sawPost: %v", test.expectPOST, sawPOST) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/scale.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/scale.go deleted file mode 100644 index bbd629a7d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/scale.go +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - "os" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" -) - -// ScaleOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type ScaleOptions struct { - Filenames []string - Recursive bool -} - -const ( - scale_long = `Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job. - -Scale also allows users to specify one or more preconditions for the scale action. -If --current-replicas or --resource-version is specified, it is validated before the -scale is attempted, and it is guaranteed that the precondition holds true when the -scale is sent to the server.` - scale_example = `# Scale a replicaset named 'foo' to 3. -kubectl scale --replicas=3 rs/foo - -# Scale a resource identified by type and name specified in "foo.yaml" to 3. -kubectl scale --replicas=3 -f foo.yaml - -# If the deployment named mysql's current size is 2, scale mysql to 3. -kubectl scale --current-replicas=2 --replicas=3 deployment/mysql - -# Scale multiple replication controllers. -kubectl scale --replicas=5 rc/foo rc/bar rc/baz - -# Scale job named 'cron' to 3. -kubectl scale --replicas=3 job/cron` -) - -// NewCmdScale returns a cobra command with the appropriate configuration and flags to run scale -func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &ScaleOptions{} - - cmd := &cobra.Command{ - Use: "scale [--resource-version=version] [--current-replicas=count] --replicas=COUNT (-f FILENAME | TYPE NAME)", - // resize is deprecated - Aliases: []string{"resize"}, - Short: "Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job.", - Long: scale_long, - Example: scale_example, - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - err := RunScale(f, out, cmd, args, shortOutput, options) - cmdutil.CheckErr(err) - }, - } - cmd.Flags().String("resource-version", "", "Precondition for resource version. Requires that the current resource version match this value in order to scale.") - cmd.Flags().Int("current-replicas", -1, "Precondition for current size. Requires that the current size of the resource match this value in order to scale.") - cmd.Flags().Int("replicas", -1, "The new desired number of replicas. Required.") - cmd.MarkFlagRequired("replicas") - cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a scale operation, zero means don't wait.") - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddRecordFlag(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - - usage := "Filename, directory, or URL to a file identifying the resource to set a new size" - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - return cmd -} - -// RunScale executes the scaling -func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *ScaleOptions) error { - if len(os.Args) > 1 && os.Args[1] == "resize" { - printDeprecationWarning("scale", "resize") - } - - count := cmdutil.GetFlagInt(cmd, "replicas") - if count < 0 { - return cmdutil.UsageError(cmd, "--replicas=COUNT is required, and COUNT must be greater than or equal to 0") - } - - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - ResourceTypeOrNameArgs(false, args...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return err - } - - infos := []*resource.Info{} - err = r.Visit(func(info *resource.Info, err error) error { - if err == nil { - infos = append(infos, info) - } - return nil - }) - - resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") - if len(resourceVersion) != 0 && len(infos) > 1 { - return fmt.Errorf("cannot use --resource-version with multiple resources") - } - - counter := 0 - err = r.Visit(func(info *resource.Info, err error) error { - if err != nil { - return err - } - - mapping := info.ResourceMapping() - scaler, err := f.Scaler(mapping) - if err != nil { - return err - } - - currentSize := cmdutil.GetFlagInt(cmd, "current-replicas") - precondition := &kubectl.ScalePrecondition{Size: currentSize, ResourceVersion: resourceVersion} - retry := kubectl.NewRetryParams(kubectl.Interval, kubectl.Timeout) - - var waitForReplicas *kubectl.RetryParams - if timeout := cmdutil.GetFlagDuration(cmd, "timeout"); timeout != 0 { - waitForReplicas = kubectl.NewRetryParams(kubectl.Interval, timeout) - } - - if err := scaler.Scale(info.Namespace, info.Name, uint(count), precondition, retry, waitForReplicas); err != nil { - return err - } - if cmdutil.ShouldRecord(cmd, info) { - patchBytes, err := cmdutil.ChangeResourcePatch(info, f.Command()) - if err != nil { - return err - } - mapping := info.ResourceMapping() - client, err := f.ClientForMapping(mapping) - if err != nil { - return err - } - helper := resource.NewHelper(client, mapping) - _, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patchBytes) - if err != nil { - return err - } - } - counter++ - cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "scaled") - return nil - }) - if err != nil { - return err - } - if counter == 0 { - return fmt.Errorf("no objects passed to scale") - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/stop.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/stop.go deleted file mode 100644 index fc25be9ae..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/stop.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "fmt" - "io" - - "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" - "k8s.io/kubernetes/pkg/kubectl/resource" -) - -// StopOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of -// referencing the cmd.Flags() -type StopOptions struct { - Filenames []string - Recursive bool -} - -const ( - stop_long = `Deprecated: Gracefully shut down a resource by name or filename. - -The stop command is deprecated, all its functionalities are covered by delete command. -See 'kubectl delete --help' for more details. - -Attempts to shut down and delete a resource that supports graceful termination. -If the resource is scalable it will be scaled to 0 before deletion.` - stop_example = `# Shut down foo. -kubectl stop replicationcontroller foo - -# Stop pods and services with label name=myLabel. -kubectl stop pods,services -l name=myLabel - -# Shut down the service defined in service.json -kubectl stop -f service.json - -# Shut down all resources in the path/to/resources directory -kubectl stop -f path/to/resources` -) - -func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command { - options := &StopOptions{} - - cmd := &cobra.Command{ - Use: "stop (-f FILENAME | TYPE (NAME | -l label | --all))", - Short: "Deprecated: Gracefully shut down a resource by name or filename.", - Long: stop_long, - Example: stop_example, - Deprecated: fmt.Sprintf("use %q instead.", "delete"), - Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) - cmdutil.CheckErr(RunStop(f, cmd, args, out, options)) - }, - } - usage := "Filename, directory, or URL to file of resource(s) to be stopped." - kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) - cmdutil.AddRecursiveFlag(cmd, &options.Recursive) - cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.") - cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.") - cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful stop.") - cmd.Flags().Int("grace-period", -1, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.") - cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object") - cmdutil.AddOutputFlagsForMutation(cmd) - cmdutil.AddInclude3rdPartyFlags(cmd) - return cmd -} - -func RunStop(f *cmdutil.Factory, cmd *cobra.Command, args []string, out io.Writer, options *StopOptions) error { - cmdNamespace, enforceNamespace, err := f.DefaultNamespace() - if err != nil { - return err - } - - mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) - r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - ResourceTypeOrNameArgs(false, args...). - FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). - SelectorParam(cmdutil.GetFlagString(cmd, "selector")). - SelectAllParam(cmdutil.GetFlagBool(cmd, "all")). - Flatten(). - Do() - if r.Err() != nil { - return r.Err() - } - shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" - return ReapResult(r, f, out, false, cmdutil.GetFlagBool(cmd, "ignore-not-found"), cmdutil.GetFlagDuration(cmd, "timeout"), cmdutil.GetFlagInt(cmd, "grace-period"), shortOutput, mapper) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editor.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editor.go deleted file mode 100644 index 1c58d846b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editor.go +++ /dev/null @@ -1,192 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 editor - -import ( - "fmt" - "io" - "io/ioutil" - "math/rand" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - - "github.com/golang/glog" - - "k8s.io/kubernetes/pkg/util/term" -) - -const ( - // sorry, blame Git - // TODO: on Windows rely on 'start' to launch the editor associated - // with the given file type. If we can't because of the need of - // blocking, use a script with 'ftype' and 'assoc' to detect it. - defaultEditor = "vi" - defaultShell = "/bin/bash" - windowsEditor = "notepad" - windowsShell = "cmd" -) - -type Editor struct { - Args []string - Shell bool -} - -// NewDefaultEditor creates a struct Editor that uses the OS environment to -// locate the editor program, looking at EDITOR environment variable to find -// the proper command line. If the provided editor has no spaces, or no quotes, -// it is treated as a bare command to be loaded. Otherwise, the string will -// be passed to the user's shell for execution. -func NewDefaultEditor(envs []string) Editor { - args, shell := defaultEnvEditor(envs) - return Editor{ - Args: args, - Shell: shell, - } -} - -func defaultEnvShell() []string { - shell := os.Getenv("SHELL") - if len(shell) == 0 { - shell = platformize(defaultShell, windowsShell) - } - flag := "-c" - if shell == windowsShell { - flag = "/C" - } - return []string{shell, flag} -} - -func defaultEnvEditor(envs []string) ([]string, bool) { - var editor string - for _, env := range envs { - if len(env) > 0 { - editor = os.Getenv(env) - } - if len(editor) > 0 { - break - } - } - if len(editor) == 0 { - editor = platformize(defaultEditor, windowsEditor) - } - if !strings.Contains(editor, " ") { - return []string{editor}, false - } - if !strings.ContainsAny(editor, "\"'\\") { - return strings.Split(editor, " "), false - } - // rather than parse the shell arguments ourselves, punt to the shell - shell := defaultEnvShell() - return append(shell, editor), true -} - -func (e Editor) args(path string) []string { - args := make([]string, len(e.Args)) - copy(args, e.Args) - if e.Shell { - last := args[len(args)-1] - args[len(args)-1] = fmt.Sprintf("%s %q", last, path) - } else { - args = append(args, path) - } - return args -} - -// Launch opens the described or returns an error. The TTY will be protected, and -// SIGQUIT, SIGTERM, and SIGINT will all be trapped. -func (e Editor) Launch(path string) error { - if len(e.Args) == 0 { - return fmt.Errorf("no editor defined, can't open %s", path) - } - abs, err := filepath.Abs(path) - if err != nil { - return err - } - args := e.args(abs) - cmd := exec.Command(args[0], args[1:]...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = os.Stdin - glog.V(5).Infof("Opening file with editor %v", args) - if err := (term.TTY{In: os.Stdin, TryDev: true}).Safe(cmd.Run); err != nil { - if err, ok := err.(*exec.Error); ok { - if err.Err == exec.ErrNotFound { - return fmt.Errorf("unable to launch the editor %q", strings.Join(e.Args, " ")) - } - } - return fmt.Errorf("there was a problem with the editor %q", strings.Join(e.Args, " ")) - } - return nil -} - -// LaunchTempFile reads the provided stream into a temporary file in the given directory -// and file prefix, and then invokes Launch with the path of that file. It will return -// the contents of the file after launch, any errors that occur, and the path of the -// temporary file so the caller can clean it up as needed. -func (e Editor) LaunchTempFile(prefix, suffix string, r io.Reader) ([]byte, string, error) { - f, err := tempFile(prefix, suffix) - if err != nil { - return nil, "", err - } - defer f.Close() - path := f.Name() - if _, err := io.Copy(f, r); err != nil { - os.Remove(path) - return nil, path, err - } - // This file descriptor needs to close so the next process (Launch) can claim it. - f.Close() - if err := e.Launch(path); err != nil { - return nil, path, err - } - bytes, err := ioutil.ReadFile(path) - return bytes, path, err -} - -func tempFile(prefix, suffix string) (f *os.File, err error) { - dir := os.TempDir() - - for i := 0; i < 10000; i++ { - name := filepath.Join(dir, prefix+randSeq(5)+suffix) - f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if os.IsExist(err) { - continue - } - break - } - return -} - -var letters = []rune("abcdefghijklmnopqrstuvwxyz0123456789") - -func randSeq(n int) string { - b := make([]rune, n) - for i := range b { - b[i] = letters[rand.Intn(len(letters))] - } - return string(b) -} - -func platformize(linux, windows string) string { - if runtime.GOOS == "windows" { - return windows - } - return linux -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editor_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editor_test.go deleted file mode 100644 index 9be83a042..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editor_test.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 editor - -import ( - "bytes" - "io/ioutil" - "os" - "reflect" - "strings" - "testing" -) - -func TestArgs(t *testing.T) { - if e, a := []string{"/bin/bash", "-c \"test\""}, (Editor{Args: []string{"/bin/bash", "-c"}, Shell: true}).args("test"); !reflect.DeepEqual(e, a) { - t.Errorf("unexpected args: %v", a) - } - if e, a := []string{"/bin/bash", "-c", "test"}, (Editor{Args: []string{"/bin/bash", "-c"}, Shell: false}).args("test"); !reflect.DeepEqual(e, a) { - t.Errorf("unexpected args: %v", a) - } - if e, a := []string{"/bin/bash", "-i -c \"test\""}, (Editor{Args: []string{"/bin/bash", "-i -c"}, Shell: true}).args("test"); !reflect.DeepEqual(e, a) { - t.Errorf("unexpected args: %v", a) - } - if e, a := []string{"/test", "test"}, (Editor{Args: []string{"/test"}}).args("test"); !reflect.DeepEqual(e, a) { - t.Errorf("unexpected args: %v", a) - } -} - -func TestEditor(t *testing.T) { - edit := Editor{Args: []string{"cat"}} - testStr := "test something\n" - contents, path, err := edit.LaunchTempFile("", "someprefix", bytes.NewBufferString(testStr)) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if _, err := os.Stat(path); err != nil { - t.Fatalf("no temp file: %s", path) - } - defer os.Remove(path) - if disk, err := ioutil.ReadFile(path); err != nil || !bytes.Equal(contents, disk) { - t.Errorf("unexpected file on disk: %v %s", err, string(disk)) - } - if !bytes.Equal(contents, []byte(testStr)) { - t.Errorf("unexpected contents: %s", string(contents)) - } - if !strings.Contains(path, "someprefix") { - t.Errorf("path not expected: %s", path) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go deleted file mode 100644 index 07fb3a7fd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go +++ /dev/null @@ -1,577 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 util - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os" - "os/user" - "path" - "reflect" - "sort" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" - clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/client/unversioned/testclient" - "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/kubectl" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/flag" - "k8s.io/kubernetes/pkg/watch" -) - -func TestNewFactoryDefaultFlagBindings(t *testing.T) { - factory := NewFactory(nil) - - if !factory.flags.HasFlags() { - t.Errorf("Expected flags, but didn't get any") - } -} - -func TestNewFactoryNoFlagBindings(t *testing.T) { - clientConfig := clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{}) - factory := NewFactory(clientConfig) - - if factory.flags.HasFlags() { - t.Errorf("Expected zero flags, but got %v", factory.flags) - } -} - -func TestPortsForObject(t *testing.T) { - f := NewFactory(nil) - - pod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Ports: []api.ContainerPort{ - { - ContainerPort: 101, - }, - }, - }, - }, - }, - } - - expected := []string{"101"} - got, err := f.PortsForObject(pod) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if len(expected) != len(got) { - t.Fatalf("Ports size mismatch! Expected %d, got %d", len(expected), len(got)) - } - - sort.Strings(expected) - sort.Strings(got) - - for i, port := range got { - if port != expected[i] { - t.Fatalf("Port mismatch! Expected %s, got %s", expected[i], port) - } - } -} - -func TestLabelsForObject(t *testing.T) { - f := NewFactory(nil) - - tests := []struct { - name string - object runtime.Object - expected string - err error - }{ - { - name: "successful re-use of labels", - object: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", Labels: map[string]string{"svc": "test"}}, - TypeMeta: unversioned.TypeMeta{Kind: "Service", APIVersion: "v1"}, - }, - expected: "svc=test", - err: nil, - }, - { - name: "empty labels", - object: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", Labels: map[string]string{}}, - TypeMeta: unversioned.TypeMeta{Kind: "Service", APIVersion: "v1"}, - }, - expected: "", - err: nil, - }, - { - name: "nil labels", - object: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "zen", Namespace: "test", Labels: nil}, - TypeMeta: unversioned.TypeMeta{Kind: "Service", APIVersion: "v1"}, - }, - expected: "", - err: nil, - }, - } - - for _, test := range tests { - gotLabels, err := f.LabelsForObject(test.object) - if err != test.err { - t.Fatalf("%s: Error mismatch: Expected %v, got %v", test.name, test.err, err) - } - got := kubectl.MakeLabels(gotLabels) - if test.expected != got { - t.Fatalf("%s: Labels mismatch! Expected %s, got %s", test.name, test.expected, got) - } - - } -} - -func TestCanBeExposed(t *testing.T) { - factory := NewFactory(nil) - tests := []struct { - kind unversioned.GroupKind - expectErr bool - }{ - { - kind: api.Kind("ReplicationController"), - expectErr: false, - }, - { - kind: api.Kind("Node"), - expectErr: true, - }, - } - - for _, test := range tests { - err := factory.CanBeExposed(test.kind) - if test.expectErr && err == nil { - t.Error("unexpected non-error") - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - } -} - -func TestFlagUnderscoreRenaming(t *testing.T) { - factory := NewFactory(nil) - - factory.flags.SetNormalizeFunc(flag.WordSepNormalizeFunc) - factory.flags.Bool("valid_flag", false, "bool value") - - // In case of failure of this test check this PR: spf13/pflag#23 - if factory.flags.Lookup("valid_flag").Name != "valid-flag" { - t.Fatalf("Expected flag name to be valid-flag, got %s", factory.flags.Lookup("valid_flag").Name) - } -} - -func loadSchemaForTest() (validation.Schema, error) { - pathToSwaggerSpec := "../../../../api/swagger-spec/" + testapi.Default.GroupVersion().Version + ".json" - data, err := ioutil.ReadFile(pathToSwaggerSpec) - if err != nil { - return nil, err - } - return validation.NewSwaggerSchemaFromBytes(data) -} - -func TestRefetchSchemaWhenValidationFails(t *testing.T) { - schema, err := loadSchemaForTest() - if err != nil { - t.Errorf("Error loading schema: %v", err) - t.FailNow() - } - output, err := json.Marshal(schema) - if err != nil { - t.Errorf("Error serializing schema: %v", err) - t.FailNow() - } - requests := map[string]int{} - - c := &fake.RESTClient{ - Codec: testapi.Default.Codec(), - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case strings.HasPrefix(p, "/swaggerapi") && m == "GET": - requests[p] = requests[p] + 1 - return &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewBuffer(output))}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - dir := os.TempDir() + "/schemaCache" - os.RemoveAll(dir) - - fullDir, err := substituteUserHome(dir) - if err != nil { - t.Errorf("Error getting fullDir: %v", err) - t.FailNow() - } - cacheFile := path.Join(fullDir, "foo", "bar", schemaFileName) - err = writeSchemaFile(output, fullDir, cacheFile, "foo", "bar") - if err != nil { - t.Errorf("Error building old cache schema: %v", err) - t.FailNow() - } - - obj := &extensions.Deployment{} - data, err := runtime.Encode(testapi.Extensions.Codec(), obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } - - // Re-get request, should use HTTP and write - if getSchemaAndValidate(c, data, "foo", "bar", dir); err != nil { - t.Errorf("unexpected error validating: %v", err) - } - if requests["/swaggerapi/foo/bar"] != 1 { - t.Errorf("expected 1 schema request, saw: %d", requests["/swaggerapi/foo/bar"]) - } -} - -func TestValidateCachesSchema(t *testing.T) { - schema, err := loadSchemaForTest() - if err != nil { - t.Errorf("Error loading schema: %v", err) - t.FailNow() - } - output, err := json.Marshal(schema) - if err != nil { - t.Errorf("Error serializing schema: %v", err) - t.FailNow() - } - requests := map[string]int{} - - c := &fake.RESTClient{ - Codec: testapi.Default.Codec(), - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case strings.HasPrefix(p, "/swaggerapi") && m == "GET": - requests[p] = requests[p] + 1 - return &http.Response{StatusCode: 200, Body: ioutil.NopCloser(bytes.NewBuffer(output))}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - dir := os.TempDir() + "/schemaCache" - os.RemoveAll(dir) - - obj := &api.Pod{} - data, err := runtime.Encode(testapi.Default.Codec(), obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() - } - - // Initial request, should use HTTP and write - if getSchemaAndValidate(c, data, "foo", "bar", dir); err != nil { - t.Errorf("unexpected error validating: %v", err) - } - if _, err := os.Stat(path.Join(dir, "foo", "bar", schemaFileName)); err != nil { - t.Errorf("unexpected missing cache file: %v", err) - } - if requests["/swaggerapi/foo/bar"] != 1 { - t.Errorf("expected 1 schema request, saw: %d", requests["/swaggerapi/foo/bar"]) - } - - // Same version and group, should skip HTTP - if getSchemaAndValidate(c, data, "foo", "bar", dir); err != nil { - t.Errorf("unexpected error validating: %v", err) - } - if requests["/swaggerapi/foo/bar"] != 2 { - t.Errorf("expected 1 schema request, saw: %d", requests["/swaggerapi/foo/bar"]) - } - - // Different API group, should go to HTTP and write - if getSchemaAndValidate(c, data, "foo", "baz", dir); err != nil { - t.Errorf("unexpected error validating: %v", err) - } - if _, err := os.Stat(path.Join(dir, "foo", "baz", schemaFileName)); err != nil { - t.Errorf("unexpected missing cache file: %v", err) - } - if requests["/swaggerapi/foo/baz"] != 1 { - t.Errorf("expected 1 schema request, saw: %d", requests["/swaggerapi/foo/baz"]) - } - - // Different version, should go to HTTP and write - if getSchemaAndValidate(c, data, "foo2", "bar", dir); err != nil { - t.Errorf("unexpected error validating: %v", err) - } - if _, err := os.Stat(path.Join(dir, "foo2", "bar", schemaFileName)); err != nil { - t.Errorf("unexpected missing cache file: %v", err) - } - if requests["/swaggerapi/foo2/bar"] != 1 { - t.Errorf("expected 1 schema request, saw: %d", requests["/swaggerapi/foo2/bar"]) - } - - // No cache dir, should go straight to HTTP and not write - if getSchemaAndValidate(c, data, "foo", "blah", ""); err != nil { - t.Errorf("unexpected error validating: %v", err) - } - if requests["/swaggerapi/foo/blah"] != 1 { - t.Errorf("expected 1 schema request, saw: %d", requests["/swaggerapi/foo/blah"]) - } - if _, err := os.Stat(path.Join(dir, "foo", "blah", schemaFileName)); err == nil || !os.IsNotExist(err) { - t.Errorf("unexpected cache file error: %v", err) - } -} - -func TestSubstitueUser(t *testing.T) { - usr, err := user.Current() - if err != nil { - t.Logf("SKIPPING TEST: unexpected error: %v", err) - return - } - tests := []struct { - input string - expected string - expectErr bool - }{ - {input: "~/foo", expected: path.Join(os.Getenv("HOME"), "foo")}, - {input: "~" + usr.Username + "/bar", expected: usr.HomeDir + "/bar"}, - {input: "/foo/bar", expected: "/foo/bar"}, - {input: "~doesntexit/bar", expectErr: true}, - } - for _, test := range tests { - output, err := substituteUserHome(test.input) - if test.expectErr { - if err == nil { - t.Error("unexpected non-error") - } - continue - } - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if output != test.expected { - t.Errorf("expected: %s, saw: %s", test.expected, output) - } - } -} - -func newPodList(count, isUnready, isUnhealthy int, labels map[string]string) *api.PodList { - pods := []api.Pod{} - for i := 0; i < count; i++ { - newPod := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: fmt.Sprintf("pod-%d", i+1), - Namespace: api.NamespaceDefault, - CreationTimestamp: unversioned.Date(2016, time.April, 1, 1, 0, i, 0, time.UTC), - Labels: labels, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - } - pods = append(pods, newPod) - } - if isUnready > -1 && isUnready < count { - pods[isUnready].Status.Conditions[0].Status = api.ConditionFalse - } - if isUnhealthy > -1 && isUnhealthy < count { - pods[isUnhealthy].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 5}} - } - return &api.PodList{ - Items: pods, - } -} - -func TestGetFirstPod(t *testing.T) { - labelSet := map[string]string{"test": "selector"} - tests := []struct { - name string - - podList *api.PodList - watching []watch.Event - sortBy func([]*api.Pod) sort.Interface - - expected *api.Pod - expectedNum int - expectedErr bool - }{ - { - name: "kubectl logs - two ready pods", - podList: newPodList(2, -1, -1, labelSet), - sortBy: func(pods []*api.Pod) sort.Interface { return controller.ActivePods(pods) }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod-2", - Namespace: api.NamespaceDefault, - CreationTimestamp: unversioned.Date(2016, time.April, 1, 1, 0, 1, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - expectedNum: 2, - }, - { - name: "kubectl logs - one unhealthy, one healthy", - podList: newPodList(2, -1, 1, labelSet), - sortBy: func(pods []*api.Pod) sort.Interface { return controller.ActivePods(pods) }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod-2", - Namespace: api.NamespaceDefault, - CreationTimestamp: unversioned.Date(2016, time.April, 1, 1, 0, 1, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - ContainerStatuses: []api.ContainerStatus{{RestartCount: 5}}, - }, - }, - expectedNum: 2, - }, - { - name: "kubectl attach - two ready pods", - podList: newPodList(2, -1, -1, labelSet), - sortBy: func(pods []*api.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod-1", - Namespace: api.NamespaceDefault, - CreationTimestamp: unversioned.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - expectedNum: 2, - }, - { - name: "kubectl attach - wait for ready pod", - podList: newPodList(1, 1, -1, labelSet), - watching: []watch.Event{ - { - Type: watch.Modified, - Object: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod-1", - Namespace: api.NamespaceDefault, - CreationTimestamp: unversioned.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - }, - }, - sortBy: func(pods []*api.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod-1", - Namespace: api.NamespaceDefault, - CreationTimestamp: unversioned.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC), - Labels: map[string]string{"test": "selector"}, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Status: api.ConditionTrue, - Type: api.PodReady, - }, - }, - }, - }, - expectedNum: 1, - }, - } - - for i := range tests { - test := tests[i] - client := &testclient.Fake{} - client.PrependReactor("list", "pods", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { - return true, test.podList, nil - }) - if len(test.watching) > 0 { - watcher := watch.NewFake() - for _, event := range test.watching { - switch event.Type { - case watch.Added: - go watcher.Add(event.Object) - case watch.Modified: - go watcher.Modify(event.Object) - } - } - client.PrependWatchReactor("pods", testclient.DefaultWatchReactor(watcher, nil)) - } - selector := labels.Set(labelSet).AsSelector() - - pod, numPods, err := GetFirstPod(client, api.NamespaceDefault, selector, 1*time.Minute, test.sortBy) - if !test.expectedErr && err != nil { - t.Errorf("%s: unexpected error: %v", test.name, err) - continue - } - if test.expectedErr && err == nil { - t.Errorf("%s: expected an error", test.name) - continue - } - if test.expectedNum != numPods { - t.Errorf("%s: expected %d pods, got %d", test.name, test.expectedNum, numPods) - continue - } - if !reflect.DeepEqual(test.expected, pod) { - t.Errorf("%s:\nexpected pod:\n%#v\ngot:\n%#v\n\n", test.name, test.expected, pod) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers_test.go deleted file mode 100644 index 95c68070d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers_test.go +++ /dev/null @@ -1,304 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 util - -import ( - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strings" - "syscall" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -func TestMerge(t *testing.T) { - grace := int64(30) - tests := []struct { - obj runtime.Object - fragment string - expected runtime.Object - expectErr bool - kind string - }{ - { - kind: "Pod", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s" }`, testapi.Default.GroupVersion().String()), - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - /* TODO: uncomment this test once Merge is updated to use - strategic-merge-patch. See #8449. - { - kind: "Pod", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - api.Container{ - Name: "c1", - Image: "red-image", - }, - api.Container{ - Name: "c2", - Image: "blue-image", - }, - }, - }, - }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "containers": [ { "name": "c1", "image": "green-image" } ] } }`, testapi.Default.GroupVersion().String()), - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - api.Container{ - Name: "c1", - Image: "green-image", - }, - api.Container{ - Name: "c2", - Image: "blue-image", - }, - }, - }, - }, - }, */ - { - kind: "Pod", - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "volumes": [ {"name": "v1"}, {"name": "v2"} ] } }`, testapi.Default.GroupVersion().String()), - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Volumes: []api.Volume{ - { - Name: "v1", - VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}, - }, - { - Name: "v2", - VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}, - }, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSClusterFirst, - TerminationGracePeriodSeconds: &grace, - SecurityContext: &api.PodSecurityContext{}, - }, - }, - }, - { - kind: "Pod", - obj: &api.Pod{}, - fragment: "invalid json", - expected: &api.Pod{}, - expectErr: true, - }, - { - kind: "Service", - obj: &api.Service{}, - fragment: `{ "apiVersion": "badVersion" }`, - expectErr: true, - }, - { - kind: "Service", - obj: &api.Service{ - Spec: api.ServiceSpec{}, - }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "ports": [ { "port": 0 } ] } }`, testapi.Default.GroupVersion().String()), - expected: &api.Service{ - Spec: api.ServiceSpec{ - SessionAffinity: "None", - Type: api.ServiceTypeClusterIP, - Ports: []api.ServicePort{ - { - Protocol: api.ProtocolTCP, - Port: 0, - }, - }, - }, - }, - }, - { - kind: "Service", - obj: &api.Service{ - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "version": "v1", - }, - }, - }, - fragment: fmt.Sprintf(`{ "apiVersion": "%s", "spec": { "selector": { "version": "v2" } } }`, testapi.Default.GroupVersion().String()), - expected: &api.Service{ - Spec: api.ServiceSpec{ - SessionAffinity: "None", - Type: api.ServiceTypeClusterIP, - Selector: map[string]string{ - "version": "v2", - }, - }, - }, - }, - } - - for i, test := range tests { - out, err := Merge(testapi.Default.Codec(), test.obj, test.fragment, test.kind) - if !test.expectErr { - if err != nil { - t.Errorf("testcase[%d], unexpected error: %v", i, err) - } else if !reflect.DeepEqual(out, test.expected) { - t.Errorf("\n\ntestcase[%d]\nexpected:\n%+v\nsaw:\n%+v", i, test.expected, out) - } - } - if test.expectErr && err == nil { - t.Errorf("testcase[%d], unexpected non-error", i) - } - } -} - -type fileHandler struct { - data []byte -} - -func (f *fileHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) { - if req.URL.Path == "/error" { - res.WriteHeader(http.StatusNotFound) - return - } - res.WriteHeader(http.StatusOK) - res.Write(f.data) -} - -func TestCheckInvalidErr(t *testing.T) { - tests := []struct { - err error - expected string - }{ - { - errors.NewInvalid(api.Kind("Invalid1"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field"), "single", "details")}), - `Error from server: Invalid1 "invalidation" is invalid: field: Invalid value: "single": details`, - }, - { - errors.NewInvalid(api.Kind("Invalid2"), "invalidation", field.ErrorList{field.Invalid(field.NewPath("field1"), "multi1", "details"), field.Invalid(field.NewPath("field2"), "multi2", "details")}), - `Error from server: Invalid2 "invalidation" is invalid: [field1: Invalid value: "multi1": details, field2: Invalid value: "multi2": details]`, - }, - { - errors.NewInvalid(api.Kind("Invalid3"), "invalidation", field.ErrorList{}), - `Error from server: Invalid3 "invalidation" is invalid: `, - }, - } - - var errReturned string - errHandle := func(err string) { - errReturned = err - } - - for _, test := range tests { - checkErr(test.err, errHandle) - - if errReturned != test.expected { - t.Fatalf("Got: %s, expected: %s", errReturned, test.expected) - } - } -} - -func TestCheckNoResourceMatchError(t *testing.T) { - tests := []struct { - err error - expected string - }{ - { - &meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Resource: "foo"}}, - `the server doesn't have a resource type "foo"`, - }, - { - &meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Version: "theversion", Resource: "foo"}}, - `the server doesn't have a resource type "foo" in version "theversion"`, - }, - { - &meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Group: "thegroup", Version: "theversion", Resource: "foo"}}, - `the server doesn't have a resource type "foo" in group "thegroup" and version "theversion"`, - }, - { - &meta.NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Group: "thegroup", Resource: "foo"}}, - `the server doesn't have a resource type "foo" in group "thegroup"`, - }, - } - - var errReturned string - errHandle := func(err string) { - errReturned = err - } - - for _, test := range tests { - checkErr(test.err, errHandle) - - if errReturned != test.expected { - t.Fatalf("Got: %s, expected: %s", errReturned, test.expected) - } - } -} - -func TestDumpReaderToFile(t *testing.T) { - testString := "TEST STRING" - tempFile, err := ioutil.TempFile("", "hlpers_test_dump_") - if err != nil { - t.Errorf("unexpected error setting up a temporary file %v", err) - } - defer syscall.Unlink(tempFile.Name()) - defer tempFile.Close() - err = DumpReaderToFile(strings.NewReader(testString), tempFile.Name()) - if err != nil { - t.Errorf("error in DumpReaderToFile: %v", err) - } - data, err := ioutil.ReadFile(tempFile.Name()) - if err != nil { - t.Errorf("error when reading %s: %v", tempFile.Name(), err) - } - stringData := string(data) - if stringData != testString { - t.Fatalf("Wrong file content %s != %s", testString, stringData) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go deleted file mode 100644 index 84a76da95..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/util/jsonmerge/jsonmerge.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 jsonmerge - -import ( - "encoding/json" - "fmt" - - "github.com/evanphx/json-patch" - "github.com/golang/glog" - - "k8s.io/kubernetes/pkg/util/strategicpatch" - "k8s.io/kubernetes/pkg/util/yaml" -) - -// Delta represents a change between two JSON documents. -type Delta struct { - original []byte - edit []byte - - preconditions []PreconditionFunc -} - -// PreconditionFunc is a test to verify that an incompatible change -// has occurred before an Apply can be successful. -type PreconditionFunc func(interface{}) (hold bool, message string) - -// AddPreconditions adds precondition checks to a change which must -// be satisfied before an Apply is considered successful. If a -// precondition returns false, the Apply is failed with -// ErrPreconditionFailed. -func (d *Delta) AddPreconditions(fns ...PreconditionFunc) { - d.preconditions = append(d.preconditions, fns...) -} - -// RequireKeyUnchanged creates a precondition function that fails -// if the provided key is present in the diff (indicating its value -// has changed). -func RequireKeyUnchanged(key string) PreconditionFunc { - return func(diff interface{}) (bool, string) { - m, ok := diff.(map[string]interface{}) - if !ok { - return true, "" - } - // the presence of key in a diff means that its value has been changed, therefore - // we should fail the precondition. - _, ok = m[key] - if ok { - return false, key + " should not be changed\n" - } else { - return true, "" - } - } -} - -// RequireKeyUnchanged creates a precondition function that fails -// if the metadata.key is present in the diff (indicating its value -// has changed). -func RequireMetadataKeyUnchanged(key string) PreconditionFunc { - return func(diff interface{}) (bool, string) { - m, ok := diff.(map[string]interface{}) - if !ok { - return true, "" - } - m1, ok := m["metadata"] - if !ok { - return true, "" - } - m2, ok := m1.(map[string]interface{}) - if !ok { - return true, "" - } - _, ok = m2[key] - if ok { - return false, "metadata." + key + " should not be changed\n" - } else { - return true, "" - } - } -} - -// TestPreconditions test if preconditions hold given the edit -func TestPreconditionsHold(edit []byte, preconditions []PreconditionFunc) (bool, string) { - diff := make(map[string]interface{}) - if err := json.Unmarshal(edit, &diff); err != nil { - return false, err.Error() - } - for _, fn := range preconditions { - if hold, msg := fn(diff); !hold { - return false, msg - } - } - return true, "" -} - -// NewDelta accepts two JSON or YAML documents and calculates the difference -// between them. It returns a Delta object which can be used to resolve -// conflicts against a third version with a common parent, or an error -// if either document is in error. -func NewDelta(from, to []byte) (*Delta, error) { - d := &Delta{} - before, err := yaml.ToJSON(from) - if err != nil { - return nil, err - } - after, err := yaml.ToJSON(to) - if err != nil { - return nil, err - } - diff, err := jsonpatch.CreateMergePatch(before, after) - if err != nil { - return nil, err - } - glog.V(6).Infof("Patch created from:\n%s\n%s\n%s", string(before), string(after), string(diff)) - d.original = before - d.edit = diff - return d, nil -} - -// Apply attempts to apply the changes described by Delta onto latest, -// returning an error if the changes cannot be applied cleanly. -// IsConflicting will be true if the changes overlap, otherwise a -// generic error will be returned. -func (d *Delta) Apply(latest []byte) ([]byte, error) { - base, err := yaml.ToJSON(latest) - if err != nil { - return nil, err - } - changes, err := jsonpatch.CreateMergePatch(d.original, base) - if err != nil { - return nil, err - } - diff1 := make(map[string]interface{}) - if err := json.Unmarshal(d.edit, &diff1); err != nil { - return nil, err - } - diff2 := make(map[string]interface{}) - if err := json.Unmarshal(changes, &diff2); err != nil { - return nil, err - } - for _, fn := range d.preconditions { - hold1, _ := fn(diff1) - hold2, _ := fn(diff2) - if !hold1 || !hold2 { - return nil, ErrPreconditionFailed - } - } - - glog.V(6).Infof("Testing for conflict between:\n%s\n%s", string(d.edit), string(changes)) - hasConflicts, err := strategicpatch.HasConflicts(diff1, diff2) - if err != nil { - return nil, err - } - if hasConflicts { - return nil, ErrConflict - } - - return jsonpatch.MergePatch(base, d.edit) -} - -// IsConflicting returns true if the provided error indicates a -// conflict exists between the original changes and the applied -// changes. -func IsConflicting(err error) bool { - return err == ErrConflict -} - -// IsPreconditionFailed returns true if the provided error indicates -// a Delta precondition did not succeed. -func IsPreconditionFailed(err error) bool { - return err == ErrPreconditionFailed -} - -var ErrPreconditionFailed = fmt.Errorf("a precondition failed") -var ErrConflict = fmt.Errorf("changes are in conflict") - -func (d *Delta) Edit() []byte { - return d.edit -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/version.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/version.go deleted file mode 100644 index beaeda7bb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/cmd/version.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cmd - -import ( - "io" - - "github.com/spf13/cobra" - - "k8s.io/kubernetes/pkg/kubectl" - cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" -) - -func NewCmdVersion(f *cmdutil.Factory, out io.Writer) *cobra.Command { - cmd := &cobra.Command{ - Use: "version", - Short: "Print the client and server version information.", - Run: func(cmd *cobra.Command, args []string) { - err := RunVersion(f, out, cmd) - cmdutil.CheckErr(err) - }, - } - cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).") - cmd.Flags().MarkShorthandDeprecated("client", "please use --client instead.") - return cmd -} - -func RunVersion(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { - kubectl.GetClientVersion(out) - if cmdutil.GetFlagBool(cmd, "client") { - return nil - } - - client, err := f.Client() - if err != nil { - return err - } - - kubectl.GetServerVersion(out, client) - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/configmap_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/configmap_test.go deleted file mode 100644 index d4458bdd0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/configmap_test.go +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func TestConfigMapGenerate(t *testing.T) { - tests := []struct { - params map[string]interface{} - expected *api.ConfigMap - expectErr bool - }{ - { - params: map[string]interface{}{ - "name": "foo", - }, - expected: &api.ConfigMap{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string]string{}, - }, - expectErr: false, - }, - { - params: map[string]interface{}{ - "name": "foo", - "type": "my-type", - }, - expected: &api.ConfigMap{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string]string{}, - }, - expectErr: false, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-literal": []string{"key1=value1", "key2=value2"}, - }, - expected: &api.ConfigMap{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string]string{ - "key1": "value1", - "key2": "value2", - }, - }, - expectErr: false, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-literal": []string{"key1value1"}, - }, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-file": []string{"key1=/file=2"}, - }, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-file": []string{"key1==value"}, - }, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-literal": []string{"key1==value1"}, - }, - expected: &api.ConfigMap{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string]string{ - "key1": "=value1", - }, - }, - expectErr: false, - }, - } - generator := ConfigMapGeneratorV1{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*api.ConfigMap), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.ConfigMap)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/custom_column_printer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/custom_column_printer_test.go deleted file mode 100644 index 531881a73..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/custom_column_printer_test.go +++ /dev/null @@ -1,276 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "bytes" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestMassageJSONPath(t *testing.T) { - tests := []struct { - input string - expectedOutput string - expectErr bool - }{ - {input: "foo.bar", expectedOutput: "{.foo.bar}"}, - {input: "{foo.bar}", expectedOutput: "{.foo.bar}"}, - {input: ".foo.bar", expectedOutput: "{.foo.bar}"}, - {input: "{.foo.bar}", expectedOutput: "{.foo.bar}"}, - {input: "", expectedOutput: ""}, - {input: "{foo.bar", expectErr: true}, - {input: "foo.bar}", expectErr: true}, - {input: "{foo.bar}}", expectErr: true}, - {input: "{{foo.bar}", expectErr: true}, - } - for _, test := range tests { - output, err := massageJSONPath(test.input) - if err != nil && !test.expectErr { - t.Errorf("unexpected error: %v", err) - continue - } - if test.expectErr { - if err == nil { - t.Error("unexpected non-error") - } - continue - } - if output != test.expectedOutput { - t.Errorf("input: %s, expected: %s, saw: %s", test.input, test.expectedOutput, output) - } - } -} - -func TestNewColumnPrinterFromSpec(t *testing.T) { - tests := []struct { - spec string - expectedColumns []Column - expectErr bool - name string - }{ - { - spec: "", - expectErr: true, - name: "empty", - }, - { - spec: "invalid", - expectErr: true, - name: "invalid1", - }, - { - spec: "invalid=foobar", - expectErr: true, - name: "invalid2", - }, - { - spec: "invalid,foobar:blah", - expectErr: true, - name: "invalid3", - }, - { - spec: "NAME:metadata.name,API_VERSION:apiVersion", - name: "ok", - expectedColumns: []Column{ - { - Header: "NAME", - FieldSpec: "{.metadata.name}", - }, - { - Header: "API_VERSION", - FieldSpec: "{.apiVersion}", - }, - }, - }, - } - for _, test := range tests { - printer, err := NewCustomColumnsPrinterFromSpec(test.spec, api.Codecs.UniversalDecoder()) - if test.expectErr { - if err == nil { - t.Errorf("[%s] unexpected non-error", test.name) - } - continue - } - if !test.expectErr && err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - - if !reflect.DeepEqual(test.expectedColumns, printer.Columns) { - t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns) - } - - } -} - -const exampleTemplateOne = `NAME API_VERSION -{metadata.name} {apiVersion}` - -const exampleTemplateTwo = `NAME API_VERSION - {metadata.name} {apiVersion}` - -func TestNewColumnPrinterFromTemplate(t *testing.T) { - tests := []struct { - spec string - expectedColumns []Column - expectErr bool - name string - }{ - { - spec: "", - expectErr: true, - name: "empty", - }, - { - spec: "invalid", - expectErr: true, - name: "invalid1", - }, - { - spec: "invalid=foobar", - expectErr: true, - name: "invalid2", - }, - { - spec: "invalid,foobar:blah", - expectErr: true, - name: "invalid3", - }, - { - spec: exampleTemplateOne, - name: "ok", - expectedColumns: []Column{ - { - Header: "NAME", - FieldSpec: "{.metadata.name}", - }, - { - Header: "API_VERSION", - FieldSpec: "{.apiVersion}", - }, - }, - }, - { - spec: exampleTemplateTwo, - name: "ok-2", - expectedColumns: []Column{ - { - Header: "NAME", - FieldSpec: "{.metadata.name}", - }, - { - Header: "API_VERSION", - FieldSpec: "{.apiVersion}", - }, - }, - }, - } - for _, test := range tests { - reader := bytes.NewBufferString(test.spec) - printer, err := NewCustomColumnsPrinterFromTemplate(reader, api.Codecs.UniversalDecoder()) - if test.expectErr { - if err == nil { - t.Errorf("[%s] unexpected non-error", test.name) - } - continue - } - if !test.expectErr && err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - - if !reflect.DeepEqual(test.expectedColumns, printer.Columns) { - t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns) - } - - } -} - -func TestColumnPrint(t *testing.T) { - tests := []struct { - columns []Column - obj runtime.Object - expectedOutput string - }{ - { - columns: []Column{ - { - Header: "NAME", - FieldSpec: "{.metadata.name}", - }, - }, - obj: &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "foo"}}, - expectedOutput: `NAME -foo -`, - }, - { - columns: []Column{ - { - Header: "NAME", - FieldSpec: "{.metadata.name}", - }, - }, - obj: &v1.PodList{ - Items: []v1.Pod{ - {ObjectMeta: v1.ObjectMeta{Name: "foo"}}, - {ObjectMeta: v1.ObjectMeta{Name: "bar"}}, - }, - }, - expectedOutput: `NAME -foo -bar -`, - }, - { - columns: []Column{ - { - Header: "NAME", - FieldSpec: "{.metadata.name}", - }, - { - Header: "API_VERSION", - FieldSpec: "{.apiVersion}", - }, - }, - obj: &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "foo"}, TypeMeta: unversioned.TypeMeta{APIVersion: "baz"}}, - expectedOutput: `NAME API_VERSION -foo baz -`, - }, - } - - for _, test := range tests { - printer := &CustomColumnsPrinter{ - Columns: test.columns, - Decoder: api.Codecs.UniversalDecoder(), - } - buffer := &bytes.Buffer{} - if err := printer.PrintObj(test.obj, buffer); err != nil { - t.Errorf("unexpected error: %v", err) - } - if buffer.String() != test.expectedOutput { - t.Errorf("\nexpected:\n'%s'\nsaw\n'%s'\n", test.expectedOutput, buffer.String()) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe_test.go deleted file mode 100644 index f073d3050..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/describe_test.go +++ /dev/null @@ -1,636 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "bytes" - "fmt" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient" -) - -type describeClient struct { - T *testing.T - Namespace string - Err error - client.Interface -} - -func TestDescribePod(t *testing.T) { - fake := testclient.NewSimpleFake(&api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }) - c := &describeClient{T: t, Namespace: "foo", Interface: fake} - d := PodDescriber{c} - out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !strings.Contains(out, "bar") || !strings.Contains(out, "Status:") { - t.Errorf("unexpected out: %s", out) - } -} - -func TestDescribeService(t *testing.T) { - fake := testclient.NewSimpleFake(&api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }) - c := &describeClient{T: t, Namespace: "foo", Interface: fake} - d := ServiceDescriber{c} - out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !strings.Contains(out, "Labels:") || !strings.Contains(out, "bar") { - t.Errorf("unexpected out: %s", out) - } -} - -func TestPodDescribeResultsSorted(t *testing.T) { - // Arrange - fake := testclient.NewSimpleFake(&api.EventList{ - Items: []api.Event{ - { - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 1", - FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - { - Source: api.EventSource{Component: "scheduler"}, - Message: "Item 2", - FirstTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - { - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 3", - FirstTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - }, - }) - c := &describeClient{T: t, Namespace: "foo", Interface: fake} - d := PodDescriber{c} - - // Act - out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) - - // Assert - if err != nil { - t.Errorf("unexpected error: %v", err) - } - VerifyDatesInOrder(out, "\n" /* rowDelimiter */, "\t" /* columnDelimiter */, t) -} - -func TestDescribeContainers(t *testing.T) { - testCases := []struct { - container api.Container - status api.ContainerStatus - expectedElements []string - }{ - // Running state. - { - container: api.Container{Name: "test", Image: "image"}, - status: api.ContainerStatus{ - Name: "test", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ - StartedAt: unversioned.NewTime(time.Now()), - }, - }, - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Running", "Ready", "True", "Restart Count", "7", "Image", "image", "Started"}, - }, - // Waiting state. - { - container: api.Container{Name: "test", Image: "image"}, - status: api.ContainerStatus{ - Name: "test", - State: api.ContainerState{ - Waiting: &api.ContainerStateWaiting{ - Reason: "potato", - }, - }, - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato"}, - }, - // Terminated state. - { - container: api.Container{Name: "test", Image: "image"}, - status: api.ContainerStatus{ - Name: "test", - State: api.ContainerState{ - Terminated: &api.ContainerStateTerminated{ - StartedAt: unversioned.NewTime(time.Now()), - FinishedAt: unversioned.NewTime(time.Now()), - Reason: "potato", - ExitCode: 2, - }, - }, - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato", "Started", "Finished", "Exit Code", "2"}, - }, - // Last Terminated - { - container: api.Container{Name: "test", Image: "image"}, - status: api.ContainerStatus{ - Name: "test", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ - StartedAt: unversioned.NewTime(time.Now()), - }, - }, - LastTerminationState: api.ContainerState{ - Terminated: &api.ContainerStateTerminated{ - StartedAt: unversioned.NewTime(time.Now().Add(time.Second * 3)), - FinishedAt: unversioned.NewTime(time.Now()), - Reason: "crashing", - ExitCode: 3, - }, - }, - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Started", "Finished", "Exit Code", "2", "crashing", "3"}, - }, - // No state defaults to waiting. - { - container: api.Container{Name: "test", Image: "image"}, - status: api.ContainerStatus{ - Name: "test", - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image"}, - }, - // Env - { - container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}}, - status: api.ContainerStatus{ - Name: "test", - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz"}, - }, - // Command - { - container: api.Container{Name: "test", Image: "image", Command: []string{"sleep", "1000"}}, - status: api.ContainerStatus{ - Name: "test", - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "sleep", "1000"}, - }, - // Args - { - container: api.Container{Name: "test", Image: "image", Args: []string{"time", "1000"}}, - status: api.ContainerStatus{ - Name: "test", - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "time", "1000"}, - }, - // Using limits. - { - container: api.Container{ - Name: "test", - Image: "image", - Resources: api.ResourceRequirements{ - Limits: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("1000"), - api.ResourceName(api.ResourceMemory): resource.MustParse("4G"), - api.ResourceName(api.ResourceStorage): resource.MustParse("20G"), - }, - }, - }, - status: api.ContainerStatus{ - Name: "test", - Ready: true, - RestartCount: 7, - }, - expectedElements: []string{"cpu", "1k", "memory", "4G", "storage", "20G"}, - }, - } - - for i, testCase := range testCases { - out := new(bytes.Buffer) - pod := api.Pod{ - Spec: api.PodSpec{ - Containers: []api.Container{testCase.container}, - }, - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{testCase.status}, - }, - } - describeContainers(pod.Spec.Containers, pod.Status.ContainerStatuses, EnvValueRetriever(&pod), out, "") - output := out.String() - for _, expected := range testCase.expectedElements { - if !strings.Contains(output, expected) { - t.Errorf("Test case %d: expected to find %q in output: %q", i, expected, output) - } - } - } -} - -func TestDescribers(t *testing.T) { - first := &api.Event{} - second := &api.Pod{} - var third *api.Pod - testErr := fmt.Errorf("test") - d := Describers{} - d.Add( - func(e *api.Event, p *api.Pod) (string, error) { - if e != first { - t.Errorf("first argument not equal: %#v", e) - } - if p != second { - t.Errorf("second argument not equal: %#v", p) - } - return "test", testErr - }, - ) - if out, err := d.DescribeObject(first, second); out != "test" || err != testErr { - t.Errorf("unexpected result: %s %v", out, err) - } - - if out, err := d.DescribeObject(first, second, third); out != "" || err == nil { - t.Errorf("unexpected result: %s %v", out, err) - } else { - if noDescriber, ok := err.(ErrNoDescriber); ok { - if !reflect.DeepEqual(noDescriber.Types, []string{"*api.Event", "*api.Pod", "*api.Pod"}) { - t.Errorf("unexpected describer: %v", err) - } - } else { - t.Errorf("unexpected error type: %v", err) - } - } - - d.Add( - func(e *api.Event) (string, error) { - if e != first { - t.Errorf("first argument not equal: %#v", e) - } - return "simpler", testErr - }, - ) - if out, err := d.DescribeObject(first); out != "simpler" || err != testErr { - t.Errorf("unexpected result: %s %v", out, err) - } -} - -func TestDefaultDescribers(t *testing.T) { - out, err := DefaultObjectDescriber.DescribeObject(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !strings.Contains(out, "foo") { - t.Errorf("unexpected output: %s", out) - } - - out, err = DefaultObjectDescriber.DescribeObject(&api.Service{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !strings.Contains(out, "foo") { - t.Errorf("unexpected output: %s", out) - } - - out, err = DefaultObjectDescriber.DescribeObject(&api.ReplicationController{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !strings.Contains(out, "foo") { - t.Errorf("unexpected output: %s", out) - } - - out, err = DefaultObjectDescriber.DescribeObject(&api.Node{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !strings.Contains(out, "foo") { - t.Errorf("unexpected output: %s", out) - } -} - -func TestGetPodsTotalRequests(t *testing.T) { - testCases := []struct { - pods *api.PodList - expectedReqs, expectedLimits map[api.ResourceName]resource.Quantity - }{ - { - pods: &api.PodList{ - Items: []api.Pod{ - { - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("1"), - api.ResourceName(api.ResourceMemory): resource.MustParse("300Mi"), - api.ResourceName(api.ResourceStorage): resource.MustParse("1G"), - }, - }, - }, - { - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("90m"), - api.ResourceName(api.ResourceMemory): resource.MustParse("120Mi"), - api.ResourceName(api.ResourceStorage): resource.MustParse("200M"), - }, - }, - }, - }, - }, - }, - { - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("60m"), - api.ResourceName(api.ResourceMemory): resource.MustParse("43Mi"), - api.ResourceName(api.ResourceStorage): resource.MustParse("500M"), - }, - }, - }, - { - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("34m"), - api.ResourceName(api.ResourceMemory): resource.MustParse("83Mi"), - api.ResourceName(api.ResourceStorage): resource.MustParse("700M"), - }, - }, - }, - }, - }, - }, - }, - }, - expectedReqs: map[api.ResourceName]resource.Quantity{ - api.ResourceName(api.ResourceCPU): resource.MustParse("1.184"), - api.ResourceName(api.ResourceMemory): resource.MustParse("546Mi"), - api.ResourceName(api.ResourceStorage): resource.MustParse("2.4G"), - }, - }, - } - - for _, testCase := range testCases { - reqs, _, err := getPodsTotalRequestsAndLimits(testCase.pods) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - if !reflect.DeepEqual(reqs, testCase.expectedReqs) { - t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs) - } - } -} - -func TestPersistentVolumeDescriber(t *testing.T) { - tests := map[string]*api.PersistentVolume{ - - "hostpath": { - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - HostPath: &api.HostPathVolumeSource{}, - }, - }, - }, - "gce": { - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{}, - }, - }, - }, - "ebs": { - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{}, - }, - }, - }, - "nfs": { - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - NFS: &api.NFSVolumeSource{}, - }, - }, - }, - "iscsi": { - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - ISCSI: &api.ISCSIVolumeSource{}, - }, - }, - }, - "gluster": { - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - Glusterfs: &api.GlusterfsVolumeSource{}, - }, - }, - }, - "rbd": { - Spec: api.PersistentVolumeSpec{ - PersistentVolumeSource: api.PersistentVolumeSource{ - RBD: &api.RBDVolumeSource{}, - }, - }, - }, - } - - for name, pv := range tests { - fake := testclient.NewSimpleFake(pv) - c := PersistentVolumeDescriber{fake} - str, err := c.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("Unexpected error for test %s: %v", name, err) - } - if str == "" { - t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", name) - } - } -} - -func TestDescribeDeployment(t *testing.T) { - fake := fake.NewSimpleClientset(&extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - Spec: extensions.DeploymentSpec{ - Template: api.PodTemplateSpec{}, - }, - }) - d := DeploymentDescriber{fake} - out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !strings.Contains(out, "bar") || !strings.Contains(out, "foo") { - t.Errorf("unexpected out: %s", out) - } -} - -func TestDescribeEvents(t *testing.T) { - - events := &api.EventList{ - Items: []api.Event{ - { - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 1", - FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - }, - } - - m := map[string]Describer{ - "DaemonSetDescriber": &DaemonSetDescriber{ - testclient.NewSimpleFake(&extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }, events), - }, - "DeploymentDescriber": &DeploymentDescriber{ - fake.NewSimpleClientset(&extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }, events), - }, - "EndpointsDescriber": &EndpointsDescriber{ - testclient.NewSimpleFake(&api.Endpoints{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }, events), - }, - // TODO(jchaloup): add tests for: - // - HorizontalPodAutoscalerDescriber - // - IngressDescriber - // - JobDescriber - "NodeDescriber": &NodeDescriber{ - testclient.NewSimpleFake(&api.Node{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - SelfLink: "url/url/url", - }, - }, events), - }, - "PodDescriber": &PodDescriber{ - testclient.NewSimpleFake(&api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - SelfLink: "url/url/url", - }, - }, events), - }, - "ReplicaSetDescriber": &ReplicaSetDescriber{ - testclient.NewSimpleFake(&extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }, events), - }, - "ReplicationControllerDescriber": &ReplicationControllerDescriber{ - testclient.NewSimpleFake(&api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }, events), - }, - "Service": &ServiceDescriber{ - testclient.NewSimpleFake(&api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Namespace: "foo", - }, - }, events), - }, - } - - for name, d := range m { - out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) - if err != nil { - t.Errorf("unexpected error for %q: %v", name, err) - } - if !strings.Contains(out, "bar") { - t.Errorf("unexpected out for %q: %s", name, out) - } - if !strings.Contains(out, "Events:") { - t.Errorf("events not found for %q when ShowEvents=true: %s", name, out) - } - - out, err = d.Describe("foo", "bar", DescriberSettings{ShowEvents: false}) - if err != nil { - t.Errorf("unexpected error for %q: %s", name, err) - } - if !strings.Contains(out, "bar") { - t.Errorf("unexpected out for %q: %s", name, out) - } - if strings.Contains(out, "Events:") { - t.Errorf("events found for %q when ShowEvents=false: %s", name, out) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/generate_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/generate_test.go deleted file mode 100644 index 62823f9dc..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/generate_test.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "github.com/spf13/cobra" -) - -type TestStruct struct { - val int -} - -func TestIsZero(t *testing.T) { - tests := []struct { - val interface{} - expectZero bool - }{ - {"", true}, - {nil, true}, - {0, true}, - {TestStruct{}, true}, - {"foo", false}, - {1, false}, - {TestStruct{val: 2}, false}, - } - - for _, test := range tests { - output := IsZero(test.val) - if output != test.expectZero { - t.Errorf("expected: %v, saw %v", test.expectZero, output) - } - } -} - -func TestValidateParams(t *testing.T) { - tests := []struct { - paramSpec []GeneratorParam - params map[string]interface{} - valid bool - }{ - { - paramSpec: []GeneratorParam{}, - params: map[string]interface{}{}, - valid: true, - }, - { - paramSpec: []GeneratorParam{ - {Name: "foo"}, - }, - params: map[string]interface{}{}, - valid: true, - }, - { - paramSpec: []GeneratorParam{ - {Name: "foo", Required: true}, - }, - params: map[string]interface{}{ - "foo": "bar", - }, - valid: true, - }, - { - paramSpec: []GeneratorParam{ - {Name: "foo", Required: true}, - }, - params: map[string]interface{}{ - "baz": "blah", - "foo": "bar", - }, - valid: true, - }, - { - paramSpec: []GeneratorParam{ - {Name: "foo", Required: true}, - {Name: "baz", Required: true}, - }, - params: map[string]interface{}{ - "baz": "blah", - "foo": "bar", - }, - valid: true, - }, - { - paramSpec: []GeneratorParam{ - {Name: "foo", Required: true}, - {Name: "baz", Required: true}, - }, - params: map[string]interface{}{ - "foo": "bar", - }, - valid: false, - }, - } - for _, test := range tests { - err := ValidateParams(test.paramSpec, test.params) - if test.valid && err != nil { - t.Errorf("unexpected error: %v", err) - } - if !test.valid && err == nil { - t.Errorf("unexpected non-error") - } - } -} - -func TestMakeParams(t *testing.T) { - cmd := &cobra.Command{} - cmd.Flags().String("foo", "bar", "") - cmd.Flags().String("baz", "", "") - cmd.Flags().Set("baz", "blah") - - paramSpec := []GeneratorParam{ - {Name: "foo", Required: true}, - {Name: "baz", Required: true}, - } - expected := map[string]interface{}{ - "foo": "bar", - "baz": "blah", - } - params := MakeParams(cmd, paramSpec) - if !reflect.DeepEqual(params, expected) { - t.Errorf("\nexpected:\n%v\nsaw:\n%v", expected, params) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/kubectl.test b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/kubectl.test deleted file mode 100644 index 152a3526f..000000000 Binary files a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/kubectl.test and /dev/null differ diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/kubectl_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/kubectl_test.go deleted file mode 100644 index 1cd69d11e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/kubectl_test.go +++ /dev/null @@ -1,200 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 kubectl - -import ( - "testing" -) - -func TestParseFileSource(t *testing.T) { - cases := []struct { - name string - input string - key string - filepath string - err bool - }{ - { - name: "success 1", - input: "boo=zoo", - key: "boo", - filepath: "zoo", - err: false, - }, - { - name: "success 2", - input: "boo=/path/to/zoo", - key: "boo", - filepath: "/path/to/zoo", - err: false, - }, - { - name: "success 3", - input: "boo-2=/1/2/3/4/5/zab.txt", - key: "boo-2", - filepath: "/1/2/3/4/5/zab.txt", - err: false, - }, - { - name: "success 4", - input: "boo-=this/seems/weird.txt", - key: "boo-", - filepath: "this/seems/weird.txt", - err: false, - }, - { - name: "success 5", - input: "-key=some/path", - key: "-key", - filepath: "some/path", - err: false, - }, - { - name: "invalid 1", - input: "key==some/path", - err: true, - }, - { - name: "invalid 2", - input: "=key=some/path", - err: true, - }, - { - name: "invalid 3", - input: "==key=/some/other/path", - err: true, - }, - { - name: "invalid 4", - input: "=key", - err: true, - }, - { - name: "invalid 5", - input: "key=", - err: true, - }, - } - - for _, tc := range cases { - key, filepath, err := parseFileSource(tc.input) - if err != nil { - if tc.err { - continue - } - - t.Errorf("%v: unexpected error: %v", tc.name, err) - continue - } - - if tc.err { - t.Errorf("%v: unexpected success", tc.name) - continue - } - - if e, a := tc.key, key; e != a { - t.Errorf("%v: expected key %v; got %v", tc.name, e, a) - continue - } - - if e, a := tc.filepath, filepath; e != a { - t.Errorf("%v: expected filepath %v; got %v", tc.name, e, a) - } - } -} - -func TestParseLiteralSource(t *testing.T) { - cases := []struct { - name string - input string - key string - value string - err bool - }{ - { - name: "success 1", - input: "key=value", - key: "key", - value: "value", - err: false, - }, - { - name: "success 2", - input: "key=value/with/slashes", - key: "key", - value: "value/with/slashes", - err: false, - }, - { - name: "err 1", - input: "key==value", - key: "key", - value: "=value", - err: false, - }, - { - name: "err 2", - input: "key=value=", - key: "key", - value: "value=", - err: false, - }, - { - name: "err 3", - input: "key2=value==", - key: "key2", - value: "value==", - err: false, - }, - { - name: "err 4", - input: "==key", - err: true, - }, - { - name: "err 5", - input: "=key=", - err: true, - }, - } - - for _, tc := range cases { - key, value, err := parseLiteralSource(tc.input) - if err != nil { - if tc.err { - continue - } - - t.Errorf("%v: unexpected error: %v", tc.name, err) - continue - } - - if tc.err { - t.Errorf("%v: unexpected success", tc.name) - continue - } - - if e, a := tc.key, key; e != a { - t.Errorf("%v: expected key %v; got %v", tc.name, e, a) - continue - } - - if e, a := tc.value, value; e != a { - t.Errorf("%v: expected value %v; got %v", tc.name, e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/namespace_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/namespace_test.go deleted file mode 100644 index b0445bd29..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/namespace_test.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func TestNamespaceGenerate(t *testing.T) { - tests := []struct { - params map[string]interface{} - expected *api.Namespace - expectErr bool - }{ - { - params: map[string]interface{}{ - "name": "foo", - }, - expected: &api.Namespace{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - }, - expectErr: false, - }, - { - params: map[string]interface{}{}, - expectErr: true, - }, - } - generator := NamespaceGeneratorV1{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*api.Namespace), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Namespace)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/proxy_server_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/proxy_server_test.go deleted file mode 100644 index 79d1365a3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/proxy_server_test.go +++ /dev/null @@ -1,333 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "path/filepath" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/client/restclient" -) - -func TestAccept(t *testing.T) { - tests := []struct { - acceptPaths string - rejectPaths string - acceptHosts string - path string - host string - method string - expectAccept bool - }{ - - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "127.0.0.1", - method: "GET", - expectAccept: true, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "localhost", - method: "GET", - expectAccept: true, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods/foo/exec", - host: "127.0.0.1", - method: "GET", - expectAccept: false, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods/foo/attach", - host: "127.0.0.1", - method: "GET", - expectAccept: false, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "evil.com", - method: "GET", - expectAccept: false, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "localhost.evil.com", - method: "GET", - expectAccept: false, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "127a0b0c1", - method: "GET", - expectAccept: false, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/ui", - host: "localhost", - method: "GET", - expectAccept: true, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods", - host: "localhost", - method: "POST", - expectAccept: false, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods/somepod", - host: "localhost", - method: "PUT", - expectAccept: false, - }, - { - acceptPaths: DefaultPathAcceptRE, - rejectPaths: DefaultPathRejectRE, - acceptHosts: DefaultHostAcceptRE, - path: "/api/v1/pods/somepod", - host: "localhost", - method: "PATCH", - expectAccept: false, - }, - } - for _, test := range tests { - filter := &FilterServer{ - AcceptPaths: MakeRegexpArrayOrDie(test.acceptPaths), - RejectPaths: MakeRegexpArrayOrDie(test.rejectPaths), - AcceptHosts: MakeRegexpArrayOrDie(test.acceptHosts), - RejectMethods: MakeRegexpArrayOrDie(DefaultMethodRejectRE), - } - accept := filter.accept(test.method, test.path, test.host) - if accept != test.expectAccept { - t.Errorf("expected: %v, got %v for %#v", test.expectAccept, accept, test) - } - } -} - -func TestRegexpMatch(t *testing.T) { - tests := []struct { - str string - regexps string - expectMatch bool - }{ - { - str: "foo", - regexps: "bar,.*", - expectMatch: true, - }, - { - str: "foo", - regexps: "bar,fo.*", - expectMatch: true, - }, - { - str: "bar", - regexps: "bar,fo.*", - expectMatch: true, - }, - { - str: "baz", - regexps: "bar,fo.*", - expectMatch: false, - }, - } - for _, test := range tests { - match := matchesRegexp(test.str, MakeRegexpArrayOrDie(test.regexps)) - if test.expectMatch != match { - t.Errorf("expected: %v, found: %v, for %s and %v", test.expectMatch, match, test.str, test.regexps) - } - } -} - -func TestFileServing(t *testing.T) { - const ( - fname = "test.txt" - data = "This is test data" - ) - dir, err := ioutil.TempDir("", "data") - if err != nil { - t.Fatalf("error creating tmp dir: %v", err) - } - if err := ioutil.WriteFile(filepath.Join(dir, fname), []byte(data), 0755); err != nil { - t.Fatalf("error writing tmp file: %v", err) - } - - const prefix = "/foo/" - handler := newFileHandler(prefix, dir) - server := httptest.NewServer(handler) - defer server.Close() - - url := server.URL + prefix + fname - res, err := http.Get(url) - if err != nil { - t.Fatalf("http.Get(%q) error: %v", url, err) - } - defer res.Body.Close() - - if res.StatusCode != http.StatusOK { - t.Errorf("res.StatusCode = %d; want %d", res.StatusCode, http.StatusOK) - } - b, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("error reading resp body: %v", err) - } - if string(b) != data { - t.Errorf("have %q; want %q", string(b), data) - } -} - -func TestAPIRequests(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - b, err := ioutil.ReadAll(r.Body) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - fmt.Fprintf(w, "%s %s %s", r.Method, r.RequestURI, string(b)) - })) - defer ts.Close() - - // httptest.NewServer should always generate a valid URL. - target, _ := url.Parse(ts.URL) - proxy := newProxy(target) - - tests := []struct{ method, body string }{ - {"GET", ""}, - {"DELETE", ""}, - {"POST", "test payload"}, - {"PUT", "test payload"}, - } - - const path = "/api/test?fields=ID%3Dfoo&labels=key%3Dvalue" - for i, tt := range tests { - r, err := http.NewRequest(tt.method, path, strings.NewReader(tt.body)) - if err != nil { - t.Errorf("error creating request: %v", err) - continue - } - w := httptest.NewRecorder() - proxy.ServeHTTP(w, r) - if w.Code != http.StatusOK { - t.Errorf("%d: proxy.ServeHTTP w.Code = %d; want %d", i, w.Code, http.StatusOK) - } - want := strings.Join([]string{tt.method, path, tt.body}, " ") - if w.Body.String() != want { - t.Errorf("%d: response body = %q; want %q", i, w.Body.String(), want) - } - } -} - -func TestPathHandling(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, r.URL.Path) - })) - defer ts.Close() - - table := []struct { - prefix string - reqPath string - expectPath string - }{ - {"/api/", "/metrics", "404 page not found\n"}, - {"/api/", "/api/metrics", "/api/metrics"}, - {"/api/", "/api/v1/pods/", "/api/v1/pods/"}, - {"/", "/metrics", "/metrics"}, - {"/", "/api/v1/pods/", "/api/v1/pods/"}, - {"/custom/", "/metrics", "404 page not found\n"}, - {"/custom/", "/api/metrics", "404 page not found\n"}, - {"/custom/", "/api/v1/pods/", "404 page not found\n"}, - {"/custom/", "/custom/api/metrics", "/api/metrics"}, - {"/custom/", "/custom/api/v1/pods/", "/api/v1/pods/"}, - } - - cc := &restclient.Config{ - Host: ts.URL, - } - - for _, item := range table { - func() { - p, err := NewProxyServer("", item.prefix, "/not/used/for/this/test", nil, cc) - if err != nil { - t.Fatalf("%#v: %v", item, err) - } - pts := httptest.NewServer(p.handler) - defer pts.Close() - - r, err := http.Get(pts.URL + item.reqPath) - if err != nil { - t.Fatalf("%#v: %v", item, err) - } - body, err := ioutil.ReadAll(r.Body) - r.Body.Close() - if err != nil { - t.Fatalf("%#v: %v", item, err) - } - if e, a := item.expectPath, string(body); e != a { - t.Errorf("%#v: Wanted %q, got %q", item, e, a) - } - }() - } -} - -func TestExtractHost(t *testing.T) { - fixtures := map[string]string{ - "localhost:8085": "localhost", - "marmalade": "marmalade", - } - for header, expected := range fixtures { - host := extractHost(header) - if host != expected { - t.Fatalf("%s != %s", host, expected) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource/builder_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource/builder_test.go deleted file mode 100644 index 15abe6fe8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource/builder_test.go +++ /dev/null @@ -1,1243 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 resource - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "reflect" - "strings" - "testing" - - "github.com/ghodss/yaml" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/streaming" - utilerrors "k8s.io/kubernetes/pkg/util/errors" - utiltesting "k8s.io/kubernetes/pkg/util/testing" - "k8s.io/kubernetes/pkg/watch" - "k8s.io/kubernetes/pkg/watch/versioned" -) - -func stringBody(body string) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(body))) -} - -func watchBody(events ...watch.Event) string { - buf := &bytes.Buffer{} - codec := testapi.Default.Codec() - enc := versioned.NewEncoder(streaming.NewEncoder(buf, codec), codec) - for _, e := range events { - enc.Encode(&e) - } - return buf.String() -} - -func fakeClient() ClientMapper { - return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) { - return &fake.RESTClient{}, nil - }) -} - -func fakeClientWith(testName string, t *testing.T, data map[string]string) ClientMapper { - return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) { - return &fake.RESTClient{ - Codec: testapi.Default.Codec(), - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - p := req.URL.Path - q := req.URL.RawQuery - if len(q) != 0 { - p = p + "?" + q - } - body, ok := data[p] - if !ok { - t.Fatalf("%s: unexpected request: %s (%s)\n%#v", testName, p, req.URL, req) - } - return &http.Response{ - StatusCode: http.StatusOK, - Body: stringBody(body), - }, nil - }), - }, nil - }) -} - -func testData() (*api.PodList, *api.ServiceList) { - pods := &api.PodList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "15", - }, - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "10"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "11"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - svc := &api.ServiceList{ - ListMeta: unversioned.ListMeta{ - ResourceVersion: "16", - }, - Items: []api.Service{ - { - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"}, - Spec: api.ServiceSpec{ - Type: "ClusterIP", - SessionAffinity: "None", - }, - }, - }, - } - return pods, svc -} - -func streamTestData() (io.Reader, *api.PodList, *api.ServiceList) { - pods, svc := testData() - r, w := io.Pipe() - go func() { - defer w.Close() - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), pods))) - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), svc))) - }() - return r, pods, svc -} - -func JSONToYAMLOrDie(in []byte) []byte { - data, err := yaml.JSONToYAML(in) - if err != nil { - panic(err) - } - return data -} - -func streamYAMLTestData() (io.Reader, *api.PodList, *api.ServiceList) { - pods, svc := testData() - r, w := io.Pipe() - go func() { - defer w.Close() - w.Write(JSONToYAMLOrDie([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), pods)))) - w.Write([]byte("\n---\n")) - w.Write(JSONToYAMLOrDie([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), svc)))) - }() - return r, pods, svc -} - -func streamTestObject(obj runtime.Object) io.Reader { - r, w := io.Pipe() - go func() { - defer w.Close() - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), obj))) - }() - return r -} - -type testVisitor struct { - InjectErr error - Infos []*Info -} - -func (v *testVisitor) Handle(info *Info, err error) error { - if err != nil { - return err - } - v.Infos = append(v.Infos, info) - return v.InjectErr -} - -func (v *testVisitor) Objects() []runtime.Object { - objects := []runtime.Object{} - for i := range v.Infos { - objects = append(objects, v.Infos[i].Object) - } - return objects -} - -var aPod string = ` -{ - "kind": "Pod", - "apiVersion": "` + testapi.Default.GroupVersion().String() + `", - "metadata": { - "name": "busybox{id}", - "labels": { - "name": "busybox{id}" - } - }, - "spec": { - "containers": [ - { - "name": "busybox", - "image": "busybox", - "command": [ - "sleep", - "3600" - ], - "imagePullPolicy": "IfNotPresent" - } - ], - "restartPolicy": "Always" - } -} -` - -var aRC string = ` -{ - "kind": "ReplicationController", - "apiVersion": "` + testapi.Default.GroupVersion().String() + `", - "metadata": { - "name": "busybox{id}", - "labels": { - "app": "busybox" - } - }, - "spec": { - "replicas": 1, - "template": { - "metadata": { - "name": "busybox{id}", - "labels": { - "app": "busybox{id}" - } - }, - "spec": { - "containers": [ - { - "name": "busybox", - "image": "busybox", - "command": [ - "sleep", - "3600" - ], - "imagePullPolicy": "IfNotPresent" - } - ], - "restartPolicy": "Always" - } - } - } -} -` - -func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) { - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, "../../../docs/user-guide/update-demo/kitten-rc.yaml") - - test := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || !singular || len(test.Infos) != 1 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - - info := test.Infos[0] - if info.Name != "update-demo-kitten" || info.Namespace != "" || info.Object == nil { - t.Errorf("unexpected info: %#v", info) - } - version, ok := info.VersionedObject.(*v1.ReplicationController) - // versioned object does not have defaulting applied - if info.VersionedObject == nil || !ok || version.Spec.Replicas != nil { - t.Errorf("unexpected versioned object: %#v", info.VersionedObject) - } -} - -func TestNodeBuilder(t *testing.T) { - node := &api.Node{ - ObjectMeta: api.ObjectMeta{Name: "node1", Namespace: "should-not-have", ResourceVersion: "10"}, - Spec: api.NodeSpec{}, - Status: api.NodeStatus{ - Capacity: api.ResourceList{ - api.ResourceCPU: resource.MustParse("1000m"), - api.ResourceMemory: resource.MustParse("1Mi"), - }, - }, - } - r, w := io.Pipe() - go func() { - defer w.Close() - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), node))) - }() - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").Stream(r, "STDIN") - - test := &testVisitor{} - - err := b.Do().Visit(test.Handle) - if err != nil || len(test.Infos) != 1 { - t.Fatalf("unexpected response: %v %#v", err, test.Infos) - } - info := test.Infos[0] - if info.Name != "node1" || info.Namespace != "" || info.Object == nil { - t.Errorf("unexpected info: %#v", info) - } -} - -func createTestDir(t *testing.T, path string) { - if err := os.MkdirAll(path, 0750); err != nil { - t.Fatalf("error creating test dir: %v", err) - } -} - -func writeTestFile(t *testing.T, path string, contents string) { - if err := ioutil.WriteFile(path, []byte(contents), 0644); err != nil { - t.Fatalf("error creating test file %#v", err) - } -} - -func TestPathBuilderWithMultiple(t *testing.T) { - // create test dirs - tmpDir, err := utiltesting.MkTmpdir("recursive_test_multiple") - if err != nil { - t.Fatalf("error creating temp dir: %v", err) - } - createTestDir(t, fmt.Sprintf("%s/%s", tmpDir, "recursive/pod/pod_1")) - createTestDir(t, fmt.Sprintf("%s/%s", tmpDir, "recursive/rc/rc_1")) - createTestDir(t, fmt.Sprintf("%s/%s", tmpDir, "inode/hardlink")) - defer os.RemoveAll(tmpDir) - - // create test files - writeTestFile(t, fmt.Sprintf("%s/recursive/pod/busybox.json", tmpDir), strings.Replace(aPod, "{id}", "0", -1)) - writeTestFile(t, fmt.Sprintf("%s/recursive/pod/pod_1/busybox.json", tmpDir), strings.Replace(aPod, "{id}", "1", -1)) - writeTestFile(t, fmt.Sprintf("%s/recursive/rc/busybox.json", tmpDir), strings.Replace(aRC, "{id}", "0", -1)) - writeTestFile(t, fmt.Sprintf("%s/recursive/rc/rc_1/busybox.json", tmpDir), strings.Replace(aRC, "{id}", "1", -1)) - writeTestFile(t, fmt.Sprintf("%s/inode/hardlink/busybox.json", tmpDir), strings.Replace(aPod, "{id}", "0", -1)) - if err := os.Link(fmt.Sprintf("%s/inode/hardlink/busybox.json", tmpDir), fmt.Sprintf("%s/inode/hardlink/busybox-link.json", tmpDir)); err != nil { - t.Fatalf("error creating test file: %v", err) - } - - tests := []struct { - name string - object runtime.Object - recursive bool - directory string - expectedNames []string - }{ - {"pod", &api.Pod{}, false, "../../../examples/pod", []string{"nginx"}}, - {"recursive-pod", &api.Pod{}, true, fmt.Sprintf("%s/recursive/pod", tmpDir), []string{"busybox0", "busybox1"}}, - {"rc", &api.ReplicationController{}, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml", []string{"redis-master"}}, - {"recursive-rc", &api.ReplicationController{}, true, fmt.Sprintf("%s/recursive/rc", tmpDir), []string{"busybox0", "busybox1"}}, - {"hardlink", &api.Pod{}, false, fmt.Sprintf("%s/inode/hardlink/busybox-link.json", tmpDir), []string{"busybox0"}}, - {"hardlink", &api.Pod{}, true, fmt.Sprintf("%s/inode/hardlink/busybox-link.json", tmpDir), []string{"busybox0"}}, - } - - for _, test := range tests { - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, test.recursive, test.directory). - NamespaceParam("test").DefaultNamespace() - - testVisitor := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(testVisitor.Handle) - if err != nil { - t.Fatalf("unexpected response: %v %t %#v %s", err, singular, testVisitor.Infos, test.name) - } - - info := testVisitor.Infos - - for i, v := range info { - switch test.object.(type) { - case *api.Pod: - if _, ok := v.Object.(*api.Pod); !ok || v.Name != test.expectedNames[i] || v.Namespace != "test" { - t.Errorf("unexpected info: %#v", v) - } - case *api.ReplicationController: - if _, ok := v.Object.(*api.ReplicationController); !ok || v.Name != test.expectedNames[i] || v.Namespace != "test" { - t.Errorf("unexpected info: %#v", v) - } - } - } - } -} - -func TestPathBuilderWithMultipleInvalid(t *testing.T) { - // create test dirs - tmpDir, err := utiltesting.MkTmpdir("recursive_test_multiple_invalid") - if err != nil { - t.Fatalf("error creating temp dir: %v", err) - } - createTestDir(t, fmt.Sprintf("%s/%s", tmpDir, "inode/symlink/pod")) - defer os.RemoveAll(tmpDir) - - // create test files - writeTestFile(t, fmt.Sprintf("%s/inode/symlink/pod/busybox.json", tmpDir), strings.Replace(aPod, "{id}", "0", -1)) - if err := os.Symlink(fmt.Sprintf("%s/inode/symlink/pod", tmpDir), fmt.Sprintf("%s/inode/symlink/pod-link", tmpDir)); err != nil { - t.Fatalf("error creating test file: %v", err) - } - if err := os.Symlink(fmt.Sprintf("%s/inode/symlink/loop", tmpDir), fmt.Sprintf("%s/inode/symlink/loop", tmpDir)); err != nil { - t.Fatalf("error creating test file: %v", err) - } - - tests := []struct { - name string - recursive bool - directory string - }{ - {"symlink", false, fmt.Sprintf("%s/inode/symlink/pod-link", tmpDir)}, - {"symlink", true, fmt.Sprintf("%s/inode/symlink/pod-link", tmpDir)}, - {"loop", false, fmt.Sprintf("%s/inode/symlink/loop", tmpDir)}, - {"loop", true, fmt.Sprintf("%s/inode/symlink/loop", tmpDir)}, - } - - for _, test := range tests { - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, test.recursive, test.directory). - NamespaceParam("test").DefaultNamespace() - - testVisitor := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(testVisitor.Handle) - if err == nil { - t.Fatalf("unexpected response: %v %t %#v %s", err, singular, testVisitor.Infos, test.name) - } - } -} - -func TestDirectoryBuilder(t *testing.T) { - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, "../../../examples/guestbook/legacy"). - NamespaceParam("test").DefaultNamespace() - - test := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || singular || len(test.Infos) < 3 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - - found := false - for _, info := range test.Infos { - if info.Name == "redis-master" && info.Namespace == "test" && info.Object != nil { - found = true - } - } - if !found { - t.Errorf("unexpected responses: %#v", test.Infos) - } -} - -func TestNamespaceOverride(t *testing.T) { - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) - })) - defer s.Close() - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, s.URL). - NamespaceParam("test") - - test := &testVisitor{} - - err := b.Do().Visit(test.Handle) - if err != nil || len(test.Infos) != 1 && test.Infos[0].Namespace != "foo" { - t.Fatalf("unexpected response: %v %#v", err, test.Infos) - } - - b = NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(true, false, s.URL). - NamespaceParam("test") - - test = &testVisitor{} - - err = b.Do().Visit(test.Handle) - if err == nil { - t.Fatalf("expected namespace error. got: %#v", test.Infos) - } -} - -func TestURLBuilder(t *testing.T) { - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test1"}}))) - })) - defer s.Close() - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, s.URL). - NamespaceParam("foo") - - test := &testVisitor{} - - err := b.Do().Visit(test.Handle) - if err != nil || len(test.Infos) != 2 { - t.Fatalf("unexpected response: %v %#v", err, test.Infos) - } - info := test.Infos[0] - if info.Name != "test" || info.Namespace != "foo" || info.Object == nil { - t.Errorf("unexpected info: %#v", info) - } - - info = test.Infos[1] - if info.Name != "test1" || info.Namespace != "foo" || info.Object == nil { - t.Errorf("unexpected info: %#v", info) - } - -} - -func TestURLBuilderRequireNamespace(t *testing.T) { - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: "foo", Name: "test"}}))) - })) - defer s.Close() - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - FilenameParam(false, false, s.URL). - NamespaceParam("test").RequireNamespace() - - test := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err == nil || !singular || len(test.Infos) != 0 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } -} - -func TestResourceByName(t *testing.T) { - pods, _ := testData() - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), - }), testapi.Default.Codec()). - NamespaceParam("test") - - test := &testVisitor{} - singular := false - - if b.Do().Err() == nil { - t.Errorf("unexpected non-error") - } - - b.ResourceTypeOrNameArgs(true, "pods", "foo") - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || !singular || len(test.Infos) != 1 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - if !reflect.DeepEqual(&pods.Items[0], test.Objects()[0]) { - t.Errorf("unexpected object: %#v", test.Objects()[0]) - } - - mapping, err := b.Do().ResourceMapping() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if mapping.Resource != "pods" { - t.Errorf("unexpected resource mapping: %#v", mapping) - } -} - -func TestMultipleResourceByTheSameName(t *testing.T) { - pods, svcs := testData() - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), - "/namespaces/test/pods/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[1]), - "/namespaces/test/services/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &svcs.Items[0]), - "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svcs.Items[0]), - }), testapi.Default.Codec()). - NamespaceParam("test") - - test := &testVisitor{} - singular := false - - if b.Do().Err() == nil { - t.Errorf("unexpected non-error") - } - - b.ResourceTypeOrNameArgs(true, "pods,services", "foo", "baz") - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || singular || len(test.Infos) != 4 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svcs.Items[0], &svcs.Items[0]}, test.Objects()) { - t.Errorf("unexpected visited objects: %#v", test.Objects()) - } - - if _, err := b.Do().ResourceMapping(); err == nil { - t.Errorf("unexpected non-error") - } -} - -func TestResourceNames(t *testing.T) { - pods, svc := testData() - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), - "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]), - }), testapi.Default.Codec()). - NamespaceParam("test") - - test := &testVisitor{} - - if b.Do().Err() == nil { - t.Errorf("unexpected non-error") - } - - b.ResourceNames("pods", "foo", "services/baz") - - err := b.Do().Visit(test.Handle) - if err != nil || len(test.Infos) != 2 { - t.Fatalf("unexpected response: %v %#v", err, test.Infos) - } - if !reflect.DeepEqual(&pods.Items[0], test.Objects()[0]) { - t.Errorf("unexpected object: \n%#v, expected: \n%#v", test.Objects()[0], &pods.Items[0]) - } - if !reflect.DeepEqual(&svc.Items[0], test.Objects()[1]) { - t.Errorf("unexpected object: \n%#v, expected: \n%#v", test.Objects()[1], &svc.Items[0]) - } -} - -func TestResourceByNameWithoutRequireObject(t *testing.T) { - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{}), testapi.Default.Codec()). - NamespaceParam("test") - - test := &testVisitor{} - singular := false - - if b.Do().Err() == nil { - t.Errorf("unexpected non-error") - } - - b.ResourceTypeOrNameArgs(true, "pods", "foo").RequireObject(false) - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || !singular || len(test.Infos) != 1 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - if test.Infos[0].Name != "foo" { - t.Errorf("unexpected name: %#v", test.Infos[0].Name) - } - if test.Infos[0].Object != nil { - t.Errorf("unexpected object: %#v", test.Infos[0].Object) - } - - mapping, err := b.Do().ResourceMapping() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if mapping.GroupVersionKind.Kind != "Pod" || mapping.Resource != "pods" { - t.Errorf("unexpected resource mapping: %#v", mapping) - } -} - -func TestResourceByNameAndEmptySelector(t *testing.T) { - pods, _ := testData() - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), - }), testapi.Default.Codec()). - NamespaceParam("test"). - SelectorParam(""). - ResourceTypeOrNameArgs(true, "pods", "foo") - - singular := false - infos, err := b.Do().IntoSingular(&singular).Infos() - if err != nil || !singular || len(infos) != 1 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, infos) - } - if !reflect.DeepEqual(&pods.Items[0], infos[0].Object) { - t.Errorf("unexpected object: %#v", infos[0]) - } - - mapping, err := b.Do().ResourceMapping() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if mapping.Resource != "pods" { - t.Errorf("unexpected resource mapping: %#v", mapping) - } -} - -func TestSelector(t *testing.T) { - pods, svc := testData() - labelKey := unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), - "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), - }), testapi.Default.Codec()). - SelectorParam("a=b"). - NamespaceParam("test"). - Flatten() - - test := &testVisitor{} - singular := false - - if b.Do().Err() == nil { - t.Errorf("unexpected non-error") - } - - b.ResourceTypeOrNameArgs(true, "pods,service") - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || singular || len(test.Infos) != 3 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svc.Items[0]}, test.Objects()) { - t.Errorf("unexpected visited objects: %#v", test.Objects()) - } - - if _, err := b.Do().ResourceMapping(); err == nil { - t.Errorf("unexpected non-error") - } -} - -func TestSelectorRequiresKnownTypes(t *testing.T) { - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - SelectorParam("a=b"). - NamespaceParam("test"). - ResourceTypes("unknown") - - if b.Do().Err() == nil { - t.Errorf("unexpected non-error") - } -} - -func TestSingleResourceType(t *testing.T) { - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - SelectorParam("a=b"). - SingleResourceType(). - ResourceTypeOrNameArgs(true, "pods,services") - - if b.Do().Err() == nil { - t.Errorf("unexpected non-error") - } -} - -func TestResourceTuple(t *testing.T) { - expectNoErr := func(err error) bool { return err == nil } - expectErr := func(err error) bool { return err != nil } - testCases := map[string]struct { - args []string - errFn func(error) bool - }{ - "valid": { - args: []string{"pods/foo"}, - errFn: expectNoErr, - }, - "valid multiple with name indirection": { - args: []string{"pods/foo", "pod/bar"}, - errFn: expectNoErr, - }, - "valid multiple with namespaced and non-namespaced types": { - args: []string{"nodes/foo", "pod/bar"}, - errFn: expectNoErr, - }, - "mixed arg types": { - args: []string{"pods/foo", "bar"}, - errFn: expectErr, - }, - /*"missing resource": { - args: []string{"pods/foo2"}, - errFn: expectNoErr, // not an error because resources are lazily visited - },*/ - "comma in resource": { - args: []string{",pods/foo"}, - errFn: expectErr, - }, - "multiple types in resource": { - args: []string{"pods,services/foo"}, - errFn: expectErr, - }, - "unknown resource type": { - args: []string{"unknown/foo"}, - errFn: expectErr, - }, - "leading slash": { - args: []string{"/bar"}, - errFn: expectErr, - }, - "trailing slash": { - args: []string{"bar/"}, - errFn: expectErr, - }, - } - for k, testCase := range testCases { - for _, requireObject := range []bool{true, false} { - expectedRequests := map[string]string{} - if requireObject { - pods, _ := testData() - expectedRequests = map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), - "/namespaces/test/pods/bar": runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]), - "/nodes/foo": runtime.EncodeOrDie(testapi.Default.Codec(), &api.Node{ObjectMeta: api.ObjectMeta{Name: "foo"}}), - } - } - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith(k, t, expectedRequests), testapi.Default.Codec()). - NamespaceParam("test").DefaultNamespace(). - ResourceTypeOrNameArgs(true, testCase.args...).RequireObject(requireObject) - - r := b.Do() - - if !testCase.errFn(r.Err()) { - t.Errorf("%s: unexpected error: %v", k, r.Err()) - } - if r.Err() != nil { - continue - } - switch { - case (r.singular && len(testCase.args) != 1), - (!r.singular && len(testCase.args) == 1): - t.Errorf("%s: result had unexpected singular value", k) - } - info, err := r.Infos() - if err != nil { - // test error - continue - } - if len(info) != len(testCase.args) { - t.Errorf("%s: unexpected number of infos returned: %#v", k, info) - } - } - } -} - -func TestStream(t *testing.T) { - r, pods, rc := streamTestData() - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").Stream(r, "STDIN").Flatten() - - test := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || singular || len(test.Infos) != 3 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &rc.Items[0]}, test.Objects()) { - t.Errorf("unexpected visited objects: %#v", test.Objects()) - } -} - -func TestYAMLStream(t *testing.T) { - r, pods, rc := streamYAMLTestData() - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").Stream(r, "STDIN").Flatten() - - test := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || singular || len(test.Infos) != 3 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &rc.Items[0]}, test.Objects()) { - t.Errorf("unexpected visited objects: %#v", test.Objects()) - } -} - -func TestMultipleObject(t *testing.T) { - r, pods, svc := streamTestData() - obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").Stream(r, "STDIN").Flatten(). - Do().Object() - - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - expected := &api.List{ - Items: []runtime.Object{ - &pods.Items[0], - &pods.Items[1], - &svc.Items[0], - }, - } - if !api.Semantic.DeepDerivative(expected, obj) { - t.Errorf("unexpected visited objects: %#v", obj) - } -} - -func TestContinueOnErrorVisitor(t *testing.T) { - r, _, _ := streamTestData() - req := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - ContinueOnError(). - NamespaceParam("test").Stream(r, "STDIN").Flatten(). - Do() - count := 0 - testErr := fmt.Errorf("test error") - err := req.Visit(func(_ *Info, _ error) error { - count++ - if count > 1 { - return testErr - } - return nil - }) - if err == nil { - t.Fatalf("unexpected error: %v", err) - } - if count != 3 { - t.Fatalf("did not visit all infos: %d", count) - } - agg, ok := err.(utilerrors.Aggregate) - if !ok { - t.Fatalf("unexpected error: %v", err) - } - if len(agg.Errors()) != 2 || agg.Errors()[0] != testErr || agg.Errors()[1] != testErr { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestSingularObject(t *testing.T) { - obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml"). - Flatten(). - Do().Object() - - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - rc, ok := obj.(*api.ReplicationController) - if !ok { - t.Fatalf("unexpected object: %#v", obj) - } - if rc.Name != "redis-master" || rc.Namespace != "test" { - t.Errorf("unexpected controller: %#v", rc) - } -} - -func TestSingularObjectNoExtension(t *testing.T) { - obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/pod"). - Flatten(). - Do().Object() - - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - pod, ok := obj.(*api.Pod) - if !ok { - t.Fatalf("unexpected object: %#v", obj) - } - if pod.Name != "nginx" || pod.Namespace != "test" { - t.Errorf("unexpected pod: %#v", pod) - } -} - -func TestSingularRootScopedObject(t *testing.T) { - node := &api.Node{ObjectMeta: api.ObjectMeta{Name: "test"}, Spec: api.NodeSpec{ExternalID: "test"}} - r := streamTestObject(node) - infos, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").DefaultNamespace(). - Stream(r, "STDIN"). - Flatten(). - Do().Infos() - - if err != nil || len(infos) != 1 { - t.Fatalf("unexpected error: %v", err) - } - - if infos[0].Namespace != "" { - t.Errorf("namespace should be empty: %#v", infos[0]) - } - n, ok := infos[0].Object.(*api.Node) - if !ok { - t.Fatalf("unexpected object: %#v", infos[0].Object) - } - if n.Name != "test" || n.Namespace != "" { - t.Errorf("unexpected object: %#v", n) - } -} - -func TestListObject(t *testing.T) { - pods, _ := testData() - labelKey := unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), - }), testapi.Default.Codec()). - SelectorParam("a=b"). - NamespaceParam("test"). - ResourceTypeOrNameArgs(true, "pods"). - Flatten() - - obj, err := b.Do().Object() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - list, ok := obj.(*api.List) - if !ok { - t.Fatalf("unexpected object: %#v", obj) - } - if list.ResourceVersion != pods.ResourceVersion || len(list.Items) != 2 { - t.Errorf("unexpected list: %#v", list) - } - - mapping, err := b.Do().ResourceMapping() - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if mapping.Resource != "pods" { - t.Errorf("unexpected resource mapping: %#v", mapping) - } -} - -func TestListObjectWithDifferentVersions(t *testing.T) { - pods, svc := testData() - labelKey := unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()) - obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), - "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), - }), testapi.Default.Codec()). - SelectorParam("a=b"). - NamespaceParam("test"). - ResourceTypeOrNameArgs(true, "pods,services"). - Flatten(). - Do().Object() - - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - list, ok := obj.(*api.List) - if !ok { - t.Fatalf("unexpected object: %#v", obj) - } - // resource version differs between type lists, so it's not possible to get a single version. - if list.ResourceVersion != "" || len(list.Items) != 3 { - t.Errorf("unexpected list: %#v", list) - } -} - -func TestWatch(t *testing.T) { - _, svc := testData() - w, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/watch/namespaces/test/services/redis-master?resourceVersion=12": watchBody(watch.Event{ - Type: watch.Added, - Object: &svc.Items[0], - }), - }), testapi.Default.Codec()). - NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/guestbook/redis-master-service.yaml").Flatten(). - Do().Watch("12") - - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - defer w.Stop() - ch := w.ResultChan() - select { - case obj := <-ch: - if obj.Type != watch.Added { - t.Fatalf("unexpected watch event %#v", obj) - } - service, ok := obj.Object.(*api.Service) - if !ok { - t.Fatalf("unexpected object: %#v", obj) - } - if service.Name != "baz" || service.ResourceVersion != "12" { - t.Errorf("unexpected service: %#v", service) - } - } -} - -func TestWatchMultipleError(t *testing.T) { - _, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - NamespaceParam("test").DefaultNamespace(). - FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml").Flatten(). - FilenameParam(false, false, "../../../examples/guestbook/legacy/redis-master-controller.yaml").Flatten(). - Do().Watch("") - - if err == nil { - t.Fatalf("unexpected non-error") - } -} - -func TestLatest(t *testing.T) { - r, _, _ := streamTestData() - newPod := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "13"}, - } - newPod2 := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "test", ResourceVersion: "14"}, - } - newSvc := &api.Service{ - ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "15"}, - } - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ - "/namespaces/test/pods/foo": runtime.EncodeOrDie(testapi.Default.Codec(), newPod), - "/namespaces/test/pods/bar": runtime.EncodeOrDie(testapi.Default.Codec(), newPod2), - "/namespaces/test/services/baz": runtime.EncodeOrDie(testapi.Default.Codec(), newSvc), - }), testapi.Default.Codec()). - NamespaceParam("other").Stream(r, "STDIN").Flatten().Latest() - - test := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err != nil || singular || len(test.Infos) != 3 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - if !api.Semantic.DeepDerivative([]runtime.Object{newPod, newPod2, newSvc}, test.Objects()) { - t.Errorf("unexpected visited objects: %#v", test.Objects()) - } -} - -func TestReceiveMultipleErrors(t *testing.T) { - pods, svc := testData() - - r, w := io.Pipe() - go func() { - defer w.Close() - w.Write([]byte(`{}`)) - w.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &pods.Items[0]))) - }() - - r2, w2 := io.Pipe() - go func() { - defer w2.Close() - w2.Write([]byte(`{}`)) - w2.Write([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), &svc.Items[0]))) - }() - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()). - Stream(r, "1").Stream(r2, "2"). - ContinueOnError() - - test := &testVisitor{} - singular := false - - err := b.Do().IntoSingular(&singular).Visit(test.Handle) - if err == nil || singular || len(test.Infos) != 2 { - t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) - } - - errs, ok := err.(utilerrors.Aggregate) - if !ok { - t.Fatalf("unexpected error: %v", reflect.TypeOf(err)) - } - if len(errs.Errors()) != 2 { - t.Errorf("unexpected errors %v", errs) - } -} - -func TestReplaceAliases(t *testing.T) { - tests := []struct { - name string - arg string - expected string - }{ - { - name: "no-replacement", - arg: "service", - expected: "service", - }, - { - name: "all-replacement", - arg: "all", - expected: "rc,svc,pods,pvc", - }, - { - name: "alias-in-comma-separated-arg", - arg: "all,secrets", - expected: "rc,svc,pods,pvc,secrets", - }, - } - - b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClient(), testapi.Default.Codec()) - - for _, test := range tests { - replaced := b.replaceAliases(test.arg) - if replaced != test.expected { - t.Errorf("%s: unexpected argument: expected %s, got %s", test.name, test.expected, replaced) - } - } -} - -func TestHasNames(t *testing.T) { - tests := []struct { - args []string - expectedHasName bool - expectedError error - }{ - { - args: []string{""}, - expectedHasName: false, - expectedError: nil, - }, - { - args: []string{"rc"}, - expectedHasName: false, - expectedError: nil, - }, - { - args: []string{"rc,pod,svc"}, - expectedHasName: false, - expectedError: nil, - }, - { - args: []string{"rc/foo"}, - expectedHasName: true, - expectedError: nil, - }, - { - args: []string{"rc", "foo"}, - expectedHasName: true, - expectedError: nil, - }, - { - args: []string{"rc,pod,svc", "foo"}, - expectedHasName: true, - expectedError: nil, - }, - { - args: []string{"rc/foo", "rc/bar", "rc/zee"}, - expectedHasName: true, - expectedError: nil, - }, - { - args: []string{"rc/foo", "bar"}, - expectedHasName: false, - expectedError: fmt.Errorf("when passing arguments in resource/name form, all arguments must include the resource"), - }, - } - for _, test := range tests { - hasNames, err := HasNames(test.args) - if !reflect.DeepEqual(test.expectedError, err) { - t.Errorf("expected HasName to error %v, got %s", test.expectedError, err) - } - if hasNames != test.expectedHasName { - t.Errorf("expected HasName to return %v for %s", test.expectedHasName, test.args) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource/helper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource/helper_test.go deleted file mode 100644 index bfb05f7f7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource/helper_test.go +++ /dev/null @@ -1,498 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 resource - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - "net/http" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" -) - -func objBody(obj runtime.Object) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), obj)))) -} - -// splitPath returns the segments for a URL path. -func splitPath(path string) []string { - path = strings.Trim(path, "/") - if path == "" { - return []string{} - } - return strings.Split(path, "/") -} - -func TestHelperDelete(t *testing.T) { - tests := []struct { - Err bool - Req func(*http.Request) bool - Resp *http.Response - HttpErr error - }{ - { - HttpErr: errors.New("failure"), - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusNotFound, - Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), - }, - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusOK, - Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess}), - }, - Req: func(req *http.Request) bool { - if req.Method != "DELETE" { - t.Errorf("unexpected method: %#v", req) - return false - } - parts := splitPath(req.URL.Path) - if len(parts) < 3 { - t.Errorf("expected URL path to have 3 parts: %s", req.URL.Path) - return false - } - if parts[1] != "bar" { - t.Errorf("url doesn't contain namespace: %#v", req) - return false - } - if parts[2] != "foo" { - t.Errorf("url doesn't contain name: %#v", req) - return false - } - return true - }, - }, - } - for _, test := range tests { - client := &fake.RESTClient{ - Codec: testapi.Default.Codec(), - Resp: test.Resp, - Err: test.HttpErr, - } - modifier := &Helper{ - RESTClient: client, - NamespaceScoped: true, - } - err := modifier.Delete("bar", "foo") - if (err != nil) != test.Err { - t.Errorf("unexpected error: %t %v", test.Err, err) - } - if err != nil { - continue - } - if test.Req != nil && !test.Req(client.Req) { - t.Errorf("unexpected request: %#v", client.Req) - } - } -} - -func TestHelperCreate(t *testing.T) { - expectPost := func(req *http.Request) bool { - if req.Method != "POST" { - t.Errorf("unexpected method: %#v", req) - return false - } - parts := splitPath(req.URL.Path) - if parts[1] != "bar" { - t.Errorf("url doesn't contain namespace: %#v", req) - return false - } - return true - } - - tests := []struct { - Resp *http.Response - HttpErr error - Modify bool - Object runtime.Object - - ExpectObject runtime.Object - Err bool - Req func(*http.Request) bool - }{ - { - HttpErr: errors.New("failure"), - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusNotFound, - Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), - }, - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusOK, - Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess}), - }, - Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, - ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, - Req: expectPost, - }, - { - Modify: false, - Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, - ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, - Resp: &http.Response{StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, - Req: expectPost, - }, - { - Modify: true, - Object: &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - ExpectObject: &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - Resp: &http.Response{StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, - Req: expectPost, - }, - } - for i, test := range tests { - client := &fake.RESTClient{ - Codec: testapi.Default.Codec(), - Resp: test.Resp, - Err: test.HttpErr, - } - modifier := &Helper{ - RESTClient: client, - Versioner: testapi.Default.MetadataAccessor(), - NamespaceScoped: true, - } - _, err := modifier.Create("bar", test.Modify, test.Object) - if (err != nil) != test.Err { - t.Errorf("%d: unexpected error: %t %v", i, test.Err, err) - } - if err != nil { - continue - } - if test.Req != nil && !test.Req(client.Req) { - t.Errorf("%d: unexpected request: %#v", i, client.Req) - } - body, err := ioutil.ReadAll(client.Req.Body) - if err != nil { - t.Fatalf("%d: unexpected error: %#v", i, err) - } - t.Logf("got body: %s", string(body)) - expect := []byte{} - if test.ExpectObject != nil { - expect = []byte(runtime.EncodeOrDie(testapi.Default.Codec(), test.ExpectObject)) - } - if !reflect.DeepEqual(expect, body) { - t.Errorf("%d: unexpected body: %s (expected %s)", i, string(body), string(expect)) - } - - } -} - -func TestHelperGet(t *testing.T) { - tests := []struct { - Err bool - Req func(*http.Request) bool - Resp *http.Response - HttpErr error - }{ - { - HttpErr: errors.New("failure"), - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusNotFound, - Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), - }, - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusOK, - Body: objBody(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), - }, - Req: func(req *http.Request) bool { - if req.Method != "GET" { - t.Errorf("unexpected method: %#v", req) - return false - } - parts := splitPath(req.URL.Path) - if parts[1] != "bar" { - t.Errorf("url doesn't contain namespace: %#v", req) - return false - } - if parts[2] != "foo" { - t.Errorf("url doesn't contain name: %#v", req) - return false - } - return true - }, - }, - } - for _, test := range tests { - client := &fake.RESTClient{ - Codec: testapi.Default.Codec(), - Resp: test.Resp, - Err: test.HttpErr, - } - modifier := &Helper{ - RESTClient: client, - NamespaceScoped: true, - } - obj, err := modifier.Get("bar", "foo", false) - if (err != nil) != test.Err { - t.Errorf("unexpected error: %t %v", test.Err, err) - } - if err != nil { - continue - } - if obj.(*api.Pod).Name != "foo" { - t.Errorf("unexpected object: %#v", obj) - } - if test.Req != nil && !test.Req(client.Req) { - t.Errorf("unexpected request: %#v", client.Req) - } - } -} - -func TestHelperList(t *testing.T) { - tests := []struct { - Err bool - Req func(*http.Request) bool - Resp *http.Response - HttpErr error - }{ - { - HttpErr: errors.New("failure"), - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusNotFound, - Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), - }, - Err: true, - }, - { - Resp: &http.Response{ - StatusCode: http.StatusOK, - Body: objBody(&api.PodList{ - Items: []api.Pod{{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - }, - }, - }), - }, - Req: func(req *http.Request) bool { - if req.Method != "GET" { - t.Errorf("unexpected method: %#v", req) - return false - } - if req.URL.Path != "/namespaces/bar" { - t.Errorf("url doesn't contain name: %#v", req.URL) - return false - } - if req.URL.Query().Get(unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String())) != labels.SelectorFromSet(labels.Set{"foo": "baz"}).String() { - t.Errorf("url doesn't contain query parameters: %#v", req.URL) - return false - } - return true - }, - }, - } - for _, test := range tests { - client := &fake.RESTClient{ - Codec: testapi.Default.Codec(), - Resp: test.Resp, - Err: test.HttpErr, - } - modifier := &Helper{ - RESTClient: client, - NamespaceScoped: true, - } - obj, err := modifier.List("bar", testapi.Default.GroupVersion().String(), labels.SelectorFromSet(labels.Set{"foo": "baz"}), false) - if (err != nil) != test.Err { - t.Errorf("unexpected error: %t %v", test.Err, err) - } - if err != nil { - continue - } - if obj.(*api.PodList).Items[0].Name != "foo" { - t.Errorf("unexpected object: %#v", obj) - } - if test.Req != nil && !test.Req(client.Req) { - t.Errorf("unexpected request: %#v", client.Req) - } - } -} - -func TestHelperReplace(t *testing.T) { - expectPut := func(path string, req *http.Request) bool { - if req.Method != "PUT" { - t.Errorf("unexpected method: %#v", req) - return false - } - if req.URL.Path != path { - t.Errorf("unexpected url: %v", req.URL) - return false - } - return true - } - - tests := []struct { - Resp *http.Response - HTTPClient *http.Client - HttpErr error - Overwrite bool - Object runtime.Object - Namespace string - NamespaceScoped bool - - ExpectPath string - ExpectObject runtime.Object - Err bool - Req func(string, *http.Request) bool - }{ - { - Namespace: "bar", - NamespaceScoped: true, - HttpErr: errors.New("failure"), - Err: true, - }, - { - Namespace: "bar", - NamespaceScoped: true, - Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, - Resp: &http.Response{ - StatusCode: http.StatusNotFound, - Body: objBody(&unversioned.Status{Status: unversioned.StatusFailure}), - }, - Err: true, - }, - { - Namespace: "bar", - NamespaceScoped: true, - Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, - ExpectPath: "/namespaces/bar/foo", - ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, - Resp: &http.Response{ - StatusCode: http.StatusOK, - Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess}), - }, - Req: expectPut, - }, - // namespace scoped resource - { - Namespace: "bar", - NamespaceScoped: true, - Object: &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - ExpectPath: "/namespaces/bar/foo", - ExpectObject: &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - Overwrite: true, - HTTPClient: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.Method == "PUT" { - return &http.Response{StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, nil - } - return &http.Response{StatusCode: http.StatusOK, Body: objBody(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}})}, nil - }), - Req: expectPut, - }, - // cluster scoped resource - { - Object: &api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - }, - ExpectObject: &api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}, - }, - Overwrite: true, - ExpectPath: "/foo", - HTTPClient: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - if req.Method == "PUT" { - return &http.Response{StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, nil - } - return &http.Response{StatusCode: http.StatusOK, Body: objBody(&api.Node{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}})}, nil - }), - Req: expectPut, - }, - { - Namespace: "bar", - NamespaceScoped: true, - Object: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, - ExpectPath: "/namespaces/bar/foo", - ExpectObject: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", ResourceVersion: "10"}}, - Resp: &http.Response{StatusCode: http.StatusOK, Body: objBody(&unversioned.Status{Status: unversioned.StatusSuccess})}, - Req: expectPut, - }, - } - for i, test := range tests { - client := &fake.RESTClient{ - Client: test.HTTPClient, - Codec: testapi.Default.Codec(), - Resp: test.Resp, - Err: test.HttpErr, - } - modifier := &Helper{ - RESTClient: client, - Versioner: testapi.Default.MetadataAccessor(), - NamespaceScoped: test.NamespaceScoped, - } - _, err := modifier.Replace(test.Namespace, "foo", test.Overwrite, test.Object) - if (err != nil) != test.Err { - t.Errorf("%d: unexpected error: %t %v", i, test.Err, err) - } - if err != nil { - continue - } - if test.Req != nil && !test.Req(test.ExpectPath, client.Req) { - t.Errorf("%d: unexpected request: %#v", i, client.Req) - } - body, err := ioutil.ReadAll(client.Req.Body) - if err != nil { - t.Fatalf("%d: unexpected error: %#v", i, err) - } - expect := []byte{} - if test.ExpectObject != nil { - expect = []byte(runtime.EncodeOrDie(testapi.Default.Codec(), test.ExpectObject)) - } - if !reflect.DeepEqual(expect, body) { - t.Errorf("%d: unexpected body: %s", i, string(body)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource_printer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource_printer_test.go deleted file mode 100644 index f0a30edee..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/resource_printer_test.go +++ /dev/null @@ -1,1450 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" - kubectltesting "k8s.io/kubernetes/pkg/kubectl/testing" - "k8s.io/kubernetes/pkg/runtime" - yamlserializer "k8s.io/kubernetes/pkg/runtime/serializer/yaml" - "k8s.io/kubernetes/pkg/util/diff" - "k8s.io/kubernetes/pkg/util/intstr" - "k8s.io/kubernetes/pkg/util/sets" - - "github.com/ghodss/yaml" -) - -func init() { - api.Scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &kubectltesting.TestStruct{}) - api.Scheme.AddKnownTypes(*testapi.Default.GroupVersion(), &kubectltesting.TestStruct{}) -} - -var testData = kubectltesting.TestStruct{ - Key: "testValue", - Map: map[string]int{"TestSubkey": 1}, - StringList: []string{"a", "b", "c"}, - IntList: []int{1, 2, 3}, -} - -func TestVersionedPrinter(t *testing.T) { - original := &kubectltesting.TestStruct{Key: "value"} - p := NewVersionedPrinter( - ResourcePrinterFunc(func(obj runtime.Object, w io.Writer) error { - if obj == original { - t.Fatalf("object should not be identical: %#v", obj) - } - if obj.(*kubectltesting.TestStruct).Key != "value" { - t.Fatalf("object was not converted: %#v", obj) - } - return nil - }), - api.Scheme, - *testapi.Default.GroupVersion(), - ) - if err := p.PrintObj(original, nil); err != nil { - t.Errorf("unexpected error: %v", err) - } -} - -func TestPrintDefault(t *testing.T) { - printer, found, err := GetPrinter("", "") - if err != nil { - t.Fatalf("unexpected error: %#v", err) - } - if found { - t.Errorf("no printer should have been found: %#v / %v", printer, err) - } -} - -type TestPrintType struct { - Data string -} - -func (obj *TestPrintType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -type TestUnknownType struct{} - -func (obj *TestUnknownType) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -func TestPrinter(t *testing.T) { - //test inputs - simpleTest := &TestPrintType{"foo"} - podTest := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - podListTest := &api.PodList{ - Items: []api.Pod{ - {ObjectMeta: api.ObjectMeta{Name: "foo"}}, - {ObjectMeta: api.ObjectMeta{Name: "bar"}}, - }, - } - emptyListTest := &api.PodList{} - testapi, err := api.Scheme.ConvertToVersion(podTest, testapi.Default.GroupVersion().String()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - printerTests := []struct { - Name string - Format string - FormatArgument string - Input runtime.Object - Expect string - }{ - {"test json", "json", "", simpleTest, "{\n \"Data\": \"foo\"\n}\n"}, - {"test yaml", "yaml", "", simpleTest, "Data: foo\n"}, - {"test template", "template", "{{if .id}}{{.id}}{{end}}{{if .metadata.name}}{{.metadata.name}}{{end}}", - podTest, "foo"}, - {"test jsonpath", "jsonpath", "{.metadata.name}", podTest, "foo"}, - {"test jsonpath list", "jsonpath", "{.items[*].metadata.name}", podListTest, "foo bar"}, - {"test jsonpath empty list", "jsonpath", "{.items[*].metadata.name}", emptyListTest, ""}, - {"test name", "name", "", podTest, "pod/foo\n"}, - {"emits versioned objects", "template", "{{.kind}}", testapi, "Pod"}, - } - for _, test := range printerTests { - buf := bytes.NewBuffer([]byte{}) - printer, found, err := GetPrinter(test.Format, test.FormatArgument) - if err != nil || !found { - t.Errorf("in %s, unexpected error: %#v", test.Name, err) - } - if err := printer.PrintObj(test.Input, buf); err != nil { - t.Errorf("in %s, unexpected error: %#v", test.Name, err) - } - if buf.String() != test.Expect { - t.Errorf("in %s, expect %q, got %q", test.Name, test.Expect, buf.String()) - } - } - -} - -func TestBadPrinter(t *testing.T) { - badPrinterTests := []struct { - Name string - Format string - FormatArgument string - Error error - }{ - {"empty template", "template", "", fmt.Errorf("template format specified but no template given")}, - {"bad template", "template", "{{ .Name", fmt.Errorf("error parsing template {{ .Name, template: output:1: unclosed action\n")}, - {"bad templatefile", "templatefile", "", fmt.Errorf("templatefile format specified but no template file given")}, - {"bad jsonpath", "jsonpath", "{.Name", fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")}, - } - for _, test := range badPrinterTests { - _, _, err := GetPrinter(test.Format, test.FormatArgument) - if err == nil || err.Error() != test.Error.Error() { - t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err) - } - } -} - -func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data []byte, v interface{}) error) { - buf := bytes.NewBuffer([]byte{}) - - err := printer.PrintObj(&testData, buf) - if err != nil { - t.Fatal(err) - } - var poutput kubectltesting.TestStruct - // Verify that given function runs without error. - err = unmarshalFunc(buf.Bytes(), &poutput) - if err != nil { - t.Fatal(err) - } - // Use real decode function to undo the versioning process. - poutput = kubectltesting.TestStruct{} - s := yamlserializer.NewDecodingSerializer(testapi.Default.Codec()) - if err := runtime.DecodeInto(s, buf.Bytes(), &poutput); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(testData, poutput) { - t.Errorf("Test data and unmarshaled data are not equal: %v", diff.ObjectDiff(poutput, testData)) - } - - obj := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - } - buf.Reset() - printer.PrintObj(obj, buf) - var objOut api.Pod - // Verify that given function runs without error. - err = unmarshalFunc(buf.Bytes(), &objOut) - if err != nil { - t.Fatalf("unexpected error: %#v", err) - } - // Use real decode function to undo the versioning process. - objOut = api.Pod{} - if err := runtime.DecodeInto(s, buf.Bytes(), &objOut); err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(obj, &objOut) { - t.Errorf("Unexpected inequality:\n%v", diff.ObjectDiff(obj, &objOut)) - } -} - -func TestYAMLPrinter(t *testing.T) { - testPrinter(t, &YAMLPrinter{}, yaml.Unmarshal) -} - -func TestJSONPrinter(t *testing.T) { - testPrinter(t, &JSONPrinter{}, json.Unmarshal) -} - -func PrintCustomType(obj *TestPrintType, w io.Writer, options PrintOptions) error { - _, err := fmt.Fprintf(w, "%s", obj.Data) - return err -} - -func ErrorPrintHandler(obj *TestPrintType, w io.Writer, options PrintOptions) error { - return fmt.Errorf("ErrorPrintHandler error") -} - -func TestCustomTypePrinting(t *testing.T) { - columns := []string{"Data"} - printer := NewHumanReadablePrinter(false, false, false, false, false, false, []string{}) - printer.Handler(columns, PrintCustomType) - - obj := TestPrintType{"test object"} - buffer := &bytes.Buffer{} - err := printer.PrintObj(&obj, buffer) - if err != nil { - t.Fatalf("An error occurred printing the custom type: %#v", err) - } - expectedOutput := "Data\ntest object" - if buffer.String() != expectedOutput { - t.Errorf("The data was not printed as expected. Expected:\n%s\nGot:\n%s", expectedOutput, buffer.String()) - } -} - -func TestPrintHandlerError(t *testing.T) { - columns := []string{"Data"} - printer := NewHumanReadablePrinter(false, false, false, false, false, false, []string{}) - printer.Handler(columns, ErrorPrintHandler) - obj := TestPrintType{"test object"} - buffer := &bytes.Buffer{} - err := printer.PrintObj(&obj, buffer) - if err == nil || err.Error() != "ErrorPrintHandler error" { - t.Errorf("Did not get the expected error: %#v", err) - } -} - -func TestUnknownTypePrinting(t *testing.T) { - printer := NewHumanReadablePrinter(false, false, false, false, false, false, []string{}) - buffer := &bytes.Buffer{} - err := printer.PrintObj(&TestUnknownType{}, buffer) - if err == nil { - t.Errorf("An error was expected from printing unknown type") - } -} - -func TestTemplatePanic(t *testing.T) { - tmpl := `{{and ((index .currentState.info "foo").state.running.startedAt) .currentState.info.net.state.running.startedAt}}` - printer, err := NewTemplatePrinter([]byte(tmpl)) - if err != nil { - t.Fatalf("tmpl fail: %v", err) - } - buffer := &bytes.Buffer{} - err = printer.PrintObj(&api.Pod{}, buffer) - if err == nil { - t.Fatalf("expected that template to crash") - } - if buffer.String() == "" { - t.Errorf("no debugging info was printed") - } -} - -func TestNamePrinter(t *testing.T) { - tests := map[string]struct { - obj runtime.Object - expect string - }{ - "singleObject": { - &api.Pod{ - TypeMeta: unversioned.TypeMeta{ - Kind: "Pod", - }, - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - }, - "pod/foo\n"}, - "List": { - &v1.List{ - TypeMeta: unversioned.TypeMeta{ - Kind: "List", - }, - Items: []runtime.RawExtension{ - { - Raw: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "foo"}}`), - }, - { - Raw: []byte(`{"kind": "Pod", "apiVersion": "v1", "metadata": { "name": "bar"}}`), - }, - }, - }, - "pod/foo\npod/bar\n"}, - } - printer, _, _ := GetPrinter("name", "") - for name, item := range tests { - buff := &bytes.Buffer{} - err := printer.PrintObj(item.obj, buff) - if err != nil { - t.Errorf("%v: unexpected err: %v", name, err) - continue - } - got := buff.String() - if item.expect != got { - t.Errorf("%v: expected %v, got %v", name, item.expect, got) - } - } -} - -func TestTemplateStrings(t *testing.T) { - // This unit tests the "exists" function as well as the template from update.sh - table := map[string]struct { - pod api.Pod - expect string - }{ - "nilInfo": {api.Pod{}, "false"}, - "emptyInfo": {api.Pod{Status: api.PodStatus{ContainerStatuses: []api.ContainerStatus{}}}, "false"}, - "fooExists": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - { - Name: "foo", - }, - }, - }, - }, - "false", - }, - "barExists": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - { - Name: "bar", - }, - }, - }, - }, - "false", - }, - "bothExist": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - { - Name: "foo", - }, - { - Name: "bar", - }, - }, - }, - }, - "false", - }, - "barValid": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - { - Name: "foo", - }, - { - Name: "bar", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ - StartedAt: unversioned.Time{}, - }, - }, - }, - }, - }, - }, - "false", - }, - "bothValid": { - api.Pod{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - { - Name: "foo", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ - StartedAt: unversioned.Time{}, - }, - }, - }, - { - Name: "bar", - State: api.ContainerState{ - Running: &api.ContainerStateRunning{ - StartedAt: unversioned.Time{}, - }, - }, - }, - }, - }, - }, - "true", - }, - } - // The point of this test is to verify that the below template works. - tmpl := `{{if (exists . "status" "containerStatuses")}}{{range .status.containerStatuses}}{{if (and (eq .name "foo") (exists . "state" "running"))}}true{{end}}{{end}}{{end}}` - p, err := NewTemplatePrinter([]byte(tmpl)) - if err != nil { - t.Fatalf("tmpl fail: %v", err) - } - - printer := NewVersionedPrinter(p, api.Scheme, *testapi.Default.GroupVersion()) - - for name, item := range table { - buffer := &bytes.Buffer{} - err = printer.PrintObj(&item.pod, buffer) - if err != nil { - t.Errorf("%v: unexpected err: %v", name, err) - continue - } - actual := buffer.String() - if len(actual) == 0 { - actual = "false" - } - if e := item.expect; e != actual { - t.Errorf("%v: expected %v, got %v", name, e, actual) - } - } -} - -func TestPrinters(t *testing.T) { - om := func(name string) api.ObjectMeta { return api.ObjectMeta{Name: name} } - templatePrinter, err := NewTemplatePrinter([]byte("{{.name}}")) - if err != nil { - t.Fatal(err) - } - templatePrinter2, err := NewTemplatePrinter([]byte("{{len .items}}")) - if err != nil { - t.Fatal(err) - } - jsonpathPrinter, err := NewJSONPathPrinter("{.metadata.name}") - if err != nil { - t.Fatal(err) - } - printers := map[string]ResourcePrinter{ - "humanReadable": NewHumanReadablePrinter(true, false, false, false, false, false, []string{}), - "humanReadableHeaders": NewHumanReadablePrinter(false, false, false, false, false, false, []string{}), - "json": &JSONPrinter{}, - "yaml": &YAMLPrinter{}, - "template": templatePrinter, - "template2": templatePrinter2, - "jsonpath": jsonpathPrinter, - "name": &NamePrinter{ - Typer: runtime.ObjectTyperToTyper(api.Scheme), - Decoder: api.Codecs.UniversalDecoder(), - }, - } - objects := map[string]runtime.Object{ - "pod": &api.Pod{ObjectMeta: om("pod")}, - "emptyPodList": &api.PodList{}, - "nonEmptyPodList": &api.PodList{Items: []api.Pod{{}}}, - "endpoints": &api.Endpoints{ - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}, {IP: "localhost"}}, - Ports: []api.EndpointPort{{Port: 8080}}, - }}}, - } - // map of printer name to set of objects it should fail on. - expectedErrors := map[string]sets.String{ - "template2": sets.NewString("pod", "emptyPodList", "endpoints"), - "jsonpath": sets.NewString("emptyPodList", "nonEmptyPodList", "endpoints"), - } - - for pName, p := range printers { - for oName, obj := range objects { - b := &bytes.Buffer{} - if err := p.PrintObj(obj, b); err != nil { - if set, found := expectedErrors[pName]; found && set.Has(oName) { - // expected error - continue - } - t.Errorf("printer '%v', object '%v'; error: '%v'", pName, oName, err) - } - } - } -} - -func TestPrintEventsResultSorted(t *testing.T) { - // Arrange - printer := NewHumanReadablePrinter(false /* noHeaders */, false, false, false, false, false, []string{}) - - obj := api.EventList{ - Items: []api.Event{ - { - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 1", - FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - { - Source: api.EventSource{Component: "scheduler"}, - Message: "Item 2", - FirstTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - { - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 3", - FirstTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - }, - } - buffer := &bytes.Buffer{} - - // Act - err := printer.PrintObj(&obj, buffer) - - // Assert - if err != nil { - t.Fatalf("An error occurred printing the EventList: %#v", err) - } - out := buffer.String() - VerifyDatesInOrder(out, "\n" /* rowDelimiter */, " " /* columnDelimiter */, t) -} - -func TestPrintNodeStatus(t *testing.T) { - printer := NewHumanReadablePrinter(false, false, false, false, false, false, []string{}) - table := []struct { - node api.Node - status string - }{ - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo1"}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionTrue}}}, - }, - status: "Ready", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo2"}, - Spec: api.NodeSpec{Unschedulable: true}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionTrue}}}, - }, - status: "Ready,SchedulingDisabled", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo3"}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{ - {Type: api.NodeReady, Status: api.ConditionTrue}, - {Type: api.NodeReady, Status: api.ConditionTrue}}}, - }, - status: "Ready", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo4"}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionFalse}}}, - }, - status: "NotReady", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo5"}, - Spec: api.NodeSpec{Unschedulable: true}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionFalse}}}, - }, - status: "NotReady,SchedulingDisabled", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo6"}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: "InvalidValue", Status: api.ConditionTrue}}}, - }, - status: "Unknown", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo7"}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{}}}, - }, - status: "Unknown", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo8"}, - Spec: api.NodeSpec{Unschedulable: true}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: "InvalidValue", Status: api.ConditionTrue}}}, - }, - status: "Unknown,SchedulingDisabled", - }, - { - node: api.Node{ - ObjectMeta: api.ObjectMeta{Name: "foo9"}, - Spec: api.NodeSpec{Unschedulable: true}, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{}}}, - }, - status: "Unknown,SchedulingDisabled", - }, - } - - for _, test := range table { - buffer := &bytes.Buffer{} - err := printer.PrintObj(&test.node, buffer) - if err != nil { - t.Fatalf("An error occurred printing Node: %#v", err) - } - if !contains(strings.Fields(buffer.String()), test.status) { - t.Fatalf("Expect printing node %s with status %#v, got: %#v", test.node.Name, test.status, buffer.String()) - } - } -} - -func contains(fields []string, field string) bool { - for _, v := range fields { - if v == field { - return true - } - } - return false -} - -func TestPrintHunmanReadableIngressWithColumnLabels(t *testing.T) { - ingress := extensions.Ingress{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - Labels: map[string]string{ - "app_name": "kubectl_test_ingress", - }, - }, - Spec: extensions.IngressSpec{ - Backend: &extensions.IngressBackend{ - ServiceName: "svc", - ServicePort: intstr.FromInt(93), - }, - }, - Status: extensions.IngressStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - { - IP: "2.3.4.5", - Hostname: "localhost.localdomain", - }, - }, - }, - }, - } - buff := bytes.Buffer{} - printIngress(&ingress, &buff, PrintOptions{false, false, false, false, false, false, []string{"app_name"}}) - output := string(buff.Bytes()) - appName := ingress.ObjectMeta.Labels["app_name"] - if !strings.Contains(output, appName) { - t.Errorf("expected to container app_name label value %s, but doesn't %s", appName, output) - } -} - -func TestPrintHumanReadableService(t *testing.T) { - tests := []api.Service{ - { - Spec: api.ServiceSpec{ - ClusterIP: "1.2.3.4", - Type: "LoadBalancer", - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - }, - }, - Status: api.ServiceStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - { - IP: "2.3.4.5", - }, - { - IP: "3.4.5.6", - }, - }, - }, - }, - }, - { - Spec: api.ServiceSpec{ - ClusterIP: "1.2.3.4", - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - { - Port: 8090, - Protocol: "UDP", - }, - { - Port: 8000, - Protocol: "TCP", - }, - }, - }, - }, - { - Spec: api.ServiceSpec{ - ClusterIP: "1.2.3.4", - Type: "LoadBalancer", - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - { - Port: 8090, - Protocol: "UDP", - }, - { - Port: 8000, - Protocol: "TCP", - }, - }, - }, - Status: api.ServiceStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - { - IP: "2.3.4.5", - }, - }, - }, - }, - }, - { - Spec: api.ServiceSpec{ - ClusterIP: "1.2.3.4", - Type: "LoadBalancer", - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - { - Port: 8090, - Protocol: "UDP", - }, - { - Port: 8000, - Protocol: "TCP", - }, - }, - }, - Status: api.ServiceStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - { - IP: "2.3.4.5", - }, - { - IP: "3.4.5.6", - }, - { - IP: "5.6.7.8", - Hostname: "host5678", - }, - }, - }, - }, - }, - } - - for _, svc := range tests { - buff := bytes.Buffer{} - printService(&svc, &buff, PrintOptions{false, false, false, false, false, false, []string{}}) - output := string(buff.Bytes()) - ip := svc.Spec.ClusterIP - if !strings.Contains(output, ip) { - t.Errorf("expected to contain ClusterIP %s, but doesn't: %s", ip, output) - } - - for _, ingress := range svc.Status.LoadBalancer.Ingress { - ip = ingress.IP - if !strings.Contains(output, ip) { - t.Errorf("expected to contain ingress ip %s, but doesn't: %s", ip, output) - } - } - - for _, port := range svc.Spec.Ports { - portSpec := fmt.Sprintf("%d/%s", port.Port, port.Protocol) - if !strings.Contains(output, portSpec) { - t.Errorf("expected to contain port: %s, but doesn't: %s", portSpec, output) - } - } - // Each service should print on one line - if 1 != strings.Count(output, "\n") { - t.Errorf("expected a single newline, found %d", strings.Count(output, "\n")) - } - } -} - -func TestPrintHumanReadableWithNamespace(t *testing.T) { - namespaceName := "testnamespace" - name := "test" - table := []struct { - obj runtime.Object - isNamespaced bool - }{ - { - obj: &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - }, - isNamespaced: true, - }, - { - obj: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - Spec: api.ReplicationControllerSpec{ - Replicas: 2, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "name": "foo", - "type": "production", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Image: "foo/bar", - TerminationMessagePath: api.TerminationMessagePathDefault, - ImagePullPolicy: api.PullIfNotPresent, - }, - }, - RestartPolicy: api.RestartPolicyAlways, - DNSPolicy: api.DNSDefault, - NodeSelector: map[string]string{ - "baz": "blah", - }, - }, - }, - }, - }, - isNamespaced: true, - }, - { - obj: &api.Service{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - Spec: api.ServiceSpec{ - ClusterIP: "1.2.3.4", - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - }, - }, - }, - Status: api.ServiceStatus{ - LoadBalancer: api.LoadBalancerStatus{ - Ingress: []api.LoadBalancerIngress{ - { - IP: "2.3.4.5", - }, - }, - }, - }, - }, - isNamespaced: true, - }, - { - obj: &api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - Subsets: []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: "127.0.0.1"}, {IP: "localhost"}}, - Ports: []api.EndpointPort{{Port: 8080}}, - }, - }}, - isNamespaced: true, - }, - { - obj: &api.Namespace{ - ObjectMeta: api.ObjectMeta{Name: name}, - }, - isNamespaced: false, - }, - { - obj: &api.Secret{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - }, - isNamespaced: true, - }, - { - obj: &api.ServiceAccount{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - Secrets: []api.ObjectReference{}, - }, - isNamespaced: true, - }, - { - obj: &api.Node{ - ObjectMeta: api.ObjectMeta{Name: name}, - Status: api.NodeStatus{}, - }, - isNamespaced: false, - }, - { - obj: &api.PersistentVolume{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - Spec: api.PersistentVolumeSpec{}, - }, - isNamespaced: false, - }, - { - obj: &api.PersistentVolumeClaim{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - Spec: api.PersistentVolumeClaimSpec{}, - }, - isNamespaced: true, - }, - { - obj: &api.Event{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 1", - FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - isNamespaced: true, - }, - { - obj: &api.LimitRange{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - }, - isNamespaced: true, - }, - { - obj: &api.ResourceQuota{ - ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespaceName}, - }, - isNamespaced: true, - }, - { - obj: &api.ComponentStatus{ - Conditions: []api.ComponentCondition{ - {Type: api.ComponentHealthy, Status: api.ConditionTrue, Message: "ok", Error: ""}, - }, - }, - isNamespaced: false, - }, - } - - for _, test := range table { - if test.isNamespaced { - // Expect output to include namespace when requested. - printer := NewHumanReadablePrinter(false, true, false, false, false, false, []string{}) - buffer := &bytes.Buffer{} - err := printer.PrintObj(test.obj, buffer) - if err != nil { - t.Fatalf("An error occurred printing object: %#v", err) - } - matched := contains(strings.Fields(buffer.String()), fmt.Sprintf("%s", namespaceName)) - if !matched { - t.Errorf("Expect printing object to contain namespace: %#v", test.obj) - } - } else { - // Expect error when trying to get all namespaces for un-namespaced object. - printer := NewHumanReadablePrinter(false, true, false, false, false, false, []string{}) - buffer := &bytes.Buffer{} - err := printer.PrintObj(test.obj, buffer) - if err == nil { - t.Errorf("Expected error when printing un-namespaced type") - } - } - } -} - -func TestPrintPod(t *testing.T) { - tests := []struct { - pod api.Pod - expect string - }{ - { - // Test name, num of containers, restarts, container ready status - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test1"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - "test1\t1/2\tpodPhase\t6\t", - }, - { - // Test container error overwrites pod phase - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test2"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {State: api.ContainerState{Waiting: &api.ContainerStateWaiting{Reason: "ContainerWaitingReason"}}, RestartCount: 3}, - }, - }, - }, - "test2\t1/2\tContainerWaitingReason\t6\t", - }, - { - // Test the same as the above but with Terminated state and the first container overwrites the rest - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test3"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {State: api.ContainerState{Waiting: &api.ContainerStateWaiting{Reason: "ContainerWaitingReason"}}, RestartCount: 3}, - {State: api.ContainerState{Terminated: &api.ContainerStateTerminated{Reason: "ContainerTerminatedReason"}}, RestartCount: 3}, - }, - }, - }, - "test3\t0/2\tContainerWaitingReason\t6\t", - }, - { - // Test ready is not enough for reporting running - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test4"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {Ready: true, RestartCount: 3}, - }, - }, - }, - "test4\t1/2\tpodPhase\t6\t", - }, - { - // Test ready is not enough for reporting running - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test5"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Reason: "OutOfDisk", - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {Ready: true, RestartCount: 3}, - }, - }, - }, - "test5\t1/2\tOutOfDisk\t6\t", - }, - } - - buf := bytes.NewBuffer([]byte{}) - for _, test := range tests { - printPod(&test.pod, buf, PrintOptions{false, false, false, true, false, false, []string{}}) - // We ignore time - if !strings.HasPrefix(buf.String(), test.expect) { - t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) - } - buf.Reset() - } -} - -func TestPrintNonTerminatedPod(t *testing.T) { - tests := []struct { - pod api.Pod - expect string - }{ - { - // Test pod phase Running should be printed - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test1"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: api.PodRunning, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - "test1\t1/2\tRunning\t6\t", - }, - { - // Test pod phase Pending should be printed - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test2"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: api.PodPending, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - "test2\t1/2\tPending\t6\t", - }, - { - // Test pod phase Unknown should be printed - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test3"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: api.PodUnknown, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - "test3\t1/2\tUnknown\t6\t", - }, - { - // Test pod phase Succeeded shouldn't be printed - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test4"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: api.PodSucceeded, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - "", - }, - { - // Test pod phase Failed shouldn't be printed - api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "test5"}, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: api.PodFailed, - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {Ready: true, RestartCount: 3}, - }, - }, - }, - "", - }, - } - - buf := bytes.NewBuffer([]byte{}) - for _, test := range tests { - printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, false, []string{}}) - // We ignore time - if !strings.HasPrefix(buf.String(), test.expect) { - t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) - } - buf.Reset() - } -} - -func TestPrintPodWithLabels(t *testing.T) { - tests := []struct { - pod api.Pod - labelColumns []string - startsWith string - endsWith string - }{ - { - // Test name, num of containers, restarts, container ready status - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - Labels: map[string]string{"col1": "asd", "COL2": "zxc"}, - }, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - []string{"col1", "COL2"}, - "test1\t1/2\tpodPhase\t6\t", - "\tasd\tzxc\n", - }, - { - // Test name, num of containers, restarts, container ready status - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - Labels: map[string]string{"col1": "asd", "COL2": "zxc"}, - }, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - []string{}, - "test1\t1/2\tpodPhase\t6\t", - "\n", - }, - } - - buf := bytes.NewBuffer([]byte{}) - for _, test := range tests { - printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, false, test.labelColumns}) - // We ignore time - if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) { - t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String()) - } - buf.Reset() - } -} - -type stringTestList []struct { - name, got, exp string -} - -func TestTranslateTimestamp(t *testing.T) { - tl := stringTestList{ - {"a while from now", translateTimestamp(unversioned.Time{Time: time.Now().Add(2.1e9)}), ""}, - {"almost now", translateTimestamp(unversioned.Time{Time: time.Now().Add(1.9e9)}), "0s"}, - {"now", translateTimestamp(unversioned.Time{Time: time.Now()}), "0s"}, - {"unknown", translateTimestamp(unversioned.Time{}), ""}, - {"30 seconds ago", translateTimestamp(unversioned.Time{Time: time.Now().Add(-3e10)}), "30s"}, - {"5 minutes ago", translateTimestamp(unversioned.Time{Time: time.Now().Add(-3e11)}), "5m"}, - {"an hour ago", translateTimestamp(unversioned.Time{Time: time.Now().Add(-6e12)}), "1h"}, - {"2 days ago", translateTimestamp(unversioned.Time{Time: time.Now().UTC().AddDate(0, 0, -2)}), "2d"}, - {"months ago", translateTimestamp(unversioned.Time{Time: time.Now().UTC().AddDate(0, 0, -90)}), "90d"}, - {"10 years ago", translateTimestamp(unversioned.Time{Time: time.Now().UTC().AddDate(-10, 0, 0)}), "10y"}, - } - for _, test := range tl { - if test.got != test.exp { - t.Errorf("On %v, expected '%v', but got '%v'", - test.name, test.exp, test.got) - } - } -} - -func TestPrintDeployment(t *testing.T) { - tests := []struct { - deployment extensions.Deployment - expect string - }{ - { - extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - CreationTimestamp: unversioned.Time{Time: time.Now().Add(1.9e9)}, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 5, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - }, - }, - Status: extensions.DeploymentStatus{ - Replicas: 10, - UpdatedReplicas: 2, - AvailableReplicas: 1, - UnavailableReplicas: 4, - }, - }, - "test1\t5\t10\t2\t1\t0s\n", - }, - } - - buf := bytes.NewBuffer([]byte{}) - for _, test := range tests { - printDeployment(&test.deployment, buf, PrintOptions{false, false, false, true, false, false, []string{}}) - if buf.String() != test.expect { - t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) - } - buf.Reset() - } -} - -func TestPrintDaemonSet(t *testing.T) { - tests := []struct { - ds extensions.DaemonSet - startsWith string - }{ - { - extensions.DaemonSet{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - CreationTimestamp: unversioned.Time{Time: time.Now().Add(1.9e9)}, - }, - Spec: extensions.DaemonSetSpec{ - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - }, - }, - Status: extensions.DaemonSetStatus{ - CurrentNumberScheduled: 2, - DesiredNumberScheduled: 3, - }, - }, - "test1\t3\t2\t\t0s\n", - }, - } - - buf := bytes.NewBuffer([]byte{}) - for _, test := range tests { - printDaemonSet(&test.ds, buf, PrintOptions{false, false, false, false, false, false, []string{}}) - if !strings.HasPrefix(buf.String(), test.startsWith) { - t.Fatalf("Expected to start with %s but got %s", test.startsWith, buf.String()) - } - buf.Reset() - } -} - -func TestPrintJob(t *testing.T) { - completions := int32(2) - tests := []struct { - job batch.Job - expect string - }{ - { - batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "job1", - CreationTimestamp: unversioned.Time{Time: time.Now().Add(1.9e9)}, - }, - Spec: batch.JobSpec{ - Completions: &completions, - }, - Status: batch.JobStatus{ - Succeeded: 1, - }, - }, - "job1\t2\t1\t0s\n", - }, - { - batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "job2", - CreationTimestamp: unversioned.Time{Time: time.Now().AddDate(-10, 0, 0)}, - }, - Spec: batch.JobSpec{ - Completions: nil, - }, - Status: batch.JobStatus{ - Succeeded: 0, - }, - }, - "job2\t\t0\t10y\n", - }, - } - - buf := bytes.NewBuffer([]byte{}) - for _, test := range tests { - printJob(&test.job, buf, PrintOptions{false, false, false, true, false, false, []string{}}) - if buf.String() != test.expect { - t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) - } - buf.Reset() - } -} - -func TestPrintPodShowLabels(t *testing.T) { - tests := []struct { - pod api.Pod - startsWith string - endsWith string - showLabels bool - }{ - { - // Test name, num of containers, restarts, container ready status - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - Labels: map[string]string{"col1": "asd", "COL2": "zxc"}, - }, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - "test1\t1/2\tpodPhase\t6\t", - "\tCOL2=zxc,col1=asd\n", - true, - }, - { - // Test name, num of containers, restarts, container ready status - api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "test1", - Labels: map[string]string{"col3": "asd", "COL4": "zxc"}, - }, - Spec: api.PodSpec{Containers: make([]api.Container, 2)}, - Status: api.PodStatus{ - Phase: "podPhase", - ContainerStatuses: []api.ContainerStatus{ - {Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}}, - {RestartCount: 3}, - }, - }, - }, - "test1\t1/2\tpodPhase\t6\t", - "\n", - false, - }, - } - - buf := bytes.NewBuffer([]byte{}) - for _, test := range tests { - printPod(&test.pod, buf, PrintOptions{false, false, false, false, test.showLabels, false, []string{}}) - // We ignore time - if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) { - t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String()) - } - buf.Reset() - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/rolling_updater_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/rolling_updater_test.go deleted file mode 100644 index c30f08b2c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/rolling_updater_test.go +++ /dev/null @@ -1,1660 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/client/restclient" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/fake" - "k8s.io/kubernetes/pkg/client/unversioned/testclient" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/intstr" - "k8s.io/kubernetes/pkg/util/sets" -) - -func oldRc(replicas int, original int) *api.ReplicationController { - return &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo-v1", - UID: "7764ae47-9092-11e4-8393-42010af018ff", - Annotations: map[string]string{ - originalReplicasAnnotation: fmt.Sprintf("%d", original), - }, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: int32(replicas), - Selector: map[string]string{"version": "v1"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Name: "foo-v1", - Labels: map[string]string{"version": "v1"}, - }, - }, - }, - Status: api.ReplicationControllerStatus{ - Replicas: int32(replicas), - }, - } -} - -func newRc(replicas int, desired int) *api.ReplicationController { - rc := oldRc(replicas, replicas) - rc.Spec.Template = &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Name: "foo-v2", - Labels: map[string]string{"version": "v2"}, - }, - } - rc.Spec.Selector = map[string]string{"version": "v2"} - rc.ObjectMeta = api.ObjectMeta{ - Name: "foo-v2", - Annotations: map[string]string{ - desiredReplicasAnnotation: fmt.Sprintf("%d", desired), - sourceIdAnnotation: "foo-v1:7764ae47-9092-11e4-8393-42010af018ff", - }, - } - return rc -} - -// TestUpdate performs complex scenario testing for rolling updates. It -// provides fine grained control over the states for each update interval to -// allow the expression of as many edge cases as possible. -func TestUpdate(t *testing.T) { - // up represents a simulated scale up event and expectation - type up struct { - // to is the expected replica count for a scale-up - to int - } - // down represents a simulated scale down event and expectation - type down struct { - // oldReady is the number of oldRc replicas which will be seen - // as ready during the scale down attempt - oldReady int - // newReady is the number of newRc replicas which will be seen - // as ready during the scale up attempt - newReady int - // to is the expected replica count for the scale down - to int - // noop and to are mutually exclusive; if noop is true, that means for - // this down event, no scaling attempt should be made (for example, if - // by scaling down, the readiness minimum would be crossed.) - noop bool - } - - tests := []struct { - name string - // oldRc is the "from" deployment - oldRc *api.ReplicationController - // newRc is the "to" deployment - newRc *api.ReplicationController - // whether newRc existed (false means it was created) - newRcExists bool - maxUnavail intstr.IntOrString - maxSurge intstr.IntOrString - // expected is the sequence of up/down events that will be simulated and - // verified - expected []interface{} - // output is the expected textual output written - output string - }{ - { - name: "10->10 30/0 fast readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("30%"), - maxSurge: intstr.FromString("0%"), - expected: []interface{}{ - down{oldReady: 10, newReady: 0, to: 7}, - up{3}, - down{oldReady: 7, newReady: 3, to: 4}, - up{6}, - down{oldReady: 4, newReady: 6, to: 1}, - up{9}, - down{oldReady: 1, newReady: 9, to: 0}, - up{10}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 7 pods available, don't exceed 10 pods) -Scaling foo-v1 down to 7 -Scaling foo-v2 up to 3 -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 6 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 9 -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 10 -`, - }, - { - name: "10->10 30/0 delayed readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("30%"), - maxSurge: intstr.FromString("0%"), - expected: []interface{}{ - down{oldReady: 10, newReady: 0, to: 7}, - up{3}, - down{oldReady: 7, newReady: 0, noop: true}, - down{oldReady: 7, newReady: 1, to: 6}, - up{4}, - down{oldReady: 6, newReady: 4, to: 3}, - up{7}, - down{oldReady: 3, newReady: 7, to: 0}, - up{10}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 7 pods available, don't exceed 10 pods) -Scaling foo-v1 down to 7 -Scaling foo-v2 up to 3 -Scaling foo-v1 down to 6 -Scaling foo-v2 up to 4 -Scaling foo-v1 down to 3 -Scaling foo-v2 up to 7 -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 10 -`, - }, { - name: "10->10 30/0 fast readiness, continuation", - oldRc: oldRc(7, 10), - newRc: newRc(3, 10), - newRcExists: false, - maxUnavail: intstr.FromString("30%"), - maxSurge: intstr.FromString("0%"), - expected: []interface{}{ - down{oldReady: 7, newReady: 3, to: 4}, - up{6}, - down{oldReady: 4, newReady: 6, to: 1}, - up{9}, - down{oldReady: 1, newReady: 9, to: 0}, - up{10}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 3 to 10, scaling down foo-v1 from 7 to 0 (keep 7 pods available, don't exceed 10 pods) -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 6 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 9 -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 10 -`, - }, { - name: "10->10 30/0 fast readiness, continued after restart which prevented first scale-up", - oldRc: oldRc(7, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("30%"), - maxSurge: intstr.FromString("0%"), - expected: []interface{}{ - down{oldReady: 7, newReady: 0, noop: true}, - up{3}, - down{oldReady: 7, newReady: 3, to: 4}, - up{6}, - down{oldReady: 4, newReady: 6, to: 1}, - up{9}, - down{oldReady: 1, newReady: 9, to: 0}, - up{10}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 7 to 0 (keep 7 pods available, don't exceed 10 pods) -Scaling foo-v2 up to 3 -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 6 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 9 -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 10 -`, - }, { - name: "10->10 0/30 fast readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("0%"), - maxSurge: intstr.FromString("30%"), - expected: []interface{}{ - up{3}, - down{oldReady: 10, newReady: 3, to: 7}, - up{6}, - down{oldReady: 7, newReady: 6, to: 4}, - up{9}, - down{oldReady: 4, newReady: 9, to: 1}, - up{10}, - down{oldReady: 1, newReady: 10, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 10 pods available, don't exceed 13 pods) -Scaling foo-v2 up to 3 -Scaling foo-v1 down to 7 -Scaling foo-v2 up to 6 -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 9 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 0/30 delayed readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("0%"), - maxSurge: intstr.FromString("30%"), - expected: []interface{}{ - up{3}, - down{oldReady: 10, newReady: 0, noop: true}, - down{oldReady: 10, newReady: 1, to: 9}, - up{4}, - down{oldReady: 9, newReady: 3, to: 7}, - up{6}, - down{oldReady: 7, newReady: 6, to: 4}, - up{9}, - down{oldReady: 4, newReady: 9, to: 1}, - up{10}, - down{oldReady: 1, newReady: 9, noop: true}, - down{oldReady: 1, newReady: 10, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 10 pods available, don't exceed 13 pods) -Scaling foo-v2 up to 3 -Scaling foo-v1 down to 9 -Scaling foo-v2 up to 4 -Scaling foo-v1 down to 7 -Scaling foo-v2 up to 6 -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 9 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 10/20 fast readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("10%"), - maxSurge: intstr.FromString("20%"), - expected: []interface{}{ - up{2}, - down{oldReady: 10, newReady: 2, to: 7}, - up{5}, - down{oldReady: 7, newReady: 5, to: 4}, - up{8}, - down{oldReady: 4, newReady: 8, to: 1}, - up{10}, - down{oldReady: 1, newReady: 10, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 9 pods available, don't exceed 12 pods) -Scaling foo-v2 up to 2 -Scaling foo-v1 down to 7 -Scaling foo-v2 up to 5 -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 8 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 10/20 delayed readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("10%"), - maxSurge: intstr.FromString("20%"), - expected: []interface{}{ - up{2}, - down{oldReady: 10, newReady: 2, to: 7}, - up{5}, - down{oldReady: 7, newReady: 4, to: 5}, - up{7}, - down{oldReady: 5, newReady: 4, noop: true}, - down{oldReady: 5, newReady: 7, to: 2}, - up{10}, - down{oldReady: 2, newReady: 9, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 9 pods available, don't exceed 12 pods) -Scaling foo-v2 up to 2 -Scaling foo-v1 down to 7 -Scaling foo-v2 up to 5 -Scaling foo-v1 down to 5 -Scaling foo-v2 up to 7 -Scaling foo-v1 down to 2 -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 10/20 fast readiness continued after restart which prevented first scale-down", - oldRc: oldRc(10, 10), - newRc: newRc(2, 10), - newRcExists: false, - maxUnavail: intstr.FromString("10%"), - maxSurge: intstr.FromString("20%"), - expected: []interface{}{ - down{oldReady: 10, newReady: 2, to: 7}, - up{5}, - down{oldReady: 7, newReady: 5, to: 4}, - up{8}, - down{oldReady: 4, newReady: 8, to: 1}, - up{10}, - down{oldReady: 1, newReady: 10, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 2 to 10, scaling down foo-v1 from 10 to 0 (keep 9 pods available, don't exceed 12 pods) -Scaling foo-v1 down to 7 -Scaling foo-v2 up to 5 -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 8 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 0/100 fast readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("0%"), - maxSurge: intstr.FromString("100%"), - expected: []interface{}{ - up{10}, - down{oldReady: 10, newReady: 10, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 10 pods available, don't exceed 20 pods) -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 0/100 delayed readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("0%"), - maxSurge: intstr.FromString("100%"), - expected: []interface{}{ - up{10}, - down{oldReady: 10, newReady: 0, noop: true}, - down{oldReady: 10, newReady: 2, to: 8}, - down{oldReady: 8, newReady: 7, to: 3}, - down{oldReady: 3, newReady: 10, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 10 pods available, don't exceed 20 pods) -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 8 -Scaling foo-v1 down to 3 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 100/0 fast readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 10), - newRcExists: false, - maxUnavail: intstr.FromString("100%"), - maxSurge: intstr.FromString("0%"), - expected: []interface{}{ - down{oldReady: 10, newReady: 0, to: 0}, - up{10}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 10, scaling down foo-v1 from 10 to 0 (keep 0 pods available, don't exceed 10 pods) -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 10 -`, - }, { - name: "1->1 25/25 maintain minimum availability", - oldRc: oldRc(1, 1), - newRc: newRc(0, 1), - newRcExists: false, - maxUnavail: intstr.FromString("25%"), - maxSurge: intstr.FromString("25%"), - expected: []interface{}{ - up{1}, - down{oldReady: 1, newReady: 0, noop: true}, - down{oldReady: 1, newReady: 1, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 1, scaling down foo-v1 from 1 to 0 (keep 1 pods available, don't exceed 2 pods) -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 0 -`, - }, { - name: "1->1 0/10 delayed readiness", - oldRc: oldRc(1, 1), - newRc: newRc(0, 1), - newRcExists: false, - maxUnavail: intstr.FromString("0%"), - maxSurge: intstr.FromString("10%"), - expected: []interface{}{ - up{1}, - down{oldReady: 1, newReady: 0, noop: true}, - down{oldReady: 1, newReady: 1, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 1, scaling down foo-v1 from 1 to 0 (keep 1 pods available, don't exceed 2 pods) -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 0 -`, - }, { - name: "1->1 10/10 delayed readiness", - oldRc: oldRc(1, 1), - newRc: newRc(0, 1), - newRcExists: false, - maxUnavail: intstr.FromString("10%"), - maxSurge: intstr.FromString("10%"), - expected: []interface{}{ - up{1}, - down{oldReady: 1, newReady: 0, noop: true}, - down{oldReady: 1, newReady: 1, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 1, scaling down foo-v1 from 1 to 0 (keep 1 pods available, don't exceed 2 pods) -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 0 -`, - }, { - name: "3->3 1/1 fast readiness (absolute values)", - oldRc: oldRc(3, 3), - newRc: newRc(0, 3), - newRcExists: false, - maxUnavail: intstr.FromInt(0), - maxSurge: intstr.FromInt(1), - expected: []interface{}{ - up{1}, - down{oldReady: 3, newReady: 1, to: 2}, - up{2}, - down{oldReady: 2, newReady: 2, to: 1}, - up{3}, - down{oldReady: 1, newReady: 3, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 3, scaling down foo-v1 from 3 to 0 (keep 3 pods available, don't exceed 4 pods) -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 2 -Scaling foo-v2 up to 2 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 3 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->10 0/20 fast readiness, continued after restart which resulted in partial first scale-up", - oldRc: oldRc(6, 10), - newRc: newRc(5, 10), - newRcExists: false, - maxUnavail: intstr.FromString("0%"), - maxSurge: intstr.FromString("20%"), - expected: []interface{}{ - up{6}, - down{oldReady: 6, newReady: 6, to: 4}, - up{8}, - down{oldReady: 4, newReady: 8, to: 2}, - up{10}, - down{oldReady: 1, newReady: 10, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 5 to 10, scaling down foo-v1 from 6 to 0 (keep 10 pods available, don't exceed 12 pods) -Scaling foo-v2 up to 6 -Scaling foo-v1 down to 4 -Scaling foo-v2 up to 8 -Scaling foo-v1 down to 2 -Scaling foo-v2 up to 10 -Scaling foo-v1 down to 0 -`, - }, { - name: "10->20 0/300 fast readiness", - oldRc: oldRc(10, 10), - newRc: newRc(0, 20), - newRcExists: false, - maxUnavail: intstr.FromString("0%"), - maxSurge: intstr.FromString("300%"), - expected: []interface{}{ - up{20}, - down{oldReady: 10, newReady: 20, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 20, scaling down foo-v1 from 10 to 0 (keep 20 pods available, don't exceed 80 pods) -Scaling foo-v2 up to 20 -Scaling foo-v1 down to 0 -`, - }, { - name: "1->1 0/1 scale down unavailable rc to a ready rc (rollback)", - oldRc: oldRc(1, 1), - newRc: newRc(1, 1), - newRcExists: true, - maxUnavail: intstr.FromInt(0), - maxSurge: intstr.FromInt(1), - expected: []interface{}{ - up{1}, - down{oldReady: 0, newReady: 1, to: 0}, - }, - output: `Continuing update with existing controller foo-v2. -Scaling up foo-v2 from 1 to 1, scaling down foo-v1 from 1 to 0 (keep 1 pods available, don't exceed 2 pods) -Scaling foo-v1 down to 0 -`, - }, - { - name: "3->0 1/1 desired 0 (absolute values)", - oldRc: oldRc(3, 3), - newRc: newRc(0, 0), - newRcExists: true, - maxUnavail: intstr.FromInt(1), - maxSurge: intstr.FromInt(1), - expected: []interface{}{ - down{oldReady: 3, newReady: 0, to: 0}, - }, - output: `Continuing update with existing controller foo-v2. -Scaling up foo-v2 from 0 to 0, scaling down foo-v1 from 3 to 0 (keep 0 pods available, don't exceed 1 pods) -Scaling foo-v1 down to 0 -`, - }, - { - name: "3->0 10/10 desired 0 (percentages)", - oldRc: oldRc(3, 3), - newRc: newRc(0, 0), - newRcExists: true, - maxUnavail: intstr.FromString("10%"), - maxSurge: intstr.FromString("10%"), - expected: []interface{}{ - down{oldReady: 3, newReady: 0, to: 0}, - }, - output: `Continuing update with existing controller foo-v2. -Scaling up foo-v2 from 0 to 0, scaling down foo-v1 from 3 to 0 (keep 0 pods available, don't exceed 0 pods) -Scaling foo-v1 down to 0 -`, - }, - { - name: "3->0 10/10 desired 0 (create new RC)", - oldRc: oldRc(3, 3), - newRc: newRc(0, 0), - newRcExists: false, - maxUnavail: intstr.FromString("10%"), - maxSurge: intstr.FromString("10%"), - expected: []interface{}{ - down{oldReady: 3, newReady: 0, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 0, scaling down foo-v1 from 3 to 0 (keep 0 pods available, don't exceed 0 pods) -Scaling foo-v1 down to 0 -`, - }, - { - name: "0->0 1/1 desired 0 (absolute values)", - oldRc: oldRc(0, 0), - newRc: newRc(0, 0), - newRcExists: true, - maxUnavail: intstr.FromInt(1), - maxSurge: intstr.FromInt(1), - expected: []interface{}{ - down{oldReady: 0, newReady: 0, to: 0}, - }, - output: `Continuing update with existing controller foo-v2. -Scaling up foo-v2 from 0 to 0, scaling down foo-v1 from 0 to 0 (keep 0 pods available, don't exceed 1 pods) -`, - }, { - name: "30->2 50%/0", - oldRc: oldRc(30, 30), - newRc: newRc(0, 2), - newRcExists: false, - maxUnavail: intstr.FromString("50%"), - maxSurge: intstr.FromInt(0), - expected: []interface{}{ - down{oldReady: 30, newReady: 0, to: 1}, - up{1}, - down{oldReady: 1, newReady: 2, to: 0}, - up{2}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 2, scaling down foo-v1 from 30 to 0 (keep 1 pods available, don't exceed 2 pods) -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 2 -`, - }, - { - name: "2->2 1/0 blocked oldRc", - oldRc: oldRc(2, 2), - newRc: newRc(0, 2), - newRcExists: false, - maxUnavail: intstr.FromInt(1), - maxSurge: intstr.FromInt(0), - expected: []interface{}{ - down{oldReady: 1, newReady: 0, to: 1}, - up{1}, - down{oldReady: 1, newReady: 1, to: 0}, - up{2}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 2, scaling down foo-v1 from 2 to 0 (keep 1 pods available, don't exceed 2 pods) -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 2 -`, - }, - { - name: "1->1 1/0 allow maxUnavailability", - oldRc: oldRc(1, 1), - newRc: newRc(0, 1), - newRcExists: false, - maxUnavail: intstr.FromString("1%"), - maxSurge: intstr.FromInt(0), - expected: []interface{}{ - down{oldReady: 1, newReady: 0, to: 0}, - up{1}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 1, scaling down foo-v1 from 1 to 0 (keep 0 pods available, don't exceed 1 pods) -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 1 -`, - }, - { - name: "1->2 25/25 complex asymetric deployment", - oldRc: oldRc(1, 1), - newRc: newRc(0, 2), - newRcExists: false, - maxUnavail: intstr.FromString("25%"), - maxSurge: intstr.FromString("25%"), - expected: []interface{}{ - up{2}, - down{oldReady: 1, newReady: 2, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 2, scaling down foo-v1 from 1 to 0 (keep 2 pods available, don't exceed 3 pods) -Scaling foo-v2 up to 2 -Scaling foo-v1 down to 0 -`, - }, - { - name: "2->2 25/1 maxSurge trumps maxUnavailable", - oldRc: oldRc(2, 2), - newRc: newRc(0, 2), - newRcExists: false, - maxUnavail: intstr.FromString("25%"), - maxSurge: intstr.FromString("1%"), - expected: []interface{}{ - up{1}, - down{oldReady: 2, newReady: 1, to: 1}, - up{2}, - down{oldReady: 1, newReady: 2, to: 0}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 2, scaling down foo-v1 from 2 to 0 (keep 2 pods available, don't exceed 3 pods) -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 2 -Scaling foo-v1 down to 0 -`, - }, - { - name: "2->2 25/0 maxUnavailable resolves to zero, then one", - oldRc: oldRc(2, 2), - newRc: newRc(0, 2), - newRcExists: false, - maxUnavail: intstr.FromString("25%"), - maxSurge: intstr.FromString("0%"), - expected: []interface{}{ - down{oldReady: 2, newReady: 0, to: 1}, - up{1}, - down{oldReady: 1, newReady: 1, to: 0}, - up{2}, - }, - output: `Created foo-v2 -Scaling up foo-v2 from 0 to 2, scaling down foo-v1 from 2 to 0 (keep 1 pods available, don't exceed 2 pods) -Scaling foo-v1 down to 1 -Scaling foo-v2 up to 1 -Scaling foo-v1 down to 0 -Scaling foo-v2 up to 2 -`, - }, - } - - for i, test := range tests { - // Extract expectations into some makeshift FIFOs so they can be returned - // in the correct order from the right places. This lets scale downs be - // expressed a single event even though the data is used from multiple - // interface calls. - oldReady := []int{} - newReady := []int{} - upTo := []int{} - downTo := []int{} - for _, event := range test.expected { - switch e := event.(type) { - case down: - oldReady = append(oldReady, e.oldReady) - newReady = append(newReady, e.newReady) - if !e.noop { - downTo = append(downTo, e.to) - } - case up: - upTo = append(upTo, e.to) - } - } - - // Make a way to get the next item from our FIFOs. Returns -1 if the array - // is empty. - next := func(s *[]int) int { - slice := *s - v := -1 - if len(slice) > 0 { - v = slice[0] - if len(slice) > 1 { - *s = slice[1:] - } else { - *s = []int{} - } - } - return v - } - t.Logf("running test %d (%s) (up: %v, down: %v, oldReady: %v, newReady: %v)", i, test.name, upTo, downTo, oldReady, newReady) - updater := &RollingUpdater{ - ns: "default", - scaleAndWait: func(rc *api.ReplicationController, retry *RetryParams, wait *RetryParams) (*api.ReplicationController, error) { - // Return a scale up or scale down expectation depending on the rc, - // and throw errors if there is no expectation expressed for this - // call. - expected := -1 - switch { - case rc == test.newRc: - t.Logf("scaling up %s to %d", rc.Name, rc.Spec.Replicas) - expected = next(&upTo) - case rc == test.oldRc: - t.Logf("scaling down %s to %d", rc.Name, rc.Spec.Replicas) - expected = next(&downTo) - } - if expected == -1 { - t.Fatalf("unexpected scale of %s to %d", rc.Name, rc.Spec.Replicas) - } else if e, a := expected, int(rc.Spec.Replicas); e != a { - t.Fatalf("expected scale of %s to %d, got %d", rc.Name, e, a) - } - // Simulate the scale. - rc.Status.Replicas = rc.Spec.Replicas - return rc, nil - }, - getOrCreateTargetController: func(controller *api.ReplicationController, sourceId string) (*api.ReplicationController, bool, error) { - // Simulate a create vs. update of an existing controller. - return test.newRc, test.newRcExists, nil - }, - cleanup: func(oldRc, newRc *api.ReplicationController, config *RollingUpdaterConfig) error { - return nil - }, - } - // Set up a mock readiness check which handles the test assertions. - updater.getReadyPods = func(oldRc, newRc *api.ReplicationController) (int32, int32, error) { - // Return simulated readiness, and throw an error if this call has no - // expectations defined. - oldReady := next(&oldReady) - newReady := next(&newReady) - if oldReady == -1 || newReady == -1 { - t.Fatalf("unexpected getReadyPods call for:\noldRc: %+v\nnewRc: %+v", oldRc, newRc) - } - return int32(oldReady), int32(newReady), nil - } - var buffer bytes.Buffer - config := &RollingUpdaterConfig{ - Out: &buffer, - OldRc: test.oldRc, - NewRc: test.newRc, - UpdatePeriod: 0, - Interval: time.Millisecond, - Timeout: time.Millisecond, - CleanupPolicy: DeleteRollingUpdateCleanupPolicy, - MaxUnavailable: test.maxUnavail, - MaxSurge: test.maxSurge, - } - err := updater.Update(config) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if buffer.String() != test.output { - t.Errorf("Bad output. expected:\n%s\ngot:\n%s", test.output, buffer.String()) - } - } -} - -// TestUpdate_progressTimeout ensures that an update which isn't making any -// progress will eventually time out with a specified error. -func TestUpdate_progressTimeout(t *testing.T) { - oldRc := oldRc(2, 2) - newRc := newRc(0, 2) - updater := &RollingUpdater{ - ns: "default", - scaleAndWait: func(rc *api.ReplicationController, retry *RetryParams, wait *RetryParams) (*api.ReplicationController, error) { - // Do nothing. - return rc, nil - }, - getOrCreateTargetController: func(controller *api.ReplicationController, sourceId string) (*api.ReplicationController, bool, error) { - return newRc, false, nil - }, - cleanup: func(oldRc, newRc *api.ReplicationController, config *RollingUpdaterConfig) error { - return nil - }, - } - updater.getReadyPods = func(oldRc, newRc *api.ReplicationController) (int32, int32, error) { - // Coerce a timeout by pods never becoming ready. - return 0, 0, nil - } - var buffer bytes.Buffer - config := &RollingUpdaterConfig{ - Out: &buffer, - OldRc: oldRc, - NewRc: newRc, - UpdatePeriod: 0, - Interval: time.Millisecond, - Timeout: time.Millisecond, - CleanupPolicy: DeleteRollingUpdateCleanupPolicy, - MaxUnavailable: intstr.FromInt(0), - MaxSurge: intstr.FromInt(1), - } - err := updater.Update(config) - if err == nil { - t.Fatalf("expected an error") - } - if e, a := "timed out waiting for any update progress to be made", err.Error(); e != a { - t.Fatalf("expected error message: %s, got: %s", e, a) - } -} - -func TestUpdate_assignOriginalAnnotation(t *testing.T) { - oldRc := oldRc(1, 1) - delete(oldRc.Annotations, originalReplicasAnnotation) - newRc := newRc(1, 1) - var updatedOldRc *api.ReplicationController - fake := &testclient.Fake{} - fake.AddReactor("*", "*", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { - switch a := action.(type) { - case testclient.GetAction: - return true, oldRc, nil - case testclient.UpdateAction: - updatedOldRc = a.GetObject().(*api.ReplicationController) - return true, updatedOldRc, nil - } - return false, nil, nil - }) - updater := &RollingUpdater{ - c: fake, - ns: "default", - scaleAndWait: func(rc *api.ReplicationController, retry *RetryParams, wait *RetryParams) (*api.ReplicationController, error) { - return rc, nil - }, - getOrCreateTargetController: func(controller *api.ReplicationController, sourceId string) (*api.ReplicationController, bool, error) { - return newRc, false, nil - }, - cleanup: func(oldRc, newRc *api.ReplicationController, config *RollingUpdaterConfig) error { - return nil - }, - getReadyPods: func(oldRc, newRc *api.ReplicationController) (int32, int32, error) { - return 1, 1, nil - }, - } - var buffer bytes.Buffer - config := &RollingUpdaterConfig{ - Out: &buffer, - OldRc: oldRc, - NewRc: newRc, - UpdatePeriod: 0, - Interval: time.Millisecond, - Timeout: time.Millisecond, - CleanupPolicy: DeleteRollingUpdateCleanupPolicy, - MaxUnavailable: intstr.FromString("100%"), - } - err := updater.Update(config) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if updatedOldRc == nil { - t.Fatalf("expected rc to be updated") - } - if e, a := "1", updatedOldRc.Annotations[originalReplicasAnnotation]; e != a { - t.Fatalf("expected annotation value %s, got %s", e, a) - } -} - -func TestRollingUpdater_multipleContainersInPod(t *testing.T) { - tests := []struct { - oldRc *api.ReplicationController - newRc *api.ReplicationController - - container string - image string - deploymentKey string - }{ - { - oldRc: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "dk": "old", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "dk": "old", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "container1", - Image: "image1", - }, - { - Name: "container2", - Image: "image2", - }, - }, - }, - }, - }, - }, - newRc: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "dk": "old", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "dk": "old", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "container1", - Image: "newimage", - }, - { - Name: "container2", - Image: "image2", - }, - }, - }, - }, - }, - }, - container: "container1", - image: "newimage", - deploymentKey: "dk", - }, - { - oldRc: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - }, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "dk": "old", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "dk": "old", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "container1", - Image: "image1", - }, - }, - }, - }, - }, - }, - newRc: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - }, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "dk": "old", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "dk": "old", - }, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "container1", - Image: "newimage", - }, - }, - }, - }, - }, - }, - container: "container1", - image: "newimage", - deploymentKey: "dk", - }, - } - - for _, test := range tests { - fake := &testclient.Fake{} - fake.AddReactor("*", "*", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { - switch action.(type) { - case testclient.GetAction: - return true, test.oldRc, nil - } - return false, nil, nil - }) - - codec := testapi.Default.Codec() - - deploymentHash, err := api.HashObject(test.newRc, codec) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - test.newRc.Spec.Selector[test.deploymentKey] = deploymentHash - test.newRc.Spec.Template.Labels[test.deploymentKey] = deploymentHash - test.newRc.Name = fmt.Sprintf("%s-%s", test.newRc.Name, deploymentHash) - - config := &NewControllerConfig{ - OldName: test.oldRc.ObjectMeta.Name, - NewName: test.newRc.ObjectMeta.Name, - Image: test.image, - Container: test.container, - DeploymentKey: test.deploymentKey, - } - updatedRc, err := CreateNewControllerFromCurrentController(fake, codec, config) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(updatedRc, test.newRc) { - t.Errorf("expected:\n%#v\ngot:\n%#v\n", test.newRc, updatedRc) - } - } -} - -// TestRollingUpdater_cleanupWithClients ensures that the cleanup policy is -// correctly implemented. -func TestRollingUpdater_cleanupWithClients(t *testing.T) { - rc := oldRc(2, 2) - rcExisting := newRc(1, 3) - - tests := []struct { - name string - policy RollingUpdaterCleanupPolicy - responses []runtime.Object - expected []string - }{ - { - name: "preserve", - policy: PreserveRollingUpdateCleanupPolicy, - responses: []runtime.Object{rcExisting}, - expected: []string{ - "get", - "update", - "get", - "get", - }, - }, - { - name: "delete", - policy: DeleteRollingUpdateCleanupPolicy, - responses: []runtime.Object{rcExisting}, - expected: []string{ - "get", - "update", - "get", - "get", - "delete", - }, - }, - { - name: "rename", - policy: RenameRollingUpdateCleanupPolicy, - responses: []runtime.Object{rcExisting}, - expected: []string{ - "get", - "update", - "get", - "get", - "delete", - "create", - "delete", - }, - }, - } - - for _, test := range tests { - fake := testclient.NewSimpleFake(test.responses...) - updater := &RollingUpdater{ - ns: "default", - c: fake, - } - config := &RollingUpdaterConfig{ - Out: ioutil.Discard, - OldRc: rc, - NewRc: rcExisting, - UpdatePeriod: 0, - Interval: time.Millisecond, - Timeout: time.Millisecond, - CleanupPolicy: test.policy, - } - err := updater.cleanupWithClients(rc, rcExisting, config) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(fake.Actions()) != len(test.expected) { - t.Fatalf("%s: unexpected actions: %v, expected %v", test.name, fake.Actions(), test.expected) - } - for j, action := range fake.Actions() { - if e, a := test.expected[j], action.GetVerb(); e != a { - t.Errorf("%s: unexpected action: expected %s, got %s", test.name, e, a) - } - } - } -} - -func TestFindSourceController(t *testing.T) { - ctrl1 := api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Annotations: map[string]string{ - sourceIdAnnotation: "bar:1234", - }, - }, - } - ctrl2 := api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - Annotations: map[string]string{ - sourceIdAnnotation: "foo:12345", - }, - }, - } - ctrl3 := api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{ - sourceIdAnnotation: "baz:45667", - }, - }, - } - tests := []struct { - list *api.ReplicationControllerList - expectedController *api.ReplicationController - err error - name string - expectError bool - }{ - { - list: &api.ReplicationControllerList{}, - expectError: true, - }, - { - list: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ctrl1}, - }, - name: "foo", - expectError: true, - }, - { - list: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ctrl1}, - }, - name: "bar", - expectedController: &ctrl1, - }, - { - list: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ctrl1, ctrl2}, - }, - name: "bar", - expectedController: &ctrl1, - }, - { - list: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ctrl1, ctrl2}, - }, - name: "foo", - expectedController: &ctrl2, - }, - { - list: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ctrl1, ctrl2, ctrl3}, - }, - name: "baz", - expectedController: &ctrl3, - }, - } - for _, test := range tests { - fakeClient := testclient.NewSimpleFake(test.list) - ctrl, err := FindSourceController(fakeClient, "default", test.name) - if test.expectError && err == nil { - t.Errorf("unexpected non-error") - } - if !test.expectError && err != nil { - t.Errorf("unexpected error") - } - if !reflect.DeepEqual(ctrl, test.expectedController) { - t.Errorf("expected:\n%v\ngot:\n%v\n", test.expectedController, ctrl) - } - } -} - -func TestUpdateExistingReplicationController(t *testing.T) { - tests := []struct { - rc *api.ReplicationController - name string - deploymentKey string - deploymentValue string - - expectedRc *api.ReplicationController - expectErr bool - }{ - { - rc: &api.ReplicationController{ - Spec: api.ReplicationControllerSpec{ - Template: &api.PodTemplateSpec{}, - }, - }, - name: "foo", - deploymentKey: "dk", - deploymentValue: "some-hash", - - expectedRc: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{ - "kubectl.kubernetes.io/next-controller-id": "foo", - }, - }, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "dk": "some-hash", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "dk": "some-hash", - }, - }, - }, - }, - }, - }, - { - rc: &api.ReplicationController{ - Spec: api.ReplicationControllerSpec{ - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "dk": "some-other-hash", - }, - }, - }, - Selector: map[string]string{ - "dk": "some-other-hash", - }, - }, - }, - name: "foo", - deploymentKey: "dk", - deploymentValue: "some-hash", - - expectedRc: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Annotations: map[string]string{ - "kubectl.kubernetes.io/next-controller-id": "foo", - }, - }, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "dk": "some-other-hash", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "dk": "some-other-hash", - }, - }, - }, - }, - }, - }, - } - for _, test := range tests { - buffer := &bytes.Buffer{} - fakeClient := testclient.NewSimpleFake(test.expectedRc) - rc, err := UpdateExistingReplicationController(fakeClient, test.rc, "default", test.name, test.deploymentKey, test.deploymentValue, buffer) - if !reflect.DeepEqual(rc, test.expectedRc) { - t.Errorf("expected:\n%#v\ngot:\n%#v\n", test.expectedRc, rc) - } - if test.expectErr && err == nil { - t.Errorf("unexpected non-error") - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - } -} - -func TestUpdateWithRetries(t *testing.T) { - codec := testapi.Default.Codec() - rc := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "rc", - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "foo": "bar", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - - // Test end to end updating of the rc with retries. Essentially make sure the update handler - // sees the right updates, failures in update/get are handled properly, and that the updated - // rc with new resource version is returned to the caller. Without any of these rollingupdate - // will fail cryptically. - newRc := *rc - newRc.ResourceVersion = "2" - newRc.Spec.Selector["baz"] = "foobar" - updates := []*http.Response{ - {StatusCode: 500, Body: objBody(codec, &api.ReplicationController{})}, - {StatusCode: 500, Body: objBody(codec, &api.ReplicationController{})}, - {StatusCode: 200, Body: objBody(codec, &newRc)}, - } - gets := []*http.Response{ - {StatusCode: 500, Body: objBody(codec, &api.ReplicationController{})}, - {StatusCode: 200, Body: objBody(codec, rc)}, - } - fakeClient := &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == testapi.Default.ResourcePath("replicationcontrollers", "default", "rc") && m == "PUT": - update := updates[0] - updates = updates[1:] - // We should always get an update with a valid rc even when the get fails. The rc should always - // contain the update. - if c, ok := readOrDie(t, req, codec).(*api.ReplicationController); !ok || !reflect.DeepEqual(rc, c) { - t.Errorf("Unexpected update body, got %+v expected %+v", c, rc) - } else if sel, ok := c.Spec.Selector["baz"]; !ok || sel != "foobar" { - t.Errorf("Expected selector label update, got %+v", c.Spec.Selector) - } else { - delete(c.Spec.Selector, "baz") - } - return update, nil - case p == testapi.Default.ResourcePath("replicationcontrollers", "default", "rc") && m == "GET": - get := gets[0] - gets = gets[1:] - return get, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - clientConfig := &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - client := client.NewOrDie(clientConfig) - client.Client = fakeClient.Client - - if rc, err := updateWithRetries( - client.ReplicationControllers("default"), rc, func(c *api.ReplicationController) { - c.Spec.Selector["baz"] = "foobar" - }); err != nil { - t.Errorf("unexpected error: %v", err) - } else if sel, ok := rc.Spec.Selector["baz"]; !ok || sel != "foobar" || rc.ResourceVersion != "2" { - t.Errorf("Expected updated rc, got %+v", rc) - } - if len(updates) != 0 || len(gets) != 0 { - t.Errorf("Remaining updates %+v gets %+v", updates, gets) - } -} - -func readOrDie(t *testing.T, req *http.Request, codec runtime.Codec) runtime.Object { - data, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Errorf("Error reading: %v", err) - t.FailNow() - } - obj, err := runtime.Decode(codec, data) - if err != nil { - t.Errorf("error decoding: %v", err) - t.FailNow() - } - return obj -} - -func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser { - return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj)))) -} - -func TestAddDeploymentHash(t *testing.T) { - buf := &bytes.Buffer{} - codec := testapi.Default.Codec() - rc := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{Name: "rc"}, - Spec: api.ReplicationControllerSpec{ - Selector: map[string]string{ - "foo": "bar", - }, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - }, - }, - } - - podList := &api.PodList{ - Items: []api.Pod{ - {ObjectMeta: api.ObjectMeta{Name: "foo"}}, - {ObjectMeta: api.ObjectMeta{Name: "bar"}}, - {ObjectMeta: api.ObjectMeta{Name: "baz"}}, - }, - } - - seen := sets.String{} - updatedRc := false - fakeClient := &fake.RESTClient{ - Codec: codec, - Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { - switch p, m := req.URL.Path, req.Method; { - case p == testapi.Default.ResourcePath("pods", "default", "") && m == "GET": - if req.URL.RawQuery != "labelSelector=foo%3Dbar" { - t.Errorf("Unexpected query string: %s", req.URL.RawQuery) - } - return &http.Response{StatusCode: 200, Body: objBody(codec, podList)}, nil - case p == testapi.Default.ResourcePath("pods", "default", "foo") && m == "PUT": - seen.Insert("foo") - obj := readOrDie(t, req, codec) - podList.Items[0] = *(obj.(*api.Pod)) - return &http.Response{StatusCode: 200, Body: objBody(codec, &podList.Items[0])}, nil - case p == testapi.Default.ResourcePath("pods", "default", "bar") && m == "PUT": - seen.Insert("bar") - obj := readOrDie(t, req, codec) - podList.Items[1] = *(obj.(*api.Pod)) - return &http.Response{StatusCode: 200, Body: objBody(codec, &podList.Items[1])}, nil - case p == testapi.Default.ResourcePath("pods", "default", "baz") && m == "PUT": - seen.Insert("baz") - obj := readOrDie(t, req, codec) - podList.Items[2] = *(obj.(*api.Pod)) - return &http.Response{StatusCode: 200, Body: objBody(codec, &podList.Items[2])}, nil - case p == testapi.Default.ResourcePath("replicationcontrollers", "default", "rc") && m == "PUT": - updatedRc = true - return &http.Response{StatusCode: 200, Body: objBody(codec, rc)}, nil - default: - t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) - return nil, nil - } - }), - } - clientConfig := &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}} - client := client.NewOrDie(clientConfig) - client.Client = fakeClient.Client - - if _, err := AddDeploymentKeyToReplicationController(rc, client, "dk", "hash", api.NamespaceDefault, buf); err != nil { - t.Errorf("unexpected error: %v", err) - } - for _, pod := range podList.Items { - if !seen.Has(pod.Name) { - t.Errorf("Missing update for pod: %s", pod.Name) - } - } - if !updatedRc { - t.Errorf("Failed to update replication controller with new labels") - } -} - -func TestRollingUpdater_readyPods(t *testing.T) { - mkpod := func(owner *api.ReplicationController, ready bool) *api.Pod { - labels := map[string]string{} - for k, v := range owner.Spec.Selector { - labels[k] = v - } - status := api.ConditionTrue - if !ready { - status = api.ConditionFalse - } - return &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "pod", - Labels: labels, - }, - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - Status: status, - }, - }, - }, - } - } - - tests := []struct { - oldRc *api.ReplicationController - newRc *api.ReplicationController - // expectated old/new ready counts - oldReady int32 - newReady int32 - // pods owned by the rcs; indicate whether they're ready - oldPods []bool - newPods []bool - }{ - { - oldRc: oldRc(4, 4), - newRc: newRc(4, 4), - oldReady: 4, - newReady: 2, - oldPods: []bool{ - true, - true, - true, - true, - }, - newPods: []bool{ - true, - false, - true, - false, - }, - }, - { - oldRc: oldRc(4, 4), - newRc: newRc(4, 4), - oldReady: 0, - newReady: 1, - oldPods: []bool{ - false, - }, - newPods: []bool{ - true, - }, - }, - { - oldRc: oldRc(4, 4), - newRc: newRc(4, 4), - oldReady: 1, - newReady: 0, - oldPods: []bool{ - true, - }, - newPods: []bool{ - false, - }, - }, - } - - for i, test := range tests { - t.Logf("evaluating test %d", i) - // Populate the fake client with pods associated with their owners. - pods := []runtime.Object{} - for _, ready := range test.oldPods { - pods = append(pods, mkpod(test.oldRc, ready)) - } - for _, ready := range test.newPods { - pods = append(pods, mkpod(test.newRc, ready)) - } - client := testclient.NewSimpleFake(pods...) - - updater := &RollingUpdater{ - ns: "default", - c: client, - } - oldReady, newReady, err := updater.readyPods(test.oldRc, test.newRc) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if e, a := test.oldReady, oldReady; e != a { - t.Errorf("expected old ready %d, got %d", e, a) - } - if e, a := test.newReady, newReady; e != a { - t.Errorf("expected new ready %d, got %d", e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/run_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/run_test.go deleted file mode 100644 index b211fc363..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/run_test.go +++ /dev/null @@ -1,885 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" -) - -func TestGenerate(t *testing.T) { - tests := []struct { - params map[string]interface{} - expected *api.ReplicationController - expectErr bool - }{ - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "port": "-1", - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"run": "foo"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - }, - }, - }, - }, - }, - }, - - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "port": "-1", - "env": []string{"a=b", "c=d"}, - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"run": "foo"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Env: []api.EnvVar{ - { - Name: "a", - Value: "b", - }, - { - Name: "c", - Value: "d", - }, - }, - }, - }, - }, - }, - }, - }, - }, - - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "port": "-1", - "args": []string{"bar", "baz", "blah"}, - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"run": "foo"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Args: []string{"bar", "baz", "blah"}, - }, - }, - }, - }, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "port": "-1", - "args": []string{"bar", "baz", "blah"}, - "command": "true", - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"run": "foo"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Command: []string{"bar", "baz", "blah"}, - }, - }, - }, - }, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "port": "80", - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"run": "foo"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Ports: []api.ContainerPort{ - { - ContainerPort: 80, - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "port": "80", - "hostport": "80", - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"run": "foo"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"run": "foo"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Ports: []api.ContainerPort{ - { - ContainerPort: 80, - HostPort: 80, - }, - }, - }, - }, - }, - }, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "hostport": "80", - }, - expected: nil, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar", "baz": "blah"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - }, - }, - }, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "hostport": "80", - }, - expected: nil, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - "requests": "cpu100m,memory=100Mi", - }, - expected: nil, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - "requests": "cpu=100m&memory=100Mi", - }, - expected: nil, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - "requests": "cpu=", - }, - expected: nil, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - "requests": "cpu=100m,memory=100Mi", - "limits": "cpu=400m,memory=200Mi", - }, - expected: &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar", "baz": "blah"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100m"), - api.ResourceMemory: resource.MustParse("100Mi"), - }, - Limits: api.ResourceList{ - api.ResourceCPU: resource.MustParse("400m"), - api.ResourceMemory: resource.MustParse("200Mi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - generator := BasicReplicationController{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*api.ReplicationController).Spec.Template, test.expected.Spec.Template) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected.Spec.Template, obj.(*api.ReplicationController).Spec.Template) - } - } -} - -func TestGeneratePod(t *testing.T) { - tests := []struct { - params map[string]interface{} - expected *api.Pod - expectErr bool - }{ - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "port": "-1", - }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - ImagePullPolicy: api.PullIfNotPresent, - }, - }, - DNSPolicy: api.DNSClusterFirst, - RestartPolicy: api.RestartPolicyAlways, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "env": []string{"a", "c"}, - }, - - expected: nil, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "env": []string{"a=b", "c=d"}, - }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - ImagePullPolicy: api.PullIfNotPresent, - Env: []api.EnvVar{ - { - Name: "a", - Value: "b", - }, - { - Name: "c", - Value: "d", - }, - }, - }, - }, - DNSPolicy: api.DNSClusterFirst, - RestartPolicy: api.RestartPolicyAlways, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "port": "80", - }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - ImagePullPolicy: api.PullIfNotPresent, - Ports: []api.ContainerPort{ - { - ContainerPort: 80, - }, - }, - }, - }, - DNSPolicy: api.DNSClusterFirst, - RestartPolicy: api.RestartPolicyAlways, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "port": "80", - "hostport": "80", - }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - ImagePullPolicy: api.PullIfNotPresent, - Ports: []api.ContainerPort{ - { - ContainerPort: 80, - HostPort: 80, - }, - }, - }, - }, - DNSPolicy: api.DNSClusterFirst, - RestartPolicy: api.RestartPolicyAlways, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "hostport": "80", - }, - expected: nil, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - ImagePullPolicy: api.PullIfNotPresent, - }, - }, - DNSPolicy: api.DNSClusterFirst, - RestartPolicy: api.RestartPolicyAlways, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - "stdin": "true", - }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - ImagePullPolicy: api.PullIfNotPresent, - Stdin: true, - StdinOnce: true, - }, - }, - DNSPolicy: api.DNSClusterFirst, - RestartPolicy: api.RestartPolicyAlways, - }, - }, - }, - { - params: map[string]interface{}{ - "name": "foo", - "image": "someimage", - "replicas": "1", - "labels": "foo=bar,baz=blah", - "stdin": "true", - "leave-stdin-open": "true", - }, - expected: &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - ImagePullPolicy: api.PullIfNotPresent, - Stdin: true, - StdinOnce: false, - }, - }, - DNSPolicy: api.DNSClusterFirst, - RestartPolicy: api.RestartPolicyAlways, - }, - }, - }, - } - generator := BasicPod{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*api.Pod), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Pod)) - } - } -} - -func TestGenerateDeployment(t *testing.T) { - tests := []struct { - params map[string]interface{} - expected *extensions.Deployment - expectErr bool - }{ - { - params: map[string]interface{}{ - "labels": "foo=bar,baz=blah", - "name": "foo", - "replicas": "3", - "image": "someimage", - "port": "80", - "hostport": "80", - "stdin": "true", - "command": "true", - "args": []string{"bar", "baz", "blah"}, - "env": []string{"a=b", "c=d"}, - "requests": "cpu=100m,memory=100Mi", - "limits": "cpu=400m,memory=200Mi", - }, - expected: &extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 3, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar", "baz": "blah"}}, - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Stdin: true, - Ports: []api.ContainerPort{ - { - ContainerPort: 80, - HostPort: 80, - }, - }, - Command: []string{"bar", "baz", "blah"}, - Env: []api.EnvVar{ - { - Name: "a", - Value: "b", - }, - { - Name: "c", - Value: "d", - }, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100m"), - api.ResourceMemory: resource.MustParse("100Mi"), - }, - Limits: api.ResourceList{ - api.ResourceCPU: resource.MustParse("400m"), - api.ResourceMemory: resource.MustParse("200Mi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - generator := DeploymentV1Beta1{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*extensions.Deployment), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*extensions.Deployment)) - } - } -} - -func TestGenerateJob(t *testing.T) { - tests := []struct { - params map[string]interface{} - expected *batch.Job - expectErr bool - }{ - { - params: map[string]interface{}{ - "labels": "foo=bar,baz=blah", - "name": "foo", - "image": "someimage", - "port": "80", - "hostport": "80", - "stdin": "true", - "leave-stdin-open": "true", - "command": "true", - "args": []string{"bar", "baz", "blah"}, - "env": []string{"a=b", "c=d"}, - "requests": "cpu=100m,memory=100Mi", - "limits": "cpu=400m,memory=200Mi", - "restart": "OnFailure", - }, - expected: &batch.Job{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: batch.JobSpec{ - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - ManualSelector: newBool(true), - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - Spec: api.PodSpec{ - RestartPolicy: api.RestartPolicyOnFailure, - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - Stdin: true, - StdinOnce: false, - Ports: []api.ContainerPort{ - { - ContainerPort: 80, - HostPort: 80, - }, - }, - Command: []string{"bar", "baz", "blah"}, - Env: []api.EnvVar{ - { - Name: "a", - Value: "b", - }, - { - Name: "c", - Value: "d", - }, - }, - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceCPU: resource.MustParse("100m"), - api.ResourceMemory: resource.MustParse("100Mi"), - }, - Limits: api.ResourceList{ - api.ResourceCPU: resource.MustParse("400m"), - api.ResourceMemory: resource.MustParse("200Mi"), - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - generator := JobV1Beta1{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*batch.Job), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*batch.Job)) - } - } -} - -func TestParseEnv(t *testing.T) { - tests := []struct { - envArray []string - expected []api.EnvVar - expectErr bool - test string - }{ - { - envArray: []string{ - "THIS_ENV=isOK", - "HAS_COMMAS=foo,bar", - "HAS_EQUALS=jJnro54iUu75xNy==", - }, - expected: []api.EnvVar{ - { - Name: "THIS_ENV", - Value: "isOK", - }, - { - Name: "HAS_COMMAS", - Value: "foo,bar", - }, - { - Name: "HAS_EQUALS", - Value: "jJnro54iUu75xNy==", - }, - }, - expectErr: false, - test: "test case 1", - }, - { - envArray: []string{ - "WITH_OUT_EQUALS", - }, - expected: []api.EnvVar{}, - expectErr: true, - test: "test case 2", - }, - { - envArray: []string{ - "WITH_OUT_VALUES=", - }, - expected: []api.EnvVar{}, - expectErr: true, - test: "test case 3", - }, - { - envArray: []string{ - "=WITH_OUT_NAME", - }, - expected: []api.EnvVar{}, - expectErr: true, - test: "test case 4", - }, - } - - for _, test := range tests { - envs, err := parseEnvs(test.envArray) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(envs, test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v (%s)", test.expected, envs, test.test) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/scale_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/scale_test.go deleted file mode 100644 index f3ccb3ac9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/scale_test.go +++ /dev/null @@ -1,729 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "errors" - "testing" - - "k8s.io/kubernetes/pkg/api" - kerrors "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient" -) - -type ErrorReplicationControllers struct { - testclient.FakeReplicationControllers - invalid bool -} - -func (c *ErrorReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) { - if c.invalid { - return nil, kerrors.NewInvalid(api.Kind(controller.Kind), controller.Name, nil) - } - return nil, errors.New("Replication controller update failure") -} - -type ErrorReplicationControllerClient struct { - testclient.Fake - invalid bool -} - -func (c *ErrorReplicationControllerClient) ReplicationControllers(namespace string) client.ReplicationControllerInterface { - return &ErrorReplicationControllers{testclient.FakeReplicationControllers{Fake: &c.Fake, Namespace: namespace}, c.invalid} -} - -func TestReplicationControllerScaleRetry(t *testing.T) { - fake := &ErrorReplicationControllerClient{Fake: testclient.Fake{}, invalid: false} - scaler := ReplicationControllerScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - namespace := "default" - - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count) - pass, err := scaleFunc() - if pass { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } - if err != nil { - t.Errorf("Did not expect an error on update failure, got %v", err) - } - preconditions = ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(&scaler, &preconditions, namespace, name, count) - pass, err = scaleFunc() - if err == nil { - t.Errorf("Expected error on precondition failure") - } -} - -func TestReplicationControllerScaleInvalid(t *testing.T) { - fake := &ErrorReplicationControllerClient{Fake: testclient.Fake{}, invalid: true} - scaler := ReplicationControllerScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - namespace := "default" - - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count) - pass, err := scaleFunc() - if pass { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateInvalidFailure { - t.Errorf("Expected error on invalid update failure, got %v", err) - } -} - -func TestReplicationControllerScale(t *testing.T) { - fake := &testclient.Fake{} - scaler := ReplicationControllerScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) - } - if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "replicationcontrollers" || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name) - } - if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "replicationcontrollers" || action.GetObject().(*api.ReplicationController).Spec.Replicas != int32(count) { - t.Errorf("unexpected action %v, expected update-replicationController with replicas = %d", actions[1], count) - } -} - -func TestReplicationControllerScaleFailsPreconditions(t *testing.T) { - fake := testclient.NewSimpleFake(&api.ReplicationController{ - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }) - scaler := ReplicationControllerScaler{fake} - preconditions := ScalePrecondition{2, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 action (get)", actions) - } - if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "replicationcontrollers" || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name) - } -} - -func TestValidateReplicationController(t *testing.T) { - tests := []struct { - preconditions ScalePrecondition - controller api.ReplicationController - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - controller: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - controller: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 20, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 10, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - controller: api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 20, - }, - }, - expectError: true, - test: "both different", - }, - } - for _, test := range tests { - err := test.preconditions.ValidateReplicationController(&test.controller) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil && test.expectError { - t.Errorf("unexpected non-error: %v (%s)", err, test.test) - } - } -} - -type ErrorJobs struct { - testclient.FakeJobs - invalid bool -} - -func (c *ErrorJobs) Update(job *batch.Job) (*batch.Job, error) { - if c.invalid { - return nil, kerrors.NewInvalid(batch.Kind(job.Kind), job.Name, nil) - } - return nil, errors.New("Job update failure") -} - -func (c *ErrorJobs) Get(name string) (*batch.Job, error) { - zero := int32(0) - return &batch.Job{ - Spec: batch.JobSpec{ - Parallelism: &zero, - }, - }, nil -} - -type ErrorJobClient struct { - testclient.FakeExperimental - invalid bool -} - -func (c *ErrorJobClient) Jobs(namespace string) client.JobInterface { - return &ErrorJobs{testclient.FakeJobs{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid} -} - -func TestJobScaleRetry(t *testing.T) { - fake := &ErrorJobClient{FakeExperimental: testclient.FakeExperimental{}, invalid: false} - scaler := JobScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - namespace := "default" - - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count) - pass, err := scaleFunc() - if pass != false { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } - if err != nil { - t.Errorf("Did not expect an error on update failure, got %v", err) - } - preconditions = ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(&scaler, &preconditions, namespace, name, count) - pass, err = scaleFunc() - if err == nil { - t.Errorf("Expected error on precondition failure") - } -} - -func TestJobScale(t *testing.T) { - fake := &testclient.FakeExperimental{Fake: &testclient.Fake{}} - scaler := JobScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) - } - if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "jobs" || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name) - } - if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "jobs" || *action.GetObject().(*batch.Job).Spec.Parallelism != int32(count) { - t.Errorf("unexpected action %v, expected update-job with parallelism = %d", actions[1], count) - } -} - -func TestJobScaleInvalid(t *testing.T) { - fake := &ErrorJobClient{FakeExperimental: testclient.FakeExperimental{}, invalid: true} - scaler := JobScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - namespace := "default" - - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count) - pass, err := scaleFunc() - if pass { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateInvalidFailure { - t.Errorf("Expected error on invalid update failure, got %v", err) - } -} - -func TestJobScaleFailsPreconditions(t *testing.T) { - ten := int32(10) - fake := testclient.NewSimpleFake(&batch.Job{ - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }) - scaler := JobScaler{&testclient.FakeExperimental{Fake: fake}} - preconditions := ScalePrecondition{2, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions) - } - if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "jobs" || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-job %s", actions[0], name) - } -} - -func TestValidateJob(t *testing.T) { - zero, ten, twenty := int32(0), int32(10), int32(20) - tests := []struct { - preconditions ScalePrecondition - job batch.Job - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: batch.JobSpec{ - Parallelism: &twenty, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - }, - expectError: true, - test: "parallelism nil", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: batch.JobSpec{ - Parallelism: &ten, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - job: batch.Job{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: batch.JobSpec{ - Parallelism: &twenty, - }, - }, - expectError: true, - test: "both different", - }, - } - for _, test := range tests { - err := test.preconditions.ValidateJob(&test.job) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil && test.expectError { - t.Errorf("unexpected non-error: %v (%s)", err, test.test) - } - } -} - -type ErrorDeployments struct { - testclient.FakeDeployments - invalid bool -} - -func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) { - if c.invalid { - return nil, kerrors.NewInvalid(extensions.Kind(deployment.Kind), deployment.Name, nil) - } - return nil, errors.New("deployment update failure") -} - -func (c *ErrorDeployments) Get(name string) (*extensions.Deployment, error) { - return &extensions.Deployment{ - Spec: extensions.DeploymentSpec{ - Replicas: 0, - }, - }, nil -} - -type ErrorDeploymentClient struct { - testclient.FakeExperimental - invalid bool -} - -func (c *ErrorDeploymentClient) Deployments(namespace string) client.DeploymentInterface { - return &ErrorDeployments{testclient.FakeDeployments{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid} -} - -func TestDeploymentScaleRetry(t *testing.T) { - fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: false} - scaler := &DeploymentScaler{fake} - preconditions := &ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - namespace := "default" - - scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count) - pass, err := scaleFunc() - if pass != false { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } - if err != nil { - t.Errorf("Did not expect an error on update failure, got %v", err) - } - preconditions = &ScalePrecondition{3, ""} - scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count) - pass, err = scaleFunc() - if err == nil { - t.Errorf("Expected error on precondition failure") - } -} - -func TestDeploymentScale(t *testing.T) { - fake := &testclient.FakeExperimental{Fake: &testclient.Fake{}} - scaler := DeploymentScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 2 { - t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions) - } - if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name) - } - if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "deployments" || action.GetObject().(*extensions.Deployment).Spec.Replicas != int32(count) { - t.Errorf("unexpected action %v, expected update-deployment with replicas = %d", actions[1], count) - } -} - -func TestDeploymentScaleInvalid(t *testing.T) { - fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: true} - scaler := DeploymentScaler{fake} - preconditions := ScalePrecondition{-1, ""} - count := uint(3) - name := "foo" - namespace := "default" - - scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count) - pass, err := scaleFunc() - if pass { - t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass) - } - e, ok := err.(ScaleError) - if err == nil || !ok || e.FailureType != ScaleUpdateInvalidFailure { - t.Errorf("Expected error on invalid update failure, got %v", err) - } -} - -func TestDeploymentScaleFailsPreconditions(t *testing.T) { - fake := testclient.NewSimpleFake(&extensions.Deployment{ - Spec: extensions.DeploymentSpec{ - Replicas: 10, - }, - }) - scaler := DeploymentScaler{&testclient.FakeExperimental{Fake: fake}} - preconditions := ScalePrecondition{2, ""} - count := uint(3) - name := "foo" - scaler.Scale("default", name, count, &preconditions, nil, nil) - - actions := fake.Actions() - if len(actions) != 1 { - t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions) - } - if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name { - t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name) - } -} - -func TestValidateDeployment(t *testing.T) { - zero, ten, twenty := int32(0), int32(10), int32(20) - tests := []struct { - preconditions ScalePrecondition - deployment extensions.Deployment - expectError bool - test string - }{ - { - preconditions: ScalePrecondition{-1, ""}, - expectError: false, - test: "defaults", - }, - { - preconditions: ScalePrecondition{-1, ""}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "defaults 2", - }, - { - preconditions: ScalePrecondition{0, ""}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: zero, - }, - }, - expectError: false, - test: "size matches", - }, - { - preconditions: ScalePrecondition{-1, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "resource version matches", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: false, - test: "both match", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - Spec: extensions.DeploymentSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "size different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "foo", - }, - }, - expectError: true, - test: "no replicas", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: extensions.DeploymentSpec{ - Replicas: ten, - }, - }, - expectError: true, - test: "version different", - }, - { - preconditions: ScalePrecondition{10, "foo"}, - deployment: extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - ResourceVersion: "bar", - }, - Spec: extensions.DeploymentSpec{ - Replicas: twenty, - }, - }, - expectError: true, - test: "both different", - }, - } - for _, test := range tests { - err := test.preconditions.ValidateDeployment(&test.deployment) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil && test.expectError { - t.Errorf("unexpected non-error: %v (%s)", err, test.test) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/secret_for_docker_registry_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/secret_for_docker_registry_test.go deleted file mode 100644 index 65d8d397d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/secret_for_docker_registry_test.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func TestSecretForDockerRegistryGenerate(t *testing.T) { - username, password, email, server := "test-user", "test-password", "test-user@example.org", "https://index.docker.io/v1/" - secretData, err := handleDockercfgContent(username, password, email, server) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - tests := map[string]struct { - params map[string]interface{} - expected *api.Secret - expectErr bool - }{ - "test-valid-use": { - params: map[string]interface{}{ - "name": "foo", - "docker-server": server, - "docker-username": username, - "docker-password": password, - "docker-email": email, - }, - expected: &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string][]byte{ - api.DockerConfigKey: secretData, - }, - Type: api.SecretTypeDockercfg, - }, - expectErr: false, - }, - "test-missing-required-param": { - params: map[string]interface{}{ - "name": "foo", - "docker-server": server, - "docker-password": password, - "docker-email": email, - }, - expectErr: true, - }, - } - - generator := SecretForDockerRegistryGeneratorV1{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*api.Secret), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Secret)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/secret_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/secret_test.go deleted file mode 100644 index 944c42356..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/secret_test.go +++ /dev/null @@ -1,124 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func TestSecretGenerate(t *testing.T) { - tests := []struct { - params map[string]interface{} - expected *api.Secret - expectErr bool - }{ - { - params: map[string]interface{}{ - "name": "foo", - }, - expected: &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string][]byte{}, - }, - expectErr: false, - }, - { - params: map[string]interface{}{ - "name": "foo", - "type": "my-type", - }, - expected: &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string][]byte{}, - Type: "my-type", - }, - expectErr: false, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-literal": []string{"key1=value1", "key2=value2"}, - }, - expected: &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string][]byte{ - "key1": []byte("value1"), - "key2": []byte("value2"), - }, - }, - expectErr: false, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-literal": []string{"key1value1"}, - }, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-file": []string{"key1=/file=2"}, - }, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-file": []string{"key1==value"}, - }, - expectErr: true, - }, - { - params: map[string]interface{}{ - "name": "foo", - "from-literal": []string{"key1==value1"}, - }, - expected: &api.Secret{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - Data: map[string][]byte{ - "key1": []byte("=value1"), - }, - }, - expectErr: false, - }, - } - generator := SecretGeneratorV1{} - for _, test := range tests { - obj, err := generator.Generate(test.params) - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*api.Secret), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.Secret)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/service_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/service_test.go deleted file mode 100644 index 80144239e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/service_test.go +++ /dev/null @@ -1,417 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/util/intstr" -) - -func TestGenerateService(t *testing.T) { - tests := []struct { - generator Generator - params map[string]interface{} - expected api.Service - }{ - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "TCP", - "container-port": "1234", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - TargetPort: intstr.FromInt(1234), - }, - }, - }, - }, - }, - { - - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "UDP", - "container-port": "foobar", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "UDP", - TargetPort: intstr.FromString("foobar"), - }, - }, - }, - }, - }, - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "labels": "key1=value1,key2=value2", - "name": "test", - "port": "80", - "protocol": "TCP", - "container-port": "1234", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - Labels: map[string]string{ - "key1": "value1", - "key2": "value2", - }, - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "TCP", - TargetPort: intstr.FromInt(1234), - }, - }, - }, - }, - }, - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "UDP", - "container-port": "foobar", - "external-ip": "1.2.3.4", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "UDP", - TargetPort: intstr.FromString("foobar"), - }, - }, - ExternalIPs: []string{"1.2.3.4"}, - }, - }, - }, - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "UDP", - "container-port": "foobar", - "external-ip": "1.2.3.4", - "create-external-load-balancer": "true", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "UDP", - TargetPort: intstr.FromString("foobar"), - }, - }, - Type: api.ServiceTypeLoadBalancer, - ExternalIPs: []string{"1.2.3.4"}, - }, - }, - }, - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "UDP", - "container-port": "foobar", - "type": string(api.ServiceTypeNodePort), - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "UDP", - TargetPort: intstr.FromString("foobar"), - }, - }, - Type: api.ServiceTypeNodePort, - }, - }, - }, - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "UDP", - "container-port": "foobar", - "create-external-load-balancer": "true", // ignored when type is present - "type": string(api.ServiceTypeNodePort), - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Port: 80, - Protocol: "UDP", - TargetPort: intstr.FromString("foobar"), - }, - }, - Type: api.ServiceTypeNodePort, - }, - }, - }, - { - generator: ServiceGeneratorV1{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "TCP", - "container-port": "1234", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Name: "default", - Port: 80, - Protocol: "TCP", - TargetPort: intstr.FromInt(1234), - }, - }, - }, - }, - }, - { - generator: ServiceGeneratorV1{}, - params: map[string]interface{}{ - "selector": "foo=bar,baz=blah", - "name": "test", - "port": "80", - "protocol": "TCP", - "container-port": "1234", - "session-affinity": "ClientIP", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - "baz": "blah", - }, - Ports: []api.ServicePort{ - { - Name: "default", - Port: 80, - Protocol: "TCP", - TargetPort: intstr.FromInt(1234), - }, - }, - SessionAffinity: api.ServiceAffinityClientIP, - }, - }, - }, - { - generator: ServiceGeneratorV1{}, - params: map[string]interface{}{ - "selector": "foo=bar", - "name": "test", - "ports": "80,443", - "protocol": "TCP", - "container-port": "foobar", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - }, - Ports: []api.ServicePort{ - { - Name: "port-1", - Port: 80, - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromString("foobar"), - }, - { - Name: "port-2", - Port: 443, - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromString("foobar"), - }, - }, - }, - }, - }, - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar", - "name": "test", - "ports": "80,443", - "protocol": "UDP", - "target-port": "1234", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - }, - Ports: []api.ServicePort{ - { - Name: "port-1", - Port: 80, - Protocol: api.ProtocolUDP, - TargetPort: intstr.FromInt(1234), - }, - { - Name: "port-2", - Port: 443, - Protocol: api.ProtocolUDP, - TargetPort: intstr.FromInt(1234), - }, - }, - }, - }, - }, - { - generator: ServiceGeneratorV2{}, - params: map[string]interface{}{ - "selector": "foo=bar", - "name": "test", - "ports": "80,443", - "protocol": "TCP", - }, - expected: api.Service{ - ObjectMeta: api.ObjectMeta{ - Name: "test", - }, - Spec: api.ServiceSpec{ - Selector: map[string]string{ - "foo": "bar", - }, - Ports: []api.ServicePort{ - { - Name: "port-1", - Port: 80, - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(80), - }, - { - Name: "port-2", - Port: 443, - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(443), - }, - }, - }, - }, - }, - } - for _, test := range tests { - obj, err := test.generator.Generate(test.params) - if !reflect.DeepEqual(obj, &test.expected) { - t.Errorf("expected:\n%#v\ngot\n%#v\n", &test.expected, obj) - } - if err != nil { - t.Errorf("unexpected error: %v", err) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/serviceaccount_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/serviceaccount_test.go deleted file mode 100644 index ca000f85f..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/serviceaccount_test.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -func TestServiceAccountGenerate(t *testing.T) { - tests := []struct { - name string - expected *api.ServiceAccount - expectErr bool - }{ - { - name: "foo", - expected: &api.ServiceAccount{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - }, - }, - expectErr: false, - }, - { - expectErr: true, - }, - } - for _, test := range tests { - generator := ServiceAccountGeneratorV1{ - Name: test.name, - } - obj, err := generator.StructuredGenerate() - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectErr && err != nil { - continue - } - if !reflect.DeepEqual(obj.(*api.ServiceAccount), test.expected) { - t.Errorf("\nexpected:\n%#v\nsaw:\n%#v", test.expected, obj.(*api.ServiceAccount)) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/sorted_event_list_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/sorted_event_list_test.go deleted file mode 100644 index 471069ed2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/sorted_event_list_test.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "sort" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -// VerifyDatesInOrder checks the start of each line for a RFC1123Z date -// and posts error if all subsequent dates are not equal or increasing -func VerifyDatesInOrder( - resultToTest, rowDelimiter, columnDelimiter string, t *testing.T) { - lines := strings.Split(resultToTest, rowDelimiter) - var previousTime time.Time - for _, str := range lines { - columns := strings.Split(str, columnDelimiter) - if len(columns) > 0 { - currentTime, err := time.Parse(time.RFC1123Z, columns[0]) - if err == nil { - if previousTime.After(currentTime) { - t.Errorf( - "Output is not sorted by time. %s should be listed after %s. Complete output: %s", - previousTime.Format(time.RFC1123Z), - currentTime.Format(time.RFC1123Z), - resultToTest) - } - previousTime = currentTime - } - } - } - -} - -func TestSortableEvents(t *testing.T) { - // Arrange - list := SortableEvents([]api.Event{ - { - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 1", - FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - { - Source: api.EventSource{Component: "scheduler"}, - Message: "Item 2", - FirstTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(1987, time.June, 17, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - { - Source: api.EventSource{Component: "kubelet"}, - Message: "Item 3", - FirstTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), - LastTimestamp: unversioned.NewTime(time.Date(2002, time.December, 25, 0, 0, 0, 0, time.UTC)), - Count: 1, - Type: api.EventTypeNormal, - }, - }) - - // Act - sort.Sort(list) - - // Assert - if list[0].Message != "Item 2" || - list[1].Message != "Item 3" || - list[2].Message != "Item 1" { - t.Fatal("List is not sorted by time. List: ", list) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/sorting_printer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/sorting_printer_test.go deleted file mode 100644 index 4839159a3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/sorting_printer_test.go +++ /dev/null @@ -1,236 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "reflect" - "testing" - - internal "k8s.io/kubernetes/pkg/api" - api "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/runtime" -) - -func encodeOrDie(obj runtime.Object) []byte { - data, err := runtime.Encode(internal.Codecs.LegacyCodec(api.SchemeGroupVersion), obj) - if err != nil { - panic(err.Error()) - } - return data -} - -func TestSortingPrinter(t *testing.T) { - intPtr := func(val int32) *int32 { return &val } - - a := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "a", - }, - } - - b := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "b", - }, - } - - c := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "c", - }, - } - - tests := []struct { - obj runtime.Object - sort runtime.Object - field string - name string - }{ - { - name: "in-order-already", - obj: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "a", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "c", - }, - }, - }, - }, - sort: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "a", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "c", - }, - }, - }, - }, - field: "{.metadata.name}", - }, - { - name: "reverse-order", - obj: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "c", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "a", - }, - }, - }, - }, - sort: &api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "a", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "b", - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "c", - }, - }, - }, - }, - field: "{.metadata.name}", - }, - { - name: "random-order-numbers", - obj: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(5), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(1), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(9), - }, - }, - }, - }, - sort: &api.ReplicationControllerList{ - Items: []api.ReplicationController{ - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(1), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(5), - }, - }, - { - Spec: api.ReplicationControllerSpec{ - Replicas: intPtr(9), - }, - }, - }, - }, - field: "{.spec.replicas}", - }, - { - name: "v1.List in order", - obj: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, - }, - }, - sort: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, - }, - }, - field: "{.metadata.name}", - }, - { - name: "v1.List in reverse", - obj: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(c)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(a)}, - }, - }, - sort: &api.List{ - Items: []runtime.RawExtension{ - {Raw: encodeOrDie(a)}, - {Raw: encodeOrDie(b)}, - {Raw: encodeOrDie(c)}, - }, - }, - field: "{.metadata.name}", - }, - } - for _, test := range tests { - sort := &SortingPrinter{SortField: test.field, Decoder: internal.Codecs.UniversalDecoder()} - if err := sort.sortObj(test.obj); err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.name) - continue - } - if !reflect.DeepEqual(test.obj, test.sort) { - t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v", test.name, test.sort, test.obj) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/stop_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/stop_test.go deleted file mode 100644 index dfc161051..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/stop_test.go +++ /dev/null @@ -1,717 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 kubectl - -import ( - "fmt" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/batch" - "k8s.io/kubernetes/pkg/apis/extensions" - client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/client/unversioned/testclient" - "k8s.io/kubernetes/pkg/runtime" - deploymentutil "k8s.io/kubernetes/pkg/util/deployment" -) - -func TestReplicationControllerStop(t *testing.T) { - name := "foo" - ns := "default" - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "OnlyOneRC", - Objs: []runtime.Object{ - &api.ReplicationController{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "list", "get", "update", "get", "get", "delete"}, - }, - { - Name: "NoOverlapping", - Objs: []runtime.Object{ - &api.ReplicationController{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k3": "v3"}}, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "list", "get", "update", "get", "get", "delete"}, - }, - { - Name: "OverlappingError", - Objs: []runtime.Object{ - - &api.ReplicationController{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1", "k2": "v2"}}, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - StopError: fmt.Errorf("Detected overlapping controllers for rc foo: baz, please manage deletion individually with --cascade=false."), - ExpectedActions: []string{"get", "list"}, - }, - - { - Name: "OverlappingButSafeDelete", - Objs: []runtime.Object{ - - &api.ReplicationController{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1", "k2": "v2"}}, - }, - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"}}, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: "zaz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1", "k2": "v2"}}, - }, - }, - }, - }, - - StopError: fmt.Errorf("Detected overlapping controllers for rc foo: baz,zaz, please manage deletion individually with --cascade=false."), - ExpectedActions: []string{"get", "list"}, - }, - - { - Name: "TwoExactMatchRCs", - Objs: []runtime.Object{ - - &api.ReplicationController{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - &api.ReplicationControllerList{ // LIST - Items: []api.ReplicationController{ - { - ObjectMeta: api.ObjectMeta{ - Name: "zaz", - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 0, - Selector: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - - StopError: nil, - ExpectedActions: []string{"get", "list", "delete"}, - }, - } - - for _, test := range tests { - fake := testclient.NewSimpleFake(test.Objs...) - reaper := ReplicationControllerReaper{fake, time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, verb := range test.ExpectedActions { - if actions[i].GetResource() != "replicationcontrollers" { - t.Errorf("%s unexpected action: %+v, expected %s-replicationController", test.Name, actions[i], verb) - } - if actions[i].GetVerb() != verb { - t.Errorf("%s unexpected action: %+v, expected %s-replicationController", test.Name, actions[i], verb) - } - } - } -} - -func TestReplicaSetStop(t *testing.T) { - name := "foo" - ns := "default" - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "OnlyOneRS", - Objs: []runtime.Object{ - &extensions.ReplicaSet{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - }, - &extensions.ReplicaSetList{ // LIST - Items: []extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "get", "update", "get", "get", "delete"}, - }, - { - Name: "NoOverlapping", - Objs: []runtime.Object{ - &extensions.ReplicaSet{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - }, - &extensions.ReplicaSetList{ // LIST - Items: []extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{ - Name: "baz", - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"k3": "v3"}}, - }, - }, - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 0, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get", "get", "update", "get", "get", "delete"}, - }, - // TODO: Implement tests for overlapping replica sets, similar to replication controllers, - // when the overlapping checks are implemented for replica sets. - } - - for _, test := range tests { - fake := testclient.NewSimpleFake(test.Objs...) - reaper := ReplicaSetReaper{fake, time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, verb := range test.ExpectedActions { - if actions[i].GetResource() != "replicasets" { - t.Errorf("%s unexpected action: %+v, expected %s-replicaSet", test.Name, actions[i], verb) - } - if actions[i].GetVerb() != verb { - t.Errorf("%s unexpected action: %+v, expected %s-replicaSet", test.Name, actions[i], verb) - } - } - } -} - -func TestJobStop(t *testing.T) { - name := "foo" - ns := "default" - zero := int32(0) - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "OnlyOneJob", - Objs: []runtime.Object{ - &batch.Job{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"k1": "v1"}, - }, - }, - }, - &batch.JobList{ // LIST - Items: []batch.Job{ - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"k1": "v1"}, - }, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:jobs", "get:jobs", "update:jobs", - "get:jobs", "get:jobs", "list:pods", "delete:jobs"}, - }, - { - Name: "JobWithDeadPods", - Objs: []runtime.Object{ - &batch.Job{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"k1": "v1"}, - }, - }, - }, - &batch.JobList{ // LIST - Items: []batch.Job{ - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: batch.JobSpec{ - Parallelism: &zero, - Selector: &unversioned.LabelSelector{ - MatchLabels: map[string]string{"k1": "v1"}, - }, - }, - }, - }, - }, - &api.PodList{ // LIST - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - Name: "pod1", - Namespace: ns, - Labels: map[string]string{"k1": "v1"}, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:jobs", "get:jobs", "update:jobs", - "get:jobs", "get:jobs", "list:pods", "delete:pods", "delete:jobs"}, - }, - } - - for _, test := range tests { - fake := testclient.NewSimpleFake(test.Objs...) - reaper := JobReaper{fake, time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, expAction := range test.ExpectedActions { - action := strings.Split(expAction, ":") - if actions[i].GetVerb() != action[0] { - t.Errorf("%s unexpected verb: %+v, expected %s", test.Name, actions[i], expAction) - } - if actions[i].GetResource() != action[1] { - t.Errorf("%s unexpected resource: %+v, expected %s", test.Name, actions[i], expAction) - } - } - } -} - -func TestDeploymentStop(t *testing.T) { - name := "foo" - ns := "default" - deployment := extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 0, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - Status: extensions.DeploymentStatus{ - Replicas: 0, - }, - } - template := deploymentutil.GetNewReplicaSetTemplate(&deployment) - tests := []struct { - Name string - Objs []runtime.Object - StopError error - ExpectedActions []string - }{ - { - Name: "SimpleDeployment", - Objs: []runtime.Object{ - &extensions.Deployment{ // GET - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 0, - Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"k1": "v1"}}, - }, - Status: extensions.DeploymentStatus{ - Replicas: 0, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:deployments", "update:deployments", - "get:deployments", "list:replicasets", "delete:deployments"}, - }, - { - Name: "Deployment with single replicaset", - Objs: []runtime.Object{ - &deployment, // GET - &extensions.ReplicaSetList{ // LIST - Items: []extensions.ReplicaSet{ - { - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: ns, - }, - Spec: extensions.ReplicaSetSpec{ - Template: template, - }, - }, - }, - }, - }, - StopError: nil, - ExpectedActions: []string{"get:deployments", "update:deployments", - "get:deployments", "list:replicasets", "get:replicasets", - "get:replicasets", "update:replicasets", "get:replicasets", - "get:replicasets", "delete:replicasets", "delete:deployments"}, - }, - } - - for _, test := range tests { - fake := testclient.NewSimpleFake(test.Objs...) - reaper := DeploymentReaper{fake, time.Millisecond, time.Millisecond} - err := reaper.Stop(ns, name, 0, nil) - if !reflect.DeepEqual(err, test.StopError) { - t.Errorf("%s unexpected error: %v", test.Name, err) - continue - } - - actions := fake.Actions() - if len(actions) != len(test.ExpectedActions) { - t.Errorf("%s unexpected actions: %v, expected %d actions got %d", test.Name, actions, len(test.ExpectedActions), len(actions)) - continue - } - for i, expAction := range test.ExpectedActions { - action := strings.Split(expAction, ":") - if actions[i].GetVerb() != action[0] { - t.Errorf("%s unexpected verb: %+v, expected %s", test.Name, actions[i], expAction) - } - if actions[i].GetResource() != action[1] { - t.Errorf("%s unexpected resource: %+v, expected %s", test.Name, actions[i], expAction) - } - if len(action) == 3 && actions[i].GetSubresource() != action[2] { - t.Errorf("%s unexpected subresource: %+v, expected %s", test.Name, actions[i], expAction) - } - } - } -} - -type noSuchPod struct { - *testclient.FakePods -} - -func (c *noSuchPod) Get(name string) (*api.Pod, error) { - return nil, fmt.Errorf("%s does not exist", name) -} - -type noDeleteService struct { - *testclient.FakeServices -} - -func (c *noDeleteService) Delete(service string) error { - return fmt.Errorf("I'm afraid I can't do that, Dave") -} - -type reaperFake struct { - *testclient.Fake - noSuchPod, noDeleteService bool -} - -func (c *reaperFake) Pods(namespace string) client.PodInterface { - pods := &testclient.FakePods{Fake: c.Fake, Namespace: namespace} - if c.noSuchPod { - return &noSuchPod{pods} - } - return pods -} - -func (c *reaperFake) Services(namespace string) client.ServiceInterface { - services := &testclient.FakeServices{Fake: c.Fake, Namespace: namespace} - if c.noDeleteService { - return &noDeleteService{services} - } - return services -} - -func TestSimpleStop(t *testing.T) { - tests := []struct { - fake *reaperFake - kind unversioned.GroupKind - actions []testclient.Action - expectError bool - test string - }{ - { - fake: &reaperFake{ - Fake: &testclient.Fake{}, - }, - kind: api.Kind("Pod"), - actions: []testclient.Action{ - testclient.NewGetAction("pods", api.NamespaceDefault, "foo"), - testclient.NewDeleteAction("pods", api.NamespaceDefault, "foo"), - }, - expectError: false, - test: "stop pod succeeds", - }, - { - fake: &reaperFake{ - Fake: &testclient.Fake{}, - }, - kind: api.Kind("Service"), - actions: []testclient.Action{ - testclient.NewGetAction("services", api.NamespaceDefault, "foo"), - testclient.NewDeleteAction("services", api.NamespaceDefault, "foo"), - }, - expectError: false, - test: "stop service succeeds", - }, - { - fake: &reaperFake{ - Fake: &testclient.Fake{}, - noSuchPod: true, - }, - kind: api.Kind("Pod"), - actions: []testclient.Action{}, - expectError: true, - test: "stop pod fails, no pod", - }, - { - fake: &reaperFake{ - Fake: &testclient.Fake{}, - noDeleteService: true, - }, - kind: api.Kind("Service"), - actions: []testclient.Action{ - testclient.NewGetAction("services", api.NamespaceDefault, "foo"), - }, - expectError: true, - test: "stop service fails, can't delete", - }, - } - for _, test := range tests { - fake := test.fake - reaper, err := ReaperFor(test.kind, fake) - if err != nil { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - err = reaper.Stop("default", "foo", 0, nil) - if err != nil && !test.expectError { - t.Errorf("unexpected error: %v (%s)", err, test.test) - } - if err == nil { - if test.expectError { - t.Errorf("unexpected non-error: %v (%s)", err, test.test) - } - } - actions := fake.Actions() - if len(test.actions) != len(actions) { - t.Errorf("unexpected actions: %v; expected %v (%s)", actions, test.actions, test.test) - } - for i, action := range actions { - testAction := test.actions[i] - if action != testAction { - t.Errorf("unexpected action: %#v; expected %v (%s)", action, testAction, test.test) - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/testing/types.generated.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/testing/types.generated.go deleted file mode 100644 index b3dd3628d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/testing/types.generated.go +++ /dev/null @@ -1,555 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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. -*/ - -// ************************************************************ -// DO NOT EDIT. -// THIS FILE IS AUTO-GENERATED BY codecgen. -// ************************************************************ - -package testing - -import ( - "errors" - "fmt" - codec1978 "github.com/ugorji/go/codec" - pkg2_api "k8s.io/kubernetes/pkg/api" - pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned" - pkg3_types "k8s.io/kubernetes/pkg/types" - "reflect" - "runtime" - time "time" -) - -const ( - // ----- content types ---- - codecSelferC_UTF81234 = 1 - codecSelferC_RAW1234 = 0 - // ----- value types used ---- - codecSelferValueTypeArray1234 = 10 - codecSelferValueTypeMap1234 = 9 - // ----- containerStateValues ---- - codecSelfer_containerMapKey1234 = 2 - codecSelfer_containerMapValue1234 = 3 - codecSelfer_containerMapEnd1234 = 4 - codecSelfer_containerArrayElem1234 = 6 - codecSelfer_containerArrayEnd1234 = 7 -) - -var ( - codecSelferBitsize1234 = uint8(reflect.TypeOf(uint(0)).Bits()) - codecSelferOnlyMapOrArrayEncodeToStructErr1234 = errors.New(`only encoded map or array can be decoded into a struct`) -) - -type codecSelfer1234 struct{} - -func init() { - if codec1978.GenVersion != 5 { - _, file, _, _ := runtime.Caller(0) - err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v", - 5, codec1978.GenVersion, file) - panic(err) - } - if false { // reference the types, but skip this branch at build/run time - var v0 pkg2_api.ObjectMeta - var v1 pkg1_unversioned.TypeMeta - var v2 pkg3_types.UID - var v3 time.Time - _, _, _, _ = v0, v1, v2, v3 - } -} - -func (x *TestStruct) CodecEncodeSelf(e *codec1978.Encoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperEncoder(e) - _, _, _ = h, z, r - if x == nil { - r.EncodeNil() - } else { - yym1 := z.EncBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.EncExt(x) { - } else { - yysep2 := !z.EncBinary() - yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [7]bool - _, _, _ = yysep2, yyq2, yy2arr2 - const yyr2 bool = false - yyq2[0] = true - yyq2[5] = x.Kind != "" - yyq2[6] = x.APIVersion != "" - var yynn2 int - if yyr2 || yy2arr2 { - r.EncodeArrayStart(7) - } else { - yynn2 = 4 - for _, b := range yyq2 { - if b { - yynn2++ - } - } - r.EncodeMapStart(yynn2) - yynn2 = 0 - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[0] { - yy4 := &x.ObjectMeta - yy4.CodecEncodeSelf(e) - } else { - r.EncodeNil() - } - } else { - if yyq2[0] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("metadata")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy6 := &x.ObjectMeta - yy6.CodecEncodeSelf(e) - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yym9 := z.EncBinary() - _ = yym9 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Key)) - } - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("Key")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym10 := z.EncBinary() - _ = yym10 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Key)) - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if x.Map == nil { - r.EncodeNil() - } else { - yym12 := z.EncBinary() - _ = yym12 - if false { - } else { - z.F.EncMapStringIntV(x.Map, false, e) - } - } - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("Map")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.Map == nil { - r.EncodeNil() - } else { - yym13 := z.EncBinary() - _ = yym13 - if false { - } else { - z.F.EncMapStringIntV(x.Map, false, e) - } - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if x.StringList == nil { - r.EncodeNil() - } else { - yym15 := z.EncBinary() - _ = yym15 - if false { - } else { - z.F.EncSliceStringV(x.StringList, false, e) - } - } - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("StringList")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.StringList == nil { - r.EncodeNil() - } else { - yym16 := z.EncBinary() - _ = yym16 - if false { - } else { - z.F.EncSliceStringV(x.StringList, false, e) - } - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if x.IntList == nil { - r.EncodeNil() - } else { - yym18 := z.EncBinary() - _ = yym18 - if false { - } else { - z.F.EncSliceIntV(x.IntList, false, e) - } - } - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("IntList")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - if x.IntList == nil { - r.EncodeNil() - } else { - yym19 := z.EncBinary() - _ = yym19 - if false { - } else { - z.F.EncSliceIntV(x.IntList, false, e) - } - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[5] { - yym21 := z.EncBinary() - _ = yym21 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) - } - } else { - r.EncodeString(codecSelferC_UTF81234, "") - } - } else { - if yyq2[5] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("kind")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym22 := z.EncBinary() - _ = yym22 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) - } - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[6] { - yym24 := z.EncBinary() - _ = yym24 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) - } - } else { - r.EncodeString(codecSelferC_UTF81234, "") - } - } else { - if yyq2[6] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("apiVersion")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym25 := z.EncBinary() - _ = yym25 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) - } - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayEnd1234) - } else { - z.EncSendContainerState(codecSelfer_containerMapEnd1234) - } - } - } -} - -func (x *TestStruct) CodecDecodeSelf(d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - yym1 := z.DecBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.DecExt(x) { - } else { - yyct2 := r.ContainerType() - if yyct2 == codecSelferValueTypeMap1234 { - yyl2 := r.ReadMapStart() - if yyl2 == 0 { - z.DecSendContainerState(codecSelfer_containerMapEnd1234) - } else { - x.codecDecodeSelfFromMap(yyl2, d) - } - } else if yyct2 == codecSelferValueTypeArray1234 { - yyl2 := r.ReadArrayStart() - if yyl2 == 0 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - } else { - x.codecDecodeSelfFromArray(yyl2, d) - } - } else { - panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) - } - } -} - -func (x *TestStruct) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - var yys3Slc = z.DecScratchBuffer() // default slice to decode into - _ = yys3Slc - var yyhl3 bool = l >= 0 - for yyj3 := 0; ; yyj3++ { - if yyhl3 { - if yyj3 >= l { - break - } - } else { - if r.CheckBreak() { - break - } - } - z.DecSendContainerState(codecSelfer_containerMapKey1234) - yys3Slc = r.DecodeBytes(yys3Slc, true, true) - yys3 := string(yys3Slc) - z.DecSendContainerState(codecSelfer_containerMapValue1234) - switch yys3 { - case "metadata": - if r.TryDecodeAsNil() { - x.ObjectMeta = pkg2_api.ObjectMeta{} - } else { - yyv4 := &x.ObjectMeta - yyv4.CodecDecodeSelf(d) - } - case "Key": - if r.TryDecodeAsNil() { - x.Key = "" - } else { - x.Key = string(r.DecodeString()) - } - case "Map": - if r.TryDecodeAsNil() { - x.Map = nil - } else { - yyv6 := &x.Map - yym7 := z.DecBinary() - _ = yym7 - if false { - } else { - z.F.DecMapStringIntX(yyv6, false, d) - } - } - case "StringList": - if r.TryDecodeAsNil() { - x.StringList = nil - } else { - yyv8 := &x.StringList - yym9 := z.DecBinary() - _ = yym9 - if false { - } else { - z.F.DecSliceStringX(yyv8, false, d) - } - } - case "IntList": - if r.TryDecodeAsNil() { - x.IntList = nil - } else { - yyv10 := &x.IntList - yym11 := z.DecBinary() - _ = yym11 - if false { - } else { - z.F.DecSliceIntX(yyv10, false, d) - } - } - case "kind": - if r.TryDecodeAsNil() { - x.Kind = "" - } else { - x.Kind = string(r.DecodeString()) - } - case "apiVersion": - if r.TryDecodeAsNil() { - x.APIVersion = "" - } else { - x.APIVersion = string(r.DecodeString()) - } - default: - z.DecStructFieldNotFound(-1, yys3) - } // end switch yys3 - } // end for yyj3 - z.DecSendContainerState(codecSelfer_containerMapEnd1234) -} - -func (x *TestStruct) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - var yyj14 int - var yyb14 bool - var yyhl14 bool = l >= 0 - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.ObjectMeta = pkg2_api.ObjectMeta{} - } else { - yyv15 := &x.ObjectMeta - yyv15.CodecDecodeSelf(d) - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Key = "" - } else { - x.Key = string(r.DecodeString()) - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Map = nil - } else { - yyv17 := &x.Map - yym18 := z.DecBinary() - _ = yym18 - if false { - } else { - z.F.DecMapStringIntX(yyv17, false, d) - } - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.StringList = nil - } else { - yyv19 := &x.StringList - yym20 := z.DecBinary() - _ = yym20 - if false { - } else { - z.F.DecSliceStringX(yyv19, false, d) - } - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.IntList = nil - } else { - yyv21 := &x.IntList - yym22 := z.DecBinary() - _ = yym22 - if false { - } else { - z.F.DecSliceIntX(yyv21, false, d) - } - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Kind = "" - } else { - x.Kind = string(r.DecodeString()) - } - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.APIVersion = "" - } else { - x.APIVersion = string(r.DecodeString()) - } - for { - yyj14++ - if yyhl14 { - yyb14 = yyj14 > l - } else { - yyb14 = r.CheckBreak() - } - if yyb14 { - break - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj14-1, "") - } - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/testing/types.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/testing/types.go deleted file mode 100644 index 2fbc2ed45..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubectl/testing/types.go +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -type TestStruct struct { - unversioned.TypeMeta `json:",inline"` - api.ObjectMeta `json:"metadata,omitempty"` - Key string `json:"Key"` - Map map[string]int `json:"Map"` - StringList []string `json:"StringList"` - IntList []int `json:"IntList"` -} - -func (obj *TestStruct) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubelet/qos/memory_policy_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubelet/qos/memory_policy_test.go deleted file mode 100644 index 27af3fd11..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubelet/qos/memory_policy_test.go +++ /dev/null @@ -1,187 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 qos - -import ( - "strconv" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" -) - -const ( - standardMemoryAmount = 8000000000 -) - -var ( - zeroRequestMemoryBestEffort = api.Container{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("5m"), - api.ResourceName(api.ResourceMemory): resource.MustParse("0G"), - }, - Limits: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("5m"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - } - - edgeMemoryBestEffort = api.Container{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse("0G"), - }, - Limits: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse("0G"), - }, - }, - } - - noRequestMemoryBestEffort = api.Container{ - Resources: api.ResourceRequirements{ - Limits: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - } - - noLimitMemoryBestEffort = api.Container{} - - memoryGuaranteed = api.Container{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - Limits: api.ResourceList{ - api.ResourceName(api.ResourceCPU): resource.MustParse("5m"), - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - } - - memoryBurstable = api.Container{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse(strconv.Itoa(standardMemoryAmount / 2)), - }, - Limits: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse("10G"), - }, - }, - } - - memoryBurstableNoLimit = api.Container{ - Resources: api.ResourceRequirements{ - Requests: api.ResourceList{ - api.ResourceName(api.ResourceMemory): resource.MustParse(strconv.Itoa(standardMemoryAmount - 1)), - }, - }, - } -) - -func TestIsMemoryBestEffort(t *testing.T) { - validCases := []api.Container{zeroRequestMemoryBestEffort, noRequestMemoryBestEffort, noLimitMemoryBestEffort, edgeMemoryBestEffort} - for _, container := range validCases { - if !isMemoryBestEffort(&container) { - t.Errorf("container %+v is memory best-effort", container) - } - } - invalidCases := []api.Container{memoryGuaranteed, memoryBurstable} - for _, container := range invalidCases { - if isMemoryBestEffort(&container) { - t.Errorf("container %+v is not memory best-effort", container) - } - } -} - -func TestIsMemoryGuaranteed(t *testing.T) { - validCases := []api.Container{memoryGuaranteed} - for _, container := range validCases { - if !isMemoryGuaranteed(&container) { - t.Errorf("container %+v is memory guaranteed", container) - } - } - invalidCases := []api.Container{zeroRequestMemoryBestEffort, noRequestMemoryBestEffort, noLimitMemoryBestEffort, edgeMemoryBestEffort, memoryBurstable} - for _, container := range invalidCases { - if isMemoryGuaranteed(&container) { - t.Errorf("container %+v is not memory guaranteed", container) - } - } -} - -type oomTest struct { - container *api.Container - memoryCapacity int64 - lowOOMScoreAdj int // The max oom_score_adj score the container should be assigned. - highOOMScoreAdj int // The min oom_score_adj score the container should be assigned. -} - -func TestGetContainerOOMScoreAdjust(t *testing.T) { - - oomTests := []oomTest{ - { - container: &zeroRequestMemoryBestEffort, - memoryCapacity: 4000000000, - lowOOMScoreAdj: 1000, - highOOMScoreAdj: 1000, - }, - { - container: &edgeMemoryBestEffort, - memoryCapacity: 8000000000, - lowOOMScoreAdj: 1000, - highOOMScoreAdj: 1000, - }, - { - container: &noRequestMemoryBestEffort, - memoryCapacity: 7230457451, - lowOOMScoreAdj: 1000, - highOOMScoreAdj: 1000, - }, - { - container: &noLimitMemoryBestEffort, - memoryCapacity: 4000000000, - lowOOMScoreAdj: 1000, - highOOMScoreAdj: 1000, - }, - { - container: &memoryGuaranteed, - memoryCapacity: 123456789, - lowOOMScoreAdj: -999, - highOOMScoreAdj: -999, - }, - { - container: &memoryBurstable, - memoryCapacity: standardMemoryAmount, - lowOOMScoreAdj: 495, - highOOMScoreAdj: 505, - }, - { - container: &memoryBurstableNoLimit, - memoryCapacity: standardMemoryAmount, - lowOOMScoreAdj: 2, - highOOMScoreAdj: 2, - }, - } - for _, test := range oomTests { - oomScoreAdj := GetContainerOOMScoreAdjust(test.container, test.memoryCapacity) - if oomScoreAdj < test.lowOOMScoreAdj || oomScoreAdj > test.highOOMScoreAdj { - t.Errorf("oom_score_adj should be between %d and %d, but was %d", test.lowOOMScoreAdj, test.highOOMScoreAdj, oomScoreAdj) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubelet/qos/util/qos_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubelet/qos/util/qos_test.go deleted file mode 100644 index c931e204a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/kubelet/qos/util/qos_test.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 util - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/resource" -) - -func getResourceList(cpu, memory string) api.ResourceList { - res := api.ResourceList{} - if cpu != "" { - res[api.ResourceCPU] = resource.MustParse(cpu) - } - if memory != "" { - res[api.ResourceMemory] = resource.MustParse(memory) - } - return res -} - -func getResourceRequirements(requests, limits api.ResourceList) api.ResourceRequirements { - res := api.ResourceRequirements{} - res.Requests = requests - res.Limits = limits - return res -} - -func newContainer(name string, requests api.ResourceList, limits api.ResourceList) api.Container { - return api.Container{ - Name: name, - Resources: getResourceRequirements(requests, limits), - } -} - -func newPod(name string, containers []api.Container) *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: name, - }, - Spec: api.PodSpec{ - Containers: containers, - }, - } -} - -func TestGetPodQos(t *testing.T) { - testCases := []struct { - pod *api.Pod - expected string - }{ - { - pod: newPod("best-effort", []api.Container{ - newContainer("best-effort", getResourceList("", ""), getResourceList("", "")), - }), - expected: BestEffort, - }, - { - pod: newPod("best-effort-guaranteed", []api.Container{ - newContainer("best-effort", getResourceList("", ""), getResourceList("", "")), - newContainer("guaranteed", getResourceList("10m", "100Mi"), getResourceList("10m", "100Mi")), - }), - expected: BestEffort, - }, - { - pod: newPod("best-effort-cpu-guaranteed-memory", []api.Container{ - newContainer("best-effort", getResourceList("", "100Mi"), getResourceList("", "100Mi")), - }), - expected: BestEffort, - }, - { - pod: newPod("burstable", []api.Container{ - newContainer("burstable", getResourceList("10m", "100Mi"), getResourceList("100m", "200Mi")), - }), - expected: Burstable, - }, - { - pod: newPod("guaranteed", []api.Container{ - newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")), - }), - expected: Guaranteed, - }, - } - for _, testCase := range testCases { - if actual := GetPodQos(testCase.pod); testCase.expected != actual { - t.Errorf("invalid qos pod %s, expected: %s, actual: %s", testCase.pod.Name, testCase.expected, actual) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/labels/labels_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/labels/labels_test.go deleted file mode 100644 index 8d3834d51..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/labels/labels_test.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 labels - -import ( - "testing" -) - -func matches(t *testing.T, ls Set, want string) { - if ls.String() != want { - t.Errorf("Expected '%s', but got '%s'", want, ls.String()) - } -} - -func TestSetString(t *testing.T) { - matches(t, Set{"x": "y"}, "x=y") - matches(t, Set{"foo": "bar"}, "foo=bar") - matches(t, Set{"foo": "bar", "baz": "qup"}, "baz=qup,foo=bar") - - // TODO: Make our label representation robust enough to handle labels - // with ",=!" characters in their names. -} - -func TestLabelHas(t *testing.T) { - labelHasTests := []struct { - Ls Labels - Key string - Has bool - }{ - {Set{"x": "y"}, "x", true}, - {Set{"x": ""}, "x", true}, - {Set{"x": "y"}, "foo", false}, - } - for _, lh := range labelHasTests { - if has := lh.Ls.Has(lh.Key); has != lh.Has { - t.Errorf("%#v.Has(%#v) => %v, expected %v", lh.Ls, lh.Key, has, lh.Has) - } - } -} - -func TestLabelGet(t *testing.T) { - ls := Set{"x": "y"} - if ls.Get("x") != "y" { - t.Errorf("Set.Get is broken") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/labels/selector_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/labels/selector_test.go deleted file mode 100644 index 5fbb1fc76..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/labels/selector_test.go +++ /dev/null @@ -1,574 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 labels - -import ( - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/util/sets" -) - -func TestSelectorParse(t *testing.T) { - testGoodStrings := []string{ - "x=a,y=b,z=c", - "", - "x!=a,y=b", - "x=", - "x= ", - "x=,z= ", - "x= ,z= ", - "!x", - "x>1.1", - "x>1.1,z<5.3", - } - testBadStrings := []string{ - "x=a||y=b", - "x==a==b", - "!x=a", - "x1.1", Set{"x": "1.2"}) - expectMatch(t, "x<1.1", Set{"x": "0.8"}) - expectNoMatch(t, "x=z", Set{}) - expectNoMatch(t, "x=y", Set{"x": "z"}) - expectNoMatch(t, "x=y,z=w", Set{"x": "w", "z": "w"}) - expectNoMatch(t, "x!=y,z!=w", Set{"x": "z", "z": "w"}) - expectNoMatch(t, "x", Set{"y": "z"}) - expectNoMatch(t, "!x", Set{"x": "z"}) - expectNoMatch(t, "x>1.1", Set{"x": "0.8"}) - expectNoMatch(t, "x<1.1", Set{"x": "1.1"}) - - labelset := Set{ - "foo": "bar", - "baz": "blah", - } - expectMatch(t, "foo=bar", labelset) - expectMatch(t, "baz=blah", labelset) - expectMatch(t, "foo=bar,baz=blah", labelset) - expectNoMatch(t, "foo=blah", labelset) - expectNoMatch(t, "baz=bar", labelset) - expectNoMatch(t, "foo=bar,foobar=bar,baz=blah", labelset) -} - -func expectMatchDirect(t *testing.T, selector, ls Set) { - if !SelectorFromSet(selector).Matches(ls) { - t.Errorf("Wanted %s to match '%s', but it did not.\n", selector, ls) - } -} - -func expectNoMatchDirect(t *testing.T, selector, ls Set) { - if SelectorFromSet(selector).Matches(ls) { - t.Errorf("Wanted '%s' to not match '%s', but it did.", selector, ls) - } -} - -func TestSetMatches(t *testing.T) { - labelset := Set{ - "foo": "bar", - "baz": "blah", - } - expectMatchDirect(t, Set{}, labelset) - expectMatchDirect(t, Set{"foo": "bar"}, labelset) - expectMatchDirect(t, Set{"baz": "blah"}, labelset) - expectMatchDirect(t, Set{"foo": "bar", "baz": "blah"}, labelset) - - //TODO: bad values not handled for the moment in SelectorFromSet - //expectNoMatchDirect(t, Set{"foo": "=blah"}, labelset) - //expectNoMatchDirect(t, Set{"baz": "=bar"}, labelset) - //expectNoMatchDirect(t, Set{"foo": "=bar", "foobar": "bar", "baz": "blah"}, labelset) -} - -func TestNilMapIsValid(t *testing.T) { - selector := Set(nil).AsSelector() - if selector == nil { - t.Errorf("Selector for nil set should be Everything") - } - if !selector.Empty() { - t.Errorf("Selector for nil set should be Empty") - } -} - -func TestSetIsEmpty(t *testing.T) { - if !(Set{}).AsSelector().Empty() { - t.Errorf("Empty set should be empty") - } - if !(NewSelector()).Empty() { - t.Errorf("Nil Selector should be empty") - } -} - -func TestLexer(t *testing.T) { - testcases := []struct { - s string - t Token - }{ - {"", EndOfStringToken}, - {",", CommaToken}, - {"notin", NotInToken}, - {"in", InToken}, - {"=", EqualsToken}, - {"==", DoubleEqualsToken}, - {">", GreaterThanToken}, - {"<", LessThanToken}, - //Note that Lex returns the longest valid token found - {"!", DoesNotExistToken}, - {"!=", NotEqualsToken}, - {"(", OpenParToken}, - {")", ClosedParToken}, - //Non-"special" characters are considered part of an identifier - {"~", IdentifierToken}, - {"||", IdentifierToken}, - } - for _, v := range testcases { - l := &Lexer{s: v.s, pos: 0} - token, lit := l.Lex() - if token != v.t { - t.Errorf("Got %d it should be %d for '%s'", token, v.t, v.s) - } - if v.t != ErrorToken && lit != v.s { - t.Errorf("Got '%s' it should be '%s'", lit, v.s) - } - } -} - -func min(l, r int) (m int) { - m = r - if l < r { - m = l - } - return m -} - -func TestLexerSequence(t *testing.T) { - testcases := []struct { - s string - t []Token - }{ - {"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken}}, - {"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken}}, - {"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken}}, - {"key", []Token{IdentifierToken}}, - {"!key", []Token{DoesNotExistToken, IdentifierToken}}, - {"()", []Token{OpenParToken, ClosedParToken}}, - {"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken}}, - {"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken}}, - {"key>1.1", []Token{IdentifierToken, GreaterThanToken, IdentifierToken}}, - {"key<0.8", []Token{IdentifierToken, LessThanToken, IdentifierToken}}, - } - for _, v := range testcases { - var literals []string - var tokens []Token - l := &Lexer{s: v.s, pos: 0} - for { - token, lit := l.Lex() - if token == EndOfStringToken { - break - } - tokens = append(tokens, token) - literals = append(literals, lit) - } - if len(tokens) != len(v.t) { - t.Errorf("Bad number of tokens for '%s %d, %d", v.s, len(tokens), len(v.t)) - } - for i := 0; i < min(len(tokens), len(v.t)); i++ { - if tokens[i] != v.t[i] { - t.Errorf("Test '%s': Mismatching in token type found '%v' it should be '%v'", v.s, tokens[i], v.t[i]) - } - } - } -} -func TestParserLookahead(t *testing.T) { - testcases := []struct { - s string - t []Token - }{ - {"key in ( value )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}}, - {"key notin ( value )", []Token{IdentifierToken, NotInToken, OpenParToken, IdentifierToken, ClosedParToken, EndOfStringToken}}, - {"key in ( value1, value2 )", []Token{IdentifierToken, InToken, OpenParToken, IdentifierToken, CommaToken, IdentifierToken, ClosedParToken, EndOfStringToken}}, - {"key", []Token{IdentifierToken, EndOfStringToken}}, - {"!key", []Token{DoesNotExistToken, IdentifierToken, EndOfStringToken}}, - {"()", []Token{OpenParToken, ClosedParToken, EndOfStringToken}}, - {"", []Token{EndOfStringToken}}, - {"x in (),y", []Token{IdentifierToken, InToken, OpenParToken, ClosedParToken, CommaToken, IdentifierToken, EndOfStringToken}}, - {"== != (), = notin", []Token{DoubleEqualsToken, NotEqualsToken, OpenParToken, ClosedParToken, CommaToken, EqualsToken, NotInToken, EndOfStringToken}}, - {"key>1.1", []Token{IdentifierToken, GreaterThanToken, IdentifierToken, EndOfStringToken}}, - {"key<0.8", []Token{IdentifierToken, LessThanToken, IdentifierToken, EndOfStringToken}}, - } - for _, v := range testcases { - p := &Parser{l: &Lexer{s: v.s, pos: 0}, position: 0} - p.scan() - if len(p.scannedItems) != len(v.t) { - t.Errorf("Expected %d items found %d", len(v.t), len(p.scannedItems)) - } - for { - token, lit := p.lookahead(KeyAndOperator) - - token2, lit2 := p.consume(KeyAndOperator) - if token == EndOfStringToken { - break - } - if token != token2 || lit != lit2 { - t.Errorf("Bad values") - } - } - } -} - -func TestRequirementConstructor(t *testing.T) { - requirementConstructorTests := []struct { - Key string - Op Operator - Vals sets.String - Success bool - }{ - {"x", InOperator, nil, false}, - {"x", NotInOperator, sets.NewString(), false}, - {"x", InOperator, sets.NewString("foo"), true}, - {"x", NotInOperator, sets.NewString("foo"), true}, - {"x", ExistsOperator, nil, true}, - {"x", DoesNotExistOperator, nil, true}, - {"1foo", InOperator, sets.NewString("bar"), true}, - {"1234", InOperator, sets.NewString("bar"), true}, - {"y", GreaterThanOperator, sets.NewString("1.1"), true}, - {"z", LessThanOperator, sets.NewString("5.3"), true}, - {"foo", GreaterThanOperator, sets.NewString("bar"), false}, - {"barz", LessThanOperator, sets.NewString("blah"), false}, - {strings.Repeat("a", 254), ExistsOperator, nil, false}, //breaks DNS rule that len(key) <= 253 - } - for _, rc := range requirementConstructorTests { - if _, err := NewRequirement(rc.Key, rc.Op, rc.Vals); err == nil && !rc.Success { - t.Errorf("expected error with key:%#v op:%v vals:%v, got no error", rc.Key, rc.Op, rc.Vals) - } else if err != nil && rc.Success { - t.Errorf("expected no error with key:%#v op:%v vals:%v, got:%v", rc.Key, rc.Op, rc.Vals, err) - } - } -} - -func TestToString(t *testing.T) { - var req Requirement - toStringTests := []struct { - In *internalSelector - Out string - Valid bool - }{ - - {&internalSelector{ - getRequirement("x", InOperator, sets.NewString("abc", "def"), t), - getRequirement("y", NotInOperator, sets.NewString("jkl"), t), - getRequirement("z", ExistsOperator, nil, t)}, - "x in (abc,def),y notin (jkl),z", true}, - {&internalSelector{ - getRequirement("x", NotInOperator, sets.NewString("abc", "def"), t), - getRequirement("y", NotEqualsOperator, sets.NewString("jkl"), t), - getRequirement("z", DoesNotExistOperator, nil, t)}, - "x notin (abc,def),y!=jkl,!z", true}, - {&internalSelector{ - getRequirement("x", InOperator, sets.NewString("abc", "def"), t), - req}, // adding empty req for the trailing ',' - "x in (abc,def),", false}, - {&internalSelector{ - getRequirement("x", NotInOperator, sets.NewString("abc"), t), - getRequirement("y", InOperator, sets.NewString("jkl", "mno"), t), - getRequirement("z", NotInOperator, sets.NewString(""), t)}, - "x notin (abc),y in (jkl,mno),z notin ()", true}, - {&internalSelector{ - getRequirement("x", EqualsOperator, sets.NewString("abc"), t), - getRequirement("y", DoubleEqualsOperator, sets.NewString("jkl"), t), - getRequirement("z", NotEqualsOperator, sets.NewString("a"), t), - getRequirement("z", ExistsOperator, nil, t)}, - "x=abc,y==jkl,z!=a,z", true}, - {&internalSelector{ - getRequirement("x", GreaterThanOperator, sets.NewString("2.4"), t), - getRequirement("y", LessThanOperator, sets.NewString("7.1"), t), - getRequirement("z", ExistsOperator, nil, t)}, - "x>2.4,y<7.1,z", true}, - } - for _, ts := range toStringTests { - if out := ts.In.String(); out == "" && ts.Valid { - t.Errorf("%+v.String() => '%v' expected no error", ts.In, out) - } else if out != ts.Out { - t.Errorf("%+v.String() => '%v' want '%v'", ts.In, out, ts.Out) - } - } -} - -func TestRequirementSelectorMatching(t *testing.T) { - var req Requirement - labelSelectorMatchingTests := []struct { - Set Set - Sel Selector - Match bool - }{ - {Set{"x": "foo", "y": "baz"}, &internalSelector{ - req, - }, false}, - {Set{"x": "foo", "y": "baz"}, &internalSelector{ - getRequirement("x", InOperator, sets.NewString("foo"), t), - getRequirement("y", NotInOperator, sets.NewString("alpha"), t), - }, true}, - {Set{"x": "foo", "y": "baz"}, &internalSelector{ - getRequirement("x", InOperator, sets.NewString("foo"), t), - getRequirement("y", InOperator, sets.NewString("alpha"), t), - }, false}, - {Set{"y": ""}, &internalSelector{ - getRequirement("x", NotInOperator, sets.NewString(""), t), - getRequirement("y", ExistsOperator, nil, t), - }, true}, - {Set{"y": ""}, &internalSelector{ - getRequirement("x", DoesNotExistOperator, nil, t), - getRequirement("y", ExistsOperator, nil, t), - }, true}, - {Set{"y": ""}, &internalSelector{ - getRequirement("x", NotInOperator, sets.NewString(""), t), - getRequirement("y", DoesNotExistOperator, nil, t), - }, false}, - {Set{"y": "baz"}, &internalSelector{ - getRequirement("x", InOperator, sets.NewString(""), t), - }, false}, - {Set{"z": "1.2"}, &internalSelector{ - getRequirement("z", GreaterThanOperator, sets.NewString("1.0"), t), - }, true}, - {Set{"z": "v1.2"}, &internalSelector{ - getRequirement("z", GreaterThanOperator, sets.NewString("1.0"), t), - }, false}, - } - for _, lsm := range labelSelectorMatchingTests { - if match := lsm.Sel.Matches(lsm.Set); match != lsm.Match { - t.Errorf("%+v.Matches(%#v) => %v, want %v", lsm.Sel, lsm.Set, match, lsm.Match) - } - } -} - -func TestSetSelectorParser(t *testing.T) { - setSelectorParserTests := []struct { - In string - Out Selector - Match bool - Valid bool - }{ - {"", NewSelector(), true, true}, - {"\rx", internalSelector{ - getRequirement("x", ExistsOperator, nil, t), - }, true, true}, - {"this-is-a-dns.domain.com/key-with-dash", internalSelector{ - getRequirement("this-is-a-dns.domain.com/key-with-dash", ExistsOperator, nil, t), - }, true, true}, - {"this-is-another-dns.domain.com/key-with-dash in (so,what)", internalSelector{ - getRequirement("this-is-another-dns.domain.com/key-with-dash", InOperator, sets.NewString("so", "what"), t), - }, true, true}, - {"0.1.2.domain/99 notin (10.10.100.1, tick.tack.clock)", internalSelector{ - getRequirement("0.1.2.domain/99", NotInOperator, sets.NewString("10.10.100.1", "tick.tack.clock"), t), - }, true, true}, - {"foo in (abc)", internalSelector{ - getRequirement("foo", InOperator, sets.NewString("abc"), t), - }, true, true}, - {"x notin\n (abc)", internalSelector{ - getRequirement("x", NotInOperator, sets.NewString("abc"), t), - }, true, true}, - {"x notin \t (abc,def)", internalSelector{ - getRequirement("x", NotInOperator, sets.NewString("abc", "def"), t), - }, true, true}, - {"x in (abc,def)", internalSelector{ - getRequirement("x", InOperator, sets.NewString("abc", "def"), t), - }, true, true}, - {"x in (abc,)", internalSelector{ - getRequirement("x", InOperator, sets.NewString("abc", ""), t), - }, true, true}, - {"x in ()", internalSelector{ - getRequirement("x", InOperator, sets.NewString(""), t), - }, true, true}, - {"x notin (abc,,def),bar,z in (),w", internalSelector{ - getRequirement("bar", ExistsOperator, nil, t), - getRequirement("w", ExistsOperator, nil, t), - getRequirement("x", NotInOperator, sets.NewString("abc", "", "def"), t), - getRequirement("z", InOperator, sets.NewString(""), t), - }, true, true}, - {"x,y in (a)", internalSelector{ - getRequirement("y", InOperator, sets.NewString("a"), t), - getRequirement("x", ExistsOperator, nil, t), - }, false, true}, - {"x=a", internalSelector{ - getRequirement("x", EqualsOperator, sets.NewString("a"), t), - }, true, true}, - {"x>1.1", internalSelector{ - getRequirement("x", GreaterThanOperator, sets.NewString("1.1"), t), - }, true, true}, - {"x<7.1", internalSelector{ - getRequirement("x", LessThanOperator, sets.NewString("7.1"), t), - }, true, true}, - {"x=a,y!=b", internalSelector{ - getRequirement("x", EqualsOperator, sets.NewString("a"), t), - getRequirement("y", NotEqualsOperator, sets.NewString("b"), t), - }, true, true}, - {"x=a,y!=b,z in (h,i,j)", internalSelector{ - getRequirement("x", EqualsOperator, sets.NewString("a"), t), - getRequirement("y", NotEqualsOperator, sets.NewString("b"), t), - getRequirement("z", InOperator, sets.NewString("h", "i", "j"), t), - }, true, true}, - {"x=a||y=b", internalSelector{}, false, false}, - {"x,,y", nil, true, false}, - {",x,y", nil, true, false}, - {"x nott in (y)", nil, true, false}, - {"x notin ( )", internalSelector{ - getRequirement("x", NotInOperator, sets.NewString(""), t), - }, true, true}, - {"x notin (, a)", internalSelector{ - getRequirement("x", NotInOperator, sets.NewString("", "a"), t), - }, true, true}, - {"a in (xyz),", nil, true, false}, - {"a in (xyz)b notin ()", nil, true, false}, - {"a ", internalSelector{ - getRequirement("a", ExistsOperator, nil, t), - }, true, true}, - {"a in (x,y,notin, z,in)", internalSelector{ - getRequirement("a", InOperator, sets.NewString("in", "notin", "x", "y", "z"), t), - }, true, true}, // operator 'in' inside list of identifiers - {"a in (xyz abc)", nil, false, false}, // no comma - {"a notin(", nil, true, false}, // bad formed - {"a (", nil, false, false}, // cpar - {"(", nil, false, false}, // opar - } - - for _, ssp := range setSelectorParserTests { - if sel, err := Parse(ssp.In); err != nil && ssp.Valid { - t.Errorf("Parse(%s) => %v expected no error", ssp.In, err) - } else if err == nil && !ssp.Valid { - t.Errorf("Parse(%s) => %+v expected error", ssp.In, sel) - } else if ssp.Match && !reflect.DeepEqual(sel, ssp.Out) { - t.Errorf("Parse(%s) => parse output '%#v' doesn't match '%#v' expected match", ssp.In, sel, ssp.Out) - } - } -} - -func getRequirement(key string, op Operator, vals sets.String, t *testing.T) Requirement { - req, err := NewRequirement(key, op, vals) - if err != nil { - t.Errorf("NewRequirement(%v, %v, %v) resulted in error:%v", key, op, vals, err) - return Requirement{} - } - return *req -} - -func TestAdd(t *testing.T) { - testCases := []struct { - name string - sel Selector - key string - operator Operator - values []string - refSelector Selector - }{ - { - "keyInOperator", - internalSelector{}, - "key", - InOperator, - []string{"value"}, - internalSelector{Requirement{"key", InOperator, sets.NewString("value")}}, - }, - { - "keyEqualsOperator", - internalSelector{Requirement{"key", InOperator, sets.NewString("value")}}, - "key2", - EqualsOperator, - []string{"value2"}, - internalSelector{ - Requirement{"key", InOperator, sets.NewString("value")}, - Requirement{"key2", EqualsOperator, sets.NewString("value2")}, - }, - }, - } - for _, ts := range testCases { - req, err := NewRequirement(ts.key, ts.operator, sets.NewString(ts.values...)) - if err != nil { - t.Errorf("%s - Unable to create labels.Requirement", ts.name) - } - ts.sel = ts.sel.Add(*req) - if !reflect.DeepEqual(ts.sel, ts.refSelector) { - t.Errorf("%s - Expected %v found %v", ts.name, ts.refSelector, ts.sel) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/matcher_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/matcher_test.go deleted file mode 100644 index 17c7fb363..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/matcher_test.go +++ /dev/null @@ -1,130 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 generic - -import ( - "errors" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" -) - -type Ignored struct { - ID string -} - -type IgnoredList struct { - Items []Ignored -} - -func (obj *Ignored) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } -func (obj *IgnoredList) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -func TestSelectionPredicate(t *testing.T) { - table := map[string]struct { - labelSelector, fieldSelector string - labels labels.Set - fields fields.Set - err error - shouldMatch bool - matchSingleKey string - }{ - "A": { - labelSelector: "name=foo", - fieldSelector: "uid=12345", - labels: labels.Set{"name": "foo"}, - fields: fields.Set{"uid": "12345"}, - shouldMatch: true, - }, - "B": { - labelSelector: "name=foo", - fieldSelector: "uid=12345", - labels: labels.Set{"name": "foo"}, - fields: fields.Set{}, - shouldMatch: false, - }, - "C": { - labelSelector: "name=foo", - fieldSelector: "uid=12345", - labels: labels.Set{}, - fields: fields.Set{"uid": "12345"}, - shouldMatch: false, - }, - "D": { - fieldSelector: "metadata.name=12345", - labels: labels.Set{}, - fields: fields.Set{"metadata.name": "12345"}, - shouldMatch: true, - matchSingleKey: "12345", - }, - "error": { - labelSelector: "name=foo", - fieldSelector: "uid=12345", - err: errors.New("maybe this is a 'wrong object type' error"), - shouldMatch: false, - }, - } - - for name, item := range table { - parsedLabel, err := labels.Parse(item.labelSelector) - if err != nil { - panic(err) - } - parsedField, err := fields.ParseSelector(item.fieldSelector) - if err != nil { - panic(err) - } - sp := &SelectionPredicate{ - Label: parsedLabel, - Field: parsedField, - GetAttrs: func(runtime.Object) (label labels.Set, field fields.Set, err error) { - return item.labels, item.fields, item.err - }, - } - got, err := sp.Matches(&Ignored{}) - if e, a := item.err, err; e != a { - t.Errorf("%v: expected %v, got %v", name, e, a) - continue - } - if e, a := item.shouldMatch, got; e != a { - t.Errorf("%v: expected %v, got %v", name, e, a) - } - if key := item.matchSingleKey; key != "" { - got, ok := sp.MatchesSingle() - if !ok { - t.Errorf("%v: expected single match", name) - } - if e, a := key, got; e != a { - t.Errorf("%v: expected %v, got %v", name, e, a) - } - } - } -} - -func TestSingleMatch(t *testing.T) { - m := MatchOnKey("pod-name-here", func(obj runtime.Object) (bool, error) { return true, nil }) - got, ok := m.MatchesSingle() - if !ok { - t.Errorf("Expected MatchesSingle to return true") - } - if e, a := "pod-name-here", got; e != a { - t.Errorf("Expected %#v, got %#v", e, a) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/doc.go deleted file mode 100644 index ee972408d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd has a generic implementation of a registry that -// stores things in etcd. -package registry diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/storage_factory.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/storage_factory.go deleted file mode 100644 index f1c265113..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/storage_factory.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 registry - -import ( - "k8s.io/kubernetes/pkg/api/rest" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" -) - -// Creates a cacher on top of the given 'storageInterface'. -func StorageWithCacher( - storageInterface storage.Interface, - capacity int, - objectType runtime.Object, - resourcePrefix string, - scopeStrategy rest.NamespaceScopedStrategy, - newListFunc func() runtime.Object) storage.Interface { - return storage.NewCacher( - storageInterface, capacity, etcdstorage.APIObjectVersioner{}, - objectType, resourcePrefix, scopeStrategy, newListFunc) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/store.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/store.go deleted file mode 100644 index 337143ce3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/store.go +++ /dev/null @@ -1,679 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 registry - -import ( - "fmt" - "reflect" - "sync" - - "k8s.io/kubernetes/pkg/api" - kubeerr "k8s.io/kubernetes/pkg/api/errors" - storeerr "k8s.io/kubernetes/pkg/api/errors/storage" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/rest" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/util/validation/field" - "k8s.io/kubernetes/pkg/watch" - - "github.com/golang/glog" -) - -// Store implements generic.Registry. -// It's intended to be embeddable, so that you can implement any -// non-generic functions if needed. -// You must supply a value for every field below before use; these are -// left public as it's meant to be overridable if need be. -// This object is intended to be copyable so that it can be used in -// different ways but share the same underlying behavior. -// -// The intended use of this type is embedding within a Kind specific -// RESTStorage implementation. This type provides CRUD semantics on -// a Kubelike resource, handling details like conflict detection with -// ResourceVersion and semantics. The RESTCreateStrategy and -// RESTUpdateStrategy are generic across all backends, and encapsulate -// logic specific to the API. -// -// TODO: make the default exposed methods exactly match a generic RESTStorage -type Store struct { - // Called to make a new object, should return e.g., &api.Pod{} - NewFunc func() runtime.Object - - // Called to make a new listing object, should return e.g., &api.PodList{} - NewListFunc func() runtime.Object - - // Used for error reporting - QualifiedResource unversioned.GroupResource - - // Used for listing/watching; should not include trailing "/" - KeyRootFunc func(ctx api.Context) string - - // Called for Create/Update/Get/Delete. Note that 'namespace' can be - // gotten from ctx. - KeyFunc func(ctx api.Context, name string) (string, error) - - // Called to get the name of an object - ObjectNameFunc func(obj runtime.Object) (string, error) - - // Return the TTL objects should be persisted with. Update is true if this - // is an operation against an existing object. Existing is the current TTL - // or the default for this operation. - TTLFunc func(obj runtime.Object, existing uint64, update bool) (uint64, error) - - // Returns a matcher corresponding to the provided labels and fields. - PredicateFunc func(label labels.Selector, field fields.Selector) generic.Matcher - - // DeleteCollectionWorkers is the maximum number of workers in a single - // DeleteCollection call. - DeleteCollectionWorkers int - - // Called on all objects returned from the underlying store, after - // the exit hooks are invoked. Decorators are intended for integrations - // that are above storage and should only be used for specific cases where - // storage of the value is not appropriate, since they cannot - // be watched. - Decorator rest.ObjectFunc - // Allows extended behavior during creation, required - CreateStrategy rest.RESTCreateStrategy - // On create of an object, attempt to run a further operation. - AfterCreate rest.ObjectFunc - // Allows extended behavior during updates, required - UpdateStrategy rest.RESTUpdateStrategy - // On update of an object, attempt to run a further operation. - AfterUpdate rest.ObjectFunc - // Allows extended behavior during updates, optional - DeleteStrategy rest.RESTDeleteStrategy - // On deletion of an object, attempt to run a further operation. - AfterDelete rest.ObjectFunc - // If true, return the object that was deleted. Otherwise, return a generic - // success status response. - ReturnDeletedObject bool - // Allows extended behavior during export, optional - ExportStrategy rest.RESTExportStrategy - - // Used for all storage access functions - Storage storage.Interface -} - -// NamespaceKeyRootFunc is the default function for constructing storage paths to resource directories enforcing namespace rules. -func NamespaceKeyRootFunc(ctx api.Context, prefix string) string { - key := prefix - ns, ok := api.NamespaceFrom(ctx) - if ok && len(ns) > 0 { - key = key + "/" + ns - } - return key -} - -// NamespaceKeyFunc is the default function for constructing storage paths to a resource relative to prefix enforcing namespace rules. -// If no namespace is on context, it errors. -func NamespaceKeyFunc(ctx api.Context, prefix string, name string) (string, error) { - key := NamespaceKeyRootFunc(ctx, prefix) - ns, ok := api.NamespaceFrom(ctx) - if !ok || len(ns) == 0 { - return "", kubeerr.NewBadRequest("Namespace parameter required.") - } - if len(name) == 0 { - return "", kubeerr.NewBadRequest("Name parameter required.") - } - if ok, msg := validation.IsValidPathSegmentName(name); !ok { - return "", kubeerr.NewBadRequest(fmt.Sprintf("Name parameter invalid: %v.", msg)) - } - key = key + "/" + name - return key, nil -} - -// NoNamespaceKeyFunc is the default function for constructing storage paths to a resource relative to prefix without a namespace -func NoNamespaceKeyFunc(ctx api.Context, prefix string, name string) (string, error) { - if len(name) == 0 { - return "", kubeerr.NewBadRequest("Name parameter required.") - } - if ok, msg := validation.IsValidPathSegmentName(name); !ok { - return "", kubeerr.NewBadRequest(fmt.Sprintf("Name parameter invalid: %v.", msg)) - } - key := prefix + "/" + name - return key, nil -} - -// New implements RESTStorage -func (e *Store) New() runtime.Object { - return e.NewFunc() -} - -// NewList implements RESTLister -func (e *Store) NewList() runtime.Object { - return e.NewListFunc() -} - -// List returns a list of items matching labels and field -func (e *Store) List(ctx api.Context, options *api.ListOptions) (runtime.Object, error) { - label := labels.Everything() - if options != nil && options.LabelSelector != nil { - label = options.LabelSelector - } - field := fields.Everything() - if options != nil && options.FieldSelector != nil { - field = options.FieldSelector - } - return e.ListPredicate(ctx, e.PredicateFunc(label, field), options) -} - -// ListPredicate returns a list of all the items matching m. -func (e *Store) ListPredicate(ctx api.Context, m generic.Matcher, options *api.ListOptions) (runtime.Object, error) { - list := e.NewListFunc() - filterFunc := e.filterAndDecorateFunction(m) - if name, ok := m.MatchesSingle(); ok { - if key, err := e.KeyFunc(ctx, name); err == nil { - err := e.Storage.GetToList(ctx, key, filterFunc, list) - return list, storeerr.InterpretListError(err, e.QualifiedResource) - } - // if we cannot extract a key based on the current context, the optimization is skipped - } - - if options == nil { - options = &api.ListOptions{ResourceVersion: "0"} - } - err := e.Storage.List(ctx, e.KeyRootFunc(ctx), options.ResourceVersion, filterFunc, list) - return list, storeerr.InterpretListError(err, e.QualifiedResource) -} - -// Create inserts a new item according to the unique key from the object. -func (e *Store) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil { - return nil, err - } - name, err := e.ObjectNameFunc(obj) - if err != nil { - return nil, err - } - key, err := e.KeyFunc(ctx, name) - if err != nil { - return nil, err - } - ttl, err := e.calculateTTL(obj, 0, false) - if err != nil { - return nil, err - } - out := e.NewFunc() - if err := e.Storage.Create(ctx, key, obj, out, ttl); err != nil { - err = storeerr.InterpretCreateError(err, e.QualifiedResource, name) - err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj) - return nil, err - } - if e.AfterCreate != nil { - if err := e.AfterCreate(out); err != nil { - return nil, err - } - } - if e.Decorator != nil { - if err := e.Decorator(obj); err != nil { - return nil, err - } - } - return out, nil -} - -// Update performs an atomic update and set of the object. Returns the result of the update -// or an error. If the registry allows create-on-update, the create flow will be executed. -// A bool is returned along with the object and any errors, to indicate object creation. -func (e *Store) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) { - name, err := e.ObjectNameFunc(obj) - if err != nil { - return nil, false, err - } - key, err := e.KeyFunc(ctx, name) - if err != nil { - return nil, false, err - } - // If AllowUnconditionalUpdate() is true and the object specified by the user does not have a resource version, - // then we populate it with the latest version. - // Else, we check that the version specified by the user matches the version of latest storage object. - resourceVersion, err := e.Storage.Versioner().ObjectResourceVersion(obj) - if err != nil { - return nil, false, err - } - doUnconditionalUpdate := resourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate() - // TODO: expose TTL - creating := false - out := e.NewFunc() - meta, err := api.ObjectMetaFor(obj) - if err != nil { - return nil, false, kubeerr.NewInternalError(err) - } - var preconditions *storage.Preconditions - // If the UID of the new object is specified, we use it as an Update precondition. - if len(meta.UID) != 0 { - UIDCopy := meta.UID - preconditions = &storage.Preconditions{UID: &UIDCopy} - } - err = e.Storage.GuaranteedUpdate(ctx, key, out, true, preconditions, func(existing runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) { - // Since we return 'obj' from this function and it can be modified outside this - // function, we are resetting resourceVersion to the initial value here. - // - // TODO: In fact, we should probably return a DeepCopy of obj in all places. - err := e.Storage.Versioner().UpdateObject(obj, resourceVersion) - if err != nil { - return nil, nil, err - } - - version, err := e.Storage.Versioner().ObjectResourceVersion(existing) - if err != nil { - return nil, nil, err - } - if version == 0 { - if !e.UpdateStrategy.AllowCreateOnUpdate() { - return nil, nil, kubeerr.NewNotFound(e.QualifiedResource, name) - } - creating = true - if err := rest.BeforeCreate(e.CreateStrategy, ctx, obj); err != nil { - return nil, nil, err - } - ttl, err := e.calculateTTL(obj, 0, false) - if err != nil { - return nil, nil, err - } - return obj, &ttl, nil - } - - creating = false - if doUnconditionalUpdate { - // Update the object's resource version to match the latest storage object's resource version. - err = e.Storage.Versioner().UpdateObject(obj, res.ResourceVersion) - if err != nil { - return nil, nil, err - } - } else { - // Check if the object's resource version matches the latest resource version. - newVersion, err := e.Storage.Versioner().ObjectResourceVersion(obj) - if err != nil { - return nil, nil, err - } - if newVersion == 0 { - // TODO: The Invalid error should has a field for Resource. - // After that field is added, we should fill the Resource and - // leave the Kind field empty. See the discussion in #18526. - qualifiedKind := unversioned.GroupKind{Group: e.QualifiedResource.Group, Kind: e.QualifiedResource.Resource} - fieldErrList := field.ErrorList{field.Invalid(field.NewPath("metadata").Child("resourceVersion"), newVersion, "must be specified for an update")} - return nil, nil, kubeerr.NewInvalid(qualifiedKind, name, fieldErrList) - } - if newVersion != version { - return nil, nil, kubeerr.NewConflict(e.QualifiedResource, name, fmt.Errorf("the object has been modified; please apply your changes to the latest version and try again")) - } - } - if err := rest.BeforeUpdate(e.UpdateStrategy, ctx, obj, existing); err != nil { - return nil, nil, err - } - ttl, err := e.calculateTTL(obj, res.TTL, true) - if err != nil { - return nil, nil, err - } - if int64(ttl) != res.TTL { - return obj, &ttl, nil - } - return obj, nil, nil - }) - - if err != nil { - if creating { - err = storeerr.InterpretCreateError(err, e.QualifiedResource, name) - err = rest.CheckGeneratedNameError(e.CreateStrategy, err, obj) - } else { - err = storeerr.InterpretUpdateError(err, e.QualifiedResource, name) - } - return nil, false, err - } - if creating { - if e.AfterCreate != nil { - if err := e.AfterCreate(out); err != nil { - return nil, false, err - } - } - } else { - if e.AfterUpdate != nil { - if err := e.AfterUpdate(out); err != nil { - return nil, false, err - } - } - } - if e.Decorator != nil { - if err := e.Decorator(obj); err != nil { - return nil, false, err - } - } - return out, creating, nil -} - -// Get retrieves the item from storage. -func (e *Store) Get(ctx api.Context, name string) (runtime.Object, error) { - obj := e.NewFunc() - key, err := e.KeyFunc(ctx, name) - if err != nil { - return nil, err - } - if err := e.Storage.Get(ctx, key, obj, false); err != nil { - return nil, storeerr.InterpretGetError(err, e.QualifiedResource, name) - } - if e.Decorator != nil { - if err := e.Decorator(obj); err != nil { - return nil, err - } - } - return obj, nil -} - -var ( - errAlreadyDeleting = fmt.Errorf("abort delete") - errDeleteNow = fmt.Errorf("delete now") -) - -// Delete removes the item from storage. -func (e *Store) Delete(ctx api.Context, name string, options *api.DeleteOptions) (runtime.Object, error) { - key, err := e.KeyFunc(ctx, name) - if err != nil { - return nil, err - } - - obj := e.NewFunc() - if err := e.Storage.Get(ctx, key, obj, false); err != nil { - return nil, storeerr.InterpretDeleteError(err, e.QualifiedResource, name) - } - - // support older consumers of delete by treating "nil" as delete immediately - if options == nil { - options = api.NewDeleteOptions(0) - } - var preconditions storage.Preconditions - if options.Preconditions != nil { - preconditions.UID = options.Preconditions.UID - } - graceful, pendingGraceful, err := rest.BeforeDelete(e.DeleteStrategy, ctx, obj, options) - if err != nil { - return nil, err - } - if pendingGraceful { - return e.finalizeDelete(obj, false) - } - var ignoreNotFound bool = false - var lastExisting runtime.Object = nil - if graceful { - out := e.NewFunc() - lastGraceful := int64(0) - err := e.Storage.GuaranteedUpdate( - ctx, key, out, false, &preconditions, - storage.SimpleUpdate(func(existing runtime.Object) (runtime.Object, error) { - graceful, pendingGraceful, err := rest.BeforeDelete(e.DeleteStrategy, ctx, existing, options) - if err != nil { - return nil, err - } - if pendingGraceful { - return nil, errAlreadyDeleting - } - if !graceful { - return nil, errDeleteNow - } - lastGraceful = *options.GracePeriodSeconds - lastExisting = existing - return existing, nil - }), - ) - switch err { - case nil: - if lastGraceful > 0 { - return out, nil - } - // If we are here, the registry supports grace period mechanism and - // we are intentionally delete gracelessly. In this case, we may - // enter a race with other k8s components. If other component wins - // the race, the object will not be found, and we should tolerate - // the NotFound error. See - // https://github.com/kubernetes/kubernetes/issues/19403 for - // details. - ignoreNotFound = true - // exit the switch and delete immediately - case errDeleteNow: - // we've updated the object to have a zero grace period, or it's already at 0, so - // we should fall through and truly delete the object. - case errAlreadyDeleting: - return e.finalizeDelete(obj, true) - default: - return nil, storeerr.InterpretUpdateError(err, e.QualifiedResource, name) - } - } - - // delete immediately, or no graceful deletion supported - out := e.NewFunc() - if err := e.Storage.Delete(ctx, key, out, &preconditions); err != nil { - // Please refer to the place where we set ignoreNotFound for the reason - // why we ignore the NotFound error . - if storage.IsNotFound(err) && ignoreNotFound && lastExisting != nil { - // The lastExisting object may not be the last state of the object - // before its deletion, but it's the best approximation. - return e.finalizeDelete(lastExisting, true) - } - return nil, storeerr.InterpretDeleteError(err, e.QualifiedResource, name) - } - return e.finalizeDelete(out, true) -} - -// DeleteCollection remove all items returned by List with a given ListOptions from storage. -// -// DeleteCollection is currently NOT atomic. It can happen that only subset of objects -// will be deleted from storage, and then an error will be returned. -// In case of success, the list of deleted objects will be returned. -// -// TODO: Currently, there is no easy way to remove 'directory' entry from storage (if we -// are removing all objects of a given type) with the current API (it's technically -// possibly with storage API, but watch is not delivered correctly then). -// It will be possible to fix it with v3 etcd API. -func (e *Store) DeleteCollection(ctx api.Context, options *api.DeleteOptions, listOptions *api.ListOptions) (runtime.Object, error) { - listObj, err := e.List(ctx, listOptions) - if err != nil { - return nil, err - } - items, err := meta.ExtractList(listObj) - if err != nil { - return nil, err - } - // Spawn a number of goroutines, so that we can issue requests to storage - // in parallel to speed up deletion. - // TODO: Make this proportional to the number of items to delete, up to - // DeleteCollectionWorkers (it doesn't make much sense to spawn 16 - // workers to delete 10 items). - workersNumber := e.DeleteCollectionWorkers - if workersNumber < 1 { - workersNumber = 1 - } - wg := sync.WaitGroup{} - toProcess := make(chan int, 2*workersNumber) - errs := make(chan error, workersNumber+1) - - go func() { - defer utilruntime.HandleCrash(func(panicReason interface{}) { - errs <- fmt.Errorf("DeleteCollection distributor panicked: %v", panicReason) - }) - for i := 0; i < len(items); i++ { - toProcess <- i - } - close(toProcess) - }() - - wg.Add(workersNumber) - for i := 0; i < workersNumber; i++ { - go func() { - // panics don't cross goroutine boundaries - defer utilruntime.HandleCrash(func(panicReason interface{}) { - errs <- fmt.Errorf("DeleteCollection goroutine panicked: %v", panicReason) - }) - defer wg.Done() - - for { - index, ok := <-toProcess - if !ok { - return - } - accessor, err := meta.Accessor(items[index]) - if err != nil { - errs <- err - return - } - if _, err := e.Delete(ctx, accessor.GetName(), options); err != nil && !kubeerr.IsNotFound(err) { - glog.V(4).Infof("Delete %s in DeleteCollection failed: %v", accessor.GetName(), err) - errs <- err - return - } - } - }() - } - wg.Wait() - select { - case err := <-errs: - return nil, err - default: - return listObj, nil - } -} - -func (e *Store) finalizeDelete(obj runtime.Object, runHooks bool) (runtime.Object, error) { - if runHooks && e.AfterDelete != nil { - if err := e.AfterDelete(obj); err != nil { - return nil, err - } - } - if e.ReturnDeletedObject { - if e.Decorator != nil { - if err := e.Decorator(obj); err != nil { - return nil, err - } - } - return obj, nil - } - return &unversioned.Status{Status: unversioned.StatusSuccess}, nil -} - -// Watch makes a matcher for the given label and field, and calls -// WatchPredicate. If possible, you should customize PredicateFunc to produre a -// matcher that matches by key. generic.SelectionPredicate does this for you -// automatically. -func (e *Store) Watch(ctx api.Context, options *api.ListOptions) (watch.Interface, error) { - label := labels.Everything() - if options != nil && options.LabelSelector != nil { - label = options.LabelSelector - } - field := fields.Everything() - if options != nil && options.FieldSelector != nil { - field = options.FieldSelector - } - resourceVersion := "" - if options != nil { - resourceVersion = options.ResourceVersion - } - return e.WatchPredicate(ctx, e.PredicateFunc(label, field), resourceVersion) -} - -// WatchPredicate starts a watch for the items that m matches. -func (e *Store) WatchPredicate(ctx api.Context, m generic.Matcher, resourceVersion string) (watch.Interface, error) { - filterFunc := e.filterAndDecorateFunction(m) - - if name, ok := m.MatchesSingle(); ok { - if key, err := e.KeyFunc(ctx, name); err == nil { - if err != nil { - return nil, err - } - return e.Storage.Watch(ctx, key, resourceVersion, filterFunc) - } - // if we cannot extract a key based on the current context, the optimization is skipped - } - - return e.Storage.WatchList(ctx, e.KeyRootFunc(ctx), resourceVersion, filterFunc) -} - -func (e *Store) filterAndDecorateFunction(m generic.Matcher) func(runtime.Object) bool { - return func(obj runtime.Object) bool { - matches, err := m.Matches(obj) - if err != nil { - glog.Errorf("unable to match watch: %v", err) - return false - } - if matches && e.Decorator != nil { - if err := e.Decorator(obj); err != nil { - glog.Errorf("unable to decorate watch: %v", err) - return false - } - } - return matches - } -} - -// calculateTTL is a helper for retrieving the updated TTL for an object or returning an error -// if the TTL cannot be calculated. The defaultTTL is changed to 1 if less than zero. Zero means -// no TTL, not expire immediately. -func (e *Store) calculateTTL(obj runtime.Object, defaultTTL int64, update bool) (ttl uint64, err error) { - // TODO: validate this is assertion is still valid. - // etcd may return a negative TTL for a node if the expiration has not occurred due - // to server lag - we will ensure that the value is at least set. - if defaultTTL < 0 { - defaultTTL = 1 - } - ttl = uint64(defaultTTL) - if e.TTLFunc != nil { - ttl, err = e.TTLFunc(obj, ttl, update) - } - return ttl, err -} - -func exportObjectMeta(accessor meta.Object, exact bool) { - accessor.SetUID("") - if !exact { - accessor.SetNamespace("") - } - accessor.SetCreationTimestamp(unversioned.Time{}) - accessor.SetDeletionTimestamp(nil) - accessor.SetResourceVersion("") - accessor.SetSelfLink("") - if len(accessor.GetGenerateName()) > 0 && !exact { - accessor.SetName("") - } -} - -// Implements the rest.Exporter interface -func (e *Store) Export(ctx api.Context, name string, opts unversioned.ExportOptions) (runtime.Object, error) { - obj, err := e.Get(ctx, name) - if err != nil { - return nil, err - } - if accessor, err := meta.Accessor(obj); err == nil { - exportObjectMeta(accessor, opts.Exact) - } else { - glog.V(4).Infof("Object of type %v does not have ObjectMeta: %v", reflect.TypeOf(obj), err) - } - - if e.ExportStrategy != nil { - if err = e.ExportStrategy.Export(obj, opts.Exact); err != nil { - return nil, err - } - } else { - e.CreateStrategy.PrepareForCreate(obj) - } - return obj, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/store_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/store_test.go deleted file mode 100644 index a89eca3e6..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/registry/store_test.go +++ /dev/null @@ -1,717 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 registry - -import ( - "fmt" - "path" - "reflect" - "strconv" - "testing" - - "sync" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/runtime" - etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" - "k8s.io/kubernetes/pkg/storage/etcd/etcdtest" - etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" - storagetesting "k8s.io/kubernetes/pkg/storage/testing" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/validation/field" -) - -type testRESTStrategy struct { - runtime.ObjectTyper - api.NameGenerator - namespaceScoped bool - allowCreateOnUpdate bool - allowUnconditionalUpdate bool -} - -func (t *testRESTStrategy) NamespaceScoped() bool { return t.namespaceScoped } -func (t *testRESTStrategy) AllowCreateOnUpdate() bool { return t.allowCreateOnUpdate } -func (t *testRESTStrategy) AllowUnconditionalUpdate() bool { return t.allowUnconditionalUpdate } - -func (t *testRESTStrategy) PrepareForCreate(obj runtime.Object) { - metaObj, err := meta.Accessor(obj) - if err != nil { - panic(err.Error()) - } - labels := metaObj.GetLabels() - if labels == nil { - labels = map[string]string{} - } - labels["prepare_create"] = "true" - metaObj.SetLabels(labels) -} - -func (t *testRESTStrategy) PrepareForUpdate(obj, old runtime.Object) {} -func (t *testRESTStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList { - return nil -} -func (t *testRESTStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList { - return nil -} -func (t *testRESTStrategy) Canonicalize(obj runtime.Object) {} - -func hasCreated(t *testing.T, pod *api.Pod) func(runtime.Object) bool { - return func(obj runtime.Object) bool { - actualPod := obj.(*api.Pod) - if !api.Semantic.DeepDerivative(pod.Status, actualPod.Status) { - t.Errorf("not a deep derivative %#v", actualPod) - return false - } - return api.HasObjectMetaSystemFieldValues(&actualPod.ObjectMeta) - } -} - -func NewTestGenericStoreRegistry(t *testing.T) (*etcdtesting.EtcdTestServer, *Store) { - podPrefix := "/pods" - server := etcdtesting.NewEtcdTestClientServer(t) - s := etcdstorage.NewEtcdStorage(server.Client, testapi.Default.StorageCodec(), etcdtest.PathPrefix(), false, etcdtest.DeserializationCacheSize) - strategy := &testRESTStrategy{api.Scheme, api.SimpleNameGenerator, true, false, true} - - return server, &Store{ - NewFunc: func() runtime.Object { return &api.Pod{} }, - NewListFunc: func() runtime.Object { return &api.PodList{} }, - QualifiedResource: api.Resource("pods"), - CreateStrategy: strategy, - UpdateStrategy: strategy, - DeleteStrategy: strategy, - KeyRootFunc: func(ctx api.Context) string { - return podPrefix - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - if _, ok := api.NamespaceFrom(ctx); !ok { - return "", fmt.Errorf("namespace is required") - } - return path.Join(podPrefix, id), nil - }, - ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.Pod).Name, nil }, - PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { - return &generic.SelectionPredicate{ - Label: label, - Field: field, - GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) { - pod, ok := obj.(*api.Pod) - if !ok { - return nil, nil, fmt.Errorf("not a pod") - } - return labels.Set(pod.ObjectMeta.Labels), generic.ObjectMetaFieldsSet(pod.ObjectMeta, true), nil - }, - } - }, - Storage: s, - } -} - -// setMatcher is a matcher that matches any pod with id in the set. -// Makes testing simpler. -type setMatcher struct { - sets.String -} - -func (sm setMatcher) Matches(obj runtime.Object) (bool, error) { - pod, ok := obj.(*api.Pod) - if !ok { - return false, fmt.Errorf("wrong object") - } - return sm.Has(pod.Name), nil -} - -func (sm setMatcher) MatchesSingle() (string, bool) { - if sm.Len() == 1 { - // Since pod name is its key, we can optimize this case. - return sm.List()[0], true - } - return "", false -} - -// everythingMatcher matches everything -type everythingMatcher struct{} - -func (everythingMatcher) Matches(obj runtime.Object) (bool, error) { - return true, nil -} - -func (everythingMatcher) MatchesSingle() (string, bool) { - return "", false -} - -func TestStoreList(t *testing.T) { - podA := &api.Pod{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "bar"}, - Spec: api.PodSpec{NodeName: "machine"}, - } - podB := &api.Pod{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "foo"}, - Spec: api.PodSpec{NodeName: "machine"}, - } - - testContext := api.WithNamespace(api.NewContext(), "test") - noNamespaceContext := api.NewContext() - - table := map[string]struct { - in *api.PodList - m generic.Matcher - out runtime.Object - context api.Context - }{ - "notFound": { - in: nil, - m: everythingMatcher{}, - out: &api.PodList{Items: []api.Pod{}}, - }, - "normal": { - in: &api.PodList{Items: []api.Pod{*podA, *podB}}, - m: everythingMatcher{}, - out: &api.PodList{Items: []api.Pod{*podA, *podB}}, - }, - "normalFiltered": { - in: &api.PodList{Items: []api.Pod{*podA, *podB}}, - m: setMatcher{sets.NewString("foo")}, - out: &api.PodList{Items: []api.Pod{*podB}}, - }, - "normalFilteredNoNamespace": { - in: &api.PodList{Items: []api.Pod{*podA, *podB}}, - m: setMatcher{sets.NewString("foo")}, - out: &api.PodList{Items: []api.Pod{*podB}}, - context: noNamespaceContext, - }, - "normalFilteredMatchMultiple": { - in: &api.PodList{Items: []api.Pod{*podA, *podB}}, - m: setMatcher{sets.NewString("foo", "makeMatchSingleReturnFalse")}, - out: &api.PodList{Items: []api.Pod{*podB}}, - }, - } - - for name, item := range table { - ctx := testContext - if item.context != nil { - ctx = item.context - } - server, registry := NewTestGenericStoreRegistry(t) - - if item.in != nil { - if err := storagetesting.CreateList("/pods", registry.Storage, item.in); err != nil { - t.Errorf("Unexpected error %v", err) - } - } - - list, err := registry.ListPredicate(ctx, item.m, nil) - if err != nil { - t.Errorf("Unexpected error %v", err) - continue - } - - // DeepDerivative e,a is needed here b/c the storage layer sets ResourceVersion - if e, a := item.out, list; !api.Semantic.DeepDerivative(e, a) { - t.Errorf("%v: Expected %#v, got %#v", name, e, a) - } - server.Terminate(t) - } -} - -func TestStoreCreate(t *testing.T) { - podA := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"}, - Spec: api.PodSpec{NodeName: "machine"}, - } - podB := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"}, - Spec: api.PodSpec{NodeName: "machine2"}, - } - - testContext := api.WithNamespace(api.NewContext(), "test") - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - // create the object - objA, err := registry.Create(testContext, podA) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // get the object - checkobj, err := registry.Get(testContext, podA.Name) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // verify objects are equal - if e, a := objA, checkobj; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } - - // now try to create the second pod - _, err = registry.Create(testContext, podB) - if !errors.IsAlreadyExists(err) { - t.Errorf("Unexpected error: %v", err) - } -} - -func updateAndVerify(t *testing.T, ctx api.Context, registry *Store, pod *api.Pod) bool { - obj, _, err := registry.Update(ctx, pod) - if err != nil { - t.Errorf("Unexpected error: %v", err) - return false - } - checkObj, err := registry.Get(ctx, pod.Name) - if err != nil { - t.Errorf("Unexpected error: %v", err) - return false - } - if e, a := obj, checkObj; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - return false - } - return true -} - -func TestStoreUpdate(t *testing.T) { - podA := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"}, - Spec: api.PodSpec{NodeName: "machine"}, - } - podB := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test"}, - Spec: api.PodSpec{NodeName: "machine2"}, - } - podAWithResourceVersion := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "test", ResourceVersion: "7"}, - Spec: api.PodSpec{NodeName: "machine"}, - } - - testContext := api.WithNamespace(api.NewContext(), "test") - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - // Test1 try to update a non-existing node - _, _, err := registry.Update(testContext, podA) - if !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - - // Test2 createIfNotFound and verify - registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true - if !updateAndVerify(t, testContext, registry, podA) { - t.Errorf("Unexpected error updating podA") - } - registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = false - - // Test3 outofDate - _, _, err = registry.Update(testContext, podAWithResourceVersion) - if !errors.IsConflict(err) { - t.Errorf("Unexpected error updating podAWithResourceVersion: %v", err) - } - - // Test4 normal update and verify - if !updateAndVerify(t, testContext, registry, podB) { - t.Errorf("Unexpected error updating podB") - } - - // Test5 unconditional update - // NOTE: The logic for unconditional updates doesn't make sense to me, and imho should be removed. - // doUnconditionalUpdate := resourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate() - // ^^ That condition can *never be true due to the creation of root objects. - // - // registry.UpdateStrategy.(*testRESTStrategy).allowUnconditionalUpdate = true - // updateAndVerify(t, testContext, registry, podAWithResourceVersion) - -} - -func TestNoOpUpdates(t *testing.T) { - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - newPod := func() *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: api.NamespaceDefault, - Name: "foo", - Labels: map[string]string{"prepare_create": "true"}, - }, - Spec: api.PodSpec{NodeName: "machine"}, - } - } - - var err error - var createResult runtime.Object - if createResult, err = registry.Create(api.NewDefaultContext(), newPod()); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - createdPod, err := registry.Get(api.NewDefaultContext(), "foo") - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - var updateResult runtime.Object - if updateResult, _, err = registry.Update(api.NewDefaultContext(), newPod()); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - // Check whether we do not return empty result on no-op update. - if !reflect.DeepEqual(createResult, updateResult) { - t.Errorf("no-op update should return a correct value, got: %#v", updateResult) - } - - updatedPod, err := registry.Get(api.NewDefaultContext(), "foo") - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - createdMeta, err := meta.Accessor(createdPod) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - updatedMeta, err := meta.Accessor(updatedPod) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if createdMeta.GetResourceVersion() != updatedMeta.GetResourceVersion() { - t.Errorf("no-op update should be ignored and not written to etcd") - } -} - -// TODO: Add a test to check no-op update if we have object with ResourceVersion -// already stored in etcd. Currently there is no easy way to store object with -// ResourceVersion in etcd. - -type testPodExport struct{} - -func (t testPodExport) Export(obj runtime.Object, exact bool) error { - pod := obj.(*api.Pod) - if pod.Labels == nil { - pod.Labels = map[string]string{} - } - pod.Labels["exported"] = "true" - pod.Labels["exact"] = strconv.FormatBool(exact) - - return nil -} - -func TestStoreCustomExport(t *testing.T) { - podA := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: "test", - Name: "foo", - Labels: map[string]string{}, - }, - Spec: api.PodSpec{NodeName: "machine"}, - } - - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - registry.ExportStrategy = testPodExport{} - - testContext := api.WithNamespace(api.NewContext(), "test") - registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true - if !updateAndVerify(t, testContext, registry, &podA) { - t.Errorf("Unexpected error updating podA") - } - - obj, err := registry.Export(testContext, podA.Name, unversioned.ExportOptions{}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - exportedPod := obj.(*api.Pod) - if exportedPod.Labels["exported"] != "true" { - t.Errorf("expected: exported->true, found: %s", exportedPod.Labels["exported"]) - } - if exportedPod.Labels["exact"] != "false" { - t.Errorf("expected: exact->false, found: %s", exportedPod.Labels["exact"]) - } - delete(exportedPod.Labels, "exported") - delete(exportedPod.Labels, "exact") - exportObjectMeta(&podA.ObjectMeta, false) - podA.Spec = exportedPod.Spec - if !reflect.DeepEqual(&podA, exportedPod) { - t.Errorf("expected:\n%v\nsaw:\n%v\n", &podA, exportedPod) - } -} - -func TestStoreBasicExport(t *testing.T) { - podA := api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: "test", - Name: "foo", - Labels: map[string]string{}, - }, - Spec: api.PodSpec{NodeName: "machine"}, - Status: api.PodStatus{HostIP: "1.2.3.4"}, - } - - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - testContext := api.WithNamespace(api.NewContext(), "test") - registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true - if !updateAndVerify(t, testContext, registry, &podA) { - t.Errorf("Unexpected error updating podA") - } - - obj, err := registry.Export(testContext, podA.Name, unversioned.ExportOptions{}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - exportedPod := obj.(*api.Pod) - if exportedPod.Labels["prepare_create"] != "true" { - t.Errorf("expected: prepare_create->true, found: %s", exportedPod.Labels["prepare_create"]) - } - exportObjectMeta(&podA.ObjectMeta, false) - podA.Spec = exportedPod.Spec - if !reflect.DeepEqual(&podA, exportedPod) { - t.Errorf("expected:\n%v\nsaw:\n%v\n", &podA, exportedPod) - } -} - -func TestStoreGet(t *testing.T) { - podA := &api.Pod{ - ObjectMeta: api.ObjectMeta{Namespace: "test", Name: "foo"}, - Spec: api.PodSpec{NodeName: "machine"}, - } - - testContext := api.WithNamespace(api.NewContext(), "test") - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - _, err := registry.Get(testContext, podA.Name) - if !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - - registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true - if !updateAndVerify(t, testContext, registry, podA) { - t.Errorf("Unexpected error updating podA") - } -} - -func TestStoreDelete(t *testing.T) { - podA := &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: api.PodSpec{NodeName: "machine"}, - } - - testContext := api.WithNamespace(api.NewContext(), "test") - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - // test failure condition - _, err := registry.Delete(testContext, podA.Name, nil) - if !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - - // create pod - _, err = registry.Create(testContext, podA) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // delete object - _, err = registry.Delete(testContext, podA.Name, nil) - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // try to get a item which should be deleted - _, err = registry.Get(testContext, podA.Name) - if !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestStoreDeleteCollection(t *testing.T) { - podA := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - podB := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}} - - testContext := api.WithNamespace(api.NewContext(), "test") - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - if _, err := registry.Create(testContext, podA); err != nil { - t.Errorf("Unexpected error: %v", err) - } - if _, err := registry.Create(testContext, podB); err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // Delete all pods. - deleted, err := registry.DeleteCollection(testContext, nil, &api.ListOptions{}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - deletedPods := deleted.(*api.PodList) - if len(deletedPods.Items) != 2 { - t.Errorf("Unexpected number of pods deleted: %d, expected: 2", len(deletedPods.Items)) - } - - if _, err := registry.Get(testContext, podA.Name); !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - if _, err := registry.Get(testContext, podB.Name); !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } -} - -func TestStoreDeleteCollectionNotFound(t *testing.T) { - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - testContext := api.WithNamespace(api.NewContext(), "test") - - podA := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - podB := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}} - - for i := 0; i < 10; i++ { - // Setup - if _, err := registry.Create(testContext, podA); err != nil { - t.Errorf("Unexpected error: %v", err) - } - if _, err := registry.Create(testContext, podB); err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // Kick off multiple delete collection calls to test notfound behavior - wg := &sync.WaitGroup{} - for j := 0; j < 2; j++ { - wg.Add(1) - go func() { - defer wg.Done() - _, err := registry.DeleteCollection(testContext, nil, &api.ListOptions{}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - }() - } - wg.Wait() - - if _, err := registry.Get(testContext, podA.Name); !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - if _, err := registry.Get(testContext, podB.Name); !errors.IsNotFound(err) { - t.Errorf("Unexpected error: %v", err) - } - } -} - -// Test whether objects deleted with DeleteCollection are correctly delivered -// to watchers. -func TestStoreDeleteCollectionWithWatch(t *testing.T) { - podA := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - - testContext := api.WithNamespace(api.NewContext(), "test") - server, registry := NewTestGenericStoreRegistry(t) - defer server.Terminate(t) - - objCreated, err := registry.Create(testContext, podA) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - podCreated := objCreated.(*api.Pod) - - watcher, err := registry.WatchPredicate(testContext, setMatcher{sets.NewString("foo")}, podCreated.ResourceVersion) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watcher.Stop() - - if _, err := registry.DeleteCollection(testContext, nil, &api.ListOptions{}); err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - got, open := <-watcher.ResultChan() - if !open { - t.Errorf("Unexpected channel close") - } else { - if got.Type != "DELETED" { - t.Errorf("Unexpected event type: %s", got.Type) - } - gotObject := got.Object.(*api.Pod) - gotObject.ResourceVersion = podCreated.ResourceVersion - if e, a := podCreated, gotObject; !reflect.DeepEqual(e, a) { - t.Errorf("Expected: %#v, got: %#v", e, a) - } - } -} - -func TestStoreWatch(t *testing.T) { - testContext := api.WithNamespace(api.NewContext(), "test") - noNamespaceContext := api.NewContext() - - table := map[string]struct { - generic.Matcher - context api.Context - }{ - "single": { - Matcher: setMatcher{sets.NewString("foo")}, - }, - "multi": { - Matcher: setMatcher{sets.NewString("foo", "bar")}, - }, - "singleNoNamespace": { - Matcher: setMatcher{sets.NewString("foo")}, - context: noNamespaceContext, - }, - } - - for name, m := range table { - ctx := testContext - if m.context != nil { - ctx = m.context - } - podA := &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Namespace: "test", - }, - Spec: api.PodSpec{NodeName: "machine"}, - } - - server, registry := NewTestGenericStoreRegistry(t) - wi, err := registry.WatchPredicate(ctx, m, "0") - if err != nil { - t.Errorf("%v: unexpected error: %v", name, err) - } else { - obj, err := registry.Create(testContext, podA) - if err != nil { - got, open := <-wi.ResultChan() - if !open { - t.Errorf("%v: unexpected channel close", name) - } else { - if e, a := obj, got.Object; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } - } - } - wi.Stop() - } - - server.Terminate(t) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/doc.go deleted file mode 100644 index fef461387..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rest has generic implementations of resources used for -// REST responses -package rest diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/proxy.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/proxy.go deleted file mode 100644 index ca28831c8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/proxy.go +++ /dev/null @@ -1,242 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rest - -import ( - "io" - "net/http" - "net/http/httputil" - "net/url" - "strings" - "sync" - "time" - - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/util/httpstream" - "k8s.io/kubernetes/pkg/util/net" - "k8s.io/kubernetes/pkg/util/proxy" - - "github.com/golang/glog" - "github.com/mxk/go-flowrate/flowrate" -) - -// UpgradeAwareProxyHandler is a handler for proxy requests that may require an upgrade -type UpgradeAwareProxyHandler struct { - UpgradeRequired bool - Location *url.URL - // Transport provides an optional round tripper to use to proxy. If nil, the default proxy transport is used - Transport http.RoundTripper - // WrapTransport indicates whether the provided Transport should be wrapped with default proxy transport behavior (URL rewriting, X-Forwarded-* header setting) - WrapTransport bool - FlushInterval time.Duration - MaxBytesPerSec int64 - Responder ErrorResponder -} - -const defaultFlushInterval = 200 * time.Millisecond - -// ErrorResponder abstracts error reporting to the proxy handler to remove the need to hardcode a particular -// error format. -type ErrorResponder interface { - Error(err error) -} - -// NewUpgradeAwareProxyHandler creates a new proxy handler with a default flush interval. Responder is required for returning -// errors to the caller. -func NewUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder ErrorResponder) *UpgradeAwareProxyHandler { - return &UpgradeAwareProxyHandler{ - Location: location, - Transport: transport, - WrapTransport: wrapTransport, - UpgradeRequired: upgradeRequired, - FlushInterval: defaultFlushInterval, - Responder: responder, - } -} - -// ServeHTTP handles the proxy request -func (h *UpgradeAwareProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - if len(h.Location.Scheme) == 0 { - h.Location.Scheme = "http" - } - if h.tryUpgrade(w, req) { - return - } - if h.UpgradeRequired { - h.Responder.Error(errors.NewBadRequest("Upgrade request required")) - return - } - - loc := *h.Location - loc.RawQuery = req.URL.RawQuery - - // If original request URL ended in '/', append a '/' at the end of the - // of the proxy URL - if !strings.HasSuffix(loc.Path, "/") && strings.HasSuffix(req.URL.Path, "/") { - loc.Path += "/" - } - - // From pkg/apiserver/proxy.go#ServeHTTP: - // Redirect requests with an empty path to a location that ends with a '/' - // This is essentially a hack for http://issue.k8s.io/4958. - // Note: Keep this code after tryUpgrade to not break that flow. - if len(loc.Path) == 0 { - var queryPart string - if len(req.URL.RawQuery) > 0 { - queryPart = "?" + req.URL.RawQuery - } - w.Header().Set("Location", req.URL.Path+"/"+queryPart) - w.WriteHeader(http.StatusMovedPermanently) - return - } - - if h.Transport == nil || h.WrapTransport { - h.Transport = h.defaultProxyTransport(req.URL, h.Transport) - } - - newReq, err := http.NewRequest(req.Method, loc.String(), req.Body) - if err != nil { - h.Responder.Error(err) - return - } - newReq.Header = req.Header - newReq.ContentLength = req.ContentLength - // Copy the TransferEncoding is for future-proofing. Currently Go only supports "chunked" and - // it can determine the TransferEncoding based on ContentLength and the Body. - newReq.TransferEncoding = req.TransferEncoding - - proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme: h.Location.Scheme, Host: h.Location.Host}) - proxy.Transport = h.Transport - proxy.FlushInterval = h.FlushInterval - proxy.ServeHTTP(w, newReq) -} - -// tryUpgrade returns true if the request was handled. -func (h *UpgradeAwareProxyHandler) tryUpgrade(w http.ResponseWriter, req *http.Request) bool { - if !httpstream.IsUpgradeRequest(req) { - return false - } - - backendConn, err := proxy.DialURL(h.Location, h.Transport) - if err != nil { - h.Responder.Error(err) - return true - } - defer backendConn.Close() - - requestHijackedConn, _, err := w.(http.Hijacker).Hijack() - if err != nil { - h.Responder.Error(err) - return true - } - defer requestHijackedConn.Close() - - newReq, err := http.NewRequest(req.Method, h.Location.String(), req.Body) - if err != nil { - h.Responder.Error(err) - return true - } - newReq.Header = req.Header - - if err = newReq.Write(backendConn); err != nil { - h.Responder.Error(err) - return true - } - - wg := &sync.WaitGroup{} - wg.Add(2) - - go func() { - var writer io.WriteCloser - if h.MaxBytesPerSec > 0 { - writer = flowrate.NewWriter(backendConn, h.MaxBytesPerSec) - } else { - writer = backendConn - } - _, err := io.Copy(writer, requestHijackedConn) - if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { - glog.Errorf("Error proxying data from client to backend: %v", err) - } - wg.Done() - }() - - go func() { - var reader io.ReadCloser - if h.MaxBytesPerSec > 0 { - reader = flowrate.NewReader(backendConn, h.MaxBytesPerSec) - } else { - reader = backendConn - } - _, err := io.Copy(requestHijackedConn, reader) - if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { - glog.Errorf("Error proxying data from backend to client: %v", err) - } - wg.Done() - }() - - wg.Wait() - return true -} - -func (h *UpgradeAwareProxyHandler) defaultProxyTransport(url *url.URL, internalTransport http.RoundTripper) http.RoundTripper { - scheme := url.Scheme - host := url.Host - suffix := h.Location.Path - if strings.HasSuffix(url.Path, "/") && !strings.HasSuffix(suffix, "/") { - suffix += "/" - } - pathPrepend := strings.TrimSuffix(url.Path, suffix) - rewritingTransport := &proxy.Transport{ - Scheme: scheme, - Host: host, - PathPrepend: pathPrepend, - RoundTripper: internalTransport, - } - return &corsRemovingTransport{ - RoundTripper: rewritingTransport, - } -} - -// corsRemovingTransport is a wrapper for an internal transport. It removes CORS headers -// from the internal response. -type corsRemovingTransport struct { - http.RoundTripper -} - -func (p *corsRemovingTransport) RoundTrip(req *http.Request) (*http.Response, error) { - resp, err := p.RoundTripper.RoundTrip(req) - if err != nil { - return nil, err - } - removeCORSHeaders(resp) - return resp, nil -} - -var _ = net.RoundTripperWrapper(&corsRemovingTransport{}) - -func (rt *corsRemovingTransport) WrappedRoundTripper() http.RoundTripper { - return rt.RoundTripper -} - -// removeCORSHeaders strip CORS headers sent from the backend -// This should be called on all responses before returning -func removeCORSHeaders(resp *http.Response) { - resp.Header.Del("Access-Control-Allow-Credentials") - resp.Header.Del("Access-Control-Allow-Headers") - resp.Header.Del("Access-Control-Allow-Methods") - resp.Header.Del("Access-Control-Allow-Origin") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/proxy_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/proxy_test.go deleted file mode 100644 index 8b9268402..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/proxy_test.go +++ /dev/null @@ -1,725 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rest - -import ( - "bytes" - "compress/gzip" - "crypto/tls" - "crypto/x509" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/http/httptest" - "net/http/httputil" - "net/url" - "reflect" - "strconv" - "strings" - "testing" - - "golang.org/x/net/websocket" - - utilnet "k8s.io/kubernetes/pkg/util/net" - "k8s.io/kubernetes/pkg/util/proxy" -) - -type fakeResponder struct { - called bool - err error -} - -func (r *fakeResponder) Error(err error) { - if r.called { - panic("called twice") - } - r.called = true - r.err = err -} - -type SimpleBackendHandler struct { - requestURL url.URL - requestHeader http.Header - requestBody []byte - requestMethod string - responseBody string - responseHeader map[string]string - t *testing.T -} - -func (s *SimpleBackendHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - s.requestURL = *req.URL - s.requestHeader = req.Header - s.requestMethod = req.Method - var err error - s.requestBody, err = ioutil.ReadAll(req.Body) - if err != nil { - s.t.Errorf("Unexpected error: %v", err) - return - } - - if s.responseHeader != nil { - for k, v := range s.responseHeader { - w.Header().Add(k, v) - } - } - w.Write([]byte(s.responseBody)) -} - -func validateParameters(t *testing.T, name string, actual url.Values, expected map[string]string) { - for k, v := range expected { - actualValue, ok := actual[k] - if !ok { - t.Errorf("%s: Expected parameter %s not received", name, k) - continue - } - if actualValue[0] != v { - t.Errorf("%s: Parameter %s values don't match. Actual: %#v, Expected: %s", - name, k, actualValue, v) - } - } -} - -func validateHeaders(t *testing.T, name string, actual http.Header, expected map[string]string, notExpected []string) { - for k, v := range expected { - actualValue, ok := actual[k] - if !ok { - t.Errorf("%s: Expected header %s not received", name, k) - continue - } - if actualValue[0] != v { - t.Errorf("%s: Header %s values don't match. Actual: %s, Expected: %s", - name, k, actualValue, v) - } - } - if notExpected == nil { - return - } - for _, h := range notExpected { - if _, present := actual[h]; present { - t.Errorf("%s: unexpected header: %s", name, h) - } - } -} - -func TestServeHTTP(t *testing.T) { - tests := []struct { - name string - method string - requestPath string - expectedPath string - requestBody string - requestParams map[string]string - requestHeader map[string]string - responseHeader map[string]string - expectedRespHeader map[string]string - notExpectedRespHeader []string - upgradeRequired bool - expectError func(err error) bool - }{ - { - name: "root path, simple get", - method: "GET", - requestPath: "/", - expectedPath: "/", - }, - { - name: "no upgrade header sent", - method: "GET", - requestPath: "/", - upgradeRequired: true, - expectError: func(err error) bool { - return err != nil && strings.Contains(err.Error(), "Upgrade request required") - }, - }, - { - name: "simple path, get", - method: "GET", - requestPath: "/path/to/test", - expectedPath: "/path/to/test", - }, - { - name: "request params", - method: "POST", - requestPath: "/some/path/", - expectedPath: "/some/path/", - requestParams: map[string]string{"param1": "value/1", "param2": "value%2"}, - requestBody: "test request body", - }, - { - name: "request headers", - method: "PUT", - requestPath: "/some/path", - expectedPath: "/some/path", - requestHeader: map[string]string{"Header1": "value1", "Header2": "value2"}, - }, - { - name: "empty path - slash should be added", - method: "GET", - requestPath: "", - expectedPath: "/", - }, - { - name: "remove CORS headers", - method: "GET", - requestPath: "/some/path", - expectedPath: "/some/path", - responseHeader: map[string]string{ - "Header1": "value1", - "Access-Control-Allow-Origin": "some.server", - "Access-Control-Allow-Methods": "GET"}, - expectedRespHeader: map[string]string{ - "Header1": "value1", - }, - notExpectedRespHeader: []string{ - "Access-Control-Allow-Origin", - "Access-Control-Allow-Methods", - }, - }, - } - - for i, test := range tests { - func() { - backendResponse := "Hello" - backendResponseHeader := test.responseHeader - // Test a simple header if not specified in the test - if backendResponseHeader == nil && test.expectedRespHeader == nil { - backendResponseHeader = map[string]string{"Content-Type": "text/html"} - test.expectedRespHeader = map[string]string{"Content-Type": "text/html"} - } - backendHandler := &SimpleBackendHandler{ - responseBody: backendResponse, - responseHeader: backendResponseHeader, - } - backendServer := httptest.NewServer(backendHandler) - defer backendServer.Close() - - responder := &fakeResponder{} - backendURL, _ := url.Parse(backendServer.URL) - backendURL.Path = test.requestPath - proxyHandler := &UpgradeAwareProxyHandler{ - Location: backendURL, - Responder: responder, - UpgradeRequired: test.upgradeRequired, - } - proxyServer := httptest.NewServer(proxyHandler) - defer proxyServer.Close() - proxyURL, _ := url.Parse(proxyServer.URL) - proxyURL.Path = test.requestPath - paramValues := url.Values{} - for k, v := range test.requestParams { - paramValues[k] = []string{v} - } - proxyURL.RawQuery = paramValues.Encode() - var requestBody io.Reader - if test.requestBody != "" { - requestBody = bytes.NewBufferString(test.requestBody) - } - req, err := http.NewRequest(test.method, proxyURL.String(), requestBody) - if test.requestHeader != nil { - header := http.Header{} - for k, v := range test.requestHeader { - header.Add(k, v) - } - req.Header = header - } - if err != nil { - t.Errorf("Error creating client request: %v", err) - } - client := &http.Client{} - res, err := client.Do(req) - if err != nil { - t.Errorf("Error from proxy request: %v", err) - } - - if test.expectError != nil { - if !responder.called { - t.Errorf("%d: responder was not invoked", i) - return - } - if !test.expectError(responder.err) { - t.Errorf("%d: unexpected error: %v", i, responder.err) - } - return - } - - // Validate backend request - // Method - if backendHandler.requestMethod != test.method { - t.Errorf("Unexpected request method: %s. Expected: %s", - backendHandler.requestMethod, test.method) - } - - // Body - if string(backendHandler.requestBody) != test.requestBody { - t.Errorf("Unexpected request body: %s. Expected: %s", - string(backendHandler.requestBody), test.requestBody) - } - - // Path - if backendHandler.requestURL.Path != test.expectedPath { - t.Errorf("Unexpected request path: %s", backendHandler.requestURL.Path) - } - // Parameters - validateParameters(t, test.name, backendHandler.requestURL.Query(), test.requestParams) - - // Headers - validateHeaders(t, test.name+" backend request", backendHandler.requestHeader, - test.requestHeader, nil) - - // Validate proxy response - - // Response Headers - validateHeaders(t, test.name+" backend headers", res.Header, test.expectedRespHeader, test.notExpectedRespHeader) - - // Validate Body - responseBody, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Errorf("Unexpected error reading response body: %v", err) - } - if rb := string(responseBody); rb != backendResponse { - t.Errorf("Did not get expected response body: %s. Expected: %s", rb, backendResponse) - } - - // Error - if responder.called { - t.Errorf("Unexpected proxy handler error: %v", responder.err) - } - }() - } -} - -func TestProxyUpgrade(t *testing.T) { - - localhostPool := x509.NewCertPool() - if !localhostPool.AppendCertsFromPEM(localhostCert) { - t.Errorf("error setting up localhostCert pool") - } - - testcases := map[string]struct { - ServerFunc func(http.Handler) *httptest.Server - ProxyTransport http.RoundTripper - }{ - "http": { - ServerFunc: httptest.NewServer, - ProxyTransport: nil, - }, - "https (invalid hostname + InsecureSkipVerify)": { - ServerFunc: func(h http.Handler) *httptest.Server { - cert, err := tls.X509KeyPair(exampleCert, exampleKey) - if err != nil { - t.Errorf("https (invalid hostname): proxy_test: %v", err) - } - ts := httptest.NewUnstartedServer(h) - ts.TLS = &tls.Config{ - Certificates: []tls.Certificate{cert}, - } - ts.StartTLS() - return ts - }, - ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}), - }, - "https (valid hostname + RootCAs)": { - ServerFunc: func(h http.Handler) *httptest.Server { - cert, err := tls.X509KeyPair(localhostCert, localhostKey) - if err != nil { - t.Errorf("https (valid hostname): proxy_test: %v", err) - } - ts := httptest.NewUnstartedServer(h) - ts.TLS = &tls.Config{ - Certificates: []tls.Certificate{cert}, - } - ts.StartTLS() - return ts - }, - ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), - }, - "https (valid hostname + RootCAs + custom dialer)": { - ServerFunc: func(h http.Handler) *httptest.Server { - cert, err := tls.X509KeyPair(localhostCert, localhostKey) - if err != nil { - t.Errorf("https (valid hostname): proxy_test: %v", err) - } - ts := httptest.NewUnstartedServer(h) - ts.TLS = &tls.Config{ - Certificates: []tls.Certificate{cert}, - } - ts.StartTLS() - return ts - }, - ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}), - }, - } - - for k, tc := range testcases { - - backendServer := tc.ServerFunc(websocket.Handler(func(ws *websocket.Conn) { - defer ws.Close() - body := make([]byte, 5) - ws.Read(body) - ws.Write([]byte("hello " + string(body))) - })) - defer backendServer.Close() - - serverURL, _ := url.Parse(backendServer.URL) - proxyHandler := &UpgradeAwareProxyHandler{ - Location: serverURL, - Transport: tc.ProxyTransport, - } - proxy := httptest.NewServer(proxyHandler) - defer proxy.Close() - - ws, err := websocket.Dial("ws://"+proxy.Listener.Addr().String()+"/some/path", "", "http://127.0.0.1/") - if err != nil { - t.Fatalf("%s: websocket dial err: %s", k, err) - } - defer ws.Close() - - if _, err := ws.Write([]byte("world")); err != nil { - t.Fatalf("%s: write err: %s", k, err) - } - - response := make([]byte, 20) - n, err := ws.Read(response) - if err != nil { - t.Fatalf("%s: read err: %s", k, err) - } - if e, a := "hello world", string(response[0:n]); e != a { - t.Fatalf("%s: expected '%#v', got '%#v'", k, e, a) - } - } -} - -func TestDefaultProxyTransport(t *testing.T) { - tests := []struct { - name, - url, - location, - expectedScheme, - expectedHost, - expectedPathPrepend string - }{ - - { - name: "simple path", - url: "http://test.server:8080/a/test/location", - location: "http://localhost/location", - expectedScheme: "http", - expectedHost: "test.server:8080", - expectedPathPrepend: "/a/test", - }, - { - name: "empty path", - url: "http://test.server:8080/a/test/", - location: "http://localhost", - expectedScheme: "http", - expectedHost: "test.server:8080", - expectedPathPrepend: "/a/test", - }, - { - name: "location ending in slash", - url: "http://test.server:8080/a/test/", - location: "http://localhost/", - expectedScheme: "http", - expectedHost: "test.server:8080", - expectedPathPrepend: "/a/test", - }, - } - - for _, test := range tests { - locURL, _ := url.Parse(test.location) - URL, _ := url.Parse(test.url) - h := UpgradeAwareProxyHandler{ - Location: locURL, - } - result := h.defaultProxyTransport(URL, nil) - transport := result.(*corsRemovingTransport).RoundTripper.(*proxy.Transport) - if transport.Scheme != test.expectedScheme { - t.Errorf("%s: unexpected scheme. Actual: %s, Expected: %s", test.name, transport.Scheme, test.expectedScheme) - } - if transport.Host != test.expectedHost { - t.Errorf("%s: unexpected host. Actual: %s, Expected: %s", test.name, transport.Host, test.expectedHost) - } - if transport.PathPrepend != test.expectedPathPrepend { - t.Errorf("%s: unexpected path prepend. Actual: %s, Expected: %s", test.name, transport.PathPrepend, test.expectedPathPrepend) - } - } -} - -func TestProxyRequestContentLengthAndTransferEncoding(t *testing.T) { - chunk := func(data []byte) []byte { - out := &bytes.Buffer{} - chunker := httputil.NewChunkedWriter(out) - for _, b := range data { - if _, err := chunker.Write([]byte{b}); err != nil { - panic(err) - } - } - chunker.Close() - out.Write([]byte("\r\n")) - return out.Bytes() - } - - zip := func(data []byte) []byte { - out := &bytes.Buffer{} - zipper := gzip.NewWriter(out) - if _, err := zipper.Write(data); err != nil { - panic(err) - } - zipper.Close() - return out.Bytes() - } - - sampleData := []byte("abcde") - - table := map[string]struct { - reqHeaders http.Header - reqBody []byte - - expectedHeaders http.Header - expectedBody []byte - }{ - "content-length": { - reqHeaders: http.Header{ - "Content-Length": []string{"5"}, - }, - reqBody: sampleData, - - expectedHeaders: http.Header{ - "Content-Length": []string{"5"}, - "Content-Encoding": nil, // none set - "Transfer-Encoding": nil, // none set - }, - expectedBody: sampleData, - }, - - "content-length + identity transfer-encoding": { - reqHeaders: http.Header{ - "Content-Length": []string{"5"}, - "Transfer-Encoding": []string{"identity"}, - }, - reqBody: sampleData, - - expectedHeaders: http.Header{ - "Content-Length": []string{"5"}, - "Content-Encoding": nil, // none set - "Transfer-Encoding": nil, // gets removed - }, - expectedBody: sampleData, - }, - - "content-length + gzip content-encoding": { - reqHeaders: http.Header{ - "Content-Length": []string{strconv.Itoa(len(zip(sampleData)))}, - "Content-Encoding": []string{"gzip"}, - }, - reqBody: zip(sampleData), - - expectedHeaders: http.Header{ - "Content-Length": []string{strconv.Itoa(len(zip(sampleData)))}, - "Content-Encoding": []string{"gzip"}, - "Transfer-Encoding": nil, // none set - }, - expectedBody: zip(sampleData), - }, - - "chunked transfer-encoding": { - reqHeaders: http.Header{ - "Transfer-Encoding": []string{"chunked"}, - }, - reqBody: chunk(sampleData), - - expectedHeaders: http.Header{ - "Content-Length": nil, // none set - "Content-Encoding": nil, // none set - "Transfer-Encoding": nil, // Transfer-Encoding gets removed - }, - expectedBody: sampleData, // sample data is unchunked - }, - - "chunked transfer-encoding + gzip content-encoding": { - reqHeaders: http.Header{ - "Content-Encoding": []string{"gzip"}, - "Transfer-Encoding": []string{"chunked"}, - }, - reqBody: chunk(zip(sampleData)), - - expectedHeaders: http.Header{ - "Content-Length": nil, // none set - "Content-Encoding": []string{"gzip"}, - "Transfer-Encoding": nil, // gets removed - }, - expectedBody: zip(sampleData), // sample data is unchunked, but content-encoding is preserved - }, - - // "Transfer-Encoding: gzip" is not supported by go - // See http/transfer.go#fixTransferEncoding (https://golang.org/src/net/http/transfer.go#L427) - // Once it is supported, this test case should succeed - // - // "gzip+chunked transfer-encoding": { - // reqHeaders: http.Header{ - // "Transfer-Encoding": []string{"chunked,gzip"}, - // }, - // reqBody: chunk(zip(sampleData)), - // - // expectedHeaders: http.Header{ - // "Content-Length": nil, // no content-length headers - // "Transfer-Encoding": nil, // Transfer-Encoding gets removed - // }, - // expectedBody: sampleData, - // }, - } - - successfulResponse := "backend passed tests" - for k, item := range table { - // Start the downstream server - downstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - // Verify headers - for header, v := range item.expectedHeaders { - if !reflect.DeepEqual(v, req.Header[header]) { - t.Errorf("%s: Expected headers for %s to be %v, got %v", k, header, v, req.Header[header]) - } - } - - // Read body - body, err := ioutil.ReadAll(req.Body) - if err != nil { - t.Errorf("%s: unexpected error %v", k, err) - } - req.Body.Close() - - // Verify length - if req.ContentLength > 0 && req.ContentLength != int64(len(body)) { - t.Errorf("%s: ContentLength was %d, len(data) was %d", k, req.ContentLength, len(body)) - } - - // Verify content - if !bytes.Equal(item.expectedBody, body) { - t.Errorf("%s: Expected %q, got %q", k, string(item.expectedBody), string(body)) - } - - // Write successful response - w.Write([]byte(successfulResponse)) - })) - defer downstreamServer.Close() - - responder := &fakeResponder{} - backendURL, _ := url.Parse(downstreamServer.URL) - proxyHandler := &UpgradeAwareProxyHandler{ - Location: backendURL, - Responder: responder, - UpgradeRequired: false, - } - proxyServer := httptest.NewServer(proxyHandler) - defer proxyServer.Close() - - // Dial the proxy server - conn, err := net.Dial(proxyServer.Listener.Addr().Network(), proxyServer.Listener.Addr().String()) - if err != nil { - t.Errorf("unexpected error %v", err) - continue - } - defer conn.Close() - - // Add standard http 1.1 headers - if item.reqHeaders == nil { - item.reqHeaders = http.Header{} - } - item.reqHeaders.Add("Connection", "close") - item.reqHeaders.Add("Host", proxyServer.Listener.Addr().String()) - - // Write the request headers - if _, err := fmt.Fprint(conn, "POST / HTTP/1.1\r\n"); err != nil { - t.Fatalf("%s unexpected error %v", k, err) - } - for header, values := range item.reqHeaders { - for _, value := range values { - if _, err := fmt.Fprintf(conn, "%s: %s\r\n", header, value); err != nil { - t.Fatalf("%s: unexpected error %v", k, err) - } - } - } - // Header separator - if _, err := fmt.Fprint(conn, "\r\n"); err != nil { - t.Fatalf("%s: unexpected error %v", k, err) - } - // Body - if _, err := conn.Write(item.reqBody); err != nil { - t.Fatalf("%s: unexpected error %v", k, err) - } - - // Read response - response, err := ioutil.ReadAll(conn) - if err != nil { - t.Errorf("%s: unexpected error %v", k, err) - continue - } - if !strings.HasSuffix(string(response), successfulResponse) { - t.Errorf("%s: Did not get successful response: %s", k, string(response)) - continue - } - } -} - -// exampleCert was generated from crypto/tls/generate_cert.go with the following command: -// go run generate_cert.go --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h -var exampleCert = []byte(`-----BEGIN CERTIFICATE----- -MIIBcjCCAR6gAwIBAgIQBOUTYowZaENkZi0faI9DgTALBgkqhkiG9w0BAQswEjEQ -MA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2MDAw -MFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCZ -xfR3sgeHBraGFfF/24tTn4PRVAHOf2UOOxSQRs+aYjNqimFqf/SRIblQgeXdBJDR -gVK5F1Js2zwlehw0bHxRAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIApDATBgNVHSUE -DDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4YW1w -bGUuY29tMAsGCSqGSIb3DQEBCwNBAI/mfBB8dm33IpUl+acSyWfL6gX5Wc0FFyVj -dKeesE1XBuPX1My/rzU6Oy/YwX7LOL4FaeNUS6bbL4axSLPKYSs= ------END CERTIFICATE-----`) - -var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBOgIBAAJBAJnF9HeyB4cGtoYV8X/bi1Ofg9FUAc5/ZQ47FJBGz5piM2qKYWp/ -9JEhuVCB5d0EkNGBUrkXUmzbPCV6HDRsfFECAwEAAQJBAJLH9yPuButniACTn5L5 -IJQw1mWQt6zBw9eCo41YWkA0866EgjC53aPZaRjXMp0uNJGdIsys2V5rCOOLWN2C -ODECIQDICHsi8QQQ9wpuJy8X5l8MAfxHL+DIqI84wQTeVM91FQIhAMTME8A18/7h -1Ad6drdnxAkuC0tX6Sx0LDozrmen+HFNAiAlcEDrt0RVkIcpOrg7tuhPLQf0oudl -Zvb3Xlj069awSQIgcT15E/43w2+RASifzVNhQ2MCTr1sSA8lL+xzK+REmnUCIBhQ -j4139pf8Re1J50zBxS/JlQfgDQi9sO9pYeiHIxNs ------END RSA PRIVATE KEY-----`) - -// localhostCert was generated from crypto/tls/generate_cert.go with the following command: -// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h -var localhostCert = []byte(`-----BEGIN CERTIFICATE----- -MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD -bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj -bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa -IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA -AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud -EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA -AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk -Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA== ------END CERTIFICATE-----`) - -// localhostKey is the private key for localhostCert. -var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0 -0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV -NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d -AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW -MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD -EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA -1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE= ------END RSA PRIVATE KEY-----`) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/response_checker.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/response_checker.go deleted file mode 100644 index b0c61075c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/response_checker.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rest - -import ( - "fmt" - "io" - "io/ioutil" - "net/http" - - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -// Check the http error status from a location URL. -// And convert an error into a structured API object. -// Finally ensure we close the body before returning the error -type HttpResponseChecker interface { - Check(resp *http.Response) error -} - -// Max length read from the response body of a location which returns error status -const ( - maxReadLength = 50000 -) - -// A generic http response checker to transform the error. -type GenericHttpResponseChecker struct { - QualifiedResource unversioned.GroupResource - Name string -} - -func (checker GenericHttpResponseChecker) Check(resp *http.Response) error { - if resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent { - defer resp.Body.Close() - bodyBytes, err := ioutil.ReadAll(io.LimitReader(resp.Body, maxReadLength)) - if err != nil { - return errors.NewInternalError(err) - } - bodyText := string(bodyBytes) - - switch { - case resp.StatusCode == http.StatusInternalServerError: - return errors.NewInternalError(fmt.Errorf("%s", bodyText)) - case resp.StatusCode == http.StatusBadRequest: - return errors.NewBadRequest(bodyText) - case resp.StatusCode == http.StatusNotFound: - return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false) - } - return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false) - } - return nil -} - -func NewGenericHttpResponseChecker(qualifiedResource unversioned.GroupResource, name string) GenericHttpResponseChecker { - return GenericHttpResponseChecker{QualifiedResource: qualifiedResource, Name: name} -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/response_checker_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/response_checker_test.go deleted file mode 100644 index f1ad62020..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/response_checker_test.go +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rest - -import ( - "bytes" - "fmt" - "io/ioutil" - "net/http" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" -) - -func TestGenericHttpResponseChecker(t *testing.T) { - responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo") - tests := []struct { - resp *http.Response - expectError bool - expected error - name string - }{ - { - resp: &http.Response{ - Body: ioutil.NopCloser(bytes.NewBufferString("Success")), - StatusCode: http.StatusOK, - }, - expectError: false, - name: "ok", - }, - { - resp: &http.Response{ - Body: ioutil.NopCloser(bytes.NewBufferString("Invalid request.")), - StatusCode: http.StatusBadRequest, - }, - expectError: true, - expected: errors.NewBadRequest("Invalid request."), - name: "bad request", - }, - { - resp: &http.Response{ - Body: ioutil.NopCloser(bytes.NewBufferString("Pod does not exist.")), - StatusCode: http.StatusInternalServerError, - }, - expectError: true, - expected: errors.NewInternalError(fmt.Errorf("%s", "Pod does not exist.")), - name: "internal server error", - }, - } - for _, test := range tests { - err := responseChecker.Check(test.resp) - if test.expectError && err == nil { - t.Error("unexpected non-error") - } - if !test.expectError && err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectError && !reflect.DeepEqual(err, test.expected) { - t.Errorf("expected: %s, saw: %s", test.expected, err) - } - } -} - -func TestGenericHttpResponseCheckerLimitReader(t *testing.T) { - responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo") - excessedString := strings.Repeat("a", (maxReadLength + 10000)) - resp := &http.Response{ - Body: ioutil.NopCloser(bytes.NewBufferString(excessedString)), - StatusCode: http.StatusBadRequest, - } - err := responseChecker.Check(resp) - if err == nil { - t.Error("unexpected non-error") - } - if len(err.Error()) != maxReadLength { - t.Errorf("expected lenth of error message: %d, saw: %d", maxReadLength, len(err.Error())) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/streamer.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/streamer.go deleted file mode 100644 index afa9eb5b5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/streamer.go +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rest - -import ( - "io" - "net/http" - "net/url" - "strings" - - "k8s.io/kubernetes/pkg/api/rest" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -// LocationStreamer is a resource that streams the contents of a particular -// location URL -type LocationStreamer struct { - Location *url.URL - Transport http.RoundTripper - ContentType string - Flush bool - ResponseChecker HttpResponseChecker -} - -// a LocationStreamer must implement a rest.ResourceStreamer -var _ rest.ResourceStreamer = &LocationStreamer{} - -func (obj *LocationStreamer) GetObjectKind() unversioned.ObjectKind { - return unversioned.EmptyObjectKind -} - -// InputStream returns a stream with the contents of the URL location. If no location is provided, -// a null stream is returned. -func (s *LocationStreamer) InputStream(apiVersion, acceptHeader string) (stream io.ReadCloser, flush bool, contentType string, err error) { - if s.Location == nil { - // If no location was provided, return a null stream - return nil, false, "", nil - } - transport := s.Transport - if transport == nil { - transport = http.DefaultTransport - } - client := &http.Client{Transport: transport} - resp, err := client.Get(s.Location.String()) - if err != nil { - return nil, false, "", err - } - - if s.ResponseChecker != nil { - if err = s.ResponseChecker.Check(resp); err != nil { - return nil, false, "", err - } - } - - contentType = s.ContentType - if len(contentType) == 0 { - contentType = resp.Header.Get("Content-Type") - if len(contentType) > 0 { - contentType = strings.TrimSpace(strings.SplitN(contentType, ";", 2)[0]) - } - } - flush = s.Flush - stream = resp.Body - return -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/streamer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/streamer_test.go deleted file mode 100644 index 956222837..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/generic/rest/streamer_test.go +++ /dev/null @@ -1,148 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 rest - -import ( - "bufio" - "bytes" - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" -) - -func TestInputStreamReader(t *testing.T) { - resultString := "Test output" - s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - w.Write([]byte(resultString)) - })) - defer s.Close() - u, err := url.Parse(s.URL) - if err != nil { - t.Errorf("Error parsing server URL: %v", err) - return - } - streamer := &LocationStreamer{ - Location: u, - } - readCloser, _, _, err := streamer.InputStream("", "") - if err != nil { - t.Errorf("Unexpected error when getting stream: %v", err) - return - } - defer readCloser.Close() - result, err := ioutil.ReadAll(readCloser) - if string(result) != resultString { - t.Errorf("Stream content does not match. Got: %s. Expected: %s.", string(result), resultString) - } -} - -func TestInputStreamNullLocation(t *testing.T) { - streamer := &LocationStreamer{ - Location: nil, - } - readCloser, _, _, err := streamer.InputStream("", "") - if err != nil { - t.Errorf("Unexpected error when getting stream with null location: %v", err) - } - if readCloser != nil { - t.Errorf("Expected stream to be nil. Got: %#v", readCloser) - } -} - -type testTransport struct { - body string - err error -} - -func (tt *testTransport) RoundTrip(req *http.Request) (*http.Response, error) { - r := bufio.NewReader(bytes.NewBufferString(tt.body)) - return http.ReadResponse(r, req) -} - -func fakeTransport(mime, message string) http.RoundTripper { - content := fmt.Sprintf("HTTP/1.1 200 OK\nContent-Type: %s\n\n%s", mime, message) - return &testTransport{body: content} -} - -func TestInputStreamContentType(t *testing.T) { - location, _ := url.Parse("http://www.example.com") - streamer := &LocationStreamer{ - Location: location, - Transport: fakeTransport("application/json", "hello world"), - } - readCloser, _, contentType, err := streamer.InputStream("", "") - if err != nil { - t.Errorf("Unexpected error when getting stream: %v", err) - return - } - defer readCloser.Close() - if contentType != "application/json" { - t.Errorf("Unexpected content type. Got: %s. Expected: application/json", contentType) - } -} - -func TestInputStreamTransport(t *testing.T) { - message := "hello world" - location, _ := url.Parse("http://www.example.com") - streamer := &LocationStreamer{ - Location: location, - Transport: fakeTransport("text/plain", message), - } - readCloser, _, _, err := streamer.InputStream("", "") - if err != nil { - t.Errorf("Unexpected error when getting stream: %v", err) - return - } - defer readCloser.Close() - result, err := ioutil.ReadAll(readCloser) - if string(result) != message { - t.Errorf("Stream content does not match. Got: %s. Expected: %s.", string(result), message) - } -} - -func fakeInternalServerErrorTransport(mime, message string) http.RoundTripper { - content := fmt.Sprintf("HTTP/1.1 500 \"Internal Server Error\"\nContent-Type: %s\n\n%s", mime, message) - return &testTransport{body: content} -} - -func TestInputStreamInternalServerErrorTransport(t *testing.T) { - message := "Pod is in PodPending" - location, _ := url.Parse("http://www.example.com") - streamer := &LocationStreamer{ - Location: location, - Transport: fakeInternalServerErrorTransport("text/plain", message), - ResponseChecker: NewGenericHttpResponseChecker(api.Resource(""), ""), - } - expectedError := errors.NewInternalError(fmt.Errorf("%s", message)) - - _, _, _, err := streamer.InputStream("", "") - if err == nil { - t.Errorf("unexpected non-error") - return - } - - if !reflect.DeepEqual(err, expectedError) { - t.Errorf("StreamInternalServerError does not match. Got: %s. Expected: %s.", err, expectedError) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/codec_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/codec_test.go deleted file mode 100644 index 942de910c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/codec_test.go +++ /dev/null @@ -1,181 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 thirdpartyresourcedata - -import ( - "encoding/json" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/runtime" -) - -type Foo struct { - unversioned.TypeMeta `json:",inline"` - api.ObjectMeta `json:"metadata,omitempty" description:"standard object metadata"` - - SomeField string `json:"someField"` - OtherField int `json:"otherField"` -} - -type FooList struct { - unversioned.TypeMeta `json:",inline"` - unversioned.ListMeta `json:"metadata,omitempty" description:"standard list metadata; see http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata"` - - Items []Foo `json:"items"` -} - -func TestCodec(t *testing.T) { - tests := []struct { - obj *Foo - expectErr bool - name string - }{ - { - obj: &Foo{ObjectMeta: api.ObjectMeta{Name: "bar"}}, - expectErr: true, - name: "missing kind", - }, - { - obj: &Foo{ObjectMeta: api.ObjectMeta{Name: "bar"}, TypeMeta: unversioned.TypeMeta{Kind: "Foo"}}, - name: "basic", - }, - { - obj: &Foo{ObjectMeta: api.ObjectMeta{Name: "bar", ResourceVersion: "baz"}, TypeMeta: unversioned.TypeMeta{Kind: "Foo"}}, - name: "resource version", - }, - { - obj: &Foo{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - CreationTimestamp: unversioned.Time{Time: time.Unix(100, 0)}, - }, - TypeMeta: unversioned.TypeMeta{Kind: "Foo"}, - }, - name: "creation time", - }, - { - obj: &Foo{ - ObjectMeta: api.ObjectMeta{ - Name: "bar", - ResourceVersion: "baz", - Labels: map[string]string{"foo": "bar", "baz": "blah"}, - }, - TypeMeta: unversioned.TypeMeta{Kind: "Foo"}, - }, - name: "labels", - }, - } - for _, test := range tests { - d := &thirdPartyResourceDataDecoder{kind: "Foo", delegate: testapi.Extensions.Codec()} - e := &thirdPartyResourceDataEncoder{kind: "Foo", delegate: testapi.Extensions.Codec()} - data, err := json.Marshal(test.obj) - if err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - obj, err := runtime.Decode(d, data) - if err != nil && !test.expectErr { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - if test.expectErr { - if err == nil { - t.Errorf("[%s] unexpected non-error", test.name) - } - continue - } - rsrcObj, ok := obj.(*extensions.ThirdPartyResourceData) - if !ok { - t.Errorf("[%s] unexpected object: %v", test.name, obj) - continue - } - if !reflect.DeepEqual(rsrcObj.ObjectMeta, test.obj.ObjectMeta) { - t.Errorf("[%s]\nexpected\n%v\nsaw\n%v\n", test.name, rsrcObj.ObjectMeta, test.obj.ObjectMeta) - } - var output Foo - if err := json.Unmarshal(rsrcObj.Data, &output); err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - if !reflect.DeepEqual(&output, test.obj) { - t.Errorf("[%s]\nexpected\n%v\nsaw\n%v\n", test.name, test.obj, &output) - } - - data, err = runtime.Encode(e, rsrcObj) - if err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - } - - var output2 Foo - if err := json.Unmarshal(data, &output2); err != nil { - t.Errorf("[%s] unexpected error: %v", test.name, err) - continue - } - if !reflect.DeepEqual(&output2, test.obj) { - t.Errorf("[%s]\nexpected\n%v\nsaw\n%v\n", test.name, test.obj, &output2) - } - } -} - -func TestCreater(t *testing.T) { - creater := NewObjectCreator("creater group", "creater version", api.Scheme) - tests := []struct { - name string - kind unversioned.GroupVersionKind - expectedObj runtime.Object - expectErr bool - }{ - { - name: "valid ThirdPartyResourceData creation", - kind: unversioned.GroupVersionKind{Group: "creater group", Version: "creater version", Kind: "ThirdPartyResourceData"}, - expectedObj: &extensions.ThirdPartyResourceData{}, - expectErr: false, - }, - { - name: "invalid ThirdPartyResourceData creation", - kind: unversioned.GroupVersionKind{Version: "invalid version", Kind: "ThirdPartyResourceData"}, - expectedObj: nil, - expectErr: true, - }, - { - name: "valid ListOptions creation", - kind: unversioned.GroupVersionKind{Version: "v1", Kind: "ListOptions"}, - expectedObj: &v1.ListOptions{}, - expectErr: false, - }, - } - for _, test := range tests { - out, err := creater.New(test.kind) - if err != nil && !test.expectErr { - t.Errorf("[%s] unexpected error: %v", test.name, err) - } - if err == nil && test.expectErr { - t.Errorf("[%s] unexpected non-error", test.name) - } - if !reflect.DeepEqual(test.expectedObj, out) { - t.Errorf("[%s] unexpected error: expect: %v, got: %v", test.name, test.expectedObj, out) - } - - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd/etcd.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd/etcd.go deleted file mode 100644 index 55eaf09b1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd/etcd.go +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 etcd - -import ( - "strings" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/registry/generic/registry" - "k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata" - "k8s.io/kubernetes/pkg/runtime" -) - -// REST implements a RESTStorage for ThirdPartyResourceDatas against etcd -type REST struct { - *registry.Store - kind string -} - -// NewREST returns a registry which will store ThirdPartyResourceData in the given helper -func NewREST(opts generic.RESTOptions, group, kind string) *REST { - prefix := "/ThirdPartyResourceData/" + group + "/" + strings.ToLower(kind) + "s" - - // We explicitly do NOT do any decoration here yet. - storageInterface := opts.Storage - - store := ®istry.Store{ - NewFunc: func() runtime.Object { return &extensions.ThirdPartyResourceData{} }, - NewListFunc: func() runtime.Object { return &extensions.ThirdPartyResourceDataList{} }, - KeyRootFunc: func(ctx api.Context) string { - return registry.NamespaceKeyRootFunc(ctx, prefix) - }, - KeyFunc: func(ctx api.Context, id string) (string, error) { - return registry.NamespaceKeyFunc(ctx, prefix, id) - }, - ObjectNameFunc: func(obj runtime.Object) (string, error) { - return obj.(*extensions.ThirdPartyResourceData).Name, nil - }, - PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { - return thirdpartyresourcedata.Matcher(label, field) - }, - QualifiedResource: extensions.Resource("thirdpartyresourcedatas"), - DeleteCollectionWorkers: opts.DeleteCollectionWorkers, - CreateStrategy: thirdpartyresourcedata.Strategy, - UpdateStrategy: thirdpartyresourcedata.Strategy, - DeleteStrategy: thirdpartyresourcedata.Strategy, - - Storage: storageInterface, - } - - return &REST{ - Store: store, - kind: kind, - } -} - -// Implements the rest.KindProvider interface -func (r *REST) Kind() string { - return r.kind -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd/etcd_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd/etcd_test.go deleted file mode 100644 index 6b4eabf8a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd/etcd_test.go +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 etcd - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" - // Ensure that extensions/v1beta1 package is initialized. - _ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" - "k8s.io/kubernetes/pkg/fields" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/registry/generic" - "k8s.io/kubernetes/pkg/registry/registrytest" - "k8s.io/kubernetes/pkg/runtime" - etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" -) - -func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { - etcdStorage, server := registrytest.NewEtcdStorage(t, extensions.GroupName) - restOptions := generic.RESTOptions{Storage: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1} - return NewREST(restOptions, "foo", "bar"), server -} - -func validNewThirdPartyResourceData(name string) *extensions.ThirdPartyResourceData { - return &extensions.ThirdPartyResourceData{ - ObjectMeta: api.ObjectMeta{ - Name: name, - Namespace: api.NamespaceDefault, - }, - Data: []byte("foobarbaz"), - } -} - -func TestCreate(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - test := registrytest.New(t, storage.Store) - rsrc := validNewThirdPartyResourceData("foo") - rsrc.ObjectMeta = api.ObjectMeta{} - test.TestCreate( - // valid - rsrc, - // invalid - &extensions.ThirdPartyResourceData{}, - ) -} - -func TestUpdate(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - test := registrytest.New(t, storage.Store) - test.TestUpdate( - // valid - validNewThirdPartyResourceData("foo"), - // updateFunc - func(obj runtime.Object) runtime.Object { - object := obj.(*extensions.ThirdPartyResourceData) - object.Data = []byte("new description") - return object - }, - ) -} - -func TestDelete(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - test := registrytest.New(t, storage.Store) - test.TestDelete(validNewThirdPartyResourceData("foo")) -} - -func TestGet(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - test := registrytest.New(t, storage.Store) - test.TestGet(validNewThirdPartyResourceData("foo")) -} - -func TestList(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - test := registrytest.New(t, storage.Store) - test.TestList(validNewThirdPartyResourceData("foo")) -} - -func TestWatch(t *testing.T) { - storage, server := newStorage(t) - defer server.Terminate(t) - test := registrytest.New(t, storage.Store) - test.TestWatch( - validNewThirdPartyResourceData("foo"), - // matching labels - []labels.Set{}, - // not matching labels - []labels.Set{ - {"foo": "bar"}, - }, - // matching fields - []fields.Set{}, - // not matching fields - []fields.Set{ - {"metadata.name": "bar"}, - {"name": "foo"}, - }, - ) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/strategy_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/strategy_test.go deleted file mode 100644 index 75e821944..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/strategy_test.go +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 thirdpartyresourcedata - -import ( - "testing" - - _ "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/apis/extensions" -) - -func TestSelectableFieldLabelConversions(t *testing.T) { - apitesting.TestSelectableFieldLabelConversionsOfKind(t, - testapi.Extensions.GroupVersion().String(), - "ThirdPartyResourceData", - SelectableFields(&extensions.ThirdPartyResourceData{}), - nil, - ) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/util_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/util_test.go deleted file mode 100644 index a18722c17..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/util_test.go +++ /dev/null @@ -1,66 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 thirdpartyresourcedata - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apis/extensions" -) - -func TestExtractAPIGroupAndKind(t *testing.T) { - tests := []struct { - input string - expectedKind string - expectedGroup string - expectErr bool - }{ - { - input: "foo.company.com", - expectedKind: "Foo", - expectedGroup: "company.com", - }, - { - input: "cron-tab.company.com", - expectedKind: "CronTab", - expectedGroup: "company.com", - }, - { - input: "foo", - expectErr: true, - }, - } - - for _, test := range tests { - kind, group, err := ExtractApiGroupAndKind(&extensions.ThirdPartyResource{ObjectMeta: api.ObjectMeta{Name: test.input}}) - if err != nil && !test.expectErr { - t.Errorf("unexpected error: %v", err) - continue - } - if err == nil && test.expectErr { - t.Errorf("unexpected non-error") - continue - } - if kind != test.expectedKind { - t.Errorf("expected: %s, saw: %s", test.expectedKind, kind) - } - if group != test.expectedGroup { - t.Errorf("expected: %s, saw: %s", test.expectedGroup, group) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/conversion_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/conversion_test.go deleted file mode 100644 index 6105e5aad..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/conversion_test.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 runtime_test - -import ( - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" -) - -type InternalComplex struct { - runtime.TypeMeta - String string - Integer int - Integer64 int64 - Int64 int64 - Bool bool -} - -type ExternalComplex struct { - runtime.TypeMeta `json:",inline"` - String string `json:"string" description:"testing"` - Integer int `json:"int"` - Integer64 int64 `json:",omitempty"` - Int64 int64 - Bool bool `json:"bool"` -} - -func (obj *InternalComplex) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *ExternalComplex) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } - -func TestStringMapConversion(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "external"} - - scheme := runtime.NewScheme() - scheme.Log(t) - scheme.AddKnownTypeWithName(internalGV.WithKind("Complex"), &InternalComplex{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("Complex"), &ExternalComplex{}) - - testCases := map[string]struct { - input map[string][]string - errFn func(error) bool - expected runtime.Object - }{ - "ignores omitempty": { - input: map[string][]string{ - "String": {"not_used"}, - "string": {"value"}, - "int": {"1"}, - "Integer64": {"2"}, - }, - expected: &ExternalComplex{String: "value", Integer: 1}, - }, - "returns error on bad int": { - input: map[string][]string{ - "int": {"a"}, - }, - errFn: func(err error) bool { return err != nil }, - expected: &ExternalComplex{}, - }, - "parses int64": { - input: map[string][]string{ - "Int64": {"-1"}, - }, - expected: &ExternalComplex{Int64: -1}, - }, - "returns error on bad int64": { - input: map[string][]string{ - "Int64": {"a"}, - }, - errFn: func(err error) bool { return err != nil }, - expected: &ExternalComplex{}, - }, - "parses boolean true": { - input: map[string][]string{ - "bool": {"true"}, - }, - expected: &ExternalComplex{Bool: true}, - }, - "parses boolean any value": { - input: map[string][]string{ - "bool": {"foo"}, - }, - expected: &ExternalComplex{Bool: true}, - }, - "parses boolean false": { - input: map[string][]string{ - "bool": {"false"}, - }, - expected: &ExternalComplex{Bool: false}, - }, - "parses boolean empty value": { - input: map[string][]string{ - "bool": {""}, - }, - expected: &ExternalComplex{Bool: true}, - }, - "parses boolean no value": { - input: map[string][]string{ - "bool": {}, - }, - expected: &ExternalComplex{Bool: false}, - }, - } - - for k, tc := range testCases { - out := &ExternalComplex{} - if err := scheme.Convert(&tc.input, out); (tc.errFn == nil && err != nil) || (tc.errFn != nil && !tc.errFn(err)) { - t.Errorf("%s: unexpected error: %v", k, err) - continue - } else if err != nil { - continue - } - if !reflect.DeepEqual(out, tc.expected) { - t.Errorf("%s: unexpected output: %#v", k, out) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/embedded_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/embedded_test.go deleted file mode 100644 index 6a143fb08..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/embedded_test.go +++ /dev/null @@ -1,290 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 runtime_test - -import ( - "encoding/json" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer" - "k8s.io/kubernetes/pkg/util/diff" -) - -type EmbeddedTest struct { - runtime.TypeMeta - ID string - Object runtime.Object - EmptyObject runtime.Object -} - -type EmbeddedTestExternal struct { - runtime.TypeMeta `json:",inline"` - ID string `json:"id,omitempty"` - Object runtime.RawExtension `json:"object,omitempty"` - EmptyObject runtime.RawExtension `json:"emptyObject,omitempty"` -} - -type ObjectTest struct { - runtime.TypeMeta - - ID string - Items []runtime.Object -} - -type ObjectTestExternal struct { - runtime.TypeMeta `yaml:",inline" json:",inline"` - - ID string `json:"id,omitempty"` - Items []runtime.RawExtension `json:"items,omitempty"` -} - -func (obj *ObjectTest) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *ObjectTestExternal) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *EmbeddedTest) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *EmbeddedTestExternal) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } - -func TestDecodeEmptyRawExtensionAsObject(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"} - externalGVK := externalGV.WithKind("ObjectTest") - - s := runtime.NewScheme() - s.AddKnownTypes(internalGV, &ObjectTest{}) - s.AddKnownTypeWithName(externalGVK, &ObjectTestExternal{}) - - codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) - - obj, gvk, err := codec.Decode([]byte(`{"kind":"`+externalGVK.Kind+`","apiVersion":"`+externalGV.String()+`","items":[{}]}`), nil, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - test := obj.(*ObjectTest) - if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "" || unk.APIVersion != "" || string(unk.Raw) != "{}" || unk.ContentType != runtime.ContentTypeJSON { - t.Fatalf("unexpected object: %#v", test.Items[0]) - } - if *gvk != externalGVK { - t.Fatalf("unexpected kind: %#v", gvk) - } - - obj, gvk, err = codec.Decode([]byte(`{"kind":"`+externalGVK.Kind+`","apiVersion":"`+externalGV.String()+`","items":[{"kind":"Other","apiVersion":"v1"}]}`), nil, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - test = obj.(*ObjectTest) - if unk, ok := test.Items[0].(*runtime.Unknown); !ok || unk.Kind != "" || unk.APIVersion != "" || string(unk.Raw) != `{"kind":"Other","apiVersion":"v1"}` || unk.ContentType != runtime.ContentTypeJSON { - t.Fatalf("unexpected object: %#v", test.Items[0]) - } - if *gvk != externalGVK { - t.Fatalf("unexpected kind: %#v", gvk) - } -} - -func TestArrayOfRuntimeObject(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"} - - s := runtime.NewScheme() - s.AddKnownTypes(internalGV, &EmbeddedTest{}) - s.AddKnownTypeWithName(externalGV.WithKind("EmbeddedTest"), &EmbeddedTestExternal{}) - s.AddKnownTypes(internalGV, &ObjectTest{}) - s.AddKnownTypeWithName(externalGV.WithKind("ObjectTest"), &ObjectTestExternal{}) - - codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) - - innerItems := []runtime.Object{ - &EmbeddedTest{ID: "baz"}, - } - items := []runtime.Object{ - &EmbeddedTest{ID: "foo"}, - &EmbeddedTest{ID: "bar"}, - // TODO: until YAML is removed, this JSON must be in ascending key order to ensure consistent roundtrip serialization - &runtime.Unknown{ - Raw: []byte(`{"apiVersion":"unknown.group/unknown","foo":"bar","kind":"OtherTest"}`), - ContentType: runtime.ContentTypeJSON, - }, - &ObjectTest{ - Items: runtime.NewEncodableList(codec, innerItems), - }, - } - internal := &ObjectTest{ - Items: runtime.NewEncodableList(codec, items), - } - wire, err := runtime.Encode(codec, internal) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - t.Logf("Wire format is:\n%s\n", string(wire)) - - obj := &ObjectTestExternal{} - if err := json.Unmarshal(wire, obj); err != nil { - t.Fatalf("unexpected error: %v", err) - } - t.Logf("exact wire is: %s", string(obj.Items[0].Raw)) - - items[3] = &ObjectTest{Items: innerItems} - internal.Items = items - - decoded, err := runtime.Decode(codec, wire) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - list, err := meta.ExtractList(decoded) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if errs := runtime.DecodeList(list, codec); len(errs) > 0 { - t.Fatalf("unexpected error: %v", errs) - } - - list2, err := meta.ExtractList(list[3]) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if errs := runtime.DecodeList(list2, codec); len(errs) > 0 { - t.Fatalf("unexpected error: %v", errs) - } - if err := meta.SetList(list[3], list2); err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // we want DecodeList to set type meta if possible, even on runtime.Unknown objects - internal.Items[2].(*runtime.Unknown).TypeMeta = runtime.TypeMeta{Kind: "OtherTest", APIVersion: "unknown.group/unknown"} - if e, a := internal.Items, list; !reflect.DeepEqual(e, a) { - t.Errorf("mismatched decoded: %s", diff.ObjectGoPrintSideBySide(e, a)) - } -} - -func TestNestedObject(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"} - embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest") - - s := runtime.NewScheme() - s.AddKnownTypes(internalGV, &EmbeddedTest{}) - s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{}) - - codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) - - inner := &EmbeddedTest{ - ID: "inner", - } - outer := &EmbeddedTest{ - ID: "outer", - Object: runtime.NewEncodable(codec, inner), - } - - wire, err := runtime.Encode(codec, outer) - if err != nil { - t.Fatalf("Unexpected encode error '%v'", err) - } - - t.Logf("Wire format is:\n%v\n", string(wire)) - - decoded, err := runtime.Decode(codec, wire) - if err != nil { - t.Fatalf("Unexpected decode error %v", err) - } - - // for later tests - outer.Object = inner - - if e, a := outer, decoded; reflect.DeepEqual(e, a) { - t.Errorf("Expected unequal %#v %#v", e, a) - } - - obj, err := runtime.Decode(codec, decoded.(*EmbeddedTest).Object.(*runtime.Unknown).Raw) - if err != nil { - t.Fatal(err) - } - decoded.(*EmbeddedTest).Object = obj - if e, a := outer, decoded; !reflect.DeepEqual(e, a) { - t.Errorf("Expected equal %#v %#v", e, a) - } - - // test JSON decoding of the external object, which should preserve - // raw bytes - var externalViaJSON EmbeddedTestExternal - err = json.Unmarshal(wire, &externalViaJSON) - if err != nil { - t.Fatalf("Unexpected decode error %v", err) - } - if externalViaJSON.Kind == "" || externalViaJSON.APIVersion == "" || externalViaJSON.ID != "outer" { - t.Errorf("Expected objects to have type info set, got %#v", externalViaJSON) - } - if !reflect.DeepEqual(externalViaJSON.EmptyObject.Raw, []byte("null")) || len(externalViaJSON.Object.Raw) == 0 { - t.Errorf("Expected deserialization of nested objects into bytes, got %#v", externalViaJSON) - } - - // test JSON decoding, too, since Decode uses yaml unmarshalling. - // Generic Unmarshalling of JSON cannot load the nested objects because there is - // no default schema set. Consumers wishing to get direct JSON decoding must use - // the external representation - var decodedViaJSON EmbeddedTest - err = json.Unmarshal(wire, &decodedViaJSON) - if err == nil || !strings.Contains(err.Error(), "unmarshal object into Go value of type runtime.Object") { - t.Fatalf("Unexpected decode error %v", err) - } - if a := decodedViaJSON; a.Object != nil || a.EmptyObject != nil { - t.Errorf("Expected embedded objects to be nil: %#v", a) - } -} - -// TestDeepCopyOfRuntimeObject checks to make sure that runtime.Objects's can be passed through DeepCopy with fidelity -func TestDeepCopyOfRuntimeObject(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "v1test"} - embeddedTestExternalGVK := externalGV.WithKind("EmbeddedTest") - - s := runtime.NewScheme() - s.AddKnownTypes(internalGV, &EmbeddedTest{}) - s.AddKnownTypeWithName(embeddedTestExternalGVK, &EmbeddedTestExternal{}) - - original := &EmbeddedTest{ - ID: "outer", - Object: &EmbeddedTest{ - ID: "inner", - }, - } - - codec := serializer.NewCodecFactory(s).LegacyCodec(externalGV) - - originalData, err := runtime.Encode(codec, original) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - t.Logf("originalRole = %v\n", string(originalData)) - - copyOfOriginal, err := s.DeepCopy(original) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - copiedData, err := runtime.Encode(codec, copyOfOriginal.(runtime.Object)) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - t.Logf("copyOfRole = %v\n", string(copiedData)) - - if !reflect.DeepEqual(original, copyOfOriginal) { - t.Errorf("expected \n%v\n, got \n%v", string(originalData), string(copiedData)) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/extension_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/extension_test.go deleted file mode 100644 index 3545284e9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/extension_test.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 runtime_test - -import ( - "encoding/json" - "testing" - - "k8s.io/kubernetes/pkg/runtime" -) - -func TestEmbeddedRawExtensionMarshal(t *testing.T) { - type test struct { - Ext runtime.RawExtension - } - - extension := test{Ext: runtime.RawExtension{Raw: []byte(`{"foo":"bar"}`)}} - data, err := json.Marshal(extension) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if string(data) != `{"Ext":{"foo":"bar"}}` { - t.Errorf("unexpected data: %s", string(data)) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/helper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/helper_test.go deleted file mode 100644 index e15a0e799..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/helper_test.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 runtime_test - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/runtime" -) - -func TestDecodeList(t *testing.T) { - pl := &api.List{ - Items: []runtime.Object{ - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, - &runtime.Unknown{ - TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: testapi.Default.GroupVersion().String()}, - Raw: []byte(`{"kind":"Pod","apiVersion":"` + testapi.Default.GroupVersion().String() + `","metadata":{"name":"test"}}`), - ContentType: runtime.ContentTypeJSON, - }, - &runtime.Unstructured{ - Object: map[string]interface{}{ - "kind": "Foo", - "apiVersion": "Bar", - "test": "value", - }, - }, - }, - } - if errs := runtime.DecodeList(pl.Items, testapi.Default.Codec()); len(errs) != 0 { - t.Fatalf("unexpected error %v", errs) - } - if pod, ok := pl.Items[1].(*api.Pod); !ok || pod.Name != "test" { - t.Errorf("object not converted: %#v", pl.Items[1]) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/scheme_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/scheme_test.go deleted file mode 100644 index 52cb796da..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/scheme_test.go +++ /dev/null @@ -1,675 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 runtime_test - -import ( - "reflect" - "testing" - - "github.com/google/gofuzz" - flag "github.com/spf13/pflag" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer" - "k8s.io/kubernetes/pkg/util/diff" -) - -var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.") - -type InternalSimple struct { - runtime.TypeMeta `json:",inline"` - TestString string `json:"testString"` -} - -type ExternalSimple struct { - runtime.TypeMeta `json:",inline"` - TestString string `json:"testString"` -} - -func (obj *InternalSimple) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *ExternalSimple) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } - -func TestScheme(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} - - scheme := runtime.NewScheme() - scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) - - // If set, would clear TypeMeta during conversion. - //scheme.AddIgnoredConversionType(&TypeMeta{}, &TypeMeta{}) - - // test that scheme is an ObjectTyper - var _ runtime.ObjectTyper = scheme - - internalToExternalCalls := 0 - externalToInternalCalls := 0 - - // Register functions to verify that scope.Meta() gets set correctly. - err := scheme.AddConversionFuncs( - func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error { - if e, a := internalGV.String(), scope.Meta().SrcVersion; e != a { - t.Errorf("Expected '%v', got '%v'", e, a) - } - if e, a := externalGV.String(), scope.Meta().DestVersion; e != a { - t.Errorf("Expected '%v', got '%v'", e, a) - } - scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) - scope.Convert(&in.TestString, &out.TestString, 0) - internalToExternalCalls++ - return nil - }, - func(in *ExternalSimple, out *InternalSimple, scope conversion.Scope) error { - if e, a := externalGV.String(), scope.Meta().SrcVersion; e != a { - t.Errorf("Expected '%v', got '%v'", e, a) - } - if e, a := internalGV.String(), scope.Meta().DestVersion; e != a { - t.Errorf("Expected '%v', got '%v'", e, a) - } - scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) - scope.Convert(&in.TestString, &out.TestString, 0) - externalToInternalCalls++ - return nil - }, - ) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - codecs := serializer.NewCodecFactory(scheme) - codec := codecs.LegacyCodec(externalGV) - jsonserializer, _ := codecs.SerializerForFileExtension("json") - - simple := &InternalSimple{ - TestString: "foo", - } - - // Test Encode, Decode, DecodeInto, and DecodeToVersion - obj := runtime.Object(simple) - data, err := runtime.Encode(codec, obj) - if err != nil { - t.Fatal(err) - } - - obj2, err := runtime.Decode(codec, data) - if err != nil { - t.Fatal(err) - } - if _, ok := obj2.(*InternalSimple); !ok { - t.Fatalf("Got wrong type") - } - if e, a := simple, obj2; !reflect.DeepEqual(e, a) { - t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) - } - - obj3 := &InternalSimple{} - if err := runtime.DecodeInto(codec, data, obj3); err != nil { - t.Fatal(err) - } - // clearing TypeMeta is a function of the scheme, which we do not test here (ConvertToVersion - // does not automatically clear TypeMeta anymore). - simple.TypeMeta = runtime.TypeMeta{Kind: "Simple", APIVersion: externalGV.String()} - if e, a := simple, obj3; !reflect.DeepEqual(e, a) { - t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) - } - - obj4, err := runtime.Decode(jsonserializer, data) - if err != nil { - t.Fatal(err) - } - if _, ok := obj4.(*ExternalSimple); !ok { - t.Fatalf("Got wrong type") - } - - // Test Convert - external := &ExternalSimple{} - err = scheme.Convert(simple, external) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if e, a := simple.TestString, external.TestString; e != a { - t.Errorf("Expected %v, got %v", e, a) - } - - // Encode and Convert should each have caused an increment. - if e, a := 2, internalToExternalCalls; e != a { - t.Errorf("Expected %v, got %v", e, a) - } - // DecodeInto and Decode should each have caused an increment because of a conversion - if e, a := 2, externalToInternalCalls; e != a { - t.Errorf("Expected %v, got %v", e, a) - } -} - -func TestBadJSONRejection(t *testing.T) { - scheme := runtime.NewScheme() - codecs := serializer.NewCodecFactory(scheme) - jsonserializer, _ := codecs.SerializerForFileExtension("json") - - badJSONMissingKind := []byte(`{ }`) - if _, err := runtime.Decode(jsonserializer, badJSONMissingKind); err == nil { - t.Errorf("Did not reject despite lack of kind field: %s", badJSONMissingKind) - } - badJSONUnknownType := []byte(`{"kind": "bar"}`) - if _, err1 := runtime.Decode(jsonserializer, badJSONUnknownType); err1 == nil { - t.Errorf("Did not reject despite use of unknown type: %s", badJSONUnknownType) - } - /*badJSONKindMismatch := []byte(`{"kind": "Pod"}`) - if err2 := DecodeInto(badJSONKindMismatch, &Minion{}); err2 == nil { - t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch) - }*/ -} - -type ExtensionA struct { - runtime.TypeMeta `json:",inline"` - TestString string `json:"testString"` -} - -type ExtensionB struct { - runtime.TypeMeta `json:",inline"` - TestString string `json:"testString"` -} - -type ExternalExtensionType struct { - runtime.TypeMeta `json:",inline"` - Extension runtime.RawExtension `json:"extension"` -} - -type InternalExtensionType struct { - runtime.TypeMeta `json:",inline"` - Extension runtime.Object `json:"extension"` -} - -type ExternalOptionalExtensionType struct { - runtime.TypeMeta `json:",inline"` - Extension runtime.RawExtension `json:"extension,omitempty"` -} - -type InternalOptionalExtensionType struct { - runtime.TypeMeta `json:",inline"` - Extension runtime.Object `json:"extension,omitempty"` -} - -func (obj *ExtensionA) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *ExtensionB) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *ExternalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *InternalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *ExternalOptionalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } -func (obj *InternalOptionalExtensionType) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } - -func TestExternalToInternalMapping(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} - - scheme := runtime.NewScheme() - scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{}) - - codec := serializer.NewCodecFactory(scheme).LegacyCodec(externalGV) - - table := []struct { - obj runtime.Object - encoded string - }{ - { - &InternalOptionalExtensionType{Extension: nil}, - `{"kind":"OptionalExtensionType","apiVersion":"` + externalGV.String() + `"}`, - }, - } - - for i, item := range table { - gotDecoded, err := runtime.Decode(codec, []byte(item.encoded)) - if err != nil { - t.Errorf("unexpected error '%v' (%v)", err, item.encoded) - } else if e, a := item.obj, gotDecoded; !reflect.DeepEqual(e, a) { - t.Errorf("%d: unexpected objects:\n%s", i, diff.ObjectGoPrintSideBySide(e, a)) - } - } -} - -func TestExtensionMapping(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} - - scheme := runtime.NewScheme() - scheme.AddKnownTypeWithName(internalGV.WithKind("ExtensionType"), &InternalExtensionType{}) - scheme.AddKnownTypeWithName(internalGV.WithKind("OptionalExtensionType"), &InternalOptionalExtensionType{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("ExtensionType"), &ExternalExtensionType{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("OptionalExtensionType"), &ExternalOptionalExtensionType{}) - - // register external first when the object is the same in both schemes, so ObjectVersionAndKind reports the - // external version. - scheme.AddKnownTypeWithName(externalGV.WithKind("A"), &ExtensionA{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("B"), &ExtensionB{}) - scheme.AddKnownTypeWithName(internalGV.WithKind("A"), &ExtensionA{}) - scheme.AddKnownTypeWithName(internalGV.WithKind("B"), &ExtensionB{}) - - codec := serializer.NewCodecFactory(scheme).LegacyCodec(externalGV) - - table := []struct { - obj runtime.Object - expected runtime.Object - encoded string - }{ - { - &InternalExtensionType{ - Extension: runtime.NewEncodable(codec, &ExtensionA{TestString: "foo"}), - }, - &InternalExtensionType{ - Extension: &runtime.Unknown{ - Raw: []byte(`{"apiVersion":"test.group/testExternal","kind":"A","testString":"foo"}`), - ContentType: runtime.ContentTypeJSON, - }, - }, - // apiVersion is set in the serialized object for easier consumption by clients - `{"apiVersion":"` + externalGV.String() + `","kind":"ExtensionType","extension":{"apiVersion":"test.group/testExternal","kind":"A","testString":"foo"}} -`, - }, { - &InternalExtensionType{Extension: runtime.NewEncodable(codec, &ExtensionB{TestString: "bar"})}, - &InternalExtensionType{ - Extension: &runtime.Unknown{ - Raw: []byte(`{"apiVersion":"test.group/testExternal","kind":"B","testString":"bar"}`), - ContentType: runtime.ContentTypeJSON, - }, - }, - // apiVersion is set in the serialized object for easier consumption by clients - `{"apiVersion":"` + externalGV.String() + `","kind":"ExtensionType","extension":{"apiVersion":"test.group/testExternal","kind":"B","testString":"bar"}} -`, - }, { - &InternalExtensionType{Extension: nil}, - &InternalExtensionType{ - Extension: nil, - }, - `{"apiVersion":"` + externalGV.String() + `","kind":"ExtensionType","extension":null} -`, - }, - } - - for i, item := range table { - gotEncoded, err := runtime.Encode(codec, item.obj) - if err != nil { - t.Errorf("unexpected error '%v' (%#v)", err, item.obj) - } else if e, a := item.encoded, string(gotEncoded); e != a { - t.Errorf("expected\n%#v\ngot\n%#v\n", e, a) - } - - gotDecoded, err := runtime.Decode(codec, []byte(item.encoded)) - if err != nil { - t.Errorf("unexpected error '%v' (%v)", err, item.encoded) - } else if e, a := item.expected, gotDecoded; !reflect.DeepEqual(e, a) { - t.Errorf("%d: unexpected objects:\n%s", i, diff.ObjectGoPrintSideBySide(e, a)) - } - } -} - -func TestEncode(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} - - scheme := runtime.NewScheme() - scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) - - codec := serializer.NewCodecFactory(scheme).LegacyCodec(externalGV) - - test := &InternalSimple{ - TestString: "I'm the same", - } - obj := runtime.Object(test) - data, err := runtime.Encode(codec, obj) - obj2, gvk, err2 := codec.Decode(data, nil, nil) - if err != nil || err2 != nil { - t.Fatalf("Failure: '%v' '%v'", err, err2) - } - if _, ok := obj2.(*InternalSimple); !ok { - t.Fatalf("Got wrong type") - } - if !reflect.DeepEqual(obj2, test) { - t.Errorf("Expected:\n %#v,\n Got:\n %#v", test, obj2) - } - if !reflect.DeepEqual(gvk, &unversioned.GroupVersionKind{Group: "test.group", Version: "testExternal", Kind: "Simple"}) { - t.Errorf("unexpected gvk returned by decode: %#v", gvk) - } -} - -func TestUnversionedTypes(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} - otherGV := unversioned.GroupVersion{Group: "group", Version: "other"} - - scheme := runtime.NewScheme() - scheme.AddUnversionedTypes(externalGV, &InternalSimple{}) - scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) - scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) - scheme.AddKnownTypeWithName(otherGV.WithKind("Simple"), &ExternalSimple{}) - - codec := serializer.NewCodecFactory(scheme).LegacyCodec(externalGV) - - if unv, ok := scheme.IsUnversioned(&InternalSimple{}); !unv || !ok { - t.Fatalf("type not unversioned and in scheme: %t %t", unv, ok) - } - - kind, err := scheme.ObjectKind(&InternalSimple{}) - if err != nil { - t.Fatal(err) - } - if kind != externalGV.WithKind("InternalSimple") { - t.Fatalf("unexpected: %#v", kind) - } - - test := &InternalSimple{ - TestString: "I'm the same", - } - obj := runtime.Object(test) - data, err := runtime.Encode(codec, obj) - if err != nil { - t.Fatal(err) - } - obj2, gvk, err := codec.Decode(data, nil, nil) - if err != nil { - t.Fatal(err) - } - if _, ok := obj2.(*InternalSimple); !ok { - t.Fatalf("Got wrong type") - } - if !reflect.DeepEqual(obj2, test) { - t.Errorf("Expected:\n %#v,\n Got:\n %#v", test, obj2) - } - // object is serialized as an unversioned object (in the group and version it was defined in) - if !reflect.DeepEqual(gvk, &unversioned.GroupVersionKind{Group: "test.group", Version: "testExternal", Kind: "InternalSimple"}) { - t.Errorf("unexpected gvk returned by decode: %#v", gvk) - } - - // when serialized to a different group, the object is kept in its preferred name - codec = serializer.NewCodecFactory(scheme).LegacyCodec(otherGV) - data, err = runtime.Encode(codec, obj) - if err != nil { - t.Fatal(err) - } - if string(data) != `{"apiVersion":"test.group/testExternal","kind":"InternalSimple","testString":"I'm the same"}`+"\n" { - t.Errorf("unexpected data: %s", data) - } -} - -// Test a weird version/kind embedding format. -type MyWeirdCustomEmbeddedVersionKindField struct { - ID string `json:"ID,omitempty"` - APIVersion string `json:"myVersionKey,omitempty"` - ObjectKind string `json:"myKindKey,omitempty"` - Z string `json:"Z,omitempty"` - Y uint64 `json:"Y,omitempty"` -} - -type TestType1 struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` - C int8 `json:"C,omitempty"` - D int16 `json:"D,omitempty"` - E int32 `json:"E,omitempty"` - F int64 `json:"F,omitempty"` - G uint `json:"G,omitempty"` - H uint8 `json:"H,omitempty"` - I uint16 `json:"I,omitempty"` - J uint32 `json:"J,omitempty"` - K uint64 `json:"K,omitempty"` - L bool `json:"L,omitempty"` - M map[string]int `json:"M,omitempty"` - N map[string]TestType2 `json:"N,omitempty"` - O *TestType2 `json:"O,omitempty"` - P []TestType2 `json:"Q,omitempty"` -} - -type TestType2 struct { - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` -} - -type ExternalTestType2 struct { - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` -} -type ExternalTestType1 struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` - C int8 `json:"C,omitempty"` - D int16 `json:"D,omitempty"` - E int32 `json:"E,omitempty"` - F int64 `json:"F,omitempty"` - G uint `json:"G,omitempty"` - H uint8 `json:"H,omitempty"` - I uint16 `json:"I,omitempty"` - J uint32 `json:"J,omitempty"` - K uint64 `json:"K,omitempty"` - L bool `json:"L,omitempty"` - M map[string]int `json:"M,omitempty"` - N map[string]ExternalTestType2 `json:"N,omitempty"` - O *ExternalTestType2 `json:"O,omitempty"` - P []ExternalTestType2 `json:"Q,omitempty"` -} - -type ExternalInternalSame struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A TestType2 `json:"A,omitempty"` -} - -func (obj *MyWeirdCustomEmbeddedVersionKindField) GetObjectKind() unversioned.ObjectKind { return obj } -func (obj *MyWeirdCustomEmbeddedVersionKindField) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { - obj.APIVersion, obj.ObjectKind = gvk.ToAPIVersionAndKind() -} -func (obj *MyWeirdCustomEmbeddedVersionKindField) GroupVersionKind() *unversioned.GroupVersionKind { - return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.ObjectKind) -} - -func (obj *ExternalInternalSame) GetObjectKind() unversioned.ObjectKind { - return &obj.MyWeirdCustomEmbeddedVersionKindField -} - -func (obj *TestType1) GetObjectKind() unversioned.ObjectKind { - return &obj.MyWeirdCustomEmbeddedVersionKindField -} - -func (obj *ExternalTestType1) GetObjectKind() unversioned.ObjectKind { - return &obj.MyWeirdCustomEmbeddedVersionKindField -} - -func (obj *TestType2) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } -func (obj *ExternalTestType2) GetObjectKind() unversioned.ObjectKind { - return unversioned.EmptyObjectKind -} - -// TestObjectFuzzer can randomly populate all the above objects. -var TestObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 100).Funcs( - func(j *MyWeirdCustomEmbeddedVersionKindField, c fuzz.Continue) { - // We have to customize the randomization of MyWeirdCustomEmbeddedVersionKindFields because their - // APIVersion and Kind must remain blank in memory. - j.APIVersion = "" - j.ObjectKind = "" - j.ID = c.RandString() - }, -) - -// Returns a new Scheme set up with the test objects. -func GetTestScheme() *runtime.Scheme { - internalGV := unversioned.GroupVersion{Version: "__internal"} - externalGV := unversioned.GroupVersion{Version: "v1"} - - s := runtime.NewScheme() - // Ordinarily, we wouldn't add TestType2, but because this is a test and - // both types are from the same package, we need to get it into the system - // so that converter will match it with ExternalType2. - s.AddKnownTypes(internalGV, &TestType1{}, &TestType2{}, &ExternalInternalSame{}) - s.AddKnownTypes(externalGV, &ExternalInternalSame{}) - s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{}) - s.AddKnownTypeWithName(externalGV.WithKind("TestType2"), &ExternalTestType2{}) - s.AddKnownTypeWithName(internalGV.WithKind("TestType3"), &TestType1{}) - s.AddKnownTypeWithName(externalGV.WithKind("TestType3"), &ExternalTestType1{}) - return s -} - -func TestKnownTypes(t *testing.T) { - s := GetTestScheme() - if len(s.KnownTypes(unversioned.GroupVersion{Group: "group", Version: "v2"})) != 0 { - t.Errorf("should have no known types for v2") - } - - types := s.KnownTypes(unversioned.GroupVersion{Version: "v1"}) - for _, s := range []string{"TestType1", "TestType2", "TestType3", "ExternalInternalSame"} { - if _, ok := types[s]; !ok { - t.Errorf("missing type %q", s) - } - } -} - -func TestConvertToVersion(t *testing.T) { - s := GetTestScheme() - tt := &TestType1{A: "I'm not a pointer object"} - other, err := s.ConvertToVersion(tt, "v1") - if err != nil { - t.Fatalf("Failure: %v", err) - } - converted, ok := other.(*ExternalTestType1) - if !ok { - t.Fatalf("Got wrong type") - } - if tt.A != converted.A { - t.Fatalf("Failed to convert object correctly: %#v", converted) - } -} - -func TestMetaValues(t *testing.T) { - internalGV := unversioned.GroupVersion{Group: "test.group", Version: "__internal"} - externalGV := unversioned.GroupVersion{Group: "test.group", Version: "externalVersion"} - - s := runtime.NewScheme() - s.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) - s.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) - - internalToExternalCalls := 0 - externalToInternalCalls := 0 - - // Register functions to verify that scope.Meta() gets set correctly. - err := s.AddConversionFuncs( - func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error { - t.Logf("internal -> external") - if e, a := internalGV.String(), scope.Meta().SrcVersion; e != a { - t.Fatalf("Expected '%v', got '%v'", e, a) - } - if e, a := externalGV.String(), scope.Meta().DestVersion; e != a { - t.Fatalf("Expected '%v', got '%v'", e, a) - } - scope.Convert(&in.TestString, &out.TestString, 0) - internalToExternalCalls++ - return nil - }, - func(in *ExternalSimple, out *InternalSimple, scope conversion.Scope) error { - t.Logf("external -> internal") - if e, a := externalGV.String(), scope.Meta().SrcVersion; e != a { - t.Errorf("Expected '%v', got '%v'", e, a) - } - if e, a := internalGV.String(), scope.Meta().DestVersion; e != a { - t.Fatalf("Expected '%v', got '%v'", e, a) - } - scope.Convert(&in.TestString, &out.TestString, 0) - externalToInternalCalls++ - return nil - }, - ) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - simple := &InternalSimple{ - TestString: "foo", - } - - s.Log(t) - - out, err := s.ConvertToVersion(simple, externalGV.String()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - internal, err := s.ConvertToVersion(out, internalGV.String()) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if e, a := simple, internal; !reflect.DeepEqual(e, a) { - t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) - } - - if e, a := 1, internalToExternalCalls; e != a { - t.Errorf("Expected %v, got %v", e, a) - } - if e, a := 1, externalToInternalCalls; e != a { - t.Errorf("Expected %v, got %v", e, a) - } -} - -func TestMetaValuesUnregisteredConvert(t *testing.T) { - type InternalSimple struct { - Version string `json:"apiVersion,omitempty"` - Kind string `json:"kind,omitempty"` - TestString string `json:"testString"` - } - type ExternalSimple struct { - Version string `json:"apiVersion,omitempty"` - Kind string `json:"kind,omitempty"` - TestString string `json:"testString"` - } - s := runtime.NewScheme() - // We deliberately don't register the types. - - internalToExternalCalls := 0 - - // Register functions to verify that scope.Meta() gets set correctly. - err := s.AddConversionFuncs( - func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error { - if e, a := "unknown/unknown", scope.Meta().SrcVersion; e != a { - t.Fatalf("Expected '%v', got '%v'", e, a) - } - if e, a := "unknown/unknown", scope.Meta().DestVersion; e != a { - t.Fatalf("Expected '%v', got '%v'", e, a) - } - scope.Convert(&in.TestString, &out.TestString, 0) - internalToExternalCalls++ - return nil - }, - ) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - simple := &InternalSimple{TestString: "foo"} - external := &ExternalSimple{} - err = s.Convert(simple, external) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if e, a := simple.TestString, external.TestString; e != a { - t.Errorf("Expected %v, got %v", e, a) - } - - // Verify that our conversion handler got called. - if e, a := 1, internalToExternalCalls; e != a { - t.Errorf("Expected %v, got %v", e, a) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/codec_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/codec_test.go deleted file mode 100644 index 342a2a599..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/codec_test.go +++ /dev/null @@ -1,400 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 serializer - -import ( - "encoding/json" - "fmt" - "log" - "os" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/diff" - - "github.com/ghodss/yaml" - "github.com/google/gofuzz" - flag "github.com/spf13/pflag" -) - -var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.") - -type testMetaFactory struct{} - -func (testMetaFactory) Interpret(data []byte) (*unversioned.GroupVersionKind, error) { - findKind := struct { - APIVersion string `json:"myVersionKey,omitempty"` - ObjectKind string `json:"myKindKey,omitempty"` - }{} - // yaml is a superset of json, so we use it to decode here. That way, - // we understand both. - if err := yaml.Unmarshal(data, &findKind); err != nil { - return nil, fmt.Errorf("couldn't get version/kind: %v", err) - } - gv, err := unversioned.ParseGroupVersion(findKind.APIVersion) - if err != nil { - return nil, err - } - return &unversioned.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: findKind.ObjectKind}, nil -} - -// Test a weird version/kind embedding format. -type MyWeirdCustomEmbeddedVersionKindField struct { - ID string `json:"ID,omitempty"` - APIVersion string `json:"myVersionKey,omitempty"` - ObjectKind string `json:"myKindKey,omitempty"` - Z string `json:"Z,omitempty"` - Y uint64 `json:"Y,omitempty"` -} - -type TestType1 struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` - C int8 `json:"C,omitempty"` - D int16 `json:"D,omitempty"` - E int32 `json:"E,omitempty"` - F int64 `json:"F,omitempty"` - G uint `json:"G,omitempty"` - H uint8 `json:"H,omitempty"` - I uint16 `json:"I,omitempty"` - J uint32 `json:"J,omitempty"` - K uint64 `json:"K,omitempty"` - L bool `json:"L,omitempty"` - M map[string]int `json:"M,omitempty"` - N map[string]TestType2 `json:"N,omitempty"` - O *TestType2 `json:"O,omitempty"` - P []TestType2 `json:"Q,omitempty"` -} - -type TestType2 struct { - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` -} - -type ExternalTestType2 struct { - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` -} -type ExternalTestType1 struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A string `json:"A,omitempty"` - B int `json:"B,omitempty"` - C int8 `json:"C,omitempty"` - D int16 `json:"D,omitempty"` - E int32 `json:"E,omitempty"` - F int64 `json:"F,omitempty"` - G uint `json:"G,omitempty"` - H uint8 `json:"H,omitempty"` - I uint16 `json:"I,omitempty"` - J uint32 `json:"J,omitempty"` - K uint64 `json:"K,omitempty"` - L bool `json:"L,omitempty"` - M map[string]int `json:"M,omitempty"` - N map[string]ExternalTestType2 `json:"N,omitempty"` - O *ExternalTestType2 `json:"O,omitempty"` - P []ExternalTestType2 `json:"Q,omitempty"` -} - -type ExternalInternalSame struct { - MyWeirdCustomEmbeddedVersionKindField `json:",inline"` - A TestType2 `json:"A,omitempty"` -} - -// TestObjectFuzzer can randomly populate all the above objects. -var TestObjectFuzzer = fuzz.New().NilChance(.5).NumElements(1, 100).Funcs( - func(j *MyWeirdCustomEmbeddedVersionKindField, c fuzz.Continue) { - c.FuzzNoCustom(j) - j.APIVersion = "" - j.ObjectKind = "" - }, -) - -func (obj *MyWeirdCustomEmbeddedVersionKindField) GetObjectKind() unversioned.ObjectKind { return obj } -func (obj *MyWeirdCustomEmbeddedVersionKindField) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { - obj.APIVersion, obj.ObjectKind = gvk.ToAPIVersionAndKind() -} -func (obj *MyWeirdCustomEmbeddedVersionKindField) GroupVersionKind() *unversioned.GroupVersionKind { - return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.ObjectKind) -} - -func (obj *ExternalInternalSame) GetObjectKind() unversioned.ObjectKind { - return &obj.MyWeirdCustomEmbeddedVersionKindField -} - -func (obj *TestType1) GetObjectKind() unversioned.ObjectKind { - return &obj.MyWeirdCustomEmbeddedVersionKindField -} - -func (obj *ExternalTestType1) GetObjectKind() unversioned.ObjectKind { - return &obj.MyWeirdCustomEmbeddedVersionKindField -} - -func (obj *TestType2) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } -func (obj *ExternalTestType2) GetObjectKind() unversioned.ObjectKind { - return unversioned.EmptyObjectKind -} - -// Returns a new Scheme set up with the test objects. -func GetTestScheme() (*runtime.Scheme, runtime.Codec) { - internalGV := unversioned.GroupVersion{Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Version: "v1"} - externalGV2 := unversioned.GroupVersion{Version: "v2"} - - s := runtime.NewScheme() - // Ordinarily, we wouldn't add TestType2, but because this is a test and - // both types are from the same package, we need to get it into the system - // so that converter will match it with ExternalType2. - s.AddKnownTypes(internalGV, &TestType1{}, &TestType2{}, &ExternalInternalSame{}) - s.AddKnownTypes(externalGV, &ExternalInternalSame{}) - s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{}) - s.AddKnownTypeWithName(externalGV.WithKind("TestType2"), &ExternalTestType2{}) - s.AddKnownTypeWithName(internalGV.WithKind("TestType3"), &TestType1{}) - s.AddKnownTypeWithName(externalGV.WithKind("TestType3"), &ExternalTestType1{}) - s.AddKnownTypeWithName(externalGV2.WithKind("TestType1"), &ExternalTestType1{}) - - s.AddUnversionedTypes(externalGV, &unversioned.Status{}) - - cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) - codec := cf.LegacyCodec(unversioned.GroupVersion{Version: "v1"}) - return s, codec -} - -func objDiff(a, b interface{}) string { - ab, err := json.Marshal(a) - if err != nil { - panic("a") - } - bb, err := json.Marshal(b) - if err != nil { - panic("b") - } - return diff.StringDiff(string(ab), string(bb)) - - // An alternate diff attempt, in case json isn't showing you - // the difference. (reflect.DeepEqual makes a distinction between - // nil and empty slices, for example.) - //return diff.StringDiff( - // fmt.Sprintf("%#v", a), - // fmt.Sprintf("%#v", b), - //) -} - -var semantic = conversion.EqualitiesOrDie( - func(a, b MyWeirdCustomEmbeddedVersionKindField) bool { - a.APIVersion, a.ObjectKind = "", "" - b.APIVersion, b.ObjectKind = "", "" - return a == b - }, -) - -func runTest(t *testing.T, source interface{}) { - name := reflect.TypeOf(source).Elem().Name() - TestObjectFuzzer.Fuzz(source) - - _, codec := GetTestScheme() - data, err := runtime.Encode(codec, source.(runtime.Object)) - if err != nil { - t.Errorf("%v: %v (%#v)", name, err, source) - return - } - obj2, err := runtime.Decode(codec, data) - if err != nil { - t.Errorf("%v: %v (%v)", name, err, string(data)) - return - } - if !semantic.DeepEqual(source, obj2) { - t.Errorf("1: %v: diff: %v", name, diff.ObjectGoPrintSideBySide(source, obj2)) - return - } - obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface() - if err := runtime.DecodeInto(codec, data, obj3.(runtime.Object)); err != nil { - t.Errorf("2: %v: %v", name, err) - return - } - if !semantic.DeepEqual(source, obj3) { - t.Errorf("3: %v: diff: %v", name, objDiff(source, obj3)) - return - } -} - -func TestTypes(t *testing.T) { - table := []interface{}{ - &TestType1{}, - &ExternalInternalSame{}, - } - for _, item := range table { - // Try a few times, since runTest uses random values. - for i := 0; i < *fuzzIters; i++ { - runTest(t, item) - } - } -} - -func TestVersionedEncoding(t *testing.T) { - s, codec := GetTestScheme() - out, err := runtime.Encode(codec, &TestType1{}, unversioned.GroupVersion{Version: "v2"}) - if err != nil { - t.Fatal(err) - } - if string(out) != `{"myVersionKey":"v2","myKindKey":"TestType1"}`+"\n" { - t.Fatal(string(out)) - } - _, err = runtime.Encode(codec, &TestType1{}, unversioned.GroupVersion{Version: "v3"}) - if err == nil { - t.Fatal(err) - } - - cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) - encoder, _ := cf.SerializerForFileExtension("json") - - // codec that is unversioned uses the target version - unversionedCodec := cf.CodecForVersions(encoder, nil, nil, nil) - _, err = runtime.Encode(unversionedCodec, &TestType1{}, unversioned.GroupVersion{Version: "v3"}) - if err == nil || !runtime.IsNotRegisteredError(err) { - t.Fatal(err) - } - - // unversioned encode with no versions is written directly to wire - out, err = runtime.Encode(unversionedCodec, &TestType1{}) - if err != nil { - t.Fatal(err) - } - if string(out) != `{"myVersionKey":"__internal","myKindKey":"TestType1"}`+"\n" { - t.Fatal(string(out)) - } -} - -func TestMultipleNames(t *testing.T) { - _, codec := GetTestScheme() - - obj, _, err := codec.Decode([]byte(`{"myKindKey":"TestType3","myVersionKey":"v1","A":"value"}`), nil, nil) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - internal := obj.(*TestType1) - if internal.A != "value" { - t.Fatalf("unexpected decoded object: %#v", internal) - } - - out, err := runtime.Encode(codec, internal) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !strings.Contains(string(out), `"myKindKey":"TestType1"`) { - t.Errorf("unexpected encoded output: %s", string(out)) - } -} - -func TestConvertTypesWhenDefaultNamesMatch(t *testing.T) { - internalGV := unversioned.GroupVersion{Version: runtime.APIVersionInternal} - externalGV := unversioned.GroupVersion{Version: "v1"} - - s := runtime.NewScheme() - // create two names internally, with TestType1 being preferred - s.AddKnownTypeWithName(internalGV.WithKind("TestType1"), &TestType1{}) - s.AddKnownTypeWithName(internalGV.WithKind("OtherType1"), &TestType1{}) - // create two names externally, with TestType1 being preferred - s.AddKnownTypeWithName(externalGV.WithKind("TestType1"), &ExternalTestType1{}) - s.AddKnownTypeWithName(externalGV.WithKind("OtherType1"), &ExternalTestType1{}) - - ext := &ExternalTestType1{} - ext.APIVersion = "v1" - ext.ObjectKind = "OtherType1" - ext.A = "test" - data, err := json.Marshal(ext) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - expect := &TestType1{A: "test"} - - codec := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})).LegacyCodec(unversioned.GroupVersion{Version: "v1"}) - - obj, err := runtime.Decode(codec, data) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !semantic.DeepEqual(expect, obj) { - t.Errorf("unexpected object: %#v", obj) - } - - into := &TestType1{} - if err := runtime.DecodeInto(codec, data, into); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if !semantic.DeepEqual(expect, into) { - t.Errorf("unexpected object: %#v", obj) - } -} - -func TestEncode_Ptr(t *testing.T) { - _, codec := GetTestScheme() - tt := &TestType1{A: "I am a pointer object"} - data, err := runtime.Encode(codec, tt) - obj2, err2 := runtime.Decode(codec, data) - if err != nil || err2 != nil { - t.Fatalf("Failure: '%v' '%v'\n%s", err, err2, data) - } - if _, ok := obj2.(*TestType1); !ok { - t.Fatalf("Got wrong type") - } - if !semantic.DeepEqual(obj2, tt) { - t.Errorf("Expected:\n %#v,\n Got:\n %#v", tt, obj2) - } -} - -func TestBadJSONRejection(t *testing.T) { - log.SetOutput(os.Stderr) - _, codec := GetTestScheme() - badJSONs := [][]byte{ - []byte(`{"myVersionKey":"v1"}`), // Missing kind - []byte(`{"myVersionKey":"v1","myKindKey":"bar"}`), // Unknown kind - []byte(`{"myVersionKey":"bar","myKindKey":"TestType1"}`), // Unknown version - []byte(`{"myKindKey":"TestType1"}`), // Missing version - } - for _, b := range badJSONs { - if _, err := runtime.Decode(codec, b); err == nil { - t.Errorf("Did not reject bad json: %s", string(b)) - } - } - badJSONKindMismatch := []byte(`{"myVersionKey":"v1","myKindKey":"ExternalInternalSame"}`) - if err := runtime.DecodeInto(codec, badJSONKindMismatch, &TestType1{}); err == nil { - t.Errorf("Kind is set but doesn't match the object type: %s", badJSONKindMismatch) - } - if err := runtime.DecodeInto(codec, []byte(``), &TestType1{}); err != nil { - t.Errorf("Should allow empty decode: %v", err) - } - if _, _, err := codec.Decode([]byte(``), &unversioned.GroupVersionKind{Kind: "ExternalInternalSame"}, nil); err == nil { - t.Errorf("Did not give error for empty data with only kind default") - } - if _, _, err := codec.Decode([]byte(`{"myVersionKey":"v1"}`), &unversioned.GroupVersionKind{Kind: "ExternalInternalSame"}, nil); err != nil { - t.Errorf("Gave error for version and kind default") - } - if _, _, err := codec.Decode([]byte(`{"myKindKey":"ExternalInternalSame"}`), &unversioned.GroupVersionKind{Version: "v1"}, nil); err != nil { - t.Errorf("Gave error for version and kind default") - } - if _, _, err := codec.Decode([]byte(``), &unversioned.GroupVersionKind{Kind: "ExternalInternalSame", Version: "v1"}, nil); err != nil { - t.Errorf("Gave error for version and kind defaulted: %v", err) - } - if _, err := runtime.Decode(codec, []byte(``)); err == nil { - t.Errorf("Did not give error for empty data") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/json/json_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/json/json_test.go deleted file mode 100644 index f9fbf47a0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/json/json_test.go +++ /dev/null @@ -1,271 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 json_test - -import ( - "fmt" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/json" - "k8s.io/kubernetes/pkg/util/diff" -) - -type testDecodable struct { - Other string - Value int `json:"value"` - gvk *unversioned.GroupVersionKind -} - -func (d *testDecodable) GetObjectKind() unversioned.ObjectKind { return d } -func (d *testDecodable) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { d.gvk = gvk } -func (d *testDecodable) GroupVersionKind() *unversioned.GroupVersionKind { return d.gvk } - -func TestDecode(t *testing.T) { - testCases := []struct { - creater runtime.ObjectCreater - typer runtime.Typer - yaml bool - pretty bool - - data []byte - defaultGVK *unversioned.GroupVersionKind - into runtime.Object - - errFn func(error) bool - expectedObject runtime.Object - expectedGVK *unversioned.GroupVersionKind - }{ - { - data: []byte("{}"), - - expectedGVK: &unversioned.GroupVersionKind{}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") }, - }, - { - data: []byte("{}"), - defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - creater: &mockCreater{err: fmt.Errorf("fake error")}, - - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - errFn: func(err error) bool { return err.Error() == "fake error" }, - }, - { - data: []byte("{}"), - defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - creater: &mockCreater{err: fmt.Errorf("fake error")}, - - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - errFn: func(err error) bool { return err.Error() == "fake error" }, - }, - { - data: []byte("{}"), - defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - creater: &mockCreater{obj: &testDecodable{}}, - expectedObject: &testDecodable{ - gvk: nil, // json serializer does NOT set GVK - }, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - }, - - // version without group is not defaulted - { - data: []byte(`{"apiVersion":"blah"}`), - defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - creater: &mockCreater{obj: &testDecodable{}}, - expectedObject: &testDecodable{ - gvk: nil, // json serializer does NOT set GVK - }, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "", Version: "blah"}, - }, - // group without version is defaulted - { - data: []byte(`{"apiVersion":"other/"}`), - defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - creater: &mockCreater{obj: &testDecodable{}}, - expectedObject: &testDecodable{ - gvk: nil, // json serializer does NOT set GVK - }, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - }, - - // accept runtime.Unknown as into and bypass creator - { - data: []byte(`{}`), - into: &runtime.Unknown{}, - - expectedGVK: &unversioned.GroupVersionKind{}, - expectedObject: &runtime.Unknown{ - Raw: []byte(`{}`), - ContentType: runtime.ContentTypeJSON, - }, - }, - { - data: []byte(`{"test":"object"}`), - into: &runtime.Unknown{}, - - expectedGVK: &unversioned.GroupVersionKind{}, - expectedObject: &runtime.Unknown{ - Raw: []byte(`{"test":"object"}`), - ContentType: runtime.ContentTypeJSON, - }, - }, - { - data: []byte(`{"test":"object"}`), - into: &runtime.Unknown{}, - defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - expectedObject: &runtime.Unknown{ - TypeMeta: runtime.TypeMeta{APIVersion: "other/blah", Kind: "Test"}, - Raw: []byte(`{"test":"object"}`), - ContentType: runtime.ContentTypeJSON, - }, - }, - - // unregistered objects can be decoded into directly - { - data: []byte(`{"kind":"Test","apiVersion":"other/blah","value":1,"Other":"test"}`), - into: &testDecodable{}, - typer: &mockTyper{err: runtime.NewNotRegisteredErr(unversioned.GroupVersionKind{}, nil)}, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - expectedObject: &testDecodable{ - Other: "test", - Value: 1, - }, - }, - // registered types get defaulted by the into object kind - { - data: []byte(`{"value":1,"Other":"test"}`), - into: &testDecodable{}, - typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}}, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - expectedObject: &testDecodable{ - Other: "test", - Value: 1, - }, - }, - // registered types get defaulted by the into object kind even without version, but return an error - { - data: []byte(`{"value":1,"Other":"test"}`), - into: &testDecodable{}, - typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: ""}}, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: ""}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") }, - expectedObject: &testDecodable{ - Other: "test", - Value: 1, - }, - }, - - // runtime.VersionedObjects are decoded - { - data: []byte(`{"value":1,"Other":"test"}`), - into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, - creater: &mockCreater{obj: &testDecodable{}}, - typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}}, - defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - expectedObject: &runtime.VersionedObjects{ - Objects: []runtime.Object{ - &testDecodable{ - Other: "test", - Value: 1, - }, - }, - }, - }, - // runtime.VersionedObjects with an object are decoded into - { - data: []byte(`{"Other":"test"}`), - into: &runtime.VersionedObjects{Objects: []runtime.Object{&testDecodable{Value: 2}}}, - typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}}, - expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, - expectedObject: &runtime.VersionedObjects{ - Objects: []runtime.Object{ - &testDecodable{ - Other: "test", - Value: 2, - }, - }, - }, - }, - } - - for i, test := range testCases { - var s runtime.Serializer - if test.yaml { - s = json.NewYAMLSerializer(json.DefaultMetaFactory, test.creater, test.typer) - } else { - s = json.NewSerializer(json.DefaultMetaFactory, test.creater, test.typer, test.pretty) - } - obj, gvk, err := s.Decode([]byte(test.data), test.defaultGVK, test.into) - - if !reflect.DeepEqual(test.expectedGVK, gvk) { - t.Errorf("%d: unexpected GVK: %v", i, gvk) - } - - switch { - case err == nil && test.errFn != nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil && test.errFn == nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil: - if !test.errFn(err) { - t.Errorf("%d: failed: %v", i, err) - } - if obj != nil { - t.Errorf("%d: should have returned nil object", i) - } - continue - } - - if test.into != nil && test.into != obj { - t.Errorf("%d: expected into to be returned: %v", i, obj) - continue - } - - if !reflect.DeepEqual(test.expectedObject, obj) { - t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintSideBySide(test.expectedObject, obj)) - } - } -} - -type mockCreater struct { - apiVersion string - kind string - err error - obj runtime.Object -} - -func (c *mockCreater) New(kind unversioned.GroupVersionKind) (runtime.Object, error) { - c.apiVersion, c.kind = kind.GroupVersion().String(), kind.Kind - return c.obj, c.err -} - -type mockTyper struct { - gvk *unversioned.GroupVersionKind - err error -} - -func (t *mockTyper) ObjectKind(obj runtime.Object) (*unversioned.GroupVersionKind, bool, error) { - return t.gvk, false, t.err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/json/meta_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/json/meta_test.go deleted file mode 100644 index 4b6351286..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/json/meta_test.go +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 json - -import "testing" - -func TestSimpleMetaFactoryInterpret(t *testing.T) { - factory := SimpleMetaFactory{} - gvk, err := factory.Interpret([]byte(`{"apiVersion":"1","kind":"object"}`)) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if gvk.Version != "1" || gvk.Kind != "object" { - t.Errorf("unexpected interpret: %#v", gvk) - } - - // no kind or version - gvk, err = factory.Interpret([]byte(`{}`)) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if gvk.Version != "" || gvk.Kind != "" { - t.Errorf("unexpected interpret: %#v", gvk) - } - - // unparsable - gvk, err = factory.Interpret([]byte(`{`)) - if err == nil { - t.Errorf("unexpected non-error") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/protobuf/protobuf_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/protobuf/protobuf_test.go deleted file mode 100644 index 06b3d2e55..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/protobuf/protobuf_test.go +++ /dev/null @@ -1,351 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 protobuf_test - -import ( - "bytes" - "encoding/hex" - "fmt" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api" - _ "k8s.io/kubernetes/pkg/api/install" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/v1" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/protobuf" - "k8s.io/kubernetes/pkg/util/diff" -) - -type testObject struct { - gvk *unversioned.GroupVersionKind -} - -func (d *testObject) GetObjectKind() unversioned.ObjectKind { return d } -func (d *testObject) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { d.gvk = gvk } -func (d *testObject) GroupVersionKind() *unversioned.GroupVersionKind { return d.gvk } - -type testMarshalable struct { - testObject - data []byte - err error -} - -func (d *testMarshalable) Marshal() ([]byte, error) { - return d.data, d.err -} - -type testBufferedMarshalable struct { - testObject - data []byte - err error -} - -func (d *testBufferedMarshalable) Marshal() ([]byte, error) { - return nil, fmt.Errorf("not invokable") -} - -func (d *testBufferedMarshalable) MarshalTo(data []byte) (int, error) { - copy(data, d.data) - return len(d.data), d.err -} - -func (d *testBufferedMarshalable) Size() int { - return len(d.data) -} - -func TestRecognize(t *testing.T) { - s := protobuf.NewSerializer(nil, nil, "application/protobuf") - ignores := [][]byte{ - nil, - {}, - []byte("k8s"), - {0x6b, 0x38, 0x73, 0x01}, - } - for i, data := range ignores { - if ok, err := s.RecognizesData(bytes.NewBuffer(data)); err != nil || ok { - t.Errorf("%d: should not recognize data: %v", i, err) - } - } - recognizes := [][]byte{ - {0x6b, 0x38, 0x73, 0x00}, - {0x6b, 0x38, 0x73, 0x00, 0x01}, - } - for i, data := range recognizes { - if ok, err := s.RecognizesData(bytes.NewBuffer(data)); err != nil || !ok { - t.Errorf("%d: should recognize data: %v", i, err) - } - } -} - -func TestEncode(t *testing.T) { - obj1 := &testMarshalable{testObject: testObject{}, data: []byte{}} - wire1 := []byte{ - 0x6b, 0x38, 0x73, 0x00, // prefix - 0x0a, 0x04, - 0x0a, 0x00, // apiversion - 0x12, 0x00, // kind - 0x12, 0x00, // data - 0x1a, 0x00, // content-type - 0x22, 0x00, // content-encoding - } - obj2 := &testMarshalable{ - testObject: testObject{gvk: &unversioned.GroupVersionKind{Kind: "test", Group: "other", Version: "version"}}, - data: []byte{0x01, 0x02, 0x03}, - } - wire2 := []byte{ - 0x6b, 0x38, 0x73, 0x00, // prefix - 0x0a, 0x15, - 0x0a, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // apiversion - 0x12, 0x04, 0x74, 0x65, 0x73, 0x74, // kind - 0x12, 0x03, 0x01, 0x02, 0x03, // data - 0x1a, 0x00, // content-type - 0x22, 0x00, // content-encoding - } - - err1 := fmt.Errorf("a test error") - - testCases := []struct { - obj runtime.Object - data []byte - errFn func(error) bool - }{ - { - obj: &testObject{}, - errFn: protobuf.IsNotMarshalable, - }, - { - obj: obj1, - data: wire1, - }, - { - obj: &testMarshalable{testObject: obj1.testObject, err: err1}, - errFn: func(err error) bool { return err == err1 }, - }, - { - // if this test fails, writing the "fast path" marshal is not the same as the "slow path" - obj: &testBufferedMarshalable{testObject: obj1.testObject, data: obj1.data}, - data: wire1, - }, - { - obj: obj2, - data: wire2, - }, - { - // if this test fails, writing the "fast path" marshal is not the same as the "slow path" - obj: &testBufferedMarshalable{testObject: obj2.testObject, data: obj2.data}, - data: wire2, - }, - { - obj: &testBufferedMarshalable{testObject: obj1.testObject, err: err1}, - errFn: func(err error) bool { return err == err1 }, - }, - } - - for i, test := range testCases { - s := protobuf.NewSerializer(nil, nil, "application/protobuf") - data, err := runtime.Encode(s, test.obj) - - switch { - case err == nil && test.errFn != nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil && test.errFn == nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil: - if !test.errFn(err) { - t.Errorf("%d: failed: %v", i, err) - } - if data != nil { - t.Errorf("%d: should not have returned nil data", i) - } - continue - } - - if test.data != nil && !bytes.Equal(test.data, data) { - t.Errorf("%d: unexpected data:\n%s", i, hex.Dump(data)) - continue - } - - if ok, err := s.RecognizesData(bytes.NewBuffer(data)); !ok || err != nil { - t.Errorf("%d: did not recognize data generated by call: %v", i, err) - } - } -} - -func TestDecode(t *testing.T) { - wire1 := []byte{ - 0x6b, 0x38, 0x73, 0x00, // prefix - 0x0a, 0x04, - 0x0a, 0x00, // apiversion - 0x12, 0x00, // kind - 0x12, 0x00, // data - 0x1a, 0x00, // content-type - 0x22, 0x00, // content-encoding - } - wire2 := []byte{ - 0x6b, 0x38, 0x73, 0x00, // prefix - 0x0a, 0x15, - 0x0a, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // apiversion - 0x12, 0x04, 0x74, 0x65, 0x73, 0x74, // kind - 0x12, 0x03, 0x01, 0x02, 0x03, // data - 0x1a, 0x00, // content-type - 0x22, 0x00, // content-encoding - } - - //err1 := fmt.Errorf("a test error") - - testCases := []struct { - obj runtime.Object - data []byte - errFn func(error) bool - }{ - { - obj: &runtime.Unknown{}, - errFn: func(err error) bool { return err.Error() == "empty data" }, - }, - { - data: []byte{0x6b}, - errFn: func(err error) bool { return strings.Contains(err.Error(), "does not appear to be a protobuf message") }, - }, - { - obj: &runtime.Unknown{ - ContentType: "application/protobuf", - Raw: []byte{}, - }, - data: wire1, - }, - { - obj: &runtime.Unknown{ - TypeMeta: runtime.TypeMeta{ - APIVersion: "other/version", - Kind: "test", - }, - ContentType: "application/protobuf", - Raw: []byte{0x01, 0x02, 0x03}, - }, - data: wire2, - }, - } - - for i, test := range testCases { - s := protobuf.NewSerializer(nil, nil, "application/protobuf") - unk := &runtime.Unknown{} - err := runtime.DecodeInto(s, test.data, unk) - - switch { - case err == nil && test.errFn != nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil && test.errFn == nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil: - if !test.errFn(err) { - t.Errorf("%d: failed: %v", i, err) - } - continue - } - - if !reflect.DeepEqual(unk, test.obj) { - t.Errorf("%d: unexpected object:\n%#v", i, unk) - continue - } - } -} - -func TestDecodeObjects(t *testing.T) { - obj1 := &v1.Pod{ - ObjectMeta: v1.ObjectMeta{ - Name: "cool", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "test", - }, - }, - }, - } - obj1wire, err := obj1.Marshal() - if err != nil { - t.Fatal(err) - } - - wire1, err := (&runtime.Unknown{ - TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: "v1"}, - Raw: obj1wire, - }).Marshal() - if err != nil { - t.Fatal(err) - } - - unk2 := &runtime.Unknown{ - TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: "v1"}, - } - wire2 := make([]byte, len(wire1)*2) - n, err := unk2.NestedMarshalTo(wire2, obj1, uint64(obj1.Size())) - if err != nil { - t.Fatal(err) - } - if n != len(wire1) || !bytes.Equal(wire1, wire2[:n]) { - t.Fatalf("unexpected wire:\n%s", hex.Dump(wire2[:n])) - } - - wire1 = append([]byte{0x6b, 0x38, 0x73, 0x00}, wire1...) - - testCases := []struct { - obj runtime.Object - data []byte - errFn func(error) bool - }{ - { - obj: obj1, - data: wire1, - }, - } - - for i, test := range testCases { - s := protobuf.NewSerializer(api.Scheme, runtime.ObjectTyperToTyper(api.Scheme), "application/protobuf") - obj, err := runtime.Decode(s, test.data) - - switch { - case err == nil && test.errFn != nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil && test.errFn == nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil: - if !test.errFn(err) { - t.Errorf("%d: failed: %v", i, err) - } - if obj != nil { - t.Errorf("%d: should not have returned an object", i) - } - continue - } - - if !api.Semantic.DeepEqual(obj, test.obj) { - t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintDiff(test.obj, obj)) - continue - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/recognizer/recognizer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/recognizer/recognizer_test.go deleted file mode 100644 index c83b87aa4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/recognizer/recognizer_test.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 recognizer - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer/json" -) - -type A struct{} - -func (A) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind } - -func TestRecognizer(t *testing.T) { - s := runtime.NewScheme() - s.AddKnownTypes(unversioned.GroupVersion{Version: "v1"}, &A{}) - d := NewDecoder( - json.NewSerializer(json.DefaultMetaFactory, s, runtime.ObjectTyperToTyper(s), false), - json.NewYAMLSerializer(json.DefaultMetaFactory, s, runtime.ObjectTyperToTyper(s)), - ) - out, _, err := d.Decode([]byte(` -kind: A -apiVersion: v1 -`), nil, nil) - if err != nil { - t.Fatal(err) - } - t.Logf("%#v", out) - - out, _, err = d.Decode([]byte(` -{ - "kind":"A", - "apiVersion":"v1" -} -`), nil, nil) - if err != nil { - t.Fatal(err) - } - t.Logf("%#v", out) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/streaming/streaming_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/streaming/streaming_test.go deleted file mode 100644 index b3d500c98..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/streaming/streaming_test.go +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 streaming - -import ( - "bytes" - "io" - "io/ioutil" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/framer" -) - -type fakeDecoder struct { - got []byte - obj runtime.Object - err error -} - -func (d *fakeDecoder) Decode(data []byte, gvk *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) { - d.got = data - return d.obj, nil, d.err -} - -func TestEmptyDecoder(t *testing.T) { - buf := bytes.NewBuffer([]byte{}) - d := &fakeDecoder{} - _, _, err := NewDecoder(ioutil.NopCloser(buf), d).Decode(nil, nil) - if err != io.EOF { - t.Fatal(err) - } -} - -func TestDecoder(t *testing.T) { - frames := [][]byte{ - make([]byte, 1025), - make([]byte, 1024*5), - make([]byte, 1024*1024*5), - make([]byte, 1025), - } - pr, pw := io.Pipe() - fw := framer.NewLengthDelimitedFrameWriter(pw) - go func() { - for i := range frames { - fw.Write(frames[i]) - } - pw.Close() - }() - - r := framer.NewLengthDelimitedFrameReader(pr) - d := &fakeDecoder{} - dec := NewDecoder(r, d) - if _, _, err := dec.Decode(nil, nil); err != nil || !bytes.Equal(d.got, frames[0]) { - t.Fatalf("unexpected %v %v", err, len(d.got)) - } - if _, _, err := dec.Decode(nil, nil); err != nil || !bytes.Equal(d.got, frames[1]) { - t.Fatalf("unexpected %v %v", err, len(d.got)) - } - if _, _, err := dec.Decode(nil, nil); err != ErrObjectTooLarge || !bytes.Equal(d.got, frames[1]) { - t.Fatalf("unexpected %v %v", err, len(d.got)) - } - if _, _, err := dec.Decode(nil, nil); err != nil || !bytes.Equal(d.got, frames[3]) { - t.Fatalf("unexpected %v %v", err, len(d.got)) - } - if _, _, err := dec.Decode(nil, nil); err != io.EOF { - t.Fatalf("unexpected %v %v", err, len(d.got)) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/versioning/versioning_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/versioning/versioning_test.go deleted file mode 100644 index 1b45abfd5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/versioning/versioning_test.go +++ /dev/null @@ -1,300 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 versioning - -import ( - "fmt" - "io" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/diff" -) - -type testDecodable struct { - Other string - Value int `json:"value"` - gvk *unversioned.GroupVersionKind -} - -func (d *testDecodable) GetObjectKind() unversioned.ObjectKind { return d } -func (d *testDecodable) SetGroupVersionKind(gvk *unversioned.GroupVersionKind) { d.gvk = gvk } -func (d *testDecodable) GroupVersionKind() *unversioned.GroupVersionKind { return d.gvk } - -func TestDecode(t *testing.T) { - gvk1 := &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"} - decodable1 := &testDecodable{} - decodable2 := &testDecodable{} - decodable3 := &testDecodable{} - versionedDecodable1 := &runtime.VersionedObjects{Objects: []runtime.Object{decodable1}} - - testCases := []struct { - serializer runtime.Serializer - convertor runtime.ObjectConvertor - creater runtime.ObjectCreater - copier runtime.ObjectCopier - typer runtime.Typer - yaml bool - pretty bool - - encodes, decodes []unversioned.GroupVersion - - defaultGVK *unversioned.GroupVersionKind - into runtime.Object - - errFn func(error) bool - expectedObject runtime.Object - sameObject runtime.Object - expectedGVK *unversioned.GroupVersionKind - }{ - { - serializer: &mockSerializer{actual: gvk1}, - convertor: &checkConvertor{groupVersion: "other/__internal"}, - expectedGVK: gvk1, - }, - { - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: "other/__internal"}, - expectedGVK: gvk1, - sameObject: decodable2, - }, - // defaultGVK.Group is allowed to force a conversion to the destination group - { - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - defaultGVK: &unversioned.GroupVersionKind{Group: "force"}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: "force/__internal"}, - expectedGVK: gvk1, - sameObject: decodable2, - }, - // uses direct conversion for into when objects differ - { - into: decodable3, - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - convertor: &checkConvertor{in: decodable1, obj: decodable3, directConvert: true}, - expectedGVK: gvk1, - sameObject: decodable3, - }, - { - into: versionedDecodable1, - serializer: &mockSerializer{actual: gvk1, obj: decodable3}, - convertor: &checkConvertor{in: decodable3, obj: decodable1, directConvert: true}, - expectedGVK: gvk1, - sameObject: versionedDecodable1, - }, - // returns directly when serializer returns into - { - into: decodable3, - serializer: &mockSerializer{actual: gvk1, obj: decodable3}, - expectedGVK: gvk1, - sameObject: decodable3, - }, - // returns directly when serializer returns into - { - into: versionedDecodable1, - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - expectedGVK: gvk1, - sameObject: versionedDecodable1, - }, - - // runtime.VersionedObjects are decoded - { - into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, - - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - copier: &checkCopy{in: decodable1, obj: decodable1}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: "other/__internal"}, - expectedGVK: gvk1, - expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1, decodable2}}, - }, - { - into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, - - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - copier: &checkCopy{in: decodable1, obj: nil, err: fmt.Errorf("error on copy")}, - convertor: &checkConvertor{in: decodable1, obj: decodable2, groupVersion: "other/__internal"}, - expectedGVK: gvk1, - expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1, decodable2}}, - }, - - // decode into the same version as the serialized object - { - decodes: []unversioned.GroupVersion{gvk1.GroupVersion()}, - - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - expectedGVK: gvk1, - expectedObject: decodable1, - }, - { - into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, - decodes: []unversioned.GroupVersion{gvk1.GroupVersion()}, - - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - expectedGVK: gvk1, - expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1}}, - }, - - // codec with non matching version skips conversion altogether - { - decodes: []unversioned.GroupVersion{{Group: "something", Version: "else"}}, - - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - expectedGVK: gvk1, - expectedObject: decodable1, - }, - { - into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, - decodes: []unversioned.GroupVersion{{Group: "something", Version: "else"}}, - - serializer: &mockSerializer{actual: gvk1, obj: decodable1}, - expectedGVK: gvk1, - expectedObject: &runtime.VersionedObjects{Objects: []runtime.Object{decodable1}}, - }, - } - - for i, test := range testCases { - t.Logf("%d", i) - s := NewCodec(test.serializer, test.serializer, test.convertor, test.creater, test.copier, test.typer, test.encodes, test.decodes) - obj, gvk, err := s.Decode([]byte(`{}`), test.defaultGVK, test.into) - - if !reflect.DeepEqual(test.expectedGVK, gvk) { - t.Errorf("%d: unexpected GVK: %v", i, gvk) - } - - switch { - case err == nil && test.errFn != nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil && test.errFn == nil: - t.Errorf("%d: failed: %v", i, err) - continue - case err != nil: - if !test.errFn(err) { - t.Errorf("%d: failed: %v", i, err) - } - if obj != nil { - t.Errorf("%d: should have returned nil object", i) - } - continue - } - - if test.into != nil && test.into != obj { - t.Errorf("%d: expected into to be returned: %v", i, obj) - continue - } - - switch { - case test.expectedObject != nil: - if !reflect.DeepEqual(test.expectedObject, obj) { - t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintSideBySide(test.expectedObject, obj)) - } - case test.sameObject != nil: - if test.sameObject != obj { - t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintSideBySide(test.sameObject, obj)) - } - case obj != nil: - t.Errorf("%d: unexpected object: %#v", i, obj) - } - } -} - -type checkCopy struct { - in, obj runtime.Object - err error -} - -func (c *checkCopy) Copy(obj runtime.Object) (runtime.Object, error) { - if c.in != nil && c.in != obj { - return nil, fmt.Errorf("unexpected input to copy: %#v", obj) - } - return c.obj, c.err -} - -type checkConvertor struct { - err error - in, obj runtime.Object - groupVersion string - directConvert bool -} - -func (c *checkConvertor) Convert(in, out interface{}) error { - if !c.directConvert { - return fmt.Errorf("unexpected call to Convert") - } - if c.in != nil && c.in != in { - return fmt.Errorf("unexpected in: %s", in) - } - if c.obj != nil && c.obj != out { - return fmt.Errorf("unexpected out: %s", out) - } - return c.err -} -func (c *checkConvertor) ConvertToVersion(in runtime.Object, outVersion string) (out runtime.Object, err error) { - if c.directConvert { - return nil, fmt.Errorf("unexpected call to ConvertToVersion") - } - if c.in != nil && c.in != in { - return nil, fmt.Errorf("unexpected in: %s", in) - } - if c.groupVersion != outVersion { - return nil, fmt.Errorf("unexpected outversion: %s", outVersion) - } - return c.obj, c.err -} -func (c *checkConvertor) ConvertFieldLabel(version, kind, label, value string) (string, string, error) { - return "", "", fmt.Errorf("unexpected call to ConvertFieldLabel") -} - -type mockSerializer struct { - err error - obj runtime.Object - versions []unversioned.GroupVersion - - defaults, actual *unversioned.GroupVersionKind - into runtime.Object -} - -func (s *mockSerializer) Decode(data []byte, defaults *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) { - s.defaults = defaults - s.into = into - return s.obj, s.actual, s.err -} - -func (s *mockSerializer) EncodeToStream(obj runtime.Object, w io.Writer, versions ...unversioned.GroupVersion) error { - s.obj = obj - s.versions = versions - return s.err -} - -type mockCreater struct { - err error - obj runtime.Object -} - -func (c *mockCreater) New(kind unversioned.GroupVersionKind) (runtime.Object, error) { - return c.obj, c.err -} - -type mockTyper struct { - gvk *unversioned.GroupVersionKind - err error -} - -func (t *mockTyper) ObjectKind(obj runtime.Object) (*unversioned.GroupVersionKind, bool, error) { - return t.gvk, false, t.err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/yaml/yaml.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/yaml/yaml.go deleted file mode 100644 index 637c777be..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/serializer/yaml/yaml.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 yaml - -import ( - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/yaml" -) - -// yamlSerializer converts YAML passed to the Decoder methods to JSON. -type yamlSerializer struct { - // the nested serializer - runtime.Serializer -} - -// yamlSerializer implements Serializer -var _ runtime.Serializer = yamlSerializer{} - -// NewDecodingSerializer adds YAML decoding support to a serializer that supports JSON. -func NewDecodingSerializer(jsonSerializer runtime.Serializer) runtime.Serializer { - return &yamlSerializer{jsonSerializer} -} - -func (c yamlSerializer) Decode(data []byte, gvk *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) { - out, err := yaml.ToJSON(data) - if err != nil { - return nil, nil, err - } - data = out - return c.Serializer.Decode(data, gvk, into) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/swagger_doc_generator_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/swagger_doc_generator_test.go deleted file mode 100644 index 095dddff5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/swagger_doc_generator_test.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 runtime - -import ( - "testing" -) - -func TestFmtRawDoc(t *testing.T) { - tests := []struct { - t, expected string - }{ - {"aaa\n --- asd\n TODO: tooooodo\n toooodoooooo\n", "aaa"}, - {"aaa\nasd\n TODO: tooooodo\nbbbb\n --- toooodoooooo\n", "aaa asd bbbb"}, - {" TODO: tooooodo\n", ""}, - {"Par1\n\nPar2\n\n", "Par1\\n\\nPar2"}, - {"", ""}, - {" ", ""}, - {" \n", ""}, - {" \n\n ", ""}, - {"Example:\n\tl1\n\t\tl2\n", "Example:\\n\\tl1\\n\\t\\tl2"}, - } - - for _, test := range tests { - if o := fmtRawDoc(test.t); o != test.expected { - t.Fatalf("Expected: %q, got %q", test.expected, o) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/unstructured_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/unstructured_test.go deleted file mode 100644 index 155d534ff..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/unstructured_test.go +++ /dev/null @@ -1,356 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 runtime_test - -import ( - "fmt" - "reflect" - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/api/validation" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/types" -) - -func TestDecodeUnstructured(t *testing.T) { - groupVersionString := testapi.Default.GroupVersion().String() - rawJson := fmt.Sprintf(`{"kind":"Pod","apiVersion":"%s","metadata":{"name":"test"}}`, groupVersionString) - pl := &api.List{ - Items: []runtime.Object{ - &api.Pod{ObjectMeta: api.ObjectMeta{Name: "1"}}, - &runtime.Unknown{ - TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: groupVersionString}, - Raw: []byte(rawJson), - ContentType: runtime.ContentTypeJSON, - }, - &runtime.Unknown{ - TypeMeta: runtime.TypeMeta{Kind: "", APIVersion: groupVersionString}, - Raw: []byte(rawJson), - ContentType: runtime.ContentTypeJSON, - }, - &runtime.Unstructured{ - Object: map[string]interface{}{ - "kind": "Foo", - "apiVersion": "Bar", - "test": "value", - }, - }, - }, - } - if errs := runtime.DecodeList(pl.Items, runtime.UnstructuredJSONScheme); len(errs) == 1 { - t.Fatalf("unexpected error %v", errs) - } - if pod, ok := pl.Items[1].(*runtime.Unstructured); !ok || pod.Object["kind"] != "Pod" || pod.Object["metadata"].(map[string]interface{})["name"] != "test" { - t.Errorf("object not converted: %#v", pl.Items[1]) - } - if pod, ok := pl.Items[2].(*runtime.Unstructured); !ok || pod.Object["kind"] != "Pod" || pod.Object["metadata"].(map[string]interface{})["name"] != "test" { - t.Errorf("object not converted: %#v", pl.Items[2]) - } -} - -func TestDecode(t *testing.T) { - tcs := []struct { - json []byte - want runtime.Object - }{ - { - json: []byte(`{"apiVersion": "test", "kind": "test_kind"}`), - want: &runtime.Unstructured{ - Object: map[string]interface{}{"apiVersion": "test", "kind": "test_kind"}, - }, - }, - { - json: []byte(`{"apiVersion": "test", "kind": "test_list", "items": []}`), - want: &runtime.UnstructuredList{ - Object: map[string]interface{}{"apiVersion": "test", "kind": "test_list"}, - }, - }, - { - json: []byte(`{"items": [{"metadata": {"name": "object1"}, "apiVersion": "test", "kind": "test_kind"}, {"metadata": {"name": "object2"}, "apiVersion": "test", "kind": "test_kind"}], "apiVersion": "test", "kind": "test_list"}`), - want: &runtime.UnstructuredList{ - Object: map[string]interface{}{"apiVersion": "test", "kind": "test_list"}, - Items: []*runtime.Unstructured{ - { - Object: map[string]interface{}{ - "metadata": map[string]interface{}{"name": "object1"}, - "apiVersion": "test", - "kind": "test_kind", - }, - }, - { - Object: map[string]interface{}{ - "metadata": map[string]interface{}{"name": "object2"}, - "apiVersion": "test", - "kind": "test_kind", - }, - }, - }, - }, - }, - } - - for _, tc := range tcs { - got, _, err := runtime.UnstructuredJSONScheme.Decode(tc.json, nil, nil) - if err != nil { - t.Errorf("Unexpected error for %q: %v", string(tc.json), err) - continue - } - - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("Decode(%q) want: %v\ngot: %v", string(tc.json), tc.want, got) - } - } -} - -func TestUnstructuredGetters(t *testing.T) { - unstruct := runtime.Unstructured{ - Object: map[string]interface{}{ - "kind": "test_kind", - "apiVersion": "test_version", - "metadata": map[string]interface{}{ - "name": "test_name", - "namespace": "test_namespace", - "generateName": "test_generateName", - "uid": "test_uid", - "resourceVersion": "test_resourceVersion", - "selfLink": "test_selfLink", - "creationTimestamp": "2009-11-10T23:00:00Z", - "deletionTimestamp": "2010-11-10T23:00:00Z", - "labels": map[string]interface{}{ - "test_label": "test_value", - }, - "annotations": map[string]interface{}{ - "test_annotation": "test_value", - }, - }, - }, - } - - if got, want := unstruct.GetAPIVersion(), "test_version"; got != want { - t.Errorf("GetAPIVersions() = %s, want %s", got, want) - } - - if got, want := unstruct.GetKind(), "test_kind"; got != want { - t.Errorf("GetKind() = %s, want %s", got, want) - } - - if got, want := unstruct.GetNamespace(), "test_namespace"; got != want { - t.Errorf("GetNamespace() = %s, want %s", got, want) - } - - if got, want := unstruct.GetName(), "test_name"; got != want { - t.Errorf("GetName() = %s, want %s", got, want) - } - - if got, want := unstruct.GetGenerateName(), "test_generateName"; got != want { - t.Errorf("GetGenerateName() = %s, want %s", got, want) - } - - if got, want := unstruct.GetUID(), types.UID("test_uid"); got != want { - t.Errorf("GetUID() = %s, want %s", got, want) - } - - if got, want := unstruct.GetResourceVersion(), "test_resourceVersion"; got != want { - t.Errorf("GetResourceVersion() = %s, want %s", got, want) - } - - if got, want := unstruct.GetSelfLink(), "test_selfLink"; got != want { - t.Errorf("GetSelfLink() = %s, want %s", got, want) - } - - if got, want := unstruct.GetCreationTimestamp(), unversioned.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC); !got.Equal(want) { - t.Errorf("GetCreationTimestamp() = %s, want %s", got, want) - } - - if got, want := unstruct.GetDeletionTimestamp(), unversioned.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC); got == nil || !got.Equal(want) { - t.Errorf("GetDeletionTimestamp() = %s, want %s", got, want) - } - - if got, want := unstruct.GetLabels(), map[string]string{"test_label": "test_value"}; !reflect.DeepEqual(got, want) { - t.Errorf("GetLabels() = %s, want %s", got, want) - } - - if got, want := unstruct.GetAnnotations(), map[string]string{"test_annotation": "test_value"}; !reflect.DeepEqual(got, want) { - t.Errorf("GetAnnotations() = %s, want %s", got, want) - } -} - -func TestUnstructuredSetters(t *testing.T) { - unstruct := runtime.Unstructured{} - - want := runtime.Unstructured{ - Object: map[string]interface{}{ - "kind": "test_kind", - "apiVersion": "test_version", - "metadata": map[string]interface{}{ - "name": "test_name", - "namespace": "test_namespace", - "generateName": "test_generateName", - "uid": "test_uid", - "resourceVersion": "test_resourceVersion", - "selfLink": "test_selfLink", - "creationTimestamp": "2009-11-10T23:00:00Z", - "deletionTimestamp": "2010-11-10T23:00:00Z", - "labels": map[string]interface{}{ - "test_label": "test_value", - }, - "annotations": map[string]interface{}{ - "test_annotation": "test_value", - }, - }, - }, - } - - unstruct.SetAPIVersion("test_version") - unstruct.SetKind("test_kind") - unstruct.SetNamespace("test_namespace") - unstruct.SetName("test_name") - unstruct.SetGenerateName("test_generateName") - unstruct.SetUID(types.UID("test_uid")) - unstruct.SetResourceVersion("test_resourceVersion") - unstruct.SetSelfLink("test_selfLink") - unstruct.SetCreationTimestamp(unversioned.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)) - date := unversioned.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC) - unstruct.SetDeletionTimestamp(&date) - unstruct.SetLabels(map[string]string{"test_label": "test_value"}) - unstruct.SetAnnotations(map[string]string{"test_annotation": "test_value"}) - - if !reflect.DeepEqual(unstruct, want) { - t.Errorf("Wanted: \n%s\n Got:\n%s", unstruct, want) - } -} - -func TestUnstructuredListGetters(t *testing.T) { - unstruct := runtime.UnstructuredList{ - Object: map[string]interface{}{ - "kind": "test_kind", - "apiVersion": "test_version", - "metadata": map[string]interface{}{ - "resourceVersion": "test_resourceVersion", - "selfLink": "test_selfLink", - }, - }, - } - - if got, want := unstruct.GetAPIVersion(), "test_version"; got != want { - t.Errorf("GetAPIVersions() = %s, want %s", got, want) - } - - if got, want := unstruct.GetKind(), "test_kind"; got != want { - t.Errorf("GetKind() = %s, want %s", got, want) - } - - if got, want := unstruct.GetResourceVersion(), "test_resourceVersion"; got != want { - t.Errorf("GetResourceVersion() = %s, want %s", got, want) - } - - if got, want := unstruct.GetSelfLink(), "test_selfLink"; got != want { - t.Errorf("GetSelfLink() = %s, want %s", got, want) - } -} - -func TestUnstructuredListSetters(t *testing.T) { - unstruct := runtime.UnstructuredList{} - - want := runtime.UnstructuredList{ - Object: map[string]interface{}{ - "kind": "test_kind", - "apiVersion": "test_version", - "metadata": map[string]interface{}{ - "resourceVersion": "test_resourceVersion", - "selfLink": "test_selfLink", - }, - }, - } - - unstruct.SetAPIVersion("test_version") - unstruct.SetKind("test_kind") - unstruct.SetResourceVersion("test_resourceVersion") - unstruct.SetSelfLink("test_selfLink") - - if !reflect.DeepEqual(unstruct, want) { - t.Errorf("Wanted: \n%s\n Got:\n%s", unstruct, want) - } -} - -func TestDecodeNumbers(t *testing.T) { - - // Start with a valid pod - originalJSON := []byte(`{ - "kind":"Pod", - "apiVersion":"v1", - "metadata":{"name":"pod","namespace":"foo"}, - "spec":{ - "containers":[{"name":"container","image":"container"}], - "activeDeadlineSeconds":1000030003 - } - }`) - - pod := &api.Pod{} - - // Decode with structured codec - codec, err := testapi.GetCodecForObject(pod) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - err = runtime.DecodeInto(codec, originalJSON, pod) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - // ensure pod is valid - if errs := validation.ValidatePod(pod); len(errs) > 0 { - t.Fatalf("pod should be valid: %v", errs) - } - - // Round-trip with unstructured codec - unstructuredObj, err := runtime.Decode(runtime.UnstructuredJSONScheme, originalJSON) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - roundtripJSON, err := runtime.Encode(runtime.UnstructuredJSONScheme, unstructuredObj) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // Make sure we serialize back out in int form - if !strings.Contains(string(roundtripJSON), `"activeDeadlineSeconds":1000030003`) { - t.Errorf("Expected %s, got %s", `"activeDeadlineSeconds":1000030003`, string(roundtripJSON)) - } - - // Decode with structured codec again - obj2, err := runtime.Decode(codec, roundtripJSON) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - // ensure pod is still valid - pod2, ok := obj2.(*api.Pod) - if !ok { - t.Fatalf("expected an *api.Pod, got %#v", obj2) - } - if errs := validation.ValidatePod(pod2); len(errs) > 0 { - t.Fatalf("pod should be valid: %v", errs) - } - // ensure round-trip preserved large integers - if !reflect.DeepEqual(pod, pod2) { - t.Fatalf("Expected\n\t%#v, got \n\t%#v", pod, pod2) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/unversioned_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/unversioned_test.go deleted file mode 100644 index 7943581ea..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/unversioned_test.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 runtime_test - -import ( - "encoding/json" - "reflect" - "testing" - - // TODO: Ideally we should create the necessary package structure in e.g., - // pkg/conversion/test/... instead of importing pkg/api here. - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/runtime" -) - -var status = &unversioned.Status{ - Status: unversioned.StatusFailure, - Code: 200, - Reason: unversioned.StatusReasonUnknown, - Message: "", -} - -func TestV1EncodeDecodeStatus(t *testing.T) { - - v1Codec := testapi.Default.Codec() - - encoded, err := runtime.Encode(v1Codec, status) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - typeMeta := unversioned.TypeMeta{} - if err := json.Unmarshal(encoded, &typeMeta); err != nil { - t.Errorf("unexpected error: %v", err) - } - if typeMeta.Kind != "Status" { - t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) - } - if typeMeta.APIVersion != "v1" { - t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) - } - decoded, err := runtime.Decode(v1Codec, encoded) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(status, decoded) { - t.Errorf("expected: %v, got: %v", status, decoded) - } -} - -func TestExperimentalEncodeDecodeStatus(t *testing.T) { - // TODO: caesarxuchao: use the testapi.Extensions.Codec() once the PR that - // moves experimental from v1 to v1beta1 got merged. - expCodec := api.Codecs.LegacyCodec(extensions.SchemeGroupVersion) - encoded, err := runtime.Encode(expCodec, status) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - typeMeta := unversioned.TypeMeta{} - if err := json.Unmarshal(encoded, &typeMeta); err != nil { - t.Errorf("unexpected error: %v", err) - } - if typeMeta.Kind != "Status" { - t.Errorf("Kind is not set to \"Status\". Got %s", encoded) - } - if typeMeta.APIVersion != "v1" { - t.Errorf("APIVersion is not set to \"\". Got %s", encoded) - } - decoded, err := runtime.Decode(expCodec, encoded) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if !reflect.DeepEqual(status, decoded) { - t.Errorf("expected: %v, got: %v", status, decoded) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/cacher_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/cacher_test.go deleted file mode 100644 index 67d8b4e05..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/cacher_test.go +++ /dev/null @@ -1,396 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 storage_test - -import ( - "fmt" - "reflect" - goruntime "runtime" - "strconv" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/labels" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - etcdstorage "k8s.io/kubernetes/pkg/storage/etcd" - "k8s.io/kubernetes/pkg/storage/etcd/etcdtest" - etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" - - "golang.org/x/net/context" -) - -func newEtcdTestStorage(t *testing.T, codec runtime.Codec, prefix string) (*etcdtesting.EtcdTestServer, storage.Interface) { - server := etcdtesting.NewEtcdTestClientServer(t) - storage := etcdstorage.NewEtcdStorage(server.Client, codec, prefix, false, etcdtest.DeserializationCacheSize) - return server, storage -} - -func newTestCacher(s storage.Interface) *storage.Cacher { - prefix := "pods" - config := storage.CacherConfig{ - CacheCapacity: 10, - Storage: s, - Versioner: etcdstorage.APIObjectVersioner{}, - Type: &api.Pod{}, - ResourcePrefix: prefix, - KeyFunc: func(obj runtime.Object) (string, error) { return storage.NamespaceKeyFunc(prefix, obj) }, - NewListFunc: func() runtime.Object { return &api.PodList{} }, - } - return storage.NewCacherFromConfig(config) -} - -func makeTestPod(name string) *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{Namespace: "ns", Name: name}, - Spec: apitesting.DeepEqualSafePodSpec(), - } -} - -func updatePod(t *testing.T, s storage.Interface, obj, old *api.Pod) *api.Pod { - updateFn := func(input runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) { - newObj, err := api.Scheme.DeepCopy(obj) - if err != nil { - t.Errorf("unexpected error: %v", err) - return nil, nil, err - } - return newObj.(*api.Pod), nil, nil - } - key := etcdtest.AddPrefix("pods/ns/" + obj.Name) - if err := s.GuaranteedUpdate(context.TODO(), key, &api.Pod{}, old == nil, nil, updateFn); err != nil { - t.Errorf("unexpected error: %v", err) - } - obj.ResourceVersion = "" - result := &api.Pod{} - if err := s.Get(context.TODO(), key, result, false); err != nil { - t.Errorf("unexpected error: %v", err) - } - return result -} - -func TestList(t *testing.T) { - server, etcdStorage := newEtcdTestStorage(t, testapi.Default.Codec(), etcdtest.PathPrefix()) - defer server.Terminate(t) - cacher := newTestCacher(etcdStorage) - defer cacher.Stop() - - podFoo := makeTestPod("foo") - podBar := makeTestPod("bar") - podBaz := makeTestPod("baz") - - podFooPrime := makeTestPod("foo") - podFooPrime.Spec.NodeName = "fakeNode" - - fooCreated := updatePod(t, etcdStorage, podFoo, nil) - _ = updatePod(t, etcdStorage, podBar, nil) - _ = updatePod(t, etcdStorage, podBaz, nil) - - _ = updatePod(t, etcdStorage, podFooPrime, fooCreated) - - deleted := api.Pod{} - if err := etcdStorage.Delete(context.TODO(), etcdtest.AddPrefix("pods/ns/bar"), &deleted, nil); err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // We first List directly from etcd by passing empty resourceVersion, - // to get the current etcd resourceVersion. - rvResult := &api.PodList{} - if err := cacher.List(context.TODO(), "pods/ns", "", storage.Everything, rvResult); err != nil { - t.Errorf("Unexpected error: %v", err) - } - deletedPodRV := rvResult.ListMeta.ResourceVersion - - result := &api.PodList{} - // We pass the current etcd ResourceVersion received from the above List() operation, - // since there is not easy way to get ResourceVersion of barPod deletion operation. - if err := cacher.List(context.TODO(), "pods/ns", deletedPodRV, storage.Everything, result); err != nil { - t.Errorf("Unexpected error: %v", err) - } - if result.ListMeta.ResourceVersion != deletedPodRV { - t.Errorf("Incorrect resource version: %v", result.ListMeta.ResourceVersion) - } - if len(result.Items) != 2 { - t.Errorf("Unexpected list result: %d", len(result.Items)) - } - keys := sets.String{} - for _, item := range result.Items { - keys.Insert(item.Name) - } - if !keys.HasAll("foo", "baz") { - t.Errorf("Unexpected list result: %#v", result) - } - for _, item := range result.Items { - // unset fields that are set by the infrastructure - item.ResourceVersion = "" - item.CreationTimestamp = unversioned.Time{} - - var expected *api.Pod - switch item.Name { - case "foo": - expected = podFooPrime - case "baz": - expected = podBaz - default: - t.Errorf("Unexpected item: %v", item) - } - if e, a := *expected, item; !reflect.DeepEqual(e, a) { - t.Errorf("Expected: %#v, got: %#v", e, a) - } - } -} - -func verifyWatchEvent(t *testing.T, w watch.Interface, eventType watch.EventType, eventObject runtime.Object) { - _, _, line, _ := goruntime.Caller(1) - select { - case event := <-w.ResultChan(): - if e, a := eventType, event.Type; e != a { - t.Logf("(called from line %d)", line) - t.Errorf("Expected: %s, got: %s", eventType, event.Type) - } - if e, a := eventObject, event.Object; !api.Semantic.DeepDerivative(e, a) { - t.Logf("(called from line %d)", line) - t.Errorf("Expected (%s): %#v, got: %#v", eventType, e, a) - } - case <-time.After(wait.ForeverTestTimeout): - t.Logf("(called from line %d)", line) - t.Errorf("Timed out waiting for an event") - } -} - -type injectListError struct { - errors int - storage.Interface -} - -func (self *injectListError) List(ctx context.Context, key string, resourceVersion string, filter storage.FilterFunc, listObj runtime.Object) error { - if self.errors > 0 { - self.errors-- - return fmt.Errorf("injected error") - } - return self.Interface.List(ctx, key, resourceVersion, filter, listObj) -} - -func TestWatch(t *testing.T) { - server, etcdStorage := newEtcdTestStorage(t, testapi.Default.Codec(), etcdtest.PathPrefix()) - // Inject one list error to make sure we test the relist case. - etcdStorage = &injectListError{errors: 1, Interface: etcdStorage} - defer server.Terminate(t) - cacher := newTestCacher(etcdStorage) - defer cacher.Stop() - - podFoo := makeTestPod("foo") - podBar := makeTestPod("bar") - - podFooPrime := makeTestPod("foo") - podFooPrime.Spec.NodeName = "fakeNode" - - podFooBis := makeTestPod("foo") - podFooBis.Spec.NodeName = "anotherFakeNode" - - // initialVersion is used to initate the watcher at the beginning of the world, - // which is not defined precisely in etcd. - initialVersion, err := cacher.LastSyncResourceVersion() - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - startVersion := strconv.Itoa(int(initialVersion)) - - // Set up Watch for object "podFoo". - watcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", startVersion, storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watcher.Stop() - - fooCreated := updatePod(t, etcdStorage, podFoo, nil) - _ = updatePod(t, etcdStorage, podBar, nil) - fooUpdated := updatePod(t, etcdStorage, podFooPrime, fooCreated) - - verifyWatchEvent(t, watcher, watch.Added, podFoo) - verifyWatchEvent(t, watcher, watch.Modified, podFooPrime) - - // Check whether we get too-old error. - _, err = cacher.Watch(context.TODO(), "pods/ns/foo", "1", storage.Everything) - if err == nil { - t.Errorf("Expected 'error too old' error") - } - - initialWatcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", fooCreated.ResourceVersion, storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer initialWatcher.Stop() - - verifyWatchEvent(t, initialWatcher, watch.Modified, podFooPrime) - - // Now test watch from "now". - nowWatcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer nowWatcher.Stop() - - verifyWatchEvent(t, nowWatcher, watch.Added, podFooPrime) - - _ = updatePod(t, etcdStorage, podFooBis, fooUpdated) - - verifyWatchEvent(t, nowWatcher, watch.Modified, podFooBis) -} - -func TestWatcherTimeout(t *testing.T) { - server, etcdStorage := newEtcdTestStorage(t, testapi.Default.Codec(), etcdtest.PathPrefix()) - defer server.Terminate(t) - cacher := newTestCacher(etcdStorage) - defer cacher.Stop() - - // initialVersion is used to initate the watcher at the beginning of the world, - // which is not defined precisely in etcd. - initialVersion, err := cacher.LastSyncResourceVersion() - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - startVersion := strconv.Itoa(int(initialVersion)) - - // Create a watcher that will not be reading any result. - watcher, err := cacher.WatchList(context.TODO(), "pods/ns", startVersion, storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watcher.Stop() - - // Create a second watcher that will be reading result. - readingWatcher, err := cacher.WatchList(context.TODO(), "pods/ns", startVersion, storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer readingWatcher.Stop() - - for i := 1; i <= 22; i++ { - pod := makeTestPod(strconv.Itoa(i)) - _ = updatePod(t, etcdStorage, pod, nil) - verifyWatchEvent(t, readingWatcher, watch.Added, pod) - } -} - -func TestFiltering(t *testing.T) { - server, etcdStorage := newEtcdTestStorage(t, testapi.Default.Codec(), etcdtest.PathPrefix()) - defer server.Terminate(t) - cacher := newTestCacher(etcdStorage) - defer cacher.Stop() - - // Ensure that the cacher is initialized, before creating any pods, - // so that we are sure that all events will be present in cacher. - syncWatcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - syncWatcher.Stop() - - podFoo := makeTestPod("foo") - podFoo.Labels = map[string]string{"filter": "foo"} - podFooFiltered := makeTestPod("foo") - podFooPrime := makeTestPod("foo") - podFooPrime.Labels = map[string]string{"filter": "foo"} - podFooPrime.Spec.NodeName = "fakeNode" - - fooCreated := updatePod(t, etcdStorage, podFoo, nil) - fooFiltered := updatePod(t, etcdStorage, podFooFiltered, fooCreated) - fooUnfiltered := updatePod(t, etcdStorage, podFoo, fooFiltered) - _ = updatePod(t, etcdStorage, podFooPrime, fooUnfiltered) - - deleted := api.Pod{} - if err := etcdStorage.Delete(context.TODO(), etcdtest.AddPrefix("pods/ns/foo"), &deleted, nil); err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // Set up Watch for object "podFoo" with label filter set. - selector := labels.SelectorFromSet(labels.Set{"filter": "foo"}) - filter := func(obj runtime.Object) bool { - metadata, err := meta.Accessor(obj) - if err != nil { - t.Errorf("Unexpected error: %v", err) - return false - } - return selector.Matches(labels.Set(metadata.GetLabels())) - } - watcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", fooCreated.ResourceVersion, filter) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watcher.Stop() - - verifyWatchEvent(t, watcher, watch.Deleted, podFooFiltered) - verifyWatchEvent(t, watcher, watch.Added, podFoo) - verifyWatchEvent(t, watcher, watch.Modified, podFooPrime) - verifyWatchEvent(t, watcher, watch.Deleted, podFooPrime) -} - -func TestStartingResourceVersion(t *testing.T) { - server, etcdStorage := newEtcdTestStorage(t, testapi.Default.Codec(), etcdtest.PathPrefix()) - defer server.Terminate(t) - cacher := newTestCacher(etcdStorage) - defer cacher.Stop() - - // add 1 object - podFoo := makeTestPod("foo") - fooCreated := updatePod(t, etcdStorage, podFoo, nil) - - // Set up Watch starting at fooCreated.ResourceVersion + 10 - rv, err := storage.ParseWatchResourceVersion(fooCreated.ResourceVersion) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - rv += 10 - startVersion := strconv.Itoa(int(rv)) - - watcher, err := cacher.Watch(context.TODO(), "pods/ns/foo", startVersion, storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watcher.Stop() - - lastFoo := fooCreated - for i := 0; i < 11; i++ { - podFooForUpdate := makeTestPod("foo") - podFooForUpdate.Labels = map[string]string{"foo": strconv.Itoa(i)} - lastFoo = updatePod(t, etcdStorage, podFooForUpdate, lastFoo) - } - - select { - case e := <-watcher.ResultChan(): - pod := e.Object.(*api.Pod) - podRV, err := storage.ParseWatchResourceVersion(pod.ResourceVersion) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - // event should have at least rv + 1, since we're starting the watch at rv - if podRV <= rv { - t.Errorf("expected event with resourceVersion of at least %d, got %d", rv+1, podRV) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("timed out waiting for event") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/api_object_versioner.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/api_object_versioner.go deleted file mode 100644 index 94cdd3595..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/api_object_versioner.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd - -import ( - "strconv" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" -) - -// APIObjectVersioner implements versioning and extracting etcd node information -// for objects that have an embedded ObjectMeta or ListMeta field. -type APIObjectVersioner struct{} - -// UpdateObject implements Versioner -func (a APIObjectVersioner) UpdateObject(obj runtime.Object, resourceVersion uint64) error { - accessor, err := meta.Accessor(obj) - if err != nil { - return err - } - versionString := "" - if resourceVersion != 0 { - versionString = strconv.FormatUint(resourceVersion, 10) - } - accessor.SetResourceVersion(versionString) - return nil -} - -// UpdateList implements Versioner -func (a APIObjectVersioner) UpdateList(obj runtime.Object, resourceVersion uint64) error { - listMeta, err := api.ListMetaFor(obj) - if err != nil || listMeta == nil { - return err - } - versionString := "" - if resourceVersion != 0 { - versionString = strconv.FormatUint(resourceVersion, 10) - } - listMeta.ResourceVersion = versionString - return nil -} - -// ObjectResourceVersion implements Versioner -func (a APIObjectVersioner) ObjectResourceVersion(obj runtime.Object) (uint64, error) { - accessor, err := meta.Accessor(obj) - if err != nil { - return 0, err - } - version := accessor.GetResourceVersion() - if len(version) == 0 { - return 0, nil - } - return strconv.ParseUint(version, 10, 64) -} - -// APIObjectVersioner implements Versioner -var _ storage.Versioner = APIObjectVersioner{} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/api_object_versioner_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/api_object_versioner_test.go deleted file mode 100644 index 3a32fd949..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/api_object_versioner_test.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd - -import ( - "testing" - - "k8s.io/kubernetes/pkg/api" - storagetesting "k8s.io/kubernetes/pkg/storage/testing" -) - -func TestObjectVersioner(t *testing.T) { - v := APIObjectVersioner{} - if ver, err := v.ObjectResourceVersion(&storagetesting.TestResource{ObjectMeta: api.ObjectMeta{ResourceVersion: "5"}}); err != nil || ver != 5 { - t.Errorf("unexpected version: %d %v", ver, err) - } - if ver, err := v.ObjectResourceVersion(&storagetesting.TestResource{ObjectMeta: api.ObjectMeta{ResourceVersion: "a"}}); err == nil || ver != 0 { - t.Errorf("unexpected version: %d %v", ver, err) - } - obj := &storagetesting.TestResource{ObjectMeta: api.ObjectMeta{ResourceVersion: "a"}} - if err := v.UpdateObject(obj, 5); err != nil { - t.Fatalf("unexpected error: %v", err) - } - if obj.ResourceVersion != "5" || obj.DeletionTimestamp != nil { - t.Errorf("unexpected resource version: %#v", obj) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_helper.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_helper.go deleted file mode 100644 index 42f2bc83c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_helper.go +++ /dev/null @@ -1,638 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd - -import ( - "errors" - "fmt" - "path" - "reflect" - "strings" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/storage/etcd/metrics" - etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util" - "k8s.io/kubernetes/pkg/util" - utilcache "k8s.io/kubernetes/pkg/util/cache" - "k8s.io/kubernetes/pkg/watch" - - etcd "github.com/coreos/etcd/client" - "github.com/golang/glog" - "golang.org/x/net/context" -) - -// Creates a new storage interface from the client -// TODO: deprecate in favor of storage.Config abstraction over time -func NewEtcdStorage(client etcd.Client, codec runtime.Codec, prefix string, quorum bool, cacheSize int) storage.Interface { - return &etcdHelper{ - etcdMembersAPI: etcd.NewMembersAPI(client), - etcdKeysAPI: etcd.NewKeysAPI(client), - codec: codec, - versioner: APIObjectVersioner{}, - copier: api.Scheme, - pathPrefix: path.Join("/", prefix), - quorum: quorum, - cache: utilcache.NewCache(cacheSize), - } -} - -// etcdHelper is the reference implementation of storage.Interface. -type etcdHelper struct { - etcdMembersAPI etcd.MembersAPI - etcdKeysAPI etcd.KeysAPI - codec runtime.Codec - copier runtime.ObjectCopier - // Note that versioner is required for etcdHelper to work correctly. - // The public constructors (NewStorage & NewEtcdStorage) are setting it - // correctly, so be careful when manipulating with it manually. - // optional, has to be set to perform any atomic operations - versioner storage.Versioner - // prefix for all etcd keys - pathPrefix string - // if true, perform quorum read - quorum bool - - // We cache objects stored in etcd. For keys we use Node.ModifiedIndex which is equivalent - // to resourceVersion. - // This depends on etcd's indexes being globally unique across all objects/types. This will - // have to revisited if we decide to do things like multiple etcd clusters, or etcd will - // support multi-object transaction that will result in many objects with the same index. - // Number of entries stored in the cache is controlled by maxEtcdCacheEntries constant. - // TODO: Measure how much this cache helps after the conversion code is optimized. - cache utilcache.Cache -} - -func init() { - metrics.Register() -} - -// Codec provides access to the underlying codec being used by the implementation. -func (h *etcdHelper) Codec() runtime.Codec { - return h.codec -} - -// Implements storage.Interface. -func (h *etcdHelper) Backends(ctx context.Context) []string { - if ctx == nil { - glog.Errorf("Context is nil") - } - members, err := h.etcdMembersAPI.List(ctx) - if err != nil { - glog.Errorf("Error obtaining etcd members list: %q", err) - return nil - } - mlist := []string{} - for _, member := range members { - mlist = append(mlist, member.ClientURLs...) - } - return mlist -} - -// Implements storage.Interface. -func (h *etcdHelper) Versioner() storage.Versioner { - return h.versioner -} - -// Implements storage.Interface. -func (h *etcdHelper) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64) error { - trace := util.NewTrace("etcdHelper::Create " + getTypeName(obj)) - defer trace.LogIfLong(250 * time.Millisecond) - if ctx == nil { - glog.Errorf("Context is nil") - } - key = h.prefixEtcdKey(key) - data, err := runtime.Encode(h.codec, obj) - trace.Step("Object encoded") - if err != nil { - return err - } - if version, err := h.versioner.ObjectResourceVersion(obj); err == nil && version != 0 { - return errors.New("resourceVersion may not be set on objects to be created") - } - trace.Step("Version checked") - - startTime := time.Now() - opts := etcd.SetOptions{ - TTL: time.Duration(ttl) * time.Second, - PrevExist: etcd.PrevNoExist, - } - response, err := h.etcdKeysAPI.Set(ctx, key, string(data), &opts) - metrics.RecordEtcdRequestLatency("create", getTypeName(obj), startTime) - trace.Step("Object created") - if err != nil { - return toStorageErr(err, key, 0) - } - if out != nil { - if _, err := conversion.EnforcePtr(out); err != nil { - panic("unable to convert output object to pointer") - } - _, _, err = h.extractObj(response, err, out, false, false) - } - return err -} - -func checkPreconditions(preconditions *storage.Preconditions, out runtime.Object) error { - if preconditions == nil { - return nil - } - objMeta, err := api.ObjectMetaFor(out) - if err != nil { - return storage.NewInternalErrorf("can't enforce preconditions %v on un-introspectable object %v, got error: %v", *preconditions, out, err) - } - if preconditions.UID != nil && *preconditions.UID != objMeta.UID { - return etcd.Error{Code: etcd.ErrorCodeTestFailed, Message: fmt.Sprintf("the UID in the precondition (%s) does not match the UID in record (%s). The object might have been deleted and then recreated", *preconditions.UID, objMeta.UID)} - } - return nil -} - -// Implements storage.Interface. -func (h *etcdHelper) Delete(ctx context.Context, key string, out runtime.Object, preconditions *storage.Preconditions) error { - if ctx == nil { - glog.Errorf("Context is nil") - } - key = h.prefixEtcdKey(key) - v, err := conversion.EnforcePtr(out) - if err != nil { - panic("unable to convert output object to pointer") - } - - if preconditions == nil { - startTime := time.Now() - response, err := h.etcdKeysAPI.Delete(ctx, key, nil) - metrics.RecordEtcdRequestLatency("delete", getTypeName(out), startTime) - if !etcdutil.IsEtcdNotFound(err) { - // if the object that existed prior to the delete is returned by etcd, update the out object. - if err != nil || response.PrevNode != nil { - _, _, err = h.extractObj(response, err, out, false, true) - } - } - return toStorageErr(err, key, 0) - } - - // Check the preconditions match. - obj := reflect.New(v.Type()).Interface().(runtime.Object) - for { - _, node, res, err := h.bodyAndExtractObj(ctx, key, obj, false) - if err != nil { - return toStorageErr(err, key, 0) - } - if err := checkPreconditions(preconditions, obj); err != nil { - return toStorageErr(err, key, 0) - } - index := uint64(0) - if node != nil { - index = node.ModifiedIndex - } else if res != nil { - index = res.Index - } - opt := etcd.DeleteOptions{PrevIndex: index} - startTime := time.Now() - response, err := h.etcdKeysAPI.Delete(ctx, key, &opt) - metrics.RecordEtcdRequestLatency("delete", getTypeName(out), startTime) - if etcdutil.IsEtcdTestFailed(err) { - glog.Infof("deletion of %s failed because of a conflict, going to retry", key) - } else { - if !etcdutil.IsEtcdNotFound(err) { - // if the object that existed prior to the delete is returned by etcd, update the out object. - if err != nil || response.PrevNode != nil { - _, _, err = h.extractObj(response, err, out, false, true) - } - } - return toStorageErr(err, key, 0) - } - } -} - -// Implements storage.Interface. -func (h *etcdHelper) Watch(ctx context.Context, key string, resourceVersion string, filter storage.FilterFunc) (watch.Interface, error) { - if ctx == nil { - glog.Errorf("Context is nil") - } - watchRV, err := storage.ParseWatchResourceVersion(resourceVersion) - if err != nil { - return nil, err - } - key = h.prefixEtcdKey(key) - w := newEtcdWatcher(false, h.quorum, nil, filter, h.codec, h.versioner, nil, h) - go w.etcdWatch(ctx, h.etcdKeysAPI, key, watchRV) - return w, nil -} - -// Implements storage.Interface. -func (h *etcdHelper) WatchList(ctx context.Context, key string, resourceVersion string, filter storage.FilterFunc) (watch.Interface, error) { - if ctx == nil { - glog.Errorf("Context is nil") - } - watchRV, err := storage.ParseWatchResourceVersion(resourceVersion) - if err != nil { - return nil, err - } - key = h.prefixEtcdKey(key) - w := newEtcdWatcher(true, h.quorum, exceptKey(key), filter, h.codec, h.versioner, nil, h) - go w.etcdWatch(ctx, h.etcdKeysAPI, key, watchRV) - return w, nil -} - -// Implements storage.Interface. -func (h *etcdHelper) Get(ctx context.Context, key string, objPtr runtime.Object, ignoreNotFound bool) error { - if ctx == nil { - glog.Errorf("Context is nil") - } - key = h.prefixEtcdKey(key) - _, _, _, err := h.bodyAndExtractObj(ctx, key, objPtr, ignoreNotFound) - return err -} - -// bodyAndExtractObj performs the normal Get path to etcd, returning the parsed node and response for additional information -// about the response, like the current etcd index and the ttl. -func (h *etcdHelper) bodyAndExtractObj(ctx context.Context, key string, objPtr runtime.Object, ignoreNotFound bool) (body string, node *etcd.Node, res *etcd.Response, err error) { - if ctx == nil { - glog.Errorf("Context is nil") - } - startTime := time.Now() - - opts := &etcd.GetOptions{ - Quorum: h.quorum, - } - - response, err := h.etcdKeysAPI.Get(ctx, key, opts) - metrics.RecordEtcdRequestLatency("get", getTypeName(objPtr), startTime) - if err != nil && !etcdutil.IsEtcdNotFound(err) { - return "", nil, nil, toStorageErr(err, key, 0) - } - body, node, err = h.extractObj(response, err, objPtr, ignoreNotFound, false) - return body, node, response, toStorageErr(err, key, 0) -} - -func (h *etcdHelper) extractObj(response *etcd.Response, inErr error, objPtr runtime.Object, ignoreNotFound, prevNode bool) (body string, node *etcd.Node, err error) { - if response != nil { - if prevNode { - node = response.PrevNode - } else { - node = response.Node - } - } - if inErr != nil || node == nil || len(node.Value) == 0 { - if ignoreNotFound { - v, err := conversion.EnforcePtr(objPtr) - if err != nil { - return "", nil, err - } - v.Set(reflect.Zero(v.Type())) - return "", nil, nil - } else if inErr != nil { - return "", nil, inErr - } - return "", nil, fmt.Errorf("unable to locate a value on the response: %#v", response) - } - body = node.Value - out, gvk, err := h.codec.Decode([]byte(body), nil, objPtr) - if err != nil { - return body, nil, err - } - if out != objPtr { - return body, nil, fmt.Errorf("unable to decode object %s into %v", gvk.String(), reflect.TypeOf(objPtr)) - } - // being unable to set the version does not prevent the object from being extracted - _ = h.versioner.UpdateObject(objPtr, node.ModifiedIndex) - return body, node, err -} - -// Implements storage.Interface. -func (h *etcdHelper) GetToList(ctx context.Context, key string, filter storage.FilterFunc, listObj runtime.Object) error { - if ctx == nil { - glog.Errorf("Context is nil") - } - trace := util.NewTrace("GetToList " + getTypeName(listObj)) - listPtr, err := meta.GetItemsPtr(listObj) - if err != nil { - return err - } - key = h.prefixEtcdKey(key) - startTime := time.Now() - trace.Step("About to read etcd node") - - opts := &etcd.GetOptions{ - Quorum: h.quorum, - } - response, err := h.etcdKeysAPI.Get(ctx, key, opts) - - metrics.RecordEtcdRequestLatency("get", getTypeName(listPtr), startTime) - trace.Step("Etcd node read") - if err != nil { - if etcdutil.IsEtcdNotFound(err) { - return nil - } - return toStorageErr(err, key, 0) - } - - nodes := make([]*etcd.Node, 0) - nodes = append(nodes, response.Node) - - if err := h.decodeNodeList(nodes, filter, listPtr); err != nil { - return err - } - trace.Step("Object decoded") - if err := h.versioner.UpdateList(listObj, response.Index); err != nil { - return err - } - return nil -} - -// decodeNodeList walks the tree of each node in the list and decodes into the specified object -func (h *etcdHelper) decodeNodeList(nodes []*etcd.Node, filter storage.FilterFunc, slicePtr interface{}) error { - trace := util.NewTrace("decodeNodeList " + getTypeName(slicePtr)) - defer trace.LogIfLong(500 * time.Millisecond) - v, err := conversion.EnforcePtr(slicePtr) - if err != nil || v.Kind() != reflect.Slice { - // This should not happen at runtime. - panic("need ptr to slice") - } - for _, node := range nodes { - if node.Dir { - trace.Step("Decoding dir " + node.Key + " START") - if err := h.decodeNodeList(node.Nodes, filter, slicePtr); err != nil { - return err - } - trace.Step("Decoding dir " + node.Key + " END") - continue - } - if obj, found := h.getFromCache(node.ModifiedIndex, filter); found { - // obj != nil iff it matches the filter function. - if obj != nil { - v.Set(reflect.Append(v, reflect.ValueOf(obj).Elem())) - } - } else { - obj, _, err := h.codec.Decode([]byte(node.Value), nil, reflect.New(v.Type().Elem()).Interface().(runtime.Object)) - if err != nil { - return err - } - // being unable to set the version does not prevent the object from being extracted - _ = h.versioner.UpdateObject(obj, node.ModifiedIndex) - if filter(obj) { - v.Set(reflect.Append(v, reflect.ValueOf(obj).Elem())) - } - if node.ModifiedIndex != 0 { - h.addToCache(node.ModifiedIndex, obj) - } - } - } - trace.Step(fmt.Sprintf("Decoded %v nodes", len(nodes))) - return nil -} - -// Implements storage.Interface. -func (h *etcdHelper) List(ctx context.Context, key string, resourceVersion string, filter storage.FilterFunc, listObj runtime.Object) error { - if ctx == nil { - glog.Errorf("Context is nil") - } - trace := util.NewTrace("List " + getTypeName(listObj)) - defer trace.LogIfLong(time.Second) - listPtr, err := meta.GetItemsPtr(listObj) - if err != nil { - return err - } - key = h.prefixEtcdKey(key) - startTime := time.Now() - trace.Step("About to list etcd node") - nodes, index, err := h.listEtcdNode(ctx, key) - metrics.RecordEtcdRequestLatency("list", getTypeName(listPtr), startTime) - trace.Step("Etcd node listed") - if err != nil { - return err - } - if err := h.decodeNodeList(nodes, filter, listPtr); err != nil { - return err - } - trace.Step("Node list decoded") - if err := h.versioner.UpdateList(listObj, index); err != nil { - return err - } - return nil -} - -func (h *etcdHelper) listEtcdNode(ctx context.Context, key string) ([]*etcd.Node, uint64, error) { - if ctx == nil { - glog.Errorf("Context is nil") - } - opts := etcd.GetOptions{ - Recursive: true, - Sort: true, - Quorum: h.quorum, - } - result, err := h.etcdKeysAPI.Get(ctx, key, &opts) - if err != nil { - var index uint64 - if etcdError, ok := err.(etcd.Error); ok { - index = etcdError.Index - } - nodes := make([]*etcd.Node, 0) - if etcdutil.IsEtcdNotFound(err) { - return nodes, index, nil - } else { - return nodes, index, toStorageErr(err, key, 0) - } - } - return result.Node.Nodes, result.Index, nil -} - -// Implements storage.Interface. -func (h *etcdHelper) GuaranteedUpdate(ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool, preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc) error { - if ctx == nil { - glog.Errorf("Context is nil") - } - v, err := conversion.EnforcePtr(ptrToType) - if err != nil { - // Panic is appropriate, because this is a programming error. - panic("need ptr to type") - } - key = h.prefixEtcdKey(key) - for { - obj := reflect.New(v.Type()).Interface().(runtime.Object) - origBody, node, res, err := h.bodyAndExtractObj(ctx, key, obj, ignoreNotFound) - if err != nil { - return toStorageErr(err, key, 0) - } - if err := checkPreconditions(preconditions, obj); err != nil { - return toStorageErr(err, key, 0) - } - meta := storage.ResponseMeta{} - if node != nil { - meta.TTL = node.TTL - meta.ResourceVersion = node.ModifiedIndex - } - // Get the object to be written by calling tryUpdate. - ret, newTTL, err := tryUpdate(obj, meta) - if err != nil { - return toStorageErr(err, key, 0) - } - - index := uint64(0) - ttl := uint64(0) - if node != nil { - index = node.ModifiedIndex - if node.TTL != 0 { - ttl = uint64(node.TTL) - } - if node.Expiration != nil && ttl == 0 { - ttl = 1 - } - } else if res != nil { - index = res.Index - } - - if newTTL != nil { - if ttl != 0 && *newTTL == 0 { - // TODO: remove this after we have verified this is no longer an issue - glog.V(4).Infof("GuaranteedUpdate is clearing TTL for %q, may not be intentional", key) - } - ttl = *newTTL - } - - // Since update object may have a resourceVersion set, we need to clear it here. - if err := h.versioner.UpdateObject(ret, 0); err != nil { - return errors.New("resourceVersion cannot be set on objects store in etcd") - } - - data, err := runtime.Encode(h.codec, ret) - if err != nil { - return err - } - - // First time this key has been used, try creating new value. - if index == 0 { - startTime := time.Now() - opts := etcd.SetOptions{ - TTL: time.Duration(ttl) * time.Second, - PrevExist: etcd.PrevNoExist, - } - response, err := h.etcdKeysAPI.Set(ctx, key, string(data), &opts) - metrics.RecordEtcdRequestLatency("create", getTypeName(ptrToType), startTime) - if etcdutil.IsEtcdNodeExist(err) { - continue - } - _, _, err = h.extractObj(response, err, ptrToType, false, false) - return toStorageErr(err, key, 0) - } - - if string(data) == origBody { - // If we don't send an update, we simply return the currently existing - // version of the object. - _, _, err := h.extractObj(res, nil, ptrToType, ignoreNotFound, false) - return err - } - - startTime := time.Now() - // Swap origBody with data, if origBody is the latest etcd data. - opts := etcd.SetOptions{ - PrevValue: origBody, - PrevIndex: index, - TTL: time.Duration(ttl) * time.Second, - } - response, err := h.etcdKeysAPI.Set(ctx, key, string(data), &opts) - metrics.RecordEtcdRequestLatency("compareAndSwap", getTypeName(ptrToType), startTime) - if etcdutil.IsEtcdTestFailed(err) { - // Try again. - continue - } - _, _, err = h.extractObj(response, err, ptrToType, false, false) - return toStorageErr(err, key, int64(index)) - } -} - -func (h *etcdHelper) prefixEtcdKey(key string) string { - if strings.HasPrefix(key, h.pathPrefix) { - return key - } - return path.Join(h.pathPrefix, key) -} - -// etcdCache defines interface used for caching objects stored in etcd. Objects are keyed by -// their Node.ModifiedIndex, which is unique across all types. -// All implementations must be thread-safe. -type etcdCache interface { - getFromCache(index uint64, filter storage.FilterFunc) (runtime.Object, bool) - addToCache(index uint64, obj runtime.Object) -} - -func getTypeName(obj interface{}) string { - return reflect.TypeOf(obj).String() -} - -func (h *etcdHelper) getFromCache(index uint64, filter storage.FilterFunc) (runtime.Object, bool) { - startTime := time.Now() - defer func() { - metrics.ObserveGetCache(startTime) - }() - obj, found := h.cache.Get(index) - if found { - if !filter(obj.(runtime.Object)) { - return nil, true - } - // We should not return the object itself to avoid polluting the cache if someone - // modifies returned values. - objCopy, err := h.copier.Copy(obj.(runtime.Object)) - if err != nil { - glog.Errorf("Error during DeepCopy of cached object: %q", err) - // We can't return a copy, thus we report the object as not found. - return nil, false - } - metrics.ObserveCacheHit() - return objCopy.(runtime.Object), true - } - metrics.ObserveCacheMiss() - return nil, false -} - -func (h *etcdHelper) addToCache(index uint64, obj runtime.Object) { - startTime := time.Now() - defer func() { - metrics.ObserveAddCache(startTime) - }() - objCopy, err := h.copier.Copy(obj) - if err != nil { - glog.Errorf("Error during DeepCopy of cached object: %q", err) - return - } - isOverwrite := h.cache.Add(index, objCopy) - if !isOverwrite { - metrics.ObserveNewEntry() - } -} - -func toStorageErr(err error, key string, rv int64) error { - if err == nil { - return nil - } - switch { - case etcdutil.IsEtcdNotFound(err): - return storage.NewKeyNotFoundError(key, rv) - case etcdutil.IsEtcdNodeExist(err): - return storage.NewKeyExistsError(key, rv) - case etcdutil.IsEtcdTestFailed(err): - return storage.NewResourceVersionConflictsError(key, rv) - case etcdutil.IsEtcdUnreachable(err): - return storage.NewUnreachableError(key, rv) - default: - return err - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_helper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_helper_test.go deleted file mode 100644 index a5e7f5753..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_helper_test.go +++ /dev/null @@ -1,562 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd - -import ( - "path" - "reflect" - "sync" - "testing" - "time" - - etcd "github.com/coreos/etcd/client" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - apitesting "k8s.io/kubernetes/pkg/api/testing" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/runtime/serializer" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/storage/etcd/etcdtest" - etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" - storagetesting "k8s.io/kubernetes/pkg/storage/testing" -) - -const validEtcdVersion = "etcd 2.0.9" - -func testScheme(t *testing.T) (*runtime.Scheme, runtime.Codec) { - scheme := runtime.NewScheme() - scheme.Log(t) - scheme.AddKnownTypes(*testapi.Default.GroupVersion(), &storagetesting.TestResource{}) - scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &storagetesting.TestResource{}) - if err := scheme.AddConversionFuncs( - func(in *storagetesting.TestResource, out *storagetesting.TestResource, s conversion.Scope) error { - *out = *in - return nil - }, - func(in, out *time.Time, s conversion.Scope) error { - *out = *in - return nil - }, - ); err != nil { - panic(err) - } - codec := serializer.NewCodecFactory(scheme).LegacyCodec(*testapi.Default.GroupVersion()) - return scheme, codec -} - -func newEtcdHelper(client etcd.Client, codec runtime.Codec, prefix string) etcdHelper { - return *NewEtcdStorage(client, codec, prefix, false, etcdtest.DeserializationCacheSize).(*etcdHelper) -} - -// Returns an encoded version of api.Pod with the given name. -func getEncodedPod(name string) string { - pod, _ := runtime.Encode(testapi.Default.Codec(), &api.Pod{ - ObjectMeta: api.ObjectMeta{Name: name}, - }) - return string(pod) -} - -func createObj(t *testing.T, helper etcdHelper, name string, obj, out runtime.Object, ttl uint64) error { - err := helper.Create(context.TODO(), name, obj, out, ttl) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - return err -} - -func createPodList(t *testing.T, helper etcdHelper, list *api.PodList) error { - for i := range list.Items { - returnedObj := &api.Pod{} - err := createObj(t, helper, list.Items[i].Name, &list.Items[i], returnedObj, 0) - if err != nil { - return err - } - list.Items[i] = *returnedObj - } - return nil -} - -func TestList(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) - - list := api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{Name: "bar"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "baz"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - - createPodList(t, helper, &list) - var got api.PodList - // TODO: a sorted filter function could be applied such implied - // ordering on the returned list doesn't matter. - err := helper.List(context.TODO(), key, "", storage.Everything, &got) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - - if e, a := list.Items, got.Items; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } -} - -func TestListFiltered(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) - - list := api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{Name: "bar"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "baz"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - - createPodList(t, helper, &list) - filter := func(obj runtime.Object) bool { - pod := obj.(*api.Pod) - return pod.Name == "bar" - } - - var got api.PodList - err := helper.List(context.TODO(), key, "", filter, &got) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - // Check to make certain that the filter function only returns "bar" - if e, a := list.Items[0], got.Items[0]; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } -} - -// TestListAcrossDirectories ensures that the client excludes directories and flattens tree-response - simulates cross-namespace query -func TestListAcrossDirectories(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - rootkey := etcdtest.AddPrefix("/some/key") - key1 := etcdtest.AddPrefix("/some/key/directory1") - key2 := etcdtest.AddPrefix("/some/key/directory2") - - roothelper := newEtcdHelper(server.Client, testapi.Default.Codec(), rootkey) - helper1 := newEtcdHelper(server.Client, testapi.Default.Codec(), key1) - helper2 := newEtcdHelper(server.Client, testapi.Default.Codec(), key2) - - list := api.PodList{ - Items: []api.Pod{ - { - ObjectMeta: api.ObjectMeta{Name: "baz"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - { - ObjectMeta: api.ObjectMeta{Name: "bar"}, - Spec: apitesting.DeepEqualSafePodSpec(), - }, - }, - } - - returnedObj := &api.Pod{} - // create the 1st 2 elements in one directory - createObj(t, helper1, list.Items[0].Name, &list.Items[0], returnedObj, 0) - list.Items[0] = *returnedObj - createObj(t, helper1, list.Items[1].Name, &list.Items[1], returnedObj, 0) - list.Items[1] = *returnedObj - // create the last element in the other directory - createObj(t, helper2, list.Items[2].Name, &list.Items[2], returnedObj, 0) - list.Items[2] = *returnedObj - - var got api.PodList - err := roothelper.List(context.TODO(), rootkey, "", storage.Everything, &got) - if err != nil { - t.Errorf("Unexpected error %v", err) - } - if e, a := list.Items, got.Items; !reflect.DeepEqual(e, a) { - t.Errorf("Expected %#v, got %#v", e, a) - } -} - -func TestGet(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) - expect := api.Pod{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Spec: apitesting.DeepEqualSafePodSpec(), - } - var got api.Pod - if err := helper.Create(context.TODO(), key, &expect, &got, 0); err != nil { - t.Errorf("Unexpected error %#v", err) - } - expect = got - if err := helper.Get(context.TODO(), key, &got, false); err != nil { - t.Errorf("Unexpected error %#v", err) - } - if !reflect.DeepEqual(got, expect) { - t.Errorf("Wanted %#v, got %#v", expect, got) - } -} - -func TestGetNotFoundErr(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - boguskey := etcdtest.AddPrefix("/some/boguskey") - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), key) - - var got api.Pod - err := helper.Get(context.TODO(), boguskey, &got, false) - if !storage.IsNotFound(err) { - t.Errorf("Unexpected reponse on key=%v, err=%v", key, err) - } -} - -func TestCreate(t *testing.T) { - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), etcdtest.PathPrefix()) - returnedObj := &api.Pod{} - err := helper.Create(context.TODO(), "/some/key", obj, returnedObj, 5) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - _, err = runtime.Encode(testapi.Default.Codec(), obj) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - err = helper.Get(context.TODO(), "/some/key", returnedObj, false) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - _, err = runtime.Encode(testapi.Default.Codec(), returnedObj) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - if obj.Name != returnedObj.Name { - t.Errorf("Wanted %v, got %v", obj.Name, returnedObj.Name) - } -} - -func TestCreateNilOutParam(t *testing.T) { - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), etcdtest.PathPrefix()) - err := helper.Create(context.TODO(), "/some/key", obj, nil, 5) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } -} - -func TestGuaranteedUpdate(t *testing.T) { - _, codec := testScheme(t) - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - helper := newEtcdHelper(server.Client, codec, key) - - obj := &storagetesting.TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1} - err := helper.GuaranteedUpdate(context.TODO(), key, &storagetesting.TestResource{}, true, nil, storage.SimpleUpdate(func(in runtime.Object) (runtime.Object, error) { - return obj, nil - })) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - - // Update an existing node. - callbackCalled := false - objUpdate := &storagetesting.TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 2} - err = helper.GuaranteedUpdate(context.TODO(), key, &storagetesting.TestResource{}, true, nil, storage.SimpleUpdate(func(in runtime.Object) (runtime.Object, error) { - callbackCalled = true - - if in.(*storagetesting.TestResource).Value != 1 { - t.Errorf("Callback input was not current set value") - } - - return objUpdate, nil - })) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - objCheck := &storagetesting.TestResource{} - err = helper.Get(context.TODO(), key, objCheck, false) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - if objCheck.Value != 2 { - t.Errorf("Value should have been 2 but got %v", objCheck.Value) - } - - if !callbackCalled { - t.Errorf("tryUpdate callback should have been called.") - } -} - -func TestGuaranteedUpdateNoChange(t *testing.T) { - _, codec := testScheme(t) - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - helper := newEtcdHelper(server.Client, codec, key) - - obj := &storagetesting.TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1} - err := helper.GuaranteedUpdate(context.TODO(), key, &storagetesting.TestResource{}, true, nil, storage.SimpleUpdate(func(in runtime.Object) (runtime.Object, error) { - return obj, nil - })) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - - // Update an existing node with the same data - callbackCalled := false - objUpdate := &storagetesting.TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1} - err = helper.GuaranteedUpdate(context.TODO(), key, &storagetesting.TestResource{}, true, nil, storage.SimpleUpdate(func(in runtime.Object) (runtime.Object, error) { - callbackCalled = true - return objUpdate, nil - })) - if err != nil { - t.Fatalf("Unexpected error %#v", err) - } - if !callbackCalled { - t.Errorf("tryUpdate callback should have been called.") - } -} - -func TestGuaranteedUpdateKeyNotFound(t *testing.T) { - _, codec := testScheme(t) - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - helper := newEtcdHelper(server.Client, codec, key) - - // Create a new node. - obj := &storagetesting.TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: 1} - - f := storage.SimpleUpdate(func(in runtime.Object) (runtime.Object, error) { - return obj, nil - }) - - ignoreNotFound := false - err := helper.GuaranteedUpdate(context.TODO(), key, &storagetesting.TestResource{}, ignoreNotFound, nil, f) - if err == nil { - t.Errorf("Expected error for key not found.") - } - - ignoreNotFound = true - err = helper.GuaranteedUpdate(context.TODO(), key, &storagetesting.TestResource{}, ignoreNotFound, nil, f) - if err != nil { - t.Errorf("Unexpected error %v.", err) - } -} - -func TestGuaranteedUpdate_CreateCollision(t *testing.T) { - _, codec := testScheme(t) - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := etcdtest.AddPrefix("/some/key") - helper := newEtcdHelper(server.Client, codec, etcdtest.PathPrefix()) - - const concurrency = 10 - var wgDone sync.WaitGroup - var wgForceCollision sync.WaitGroup - wgDone.Add(concurrency) - wgForceCollision.Add(concurrency) - - for i := 0; i < concurrency; i++ { - // Increment storagetesting.TestResource.Value by 1 - go func() { - defer wgDone.Done() - - firstCall := true - err := helper.GuaranteedUpdate(context.TODO(), key, &storagetesting.TestResource{}, true, nil, storage.SimpleUpdate(func(in runtime.Object) (runtime.Object, error) { - defer func() { firstCall = false }() - - if firstCall { - // Force collision by joining all concurrent GuaranteedUpdate operations here. - wgForceCollision.Done() - wgForceCollision.Wait() - } - - currValue := in.(*storagetesting.TestResource).Value - obj := &storagetesting.TestResource{ObjectMeta: api.ObjectMeta{Name: "foo"}, Value: currValue + 1} - return obj, nil - })) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - }() - } - wgDone.Wait() - - stored := &storagetesting.TestResource{} - err := helper.Get(context.TODO(), key, stored, false) - if err != nil { - t.Errorf("Unexpected error %#v", stored) - } - if stored.Value != concurrency { - t.Errorf("Some of the writes were lost. Stored value: %d", stored.Value) - } -} - -func TestGuaranteedUpdateUIDMismatch(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - prefix := path.Join("/", etcdtest.PathPrefix()) - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), prefix) - - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", UID: "A"}} - podPtr := &api.Pod{} - err := helper.Create(context.TODO(), "/some/key", obj, podPtr, 0) - if err != nil { - t.Fatalf("Unexpected error %#v", err) - } - err = helper.GuaranteedUpdate(context.TODO(), "/some/key", podPtr, true, storage.NewUIDPreconditions("B"), storage.SimpleUpdate(func(in runtime.Object) (runtime.Object, error) { - return obj, nil - })) - if !storage.IsTestFailed(err) { - t.Fatalf("Expect a Test Failed (write conflict) error, got: %v", err) - } -} - -func TestPrefixEtcdKey(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - prefix := path.Join("/", etcdtest.PathPrefix()) - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), prefix) - - baseKey := "/some/key" - - // Verify prefix is added - keyBefore := baseKey - keyAfter := helper.prefixEtcdKey(keyBefore) - - assert.Equal(t, keyAfter, path.Join(prefix, baseKey), "Prefix incorrectly added by EtcdHelper") - - // Verify prefix is not added - keyBefore = path.Join(prefix, baseKey) - keyAfter = helper.prefixEtcdKey(keyBefore) - - assert.Equal(t, keyBefore, keyAfter, "Prefix incorrectly added by EtcdHelper") -} - -func TestDeleteUIDMismatch(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - prefix := path.Join("/", etcdtest.PathPrefix()) - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), prefix) - - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", UID: "A"}} - podPtr := &api.Pod{} - err := helper.Create(context.TODO(), "/some/key", obj, podPtr, 0) - if err != nil { - t.Fatalf("Unexpected error %#v", err) - } - err = helper.Delete(context.TODO(), "/some/key", obj, storage.NewUIDPreconditions("B")) - if !storage.IsTestFailed(err) { - t.Fatalf("Expect a Test Failed (write conflict) error, got: %v", err) - } -} - -type getFunc func(ctx context.Context, key string, opts *etcd.GetOptions) (*etcd.Response, error) - -type fakeDeleteKeysAPI struct { - etcd.KeysAPI - fakeGetFunc getFunc - getCount int - // The fakeGetFunc will be called fakeGetCap times before the KeysAPI's Get will be called. - fakeGetCap int -} - -func (f *fakeDeleteKeysAPI) Get(ctx context.Context, key string, opts *etcd.GetOptions) (*etcd.Response, error) { - f.getCount++ - if f.getCount < f.fakeGetCap { - return f.fakeGetFunc(ctx, key, opts) - } - return f.KeysAPI.Get(ctx, key, opts) -} - -// This is to emulate the case where another party updates the object when -// etcdHelper.Delete has verified the preconditions, but hasn't carried out the -// deletion yet. Etcd will fail the deletion and report the conflict. etcdHelper -// should retry until there is no conflict. -func TestDeleteWithRetry(t *testing.T) { - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - prefix := path.Join("/", etcdtest.PathPrefix()) - - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", UID: "A"}} - // fakeGet returns a large ModifiedIndex to emulate the case that another - // party has updated the object. - fakeGet := func(ctx context.Context, key string, opts *etcd.GetOptions) (*etcd.Response, error) { - data, _ := runtime.Encode(testapi.Default.Codec(), obj) - return &etcd.Response{Node: &etcd.Node{Value: string(data), ModifiedIndex: 99}}, nil - } - expectedRetries := 3 - helper := newEtcdHelper(server.Client, testapi.Default.Codec(), prefix) - fake := &fakeDeleteKeysAPI{KeysAPI: helper.etcdKeysAPI, fakeGetCap: expectedRetries, fakeGetFunc: fakeGet} - helper.etcdKeysAPI = fake - - returnedObj := &api.Pod{} - err := helper.Create(context.TODO(), "/some/key", obj, returnedObj, 0) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - - err = helper.Delete(context.TODO(), "/some/key", obj, storage.NewUIDPreconditions("A")) - if err != nil { - t.Errorf("Unexpected error %#v", err) - } - if fake.getCount != expectedRetries { - t.Errorf("Expect %d retries, got %d", expectedRetries, fake.getCount) - } - err = helper.Get(context.TODO(), "/some/key", obj, false) - if !storage.IsNotFound(err) { - t.Errorf("Expect an NotFound error, got %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_watcher.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_watcher.go deleted file mode 100644 index 93c1f7a9a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_watcher.go +++ /dev/null @@ -1,494 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd - -import ( - "fmt" - "net/http" - "sync" - "sync/atomic" - "time" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util" - utilruntime "k8s.io/kubernetes/pkg/util/runtime" - "k8s.io/kubernetes/pkg/watch" - - etcd "github.com/coreos/etcd/client" - "github.com/golang/glog" - "golang.org/x/net/context" -) - -// Etcd watch event actions -const ( - EtcdCreate = "create" - EtcdGet = "get" - EtcdSet = "set" - EtcdCAS = "compareAndSwap" - EtcdDelete = "delete" - EtcdCAD = "compareAndDelete" - EtcdExpire = "expire" -) - -// HighWaterMark is a thread-safe object for tracking the maximum value seen -// for some quantity. -type HighWaterMark int64 - -// Update returns true if and only if 'current' is the highest value ever seen. -func (hwm *HighWaterMark) Update(current int64) bool { - for { - old := atomic.LoadInt64((*int64)(hwm)) - if current <= old { - return false - } - if atomic.CompareAndSwapInt64((*int64)(hwm), old, current) { - return true - } - } -} - -// TransformFunc attempts to convert an object to another object for use with a watcher. -type TransformFunc func(runtime.Object) (runtime.Object, error) - -// includeFunc returns true if the given key should be considered part of a watch -type includeFunc func(key string) bool - -// exceptKey is an includeFunc that returns false when the provided key matches the watched key -func exceptKey(except string) includeFunc { - return func(key string) bool { - return key != except - } -} - -// etcdWatcher converts a native etcd watch to a watch.Interface. -type etcdWatcher struct { - encoding runtime.Codec - // Note that versioner is required for etcdWatcher to work correctly. - // There is no public constructor of it, so be careful when manipulating - // with it manually. - versioner storage.Versioner - transform TransformFunc - - list bool // If we're doing a recursive watch, should be true. - quorum bool // If we enable quorum, shoule be true - include includeFunc - filter storage.FilterFunc - - etcdIncoming chan *etcd.Response - etcdError chan error - ctx context.Context - cancel context.CancelFunc - etcdCallEnded chan struct{} - - outgoing chan watch.Event - userStop chan struct{} - stopped bool - stopLock sync.Mutex - // wg is used to avoid calls to etcd after Stop(), and to make sure - // that the translate goroutine is not leaked. - wg sync.WaitGroup - - // Injectable for testing. Send the event down the outgoing channel. - emit func(watch.Event) - - cache etcdCache -} - -// watchWaitDuration is the amount of time to wait for an error from watch. -const watchWaitDuration = 100 * time.Millisecond - -// newEtcdWatcher returns a new etcdWatcher; if list is true, watch sub-nodes. -// The versioner must be able to handle the objects that transform creates. -func newEtcdWatcher( - list bool, quorum bool, include includeFunc, filter storage.FilterFunc, - encoding runtime.Codec, versioner storage.Versioner, transform TransformFunc, - cache etcdCache) *etcdWatcher { - w := &etcdWatcher{ - encoding: encoding, - versioner: versioner, - transform: transform, - list: list, - quorum: quorum, - include: include, - filter: filter, - // Buffer this channel, so that the etcd client is not forced - // to context switch with every object it gets, and so that a - // long time spent decoding an object won't block the *next* - // object. Basically, we see a lot of "401 window exceeded" - // errors from etcd, and that's due to the client not streaming - // results but rather getting them one at a time. So we really - // want to never block the etcd client, if possible. The 100 is - // mostly arbitrary--we know it goes as high as 50, though. - // There's a V(2) log message that prints the length so we can - // monitor how much of this buffer is actually used. - etcdIncoming: make(chan *etcd.Response, 100), - etcdError: make(chan error, 1), - outgoing: make(chan watch.Event), - userStop: make(chan struct{}), - stopped: false, - wg: sync.WaitGroup{}, - cache: cache, - ctx: nil, - cancel: nil, - } - w.emit = func(e watch.Event) { - // Give up on user stop, without this we leak a lot of goroutines in tests. - select { - case w.outgoing <- e: - case <-w.userStop: - } - } - // translate will call done. We need to Add() here because otherwise, - // if Stop() gets called before translate gets started, there'd be a - // problem. - w.wg.Add(1) - go w.translate() - return w -} - -// etcdWatch calls etcd's Watch function, and handles any errors. Meant to be called -// as a goroutine. -func (w *etcdWatcher) etcdWatch(ctx context.Context, client etcd.KeysAPI, key string, resourceVersion uint64) { - defer utilruntime.HandleCrash() - defer close(w.etcdError) - defer close(w.etcdIncoming) - - // All calls to etcd are coming from this function - once it is finished - // no other call to etcd should be generated by this watcher. - done := func() {} - - // We need to be prepared, that Stop() can be called at any time. - // It can potentially also be called, even before this function is called. - // If that is the case, we simply skip all the code here. - // See #18928 for more details. - var watcher etcd.Watcher - returned := func() bool { - w.stopLock.Lock() - defer w.stopLock.Unlock() - if w.stopped { - // Watcher has already been stopped - don't event initiate it here. - return true - } - w.wg.Add(1) - done = w.wg.Done - // Perform initialization of watcher under lock - we want to avoid situation when - // Stop() is called in the meantime (which in tests can cause etcd termination and - // strange behavior here). - if resourceVersion == 0 { - latest, err := etcdGetInitialWatchState(ctx, client, key, w.list, w.quorum, w.etcdIncoming) - if err != nil { - w.etcdError <- err - return true - } - resourceVersion = latest - } - - opts := etcd.WatcherOptions{ - Recursive: w.list, - AfterIndex: resourceVersion, - } - watcher = client.Watcher(key, &opts) - w.ctx, w.cancel = context.WithCancel(ctx) - return false - }() - defer done() - if returned { - return - } - - for { - resp, err := watcher.Next(w.ctx) - if err != nil { - w.etcdError <- err - return - } - w.etcdIncoming <- resp - } -} - -// etcdGetInitialWatchState turns an etcd Get request into a watch equivalent -func etcdGetInitialWatchState(ctx context.Context, client etcd.KeysAPI, key string, recursive bool, quorum bool, incoming chan<- *etcd.Response) (resourceVersion uint64, err error) { - opts := etcd.GetOptions{ - Recursive: recursive, - Sort: false, - Quorum: quorum, - } - resp, err := client.Get(ctx, key, &opts) - if err != nil { - if !etcdutil.IsEtcdNotFound(err) { - utilruntime.HandleError(fmt.Errorf("watch was unable to retrieve the current index for the provided key (%q): %v", key, err)) - return resourceVersion, toStorageErr(err, key, 0) - } - if etcdError, ok := err.(etcd.Error); ok { - resourceVersion = etcdError.Index - } - return resourceVersion, nil - } - resourceVersion = resp.Index - convertRecursiveResponse(resp.Node, resp, incoming) - return -} - -// convertRecursiveResponse turns a recursive get response from etcd into individual response objects -// by copying the original response. This emulates the behavior of a recursive watch. -func convertRecursiveResponse(node *etcd.Node, response *etcd.Response, incoming chan<- *etcd.Response) { - if node.Dir { - for i := range node.Nodes { - convertRecursiveResponse(node.Nodes[i], response, incoming) - } - return - } - copied := *response - copied.Action = "get" - copied.Node = node - incoming <- &copied -} - -var ( - watchChannelHWM HighWaterMark -) - -// translate pulls stuff from etcd, converts, and pushes out the outgoing channel. Meant to be -// called as a goroutine. -func (w *etcdWatcher) translate() { - defer w.wg.Done() - defer close(w.outgoing) - defer utilruntime.HandleCrash() - - for { - select { - case err := <-w.etcdError: - if err != nil { - var status *unversioned.Status - switch { - case etcdutil.IsEtcdWatchExpired(err): - status = &unversioned.Status{ - Status: unversioned.StatusFailure, - Message: err.Error(), - Code: http.StatusGone, // Gone - Reason: unversioned.StatusReasonExpired, - } - // TODO: need to generate errors using api/errors which has a circular dependency on this package - // no other way to inject errors - // case etcdutil.IsEtcdUnreachable(err): - // status = errors.NewServerTimeout(...) - default: - status = &unversioned.Status{ - Status: unversioned.StatusFailure, - Message: err.Error(), - Code: http.StatusInternalServerError, - Reason: unversioned.StatusReasonInternalError, - } - } - w.emit(watch.Event{ - Type: watch.Error, - Object: status, - }) - } - return - case <-w.userStop: - return - case res, ok := <-w.etcdIncoming: - if ok { - if curLen := int64(len(w.etcdIncoming)); watchChannelHWM.Update(curLen) { - // Monitor if this gets backed up, and how much. - glog.V(2).Infof("watch: %v objects queued in channel.", curLen) - } - w.sendResult(res) - } - // If !ok, don't return here-- must wait for etcdError channel - // to give an error or be closed. - } - } -} - -func (w *etcdWatcher) decodeObject(node *etcd.Node) (runtime.Object, error) { - if obj, found := w.cache.getFromCache(node.ModifiedIndex, storage.Everything); found { - return obj, nil - } - - obj, err := runtime.Decode(w.encoding, []byte(node.Value)) - if err != nil { - return nil, err - } - - // ensure resource version is set on the object we load from etcd - if err := w.versioner.UpdateObject(obj, node.ModifiedIndex); err != nil { - utilruntime.HandleError(fmt.Errorf("failure to version api object (%d) %#v: %v", node.ModifiedIndex, obj, err)) - } - - // perform any necessary transformation - if w.transform != nil { - obj, err = w.transform(obj) - if err != nil { - utilruntime.HandleError(fmt.Errorf("failure to transform api object %#v: %v", obj, err)) - return nil, err - } - } - - if node.ModifiedIndex != 0 { - w.cache.addToCache(node.ModifiedIndex, obj) - } - return obj, nil -} - -func (w *etcdWatcher) sendAdd(res *etcd.Response) { - if res.Node == nil { - utilruntime.HandleError(fmt.Errorf("unexpected nil node: %#v", res)) - return - } - if w.include != nil && !w.include(res.Node.Key) { - return - } - obj, err := w.decodeObject(res.Node) - if err != nil { - utilruntime.HandleError(fmt.Errorf("failure to decode api object: %v\n'%v' from %#v %#v", err, string(res.Node.Value), res, res.Node)) - // TODO: expose an error through watch.Interface? - // Ignore this value. If we stop the watch on a bad value, a client that uses - // the resourceVersion to resume will never be able to get past a bad value. - return - } - if !w.filter(obj) { - return - } - action := watch.Added - if res.Node.ModifiedIndex != res.Node.CreatedIndex { - action = watch.Modified - } - w.emit(watch.Event{ - Type: action, - Object: obj, - }) -} - -func (w *etcdWatcher) sendModify(res *etcd.Response) { - if res.Node == nil { - glog.Errorf("unexpected nil node: %#v", res) - return - } - if w.include != nil && !w.include(res.Node.Key) { - return - } - curObj, err := w.decodeObject(res.Node) - if err != nil { - utilruntime.HandleError(fmt.Errorf("failure to decode api object: %v\n'%v' from %#v %#v", err, string(res.Node.Value), res, res.Node)) - // TODO: expose an error through watch.Interface? - // Ignore this value. If we stop the watch on a bad value, a client that uses - // the resourceVersion to resume will never be able to get past a bad value. - return - } - curObjPasses := w.filter(curObj) - oldObjPasses := false - var oldObj runtime.Object - if res.PrevNode != nil && res.PrevNode.Value != "" { - // Ignore problems reading the old object. - if oldObj, err = w.decodeObject(res.PrevNode); err == nil { - oldObjPasses = w.filter(oldObj) - } - } - // Some changes to an object may cause it to start or stop matching a filter. - // We need to report those as adds/deletes. So we have to check both the previous - // and current value of the object. - switch { - case curObjPasses && oldObjPasses: - w.emit(watch.Event{ - Type: watch.Modified, - Object: curObj, - }) - case curObjPasses && !oldObjPasses: - w.emit(watch.Event{ - Type: watch.Added, - Object: curObj, - }) - case !curObjPasses && oldObjPasses: - w.emit(watch.Event{ - Type: watch.Deleted, - Object: oldObj, - }) - } - // Do nothing if neither new nor old object passed the filter. -} - -func (w *etcdWatcher) sendDelete(res *etcd.Response) { - if res.PrevNode == nil { - utilruntime.HandleError(fmt.Errorf("unexpected nil prev node: %#v", res)) - return - } - if w.include != nil && !w.include(res.PrevNode.Key) { - return - } - node := *res.PrevNode - if res.Node != nil { - // Note that this sends the *old* object with the etcd index for the time at - // which it gets deleted. This will allow users to restart the watch at the right - // index. - node.ModifiedIndex = res.Node.ModifiedIndex - } - obj, err := w.decodeObject(&node) - if err != nil { - utilruntime.HandleError(fmt.Errorf("failure to decode api object: %v\nfrom %#v %#v", err, res, res.Node)) - // TODO: expose an error through watch.Interface? - // Ignore this value. If we stop the watch on a bad value, a client that uses - // the resourceVersion to resume will never be able to get past a bad value. - return - } - if !w.filter(obj) { - return - } - w.emit(watch.Event{ - Type: watch.Deleted, - Object: obj, - }) -} - -func (w *etcdWatcher) sendResult(res *etcd.Response) { - switch res.Action { - case EtcdCreate, EtcdGet: - w.sendAdd(res) - case EtcdSet, EtcdCAS: - w.sendModify(res) - case EtcdDelete, EtcdExpire, EtcdCAD: - w.sendDelete(res) - default: - utilruntime.HandleError(fmt.Errorf("unknown action: %v", res.Action)) - } -} - -// ResultChan implements watch.Interface. -func (w *etcdWatcher) ResultChan() <-chan watch.Event { - return w.outgoing -} - -// Stop implements watch.Interface. -func (w *etcdWatcher) Stop() { - w.stopLock.Lock() - if w.cancel != nil { - w.cancel() - w.cancel = nil - } - if !w.stopped { - w.stopped = true - close(w.userStop) - } - w.stopLock.Unlock() - - // Wait until all calls to etcd are finished and no other - // will be issued. - w.wg.Wait() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_watcher_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_watcher_test.go deleted file mode 100644 index 386f59b56..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcd_watcher_test.go +++ /dev/null @@ -1,512 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcd - -import ( - "math/rand" - rt "runtime" - "sync" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/storage/etcd/etcdtest" - etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing" - "k8s.io/kubernetes/pkg/watch" - - etcd "github.com/coreos/etcd/client" - "golang.org/x/net/context" -) - -var versioner = APIObjectVersioner{} - -// Implements etcdCache interface as empty methods (i.e. does not cache any objects) -type fakeEtcdCache struct{} - -func (f *fakeEtcdCache) getFromCache(index uint64, filter storage.FilterFunc) (runtime.Object, bool) { - return nil, false -} - -func (f *fakeEtcdCache) addToCache(index uint64, obj runtime.Object) { -} - -var _ etcdCache = &fakeEtcdCache{} - -func TestWatchInterpretations(t *testing.T) { - codec := testapi.Default.Codec() - // Declare some pods to make the test cases compact. - podFoo := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - podBar := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}} - podBaz := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "baz"}} - firstLetterIsB := func(obj runtime.Object) bool { - return obj.(*api.Pod).Name[0] == 'b' - } - - // All of these test cases will be run with the firstLetterIsB FilterFunc. - table := map[string]struct { - actions []string // Run this test item for every action here. - prevNodeValue string - nodeValue string - expectEmit bool - expectType watch.EventType - expectObject runtime.Object - }{ - "create": { - actions: []string{"create", "get"}, - nodeValue: runtime.EncodeOrDie(codec, podBar), - expectEmit: true, - expectType: watch.Added, - expectObject: podBar, - }, - "create but filter blocks": { - actions: []string{"create", "get"}, - nodeValue: runtime.EncodeOrDie(codec, podFoo), - expectEmit: false, - }, - "delete": { - actions: []string{"delete"}, - prevNodeValue: runtime.EncodeOrDie(codec, podBar), - expectEmit: true, - expectType: watch.Deleted, - expectObject: podBar, - }, - "delete but filter blocks": { - actions: []string{"delete"}, - nodeValue: runtime.EncodeOrDie(codec, podFoo), - expectEmit: false, - }, - "modify appears to create 1": { - actions: []string{"set", "compareAndSwap"}, - nodeValue: runtime.EncodeOrDie(codec, podBar), - expectEmit: true, - expectType: watch.Added, - expectObject: podBar, - }, - "modify appears to create 2": { - actions: []string{"set", "compareAndSwap"}, - prevNodeValue: runtime.EncodeOrDie(codec, podFoo), - nodeValue: runtime.EncodeOrDie(codec, podBar), - expectEmit: true, - expectType: watch.Added, - expectObject: podBar, - }, - "modify appears to delete": { - actions: []string{"set", "compareAndSwap"}, - prevNodeValue: runtime.EncodeOrDie(codec, podBar), - nodeValue: runtime.EncodeOrDie(codec, podFoo), - expectEmit: true, - expectType: watch.Deleted, - expectObject: podBar, // Should return last state that passed the filter! - }, - "modify modifies": { - actions: []string{"set", "compareAndSwap"}, - prevNodeValue: runtime.EncodeOrDie(codec, podBar), - nodeValue: runtime.EncodeOrDie(codec, podBaz), - expectEmit: true, - expectType: watch.Modified, - expectObject: podBaz, - }, - "modify ignores": { - actions: []string{"set", "compareAndSwap"}, - nodeValue: runtime.EncodeOrDie(codec, podFoo), - expectEmit: false, - }, - } - - for name, item := range table { - for _, action := range item.actions { - w := newEtcdWatcher(true, false, nil, firstLetterIsB, codec, versioner, nil, &fakeEtcdCache{}) - emitCalled := false - w.emit = func(event watch.Event) { - emitCalled = true - if !item.expectEmit { - return - } - if e, a := item.expectType, event.Type; e != a { - t.Errorf("'%v - %v': expected %v, got %v", name, action, e, a) - } - if e, a := item.expectObject, event.Object; !api.Semantic.DeepDerivative(e, a) { - t.Errorf("'%v - %v': expected %v, got %v", name, action, e, a) - } - } - - var n, pn *etcd.Node - if item.nodeValue != "" { - n = &etcd.Node{Value: item.nodeValue} - } - if item.prevNodeValue != "" { - pn = &etcd.Node{Value: item.prevNodeValue} - } - - w.sendResult(&etcd.Response{ - Action: action, - Node: n, - PrevNode: pn, - }) - - if e, a := item.expectEmit, emitCalled; e != a { - t.Errorf("'%v - %v': expected %v, got %v", name, action, e, a) - } - w.Stop() - } - } -} - -func TestWatchInterpretation_ResponseNotSet(t *testing.T) { - _, codec := testScheme(t) - w := newEtcdWatcher(false, false, nil, storage.Everything, codec, versioner, nil, &fakeEtcdCache{}) - w.emit = func(e watch.Event) { - t.Errorf("Unexpected emit: %v", e) - } - - w.sendResult(&etcd.Response{ - Action: "update", - }) - w.Stop() -} - -func TestWatchInterpretation_ResponseNoNode(t *testing.T) { - _, codec := testScheme(t) - actions := []string{"create", "set", "compareAndSwap", "delete"} - for _, action := range actions { - w := newEtcdWatcher(false, false, nil, storage.Everything, codec, versioner, nil, &fakeEtcdCache{}) - w.emit = func(e watch.Event) { - t.Errorf("Unexpected emit: %v", e) - } - w.sendResult(&etcd.Response{ - Action: action, - }) - w.Stop() - } -} - -func TestWatchInterpretation_ResponseBadData(t *testing.T) { - _, codec := testScheme(t) - actions := []string{"create", "set", "compareAndSwap", "delete"} - for _, action := range actions { - w := newEtcdWatcher(false, false, nil, storage.Everything, codec, versioner, nil, &fakeEtcdCache{}) - w.emit = func(e watch.Event) { - t.Errorf("Unexpected emit: %v", e) - } - w.sendResult(&etcd.Response{ - Action: action, - Node: &etcd.Node{ - Value: "foobar", - }, - }) - w.sendResult(&etcd.Response{ - Action: action, - PrevNode: &etcd.Node{ - Value: "foobar", - }, - }) - w.Stop() - } -} - -func TestWatch(t *testing.T) { - codec := testapi.Default.Codec() - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := "/some/key" - h := newEtcdHelper(server.Client, codec, etcdtest.PathPrefix()) - - watching, err := h.Watch(context.TODO(), key, "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - // watching is explicitly closed below. - - // Test normal case - pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - returnObj := &api.Pod{} - err = h.Create(context.TODO(), key, pod, returnObj, 0) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - event := <-watching.ResultChan() - if e, a := watch.Added, event.Type; e != a { - t.Errorf("Expected %v, got %v", e, a) - } - if e, a := pod, event.Object; !api.Semantic.DeepDerivative(e, a) { - t.Errorf("Expected %v, got %v", e, a) - } - - watching.Stop() - - // There is a race in etcdWatcher so that after calling Stop() one of - // two things can happen: - // - ResultChan() may be closed (triggered by closing userStop channel) - // - an Error "context cancelled" may be emitted (triggered by cancelling request - // to etcd and putting that error to etcdError channel) - // We need to be prepared for both here. - event, open := <-watching.ResultChan() - if open && event.Type != watch.Error { - t.Errorf("Unexpected event from stopped watcher: %#v", event) - } -} - -func emptySubsets() []api.EndpointSubset { - return []api.EndpointSubset{} -} - -func makeSubsets(ip string, port int) []api.EndpointSubset { - return []api.EndpointSubset{{ - Addresses: []api.EndpointAddress{{IP: ip}}, - Ports: []api.EndpointPort{{Port: int32(port)}}, - }} -} - -func TestWatchEtcdState(t *testing.T) { - codec := testapi.Default.Codec() - key := etcdtest.AddPrefix("/somekey/foo") - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - - h := newEtcdHelper(server.Client, codec, etcdtest.PathPrefix()) - watching, err := h.Watch(context.TODO(), key, "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watching.Stop() - - endpoint := &api.Endpoints{ - ObjectMeta: api.ObjectMeta{Name: "foo"}, - Subsets: emptySubsets(), - } - - err = h.Create(context.TODO(), key, endpoint, endpoint, 0) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - event := <-watching.ResultChan() - if event.Type != watch.Added { - t.Errorf("Unexpected event %#v", event) - } - - subset := makeSubsets("127.0.0.1", 9000) - endpoint.Subsets = subset - endpoint.ResourceVersion = "" - - // CAS the previous value - updateFn := func(input runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) { - newObj, err := api.Scheme.DeepCopy(endpoint) - if err != nil { - t.Errorf("unexpected error: %v", err) - return nil, nil, err - } - return newObj.(*api.Endpoints), nil, nil - } - err = h.GuaranteedUpdate(context.TODO(), key, &api.Endpoints{}, false, nil, updateFn) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - event = <-watching.ResultChan() - if event.Type != watch.Modified { - t.Errorf("Unexpected event %#v", event) - } - - if e, a := endpoint, event.Object; !api.Semantic.DeepDerivative(e, a) { - t.Errorf("Unexpected error: expected %#v, got %#v", e, a) - } -} - -func TestWatchFromZeroIndex(t *testing.T) { - codec := testapi.Default.Codec() - pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - - key := etcdtest.AddPrefix("/somekey/foo") - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - - h := newEtcdHelper(server.Client, codec, etcdtest.PathPrefix()) - - // set before the watch and verify events - err := h.Create(context.TODO(), key, pod, pod, 0) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - pod.ResourceVersion = "" - - // check for concatenation on watch event with CAS - updateFn := func(input runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) { - pod := input.(*api.Pod) - pod.Name = "bar" - return pod, nil, nil - } - err = h.GuaranteedUpdate(context.TODO(), key, &api.Pod{}, false, nil, updateFn) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - watching, err := h.Watch(context.TODO(), key, "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watching.Stop() - - // marked as modified b/c of concatenation - event := <-watching.ResultChan() - if event.Type != watch.Modified { - t.Errorf("Unexpected event %#v", event) - } - - pod.Name = "baz" - updateFn = func(input runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) { - pod := input.(*api.Pod) - pod.Name = "baz" - return pod, nil, nil - } - err = h.GuaranteedUpdate(context.TODO(), key, &api.Pod{}, false, nil, updateFn) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - event = <-watching.ResultChan() - if event.Type != watch.Modified { - t.Errorf("Unexpected event %#v", event) - } - - if e, a := pod, event.Object; !api.Semantic.DeepDerivative(e, a) { - t.Errorf("Unexpected error: expected %#v, got %#v", e, a) - } -} - -func TestWatchListFromZeroIndex(t *testing.T) { - codec := testapi.Default.Codec() - key := etcdtest.AddPrefix("/some/key") - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - h := newEtcdHelper(server.Client, codec, key) - - watching, err := h.WatchList(context.TODO(), key, "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watching.Stop() - - // creates key/foo which should trigger the WatchList for "key" - pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - err = h.Create(context.TODO(), pod.Name, pod, pod, 0) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - event, _ := <-watching.ResultChan() - if event.Type != watch.Added { - t.Errorf("Unexpected event %#v", event) - } - - if e, a := pod, event.Object; !api.Semantic.DeepDerivative(e, a) { - t.Errorf("Unexpected error: expected %v, got %v", e, a) - } -} - -func TestWatchListIgnoresRootKey(t *testing.T) { - codec := testapi.Default.Codec() - pod := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - key := etcdtest.AddPrefix("/some/key") - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - h := newEtcdHelper(server.Client, codec, key) - - watching, err := h.WatchList(context.TODO(), key, "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - defer watching.Stop() - - // creates key/foo which should trigger the WatchList for "key" - err = h.Create(context.TODO(), key, pod, pod, 0) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - // force context switch to ensure watches would catch and notify. - rt.Gosched() - - select { - case event, _ := <-watching.ResultChan(): - t.Fatalf("Unexpected event: %#v", event) - default: - // fall through, expected behavior - } -} - -func TestWatchPurposefulShutdown(t *testing.T) { - _, codec := testScheme(t) - server := etcdtesting.NewEtcdTestClientServer(t) - defer server.Terminate(t) - key := "/some/key" - h := newEtcdHelper(server.Client, codec, etcdtest.PathPrefix()) - - // Test purposeful shutdown - watching, err := h.Watch(context.TODO(), key, "0", storage.Everything) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - watching.Stop() - rt.Gosched() - - // There is a race in etcdWatcher so that after calling Stop() one of - // two things can happen: - // - ResultChan() may be closed (triggered by closing userStop channel) - // - an Error "context cancelled" may be emitted (triggered by cancelling request - // to etcd and putting that error to etcdError channel) - // We need to be prepared for both here. - event, open := <-watching.ResultChan() - if open && event.Type != watch.Error { - t.Errorf("Unexpected event from stopped watcher: %#v", event) - } -} - -func TestHighWaterMark(t *testing.T) { - var h HighWaterMark - - for i := int64(10); i < 20; i++ { - if !h.Update(i) { - t.Errorf("unexpected false for %v", i) - } - if h.Update(i - 1) { - t.Errorf("unexpected true for %v", i-1) - } - } - - m := int64(0) - wg := sync.WaitGroup{} - for i := 0; i < 300; i++ { - wg.Add(1) - v := rand.Int63() - go func(v int64) { - defer wg.Done() - h.Update(v) - }(v) - if v > m { - m = v - } - } - wg.Wait() - if m != int64(h) { - t.Errorf("unexpected value, wanted %v, got %v", m, int64(h)) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcdtest/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcdtest/doc.go deleted file mode 100644 index ef9e6ce86..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcdtest/doc.go +++ /dev/null @@ -1,17 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcdtest diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcdtest/etcdtest.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcdtest/etcdtest.go deleted file mode 100644 index d248eedb2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/etcdtest/etcdtest.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 etcdtest - -import ( - "os" - "path" -) - -// Cache size to use for tests. -const DeserializationCacheSize = 150 - -// Returns the prefix set via the ETCD_PREFIX environment variable (if any). -func PathPrefix() string { - pref := os.Getenv("ETCD_PREFIX") - if pref == "" { - pref = "registry" - } - return path.Join("/", pref) -} - -// Adds the ETCD_PREFIX to the provided key -func AddPrefix(in string) string { - return path.Join(PathPrefix(), in) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/metrics/metrics.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/metrics/metrics.go deleted file mode 100644 index 7e88e43c2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/metrics/metrics.go +++ /dev/null @@ -1,113 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 metrics - -import ( - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" -) - -var ( - cacheHitCounter = prometheus.NewCounter( - prometheus.CounterOpts{ - Name: "etcd_helper_cache_hit_count", - Help: "Counter of etcd helper cache hits.", - }, - ) - cacheMissCounter = prometheus.NewCounter( - prometheus.CounterOpts{ - Name: "etcd_helper_cache_miss_count", - Help: "Counter of etcd helper cache miss.", - }, - ) - cacheEntryCounter = prometheus.NewCounter( - prometheus.CounterOpts{ - Name: "etcd_helper_cache_entry_count", - Help: "Counter of etcd helper cache entries. This can be different from etcd_helper_cache_miss_count " + - "because two concurrent threads can miss the cache and generate the same entry twice.", - }, - ) - cacheGetLatency = prometheus.NewSummary( - prometheus.SummaryOpts{ - Name: "etcd_request_cache_get_latencies_summary", - Help: "Latency in microseconds of getting an object from etcd cache", - }, - ) - cacheAddLatency = prometheus.NewSummary( - prometheus.SummaryOpts{ - Name: "etcd_request_cache_add_latencies_summary", - Help: "Latency in microseconds of adding an object to etcd cache", - }, - ) - etcdRequestLatenciesSummary = prometheus.NewSummaryVec( - prometheus.SummaryOpts{ - Name: "etcd_request_latencies_summary", - Help: "Etcd request latency summary in microseconds for each operation and object type.", - }, - []string{"operation", "type"}, - ) -) - -var registerMetrics sync.Once - -// Register all metrics. -func Register() { - // Register the metrics. - registerMetrics.Do(func() { - prometheus.MustRegister(cacheHitCounter) - prometheus.MustRegister(cacheMissCounter) - prometheus.MustRegister(cacheEntryCounter) - prometheus.MustRegister(cacheAddLatency) - prometheus.MustRegister(cacheGetLatency) - prometheus.MustRegister(etcdRequestLatenciesSummary) - }) -} - -func RecordEtcdRequestLatency(verb, resource string, startTime time.Time) { - etcdRequestLatenciesSummary.WithLabelValues(verb, resource).Observe(float64(time.Since(startTime) / time.Microsecond)) -} - -func ObserveGetCache(startTime time.Time) { - cacheGetLatency.Observe(float64(time.Since(startTime) / time.Microsecond)) -} - -func ObserveAddCache(startTime time.Time) { - cacheAddLatency.Observe(float64(time.Since(startTime) / time.Microsecond)) -} - -func ObserveCacheHit() { - cacheHitCounter.Inc() -} - -func ObserveCacheMiss() { - cacheMissCounter.Inc() -} - -func ObserveNewEntry() { - cacheEntryCounter.Inc() -} - -func Reset() { - cacheHitCounter.Set(0) - cacheMissCounter.Set(0) - cacheEntryCounter.Set(0) - // TODO: Reset cacheAddLatency. - // TODO: Reset cacheGetLatency. - etcdRequestLatenciesSummary.Reset() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/testing/certificates.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/testing/certificates.go deleted file mode 100644 index c3fea5ffc..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/testing/certificates.go +++ /dev/null @@ -1,113 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 testing - -// You can use cfssl tool to generate certificates, please refer -// https://github.com/coreos/etcd/tree/master/hack/tls-setup for more details. -// -// ca-config.json: -// expiry was changed from 1 year to 100 years (876000h) -// ca-csr.json: -// ca expiry was set to 100 years (876000h) ("ca":{"expiry":"876000h"}) -// key was changed from ecdsa,384 to rsa,2048 -// req-csr.json: -// key was changed from ecdsa,384 to rsa,2048 -// hosts were changed to "localhost","127.0.0.1" -const CAFileContent = ` ------BEGIN CERTIFICATE----- -MIIEUDCCAzigAwIBAgIUKfV5+qwlw3JneAPdJS7JCO8xIlYwDQYJKoZIhvcNAQEL -BQAwgawxCzAJBgNVBAYTAlVTMSowKAYDVQQKEyFIb25lc3QgQWNobWVkJ3MgVXNl -ZCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAsTIEhhc3RpbHktR2VuZXJhdGVkIFZhbHVl -cyBEaXZpc29uMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxp -Zm9ybmlhMRkwFwYDVQQDExBBdXRvZ2VuZXJhdGVkIENBMCAXDTE2MDMxMjIzMTQw -MFoYDzIxMTYwMjE3MjMxNDAwWjCBrDELMAkGA1UEBhMCVVMxKjAoBgNVBAoTIUhv -bmVzdCBBY2htZWQncyBVc2VkIENlcnRpZmljYXRlczEpMCcGA1UECxMgSGFzdGls -eS1HZW5lcmF0ZWQgVmFsdWVzIERpdmlzb24xFjAUBgNVBAcTDVNhbiBGcmFuY2lz -Y28xEzARBgNVBAgTCkNhbGlmb3JuaWExGTAXBgNVBAMTEEF1dG9nZW5lcmF0ZWQg -Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP+acpr1USrObZFu+6 -v+Bk6rYw+sWynP373cNUUiHfnZ3D7f9yJsDscV0Mo4R8DddqkxawrA5fK2Fm2Z9G -vvY5par4/JbwRIEkXmeM4e52Mqv0Yuoz62O+0jQvRawnCCJMcKuo+ijHMjmm0AF1 -JdhTpTgvUwEP9WtY9JVTkfMCnDqZiqOU5D+d4YWUtkKqgQNvbZRs6wGubhMCZe8X -m+3bK8YAsWWtoFgr7plxXk4D8MLh+PqJ3oJjfxfW5A9dHbnSEmdZ3vrYwrKgyfNf -bvHE5qQmiSZUbUaCw3mKfaEMCNesPT46nBHxhAWc5aiL1tOXzvV5Uze7A7huPoI9 -a3etAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEC -MB0GA1UdDgQWBBQYc0xXQ6VNjFvIOqWfXorxx9rKRzAfBgNVHSMEGDAWgBQYc0xX -Q6VNjFvIOqWfXorxx9rKRzANBgkqhkiG9w0BAQsFAAOCAQEAaKyHDWYVjEyEKTXJ -qS9r46ehL5FZlWD2ZytBP8aHE307l9AfQ+DFWldCNaqMXLZozsresVaSzSOI6UUD -lCIQLDpPyxbpR320u8mC08+lhhwR/YRkrEqKHk56Wl4OaqoyWmguqYU9p0DiQeTU -sZsxOwG7cyEEvvs+XmZ/vBLBOr59xyjwn4seQqzwZj3VYeiKLw40iQt1yT442rcP -CfdlE9wTEONvWT+kBGMt0JlalXH3jFvlfcGQdDfRmDeTJtA+uIbvJhwJuGCNHHAc -xqC+4mAGBPN/dMPXpjayHD5dOXIKLfrNpqse6jImYlY9zduvwIHRDK/zvqTyPlNZ -uR84Nw== ------END CERTIFICATE----- -` -const CertFileContent = ` ------BEGIN CERTIFICATE----- -MIIELzCCAxegAwIBAgIUcjkJA3cmHeoBQggaKZmfKebFL9cwDQYJKoZIhvcNAQEL -BQAwgawxCzAJBgNVBAYTAlVTMSowKAYDVQQKEyFIb25lc3QgQWNobWVkJ3MgVXNl -ZCBDZXJ0aWZpY2F0ZXMxKTAnBgNVBAsTIEhhc3RpbHktR2VuZXJhdGVkIFZhbHVl -cyBEaXZpc29uMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxp -Zm9ybmlhMRkwFwYDVQQDExBBdXRvZ2VuZXJhdGVkIENBMCAXDTE2MDMxMjIzMTQw -MFoYDzIxMTYwMjE3MjMxNDAwWjBVMRYwFAYDVQQKEw1hdXRvZ2VuZXJhdGVkMRUw -EwYDVQQLEwxldGNkIGNsdXN0ZXIxFTATBgNVBAcTDHRoZSBpbnRlcm5ldDENMAsG -A1UEAxMEZXRjZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOiW5A65 -hWGbnwceoZHM0+OexU4cPF/FpP+7BOK5i7ymSWAqfKfNuio2TB1lAErC1oX7bgTX -ieP10uz3FYWQNrlDn0I4KSA888rFPtx8GwoxH/52fGlE80BUV9PNeOVP+mYza0ih -oFj2+PhXVL/JZbx9P/2RLSNbEnq+OPk8AN82SkNtpFzanwtpb3f+kt73878KNoQu -xYZaCF1sK45Kn7mjKSDu/b3xUbTrNwnyVAGOdLzI7CCWOu+ECoZYAH4ZNHHakbyY -eWQ7U9leocEOPlqxsQAKodaCYjuAaOFIcz8/W81q+3qNw/6GbZ4znjRKQ3OtIPZ4 -JH1iNofCudWDp+0CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYw -FAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFMJE -43qLCWhyZAE/wxNneSJw7aUVMB8GA1UdIwQYMBaAFBhzTFdDpU2MW8g6pZ9eivHH -2spHMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0BAQsFAAOC -AQEAuELC8tbmpyKlA4HLSDHOUquypNyiE6ftBIifJtp8bvBd+jiv4Pr8oVGxHoqq -48X7lamvDirLV5gmK0CxO+EXkIUHhULzPyYPynqsR7KZlk1PWghqsF65nwqcjS3b -tykLttD1AUDIozYvujVYBKXGxb6jcGM1rBF1XtslciFZ5qQnj6dTUujo9/xBA2ql -kOKiVXBNU8KFzq4c20RzHFLfWkbc30Q4XG4dTDVBeGupnFQRkZ0y2dSSU82QcLA/ -HgAyQSO7+csN13r84zbmDuRpUgo6eTXzJ+77G19KDkEL7XEtlw2jB2L6/o+3RGtw -JLOpEsgi7hsvOYCuTA3Krw52Mw== ------END CERTIFICATE----- -` -const KeyFileContent = ` ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA6JbkDrmFYZufBx6hkczT457FThw8X8Wk/7sE4rmLvKZJYCp8 -p826KjZMHWUASsLWhftuBNeJ4/XS7PcVhZA2uUOfQjgpIDzzysU+3HwbCjEf/nZ8 -aUTzQFRX08145U/6ZjNrSKGgWPb4+FdUv8llvH0//ZEtI1sSer44+TwA3zZKQ22k -XNqfC2lvd/6S3vfzvwo2hC7FhloIXWwrjkqfuaMpIO79vfFRtOs3CfJUAY50vMjs -IJY674QKhlgAfhk0cdqRvJh5ZDtT2V6hwQ4+WrGxAAqh1oJiO4Bo4UhzPz9bzWr7 -eo3D/oZtnjOeNEpDc60g9ngkfWI2h8K51YOn7QIDAQABAoIBAQCj88Fc08++x0kp -ZqEzunPebsvcTLEOPa8aiUVfYLWszHbKsAhg7Pb+zHmI+upiyMcZeOvLw/eyVlVR -rrZgCRFaNN2texMaY3zigXnXSDBzVb+cyv7V4cGqpgmnBp7i3ia/Jh3I/A2gyK8l -t8HI03nAjXWvE0gDNS5okXBt16sxq6ZWyzHHVbN3UYtCDxnyh2Ibck4b+K8I8Bn1 -mwMsSqPXJS1UQ3U5UqcaMs7WOEGx+xmaPJTWm5Lb//BkakGuBTQj+7wotyXQYG5U -uZdPPcFRk6cqgjzUeKVUtGkdmfgHSTdIwZowkKibB4rdrudsRnSwfeB+83Jp9JwG -JPrGvsbNAoGBAPULIO+vVBZXVpUEAhvNSXtmOi/hAbQhOuix8iwHbJ5EbrWaDn4B -Reb2cw/fZGgGG4jtAOXdiY8R1XGGP8+RPZ5El10ZWnNrKQfpZ27gK/5yeq5dfGBG -4JLUpcrT180FJo00rgiQYJnHCk1fWrnzXNV6K08ZZHGr6yv4S/jbq/7vAoGBAPL9 -NTN/UWXWFlSHVcb2dFHcvIiPwRj9KwhuMu90b/CilBbSJ1av13xtf2ar5zkrEtWH -CB3q3wBaklQP9MfOqEWGZeOUcd9AbYWtxHjHmP5fJA9RjErjlTtqGkusNtZJbchU -UWfT/Tl9pREpCvJ/8iawc1hx7sHHKzYwnDnMaQbjAoGAfJdd9cBltr5NjZLuJ4in -dhCyQSncnePPegUQJwbXWVleGQPtnm+zRQ3Fzyo8eQ+x7Frk+/s6N/5PUlt6EmW8 -uL4TYAjGDq1LvXQVXTCp7cPzULjDxogDI2Tvr0MrFFksEtvYKQ6Pr2CeglybWrS8 -XOazIpK8mXdaKY8jwbKfrw0CgYAFnfrb3OaZzxAnFhXSiqH3vn2RPpl9JWUYRcvh -ozRvQKLhwCvuohP+KV3XlsO6m5dM3lk+r85F6NIXJWNINyvGp6u1ThovygJ+I502 -GY8c2kAwJndyx74MaJCBDVMbMwlZpzFWkBz7dj8ZnXRGVNTZNh0Ef2XAjwUdtJP3 -9hS7dwKBgQDCzq0RIxFyy3F5baGHWLVICxmhNExQ2+Vebh+DvsPKtnz6OrWdRbGX -wgGVLrn53s6eCblnXLtKr/Li+t7fS8IkQkvu5guOvI9VeVUmZhFET3GVmUxu+JTb -iQY4uBgaf8Fgay4dkOfjvlOpFDR4E7UbJpg8/cFKTrpwgOiUVyFVdQ== ------END RSA PRIVATE KEY----- -` diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/testing/utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/testing/utils.go deleted file mode 100644 index d46085e4c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/testing/utils.go +++ /dev/null @@ -1,250 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import ( - "fmt" - "io/ioutil" - "net" - "net/http" - "net/http/httptest" - "os" - "path" - "testing" - "time" - - etcd "github.com/coreos/etcd/client" - "github.com/coreos/etcd/etcdserver" - "github.com/coreos/etcd/etcdserver/api/v2http" - "github.com/coreos/etcd/pkg/testutil" - "github.com/coreos/etcd/pkg/transport" - "github.com/coreos/etcd/pkg/types" - "github.com/golang/glog" - "golang.org/x/net/context" -) - -// EtcdTestServer encapsulates the datastructures needed to start local instance for testing -type EtcdTestServer struct { - etcdserver.ServerConfig - PeerListeners, ClientListeners []net.Listener - Client etcd.Client - - CertificatesDir string - CertFile string - KeyFile string - CAFile string - - raftHandler http.Handler - s *etcdserver.EtcdServer - hss []*httptest.Server -} - -// newLocalListener opens a port localhost using any port -func newLocalListener(t *testing.T) net.Listener { - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - return l -} - -// newSecuredLocalListener opens a port localhost using any port -// with SSL enable -func newSecuredLocalListener(t *testing.T, certFile, keyFile, caFile string) net.Listener { - var l net.Listener - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - tlsInfo := transport.TLSInfo{ - CertFile: certFile, - KeyFile: keyFile, - CAFile: caFile, - } - tlscfg, err := tlsInfo.ServerConfig() - if err != nil { - t.Fatalf("unexpected serverConfig error: %v", err) - } - l, err = transport.NewKeepAliveListener(l, "https", tlscfg) - if err != nil { - t.Fatal(err) - } - return l -} - -func newHttpTransport(t *testing.T, certFile, keyFile, caFile string) etcd.CancelableTransport { - tlsInfo := transport.TLSInfo{ - CertFile: certFile, - KeyFile: keyFile, - CAFile: caFile, - } - tr, err := transport.NewTransport(tlsInfo, time.Second) - if err != nil { - t.Fatal(err) - } - return tr -} - -// configureTestCluster will set the params to start an etcd server -func configureTestCluster(t *testing.T, name string) *EtcdTestServer { - var err error - m := &EtcdTestServer{} - - pln := newLocalListener(t) - m.PeerListeners = []net.Listener{pln} - m.PeerURLs, err = types.NewURLs([]string{"http://" + pln.Addr().String()}) - if err != nil { - t.Fatal(err) - } - - m.CertificatesDir, err = ioutil.TempDir(os.TempDir(), "etcd_certificates") - if err != nil { - t.Fatal(err) - } - m.CertFile = path.Join(m.CertificatesDir, "etcdcert.pem") - if err = ioutil.WriteFile(m.CertFile, []byte(CertFileContent), 0644); err != nil { - t.Fatal(err) - } - m.KeyFile = path.Join(m.CertificatesDir, "etcdkey.pem") - if err = ioutil.WriteFile(m.KeyFile, []byte(KeyFileContent), 0644); err != nil { - t.Fatal(err) - } - m.CAFile = path.Join(m.CertificatesDir, "ca.pem") - if err = ioutil.WriteFile(m.CAFile, []byte(CAFileContent), 0644); err != nil { - t.Fatal(err) - } - - cln := newSecuredLocalListener(t, m.CertFile, m.KeyFile, m.CAFile) - m.ClientListeners = []net.Listener{cln} - m.ClientURLs, err = types.NewURLs([]string{"https://" + cln.Addr().String()}) - if err != nil { - t.Fatal(err) - } - - m.Name = name - m.DataDir, err = ioutil.TempDir(os.TempDir(), "etcd") - if err != nil { - t.Fatal(err) - } - - clusterStr := fmt.Sprintf("%s=http://%s", name, pln.Addr().String()) - m.InitialPeerURLsMap, err = types.NewURLsMap(clusterStr) - if err != nil { - t.Fatal(err) - } - m.InitialClusterToken = "TestEtcd" - m.NewCluster = true - m.ForceNewCluster = false - m.ElectionTicks = 10 - m.TickMs = uint(10) - - return m -} - -// launch will attempt to start the etcd server -func (m *EtcdTestServer) launch(t *testing.T) error { - var err error - if m.s, err = etcdserver.NewServer(&m.ServerConfig); err != nil { - return fmt.Errorf("failed to initialize the etcd server: %v", err) - } - m.s.SyncTicker = time.Tick(500 * time.Millisecond) - m.s.Start() - m.raftHandler = &testutil.PauseableHandler{Next: v2http.NewPeerHandler(m.s)} - for _, ln := range m.PeerListeners { - hs := &httptest.Server{ - Listener: ln, - Config: &http.Server{Handler: m.raftHandler}, - } - hs.Start() - m.hss = append(m.hss, hs) - } - for _, ln := range m.ClientListeners { - hs := &httptest.Server{ - Listener: ln, - Config: &http.Server{Handler: v2http.NewClientHandler(m.s, m.ServerConfig.ReqTimeout())}, - } - hs.Start() - m.hss = append(m.hss, hs) - } - return nil -} - -// waitForEtcd wait until etcd is propagated correctly -func (m *EtcdTestServer) waitUntilUp() error { - membersAPI := etcd.NewMembersAPI(m.Client) - for start := time.Now(); time.Since(start) < 5*time.Second; time.Sleep(10 * time.Millisecond) { - members, err := membersAPI.List(context.TODO()) - if err != nil { - glog.Errorf("Error when getting etcd cluster members") - continue - } - if len(members) == 1 && len(members[0].ClientURLs) > 0 { - return nil - } - } - return fmt.Errorf("timeout on waiting for etcd cluster") -} - -// Terminate will shutdown the running etcd server -func (m *EtcdTestServer) Terminate(t *testing.T) { - m.Client = nil - m.s.Stop() - // TODO: This is a pretty ugly hack to workaround races during closing - // in-memory etcd server in unit tests - see #18928 for more details. - // We should get rid of it as soon as we have a proper fix - etcd clients - // have overwritten transport counting opened connections (probably by - // overwriting Dial function) and termination function waiting for all - // connections to be closed and stopping accepting new ones. - time.Sleep(250 * time.Millisecond) - for _, hs := range m.hss { - hs.CloseClientConnections() - hs.Close() - } - if err := os.RemoveAll(m.ServerConfig.DataDir); err != nil { - t.Fatal(err) - } - if err := os.RemoveAll(m.CertificatesDir); err != nil { - t.Fatal(err) - } -} - -// NewEtcdTestClientServer creates a new client and server for testing -func NewEtcdTestClientServer(t *testing.T) *EtcdTestServer { - server := configureTestCluster(t, "foo") - err := server.launch(t) - if err != nil { - t.Fatalf("Failed to start etcd server error=%v", err) - return nil - } - - cfg := etcd.Config{ - Endpoints: server.ClientURLs.StringSlice(), - Transport: newHttpTransport(t, server.CertFile, server.KeyFile, server.CAFile), - } - server.Client, err = etcd.New(cfg) - if err != nil { - t.Errorf("Unexpected error in NewEtcdTestClientServer (%v)", err) - server.Terminate(t) - return nil - } - if err := server.waitUntilUp(); err != nil { - t.Errorf("Unexpected error in waitUntilUp (%v)", err) - server.Terminate(t) - return nil - } - return server -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/doc.go deleted file mode 100644 index aa1039faf..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 util holds generic etcd-related utility functions that any user of ectd might want to -// use, without pulling in kubernetes-specific code. -package util diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/etcd_util.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/etcd_util.go deleted file mode 100644 index b15ec5bd0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/etcd_util.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 util - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - - etcd "github.com/coreos/etcd/client" -) - -// IsEtcdNotFound returns true if and only if err is an etcd not found error. -func IsEtcdNotFound(err error) bool { - return isEtcdErrorNum(err, etcd.ErrorCodeKeyNotFound) -} - -// IsEtcdNodeExist returns true if and only if err is an etcd node already exist error. -func IsEtcdNodeExist(err error) bool { - return isEtcdErrorNum(err, etcd.ErrorCodeNodeExist) -} - -// IsEtcdTestFailed returns true if and only if err is an etcd write conflict. -func IsEtcdTestFailed(err error) bool { - return isEtcdErrorNum(err, etcd.ErrorCodeTestFailed) -} - -// IsEtcdWatchExpired returns true if and only if err indicates the watch has expired. -func IsEtcdWatchExpired(err error) bool { - // NOTE: This seems weird why it wouldn't be etcd.ErrorCodeWatcherCleared - // I'm using the previous matching value - return isEtcdErrorNum(err, etcd.ErrorCodeEventIndexCleared) -} - -// IsEtcdUnreachable returns true if and only if err indicates the server could not be reached. -func IsEtcdUnreachable(err error) bool { - // NOTE: The logic has changed previous error code no longer applies - return err == etcd.ErrClusterUnavailable -} - -// isEtcdErrorNum returns true if and only if err is an etcd error, whose errorCode matches errorCode -func isEtcdErrorNum(err error, errorCode int) bool { - if err != nil { - if etcdError, ok := err.(etcd.Error); ok { - return etcdError.Code == errorCode - } - // NOTE: There are other error types returned - } - return false -} - -// GetEtcdVersion performs a version check against the provided Etcd server, -// returning the string response, and error (if any). -func GetEtcdVersion(host string) (string, error) { - response, err := http.Get(host + "/version") - if err != nil { - return "", err - } - defer response.Body.Close() - if response.StatusCode != http.StatusOK { - return "", fmt.Errorf("unsuccessful response from etcd server %q: %v", host, err) - } - versionBytes, err := ioutil.ReadAll(response.Body) - if err != nil { - return "", err - } - return string(versionBytes), nil -} - -type etcdHealth struct { - // Note this has to be public so the json library can modify it. - Health string `json:"health"` -} - -func EtcdHealthCheck(data []byte) error { - obj := etcdHealth{} - if err := json.Unmarshal(data, &obj); err != nil { - return err - } - if obj.Health != "true" { - return fmt.Errorf("Unhealthy status: %s", obj.Health) - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/etcd_util_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/etcd_util_test.go deleted file mode 100644 index cc41958ad..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd/util/etcd_util_test.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 util - -import ( - "fmt" - "math/rand" - "net" - "net/http" - "net/http/httptest" - "strconv" - "testing" - "time" - - etcd "github.com/coreos/etcd/client" - "github.com/stretchr/testify/assert" -) - -const validEtcdVersion = "etcd 2.0.9" - -func TestIsEtcdNotFound(t *testing.T) { - try := func(err error, isNotFound bool) { - if IsEtcdNotFound(err) != isNotFound { - t.Errorf("Expected %#v to return %v, but it did not", err, isNotFound) - } - } - try(&etcd.Error{Code: 101}, false) - try(nil, false) - try(fmt.Errorf("some other kind of error"), false) -} - -func TestGetEtcdVersion_ValidVersion(t *testing.T) { - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, validEtcdVersion) - })) - defer testServer.Close() - - var version string - var err error - if version, err = GetEtcdVersion(testServer.URL); err != nil { - t.Errorf("Unexpected error: %v", err) - } - assert.Equal(t, validEtcdVersion, version, "Unexpected version") - assert.Nil(t, err) -} - -func TestGetEtcdVersion_ErrorStatus(t *testing.T) { - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusServiceUnavailable) - })) - defer testServer.Close() - - _, err := GetEtcdVersion(testServer.URL) - assert.NotNil(t, err) -} - -func TestGetEtcdVersion_NotListening(t *testing.T) { - portIsOpen := func(port int) bool { - conn, err := net.DialTimeout("tcp", "127.0.0.1:"+strconv.Itoa(port), 1*time.Second) - if err == nil { - conn.Close() - return true - } - return false - } - - port := rand.Intn((1 << 16) - 1) - for tried := 0; portIsOpen(port); tried++ { - if tried >= 10 { - t.Fatal("Couldn't find a closed TCP port to continue testing") - } - port++ - } - - _, err := GetEtcdVersion("http://127.0.0.1:" + strconv.Itoa(port)) - assert.NotNil(t, err) -} - -func TestEtcdHealthCheck(t *testing.T) { - tests := []struct { - data string - expectErr bool - }{ - { - data: "{\"health\": \"true\"}", - expectErr: false, - }, - { - data: "{\"health\": \"false\"}", - expectErr: true, - }, - { - data: "invalid json", - expectErr: true, - }, - } - for _, test := range tests { - err := EtcdHealthCheck([]byte(test.data)) - if err != nil && !test.expectErr { - t.Errorf("unexpected error: %v", err) - } - if err == nil && test.expectErr { - t.Error("unexpected non-error") - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/compact.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/compact.go deleted file mode 100644 index cfe73c597..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/compact.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 etcd3 - -import ( - "sync" - "time" - - "github.com/coreos/etcd/clientv3" - "github.com/golang/glog" - "golang.org/x/net/context" -) - -const compactInterval = 10 * time.Minute - -var ( - endpointsMapMu sync.Mutex - endpointsMap map[string]struct{} -) - -func init() { - endpointsMap = make(map[string]struct{}) -} - -// StartCompactor starts a compactor in the background in order to compact keys -// older than fixed time. -// We need to compact keys because we can't let on disk data grow forever. -// We save the most recent 10 minutes data. It should be enough for slow watchers and to tolerate burst. -// TODO: We might keep a longer history (12h) in the future once storage API can take -// advantage of multi-version key. -func StartCompactor(ctx context.Context, client *clientv3.Client) { - endpointsMapMu.Lock() - defer endpointsMapMu.Unlock() - - // We can't have multiple compaction jobs for the same cluster. - // Currently we rely on endpoints to differentiate clusters. - var emptyStruct struct{} - for _, ep := range client.Endpoints() { - if _, ok := endpointsMap[ep]; ok { - glog.V(4).Infof("compactor already exists for endpoints %v") - return - } - } - for _, ep := range client.Endpoints() { - endpointsMap[ep] = emptyStruct - } - - go compactor(ctx, client, compactInterval) -} - -// compactor periodically compacts historical versions of keys in etcd. -// After compaction, old versions of keys set before given interval will be gone. -// Any API call for the old versions of keys will return error. -// interval: the interval between each compaction. The first compaction happens after "interval". -func compactor(ctx context.Context, client *clientv3.Client, interval time.Duration) { - var curRev int64 - var err error - for { - select { - case <-time.After(interval): - case <-ctx.Done(): - return - } - - curRev, err = compact(ctx, client, curRev) - if err != nil { - glog.Error(err) - continue - } - } -} - -// compact compacts etcd store and returns current rev. -// If it couldn't get current revision, the old rev will be returned. -func compact(ctx context.Context, client *clientv3.Client, oldRev int64) (int64, error) { - resp, err := client.Get(ctx, "/") - if err != nil { - return oldRev, err - } - curRev := resp.Header.Revision - if oldRev == 0 { - return curRev, nil - } - err = client.Compact(ctx, oldRev) - if err != nil { - return curRev, err - } - glog.Infof("etcd: Compacted rev %d, endpoints %v", oldRev, client.Endpoints()) - return curRev, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/compact_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/compact_test.go deleted file mode 100644 index af5a3ed4d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/compact_test.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 etcd3 - -import ( - "testing" - - "github.com/coreos/etcd/clientv3" - etcdrpc "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" - "github.com/coreos/etcd/integration" - "golang.org/x/net/context" -) - -func TestCompact(t *testing.T) { - cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) - defer cluster.Terminate(t) - client := cluster.RandClient() - ctx := context.Background() - - putResp, err := client.Put(ctx, "/somekey", "data") - if err != nil { - t.Fatalf("Put failed: %v", err) - } - - _, err = compact(ctx, client, putResp.Header.Revision) - if err != nil { - t.Fatalf("compact failed: %v", err) - } - - _, err = client.Get(ctx, "/somekey", clientv3.WithRev(putResp.Header.Revision)) - if err != etcdrpc.ErrCompacted { - t.Errorf("Expecting ErrCompacted, but get=%v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/event.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/event.go deleted file mode 100644 index 58072bd7b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/event.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 etcd3 - -import ( - "github.com/coreos/etcd/clientv3" - "github.com/coreos/etcd/storage/storagepb" -) - -type event struct { - key string - value []byte - rev int64 - isDeleted bool - isCreated bool -} - -func parseKV(kv *storagepb.KeyValue) *event { - return &event{ - key: string(kv.Key), - value: kv.Value, - rev: kv.ModRevision, - isDeleted: false, - isCreated: kv.ModRevision == kv.CreateRevision, - } -} - -func parseEvent(e *clientv3.Event) *event { - return &event{ - key: string(e.Kv.Key), - value: e.Kv.Value, - rev: e.Kv.ModRevision, - isDeleted: e.Type == clientv3.EventTypeDelete, - isCreated: e.IsCreate(), - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/store.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/store.go deleted file mode 100644 index 4ac455df5..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/store.go +++ /dev/null @@ -1,474 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 etcd3 - -import ( - "bytes" - "errors" - "fmt" - "path" - "reflect" - "strings" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/conversion" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/storage/etcd" - "k8s.io/kubernetes/pkg/watch" - - "github.com/coreos/etcd/clientv3" - "github.com/golang/glog" - "golang.org/x/net/context" -) - -type store struct { - client *clientv3.Client - codec runtime.Codec - versioner storage.Versioner - pathPrefix string - watcher *watcher -} - -type elemForDecode struct { - data []byte - rev uint64 -} - -type objState struct { - obj runtime.Object - meta *storage.ResponseMeta - rev int64 - data []byte -} - -// New returns an etcd3 implementation of storage.Interface. -func New(c *clientv3.Client, codec runtime.Codec, prefix string) storage.Interface { - return newStore(c, codec, prefix) -} - -func newStore(c *clientv3.Client, codec runtime.Codec, prefix string) *store { - versioner := etcd.APIObjectVersioner{} - return &store{ - client: c, - versioner: versioner, - codec: codec, - pathPrefix: prefix, - watcher: newWatcher(c, codec, versioner), - } -} - -// Backends implements storage.Interface.Backends. -func (s *store) Backends(ctx context.Context) []string { - resp, err := s.client.MemberList(ctx) - if err != nil { - glog.Errorf("Error obtaining etcd members list: %q", err) - return nil - } - var mlist []string - for _, member := range resp.Members { - mlist = append(mlist, member.ClientURLs...) - } - return mlist -} - -// Codec implements storage.Interface.Codec. -func (s *store) Codec() runtime.Codec { - return s.codec -} - -// Versioner implements storage.Interface.Versioner. -func (s *store) Versioner() storage.Versioner { - return s.versioner -} - -// Get implements storage.Interface.Get. -func (s *store) Get(ctx context.Context, key string, out runtime.Object, ignoreNotFound bool) error { - key = keyWithPrefix(s.pathPrefix, key) - getResp, err := s.client.KV.Get(ctx, key) - if err != nil { - return err - } - - if len(getResp.Kvs) == 0 { - if ignoreNotFound { - return runtime.SetZeroValue(out) - } - return storage.NewKeyNotFoundError(key, 0) - } - kv := getResp.Kvs[0] - return decode(s.codec, s.versioner, kv.Value, out, kv.ModRevision) -} - -// Create implements storage.Interface.Create. -func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64) error { - if version, err := s.versioner.ObjectResourceVersion(obj); err == nil && version != 0 { - return errors.New("resourceVersion should not be set on objects to be created") - } - data, err := runtime.Encode(s.codec, obj) - if err != nil { - return err - } - key = keyWithPrefix(s.pathPrefix, key) - - opts, err := s.ttlOpts(ctx, int64(ttl)) - if err != nil { - return err - } - - txnResp, err := s.client.KV.Txn(ctx).If( - notFound(key), - ).Then( - clientv3.OpPut(key, string(data), opts...), - ).Commit() - if err != nil { - return err - } - if !txnResp.Succeeded { - return storage.NewKeyExistsError(key, 0) - } - - if out != nil { - putResp := txnResp.Responses[0].GetResponsePut() - return decode(s.codec, s.versioner, data, out, putResp.Header.Revision) - } - return nil -} - -// Delete implements storage.Interface.Delete. -func (s *store) Delete(ctx context.Context, key string, out runtime.Object, precondtions *storage.Preconditions) error { - v, err := conversion.EnforcePtr(out) - if err != nil { - panic("unable to convert output object to pointer") - } - key = keyWithPrefix(s.pathPrefix, key) - if precondtions == nil { - return s.unconditionalDelete(ctx, key, out) - } - return s.conditionalDelete(ctx, key, out, v, precondtions) -} - -func (s *store) unconditionalDelete(ctx context.Context, key string, out runtime.Object) error { - // We need to do get and delete in single transaction in order to - // know the value and revision before deleting it. - txnResp, err := s.client.KV.Txn(ctx).If().Then( - clientv3.OpGet(key), - clientv3.OpDelete(key), - ).Commit() - if err != nil { - return err - } - getResp := txnResp.Responses[0].GetResponseRange() - if len(getResp.Kvs) == 0 { - return storage.NewKeyNotFoundError(key, 0) - } - - kv := getResp.Kvs[0] - return decode(s.codec, s.versioner, kv.Value, out, kv.ModRevision) -} - -func (s *store) conditionalDelete(ctx context.Context, key string, out runtime.Object, v reflect.Value, precondtions *storage.Preconditions) error { - getResp, err := s.client.KV.Get(ctx, key) - if err != nil { - return err - } - for { - origState, err := s.getState(getResp, key, v, false) - if err != nil { - return err - } - if err := checkPreconditions(key, precondtions, origState.obj); err != nil { - return err - } - txnResp, err := s.client.KV.Txn(ctx).If( - clientv3.Compare(clientv3.ModRevision(key), "=", origState.rev), - ).Then( - clientv3.OpDelete(key), - ).Else( - clientv3.OpGet(key), - ).Commit() - if err != nil { - return err - } - if !txnResp.Succeeded { - getResp = (*clientv3.GetResponse)(txnResp.Responses[0].GetResponseRange()) - glog.V(4).Infof("deletion of %s failed because of a conflict, going to retry", key) - continue - } - return decode(s.codec, s.versioner, origState.data, out, origState.rev) - } -} - -// GuaranteedUpdate implements storage.Interface.GuaranteedUpdate. -func (s *store) GuaranteedUpdate(ctx context.Context, key string, out runtime.Object, ignoreNotFound bool, precondtions *storage.Preconditions, tryUpdate storage.UpdateFunc) error { - v, err := conversion.EnforcePtr(out) - if err != nil { - panic("unable to convert output object to pointer") - } - key = keyWithPrefix(s.pathPrefix, key) - getResp, err := s.client.KV.Get(ctx, key) - if err != nil { - return err - } - for { - origState, err := s.getState(getResp, key, v, ignoreNotFound) - if err != nil { - return err - } - - if err := checkPreconditions(key, precondtions, origState.obj); err != nil { - return err - } - - ret, ttl, err := s.updateState(origState, tryUpdate) - if err != nil { - return err - } - - data, err := runtime.Encode(s.codec, ret) - if err != nil { - return err - } - if bytes.Equal(data, origState.data) { - return decode(s.codec, s.versioner, origState.data, out, origState.rev) - } - - opts, err := s.ttlOpts(ctx, int64(ttl)) - if err != nil { - return err - } - - txnResp, err := s.client.KV.Txn(ctx).If( - clientv3.Compare(clientv3.ModRevision(key), "=", origState.rev), - ).Then( - clientv3.OpPut(key, string(data), opts...), - ).Else( - clientv3.OpGet(key), - ).Commit() - if err != nil { - return err - } - if !txnResp.Succeeded { - getResp = (*clientv3.GetResponse)(txnResp.Responses[0].GetResponseRange()) - glog.V(4).Infof("GuaranteedUpdate of %s failed because of a conflict, going to retry", key) - continue - } - putResp := txnResp.Responses[0].GetResponsePut() - return decode(s.codec, s.versioner, data, out, putResp.Header.Revision) - } -} - -// GetToList implements storage.Interface.GetToList. -func (s *store) GetToList(ctx context.Context, key string, filter storage.FilterFunc, listObj runtime.Object) error { - listPtr, err := meta.GetItemsPtr(listObj) - if err != nil { - return err - } - key = keyWithPrefix(s.pathPrefix, key) - - getResp, err := s.client.KV.Get(ctx, key) - if err != nil { - return err - } - if len(getResp.Kvs) == 0 { - return nil - } - elems := []*elemForDecode{{ - data: getResp.Kvs[0].Value, - rev: uint64(getResp.Kvs[0].ModRevision), - }} - if err := decodeList(elems, filter, listPtr, s.codec, s.versioner); err != nil { - return err - } - // update version with cluster level revision - return s.versioner.UpdateList(listObj, uint64(getResp.Header.Revision)) -} - -// List implements storage.Interface.List. -func (s *store) List(ctx context.Context, key, resourceVersion string, filter storage.FilterFunc, listObj runtime.Object) error { - listPtr, err := meta.GetItemsPtr(listObj) - if err != nil { - return err - } - key = keyWithPrefix(s.pathPrefix, key) - // We need to make sure the key ended with "/" so that we only get children "directories". - // e.g. if we have key "/a", "/a/b", "/ab", getting keys with prefix "/a" will return all three, - // while with prefix "/a/" will return only "/a/b" which is the correct answer. - if !strings.HasSuffix(key, "/") { - key += "/" - } - getResp, err := s.client.KV.Get(ctx, key, clientv3.WithPrefix()) - if err != nil { - return err - } - - elems := make([]*elemForDecode, len(getResp.Kvs)) - for i, kv := range getResp.Kvs { - elems[i] = &elemForDecode{ - data: kv.Value, - rev: uint64(kv.ModRevision), - } - } - if err := decodeList(elems, filter, listPtr, s.codec, s.versioner); err != nil { - return err - } - // update version with cluster level revision - return s.versioner.UpdateList(listObj, uint64(getResp.Header.Revision)) -} - -// Watch implements storage.Interface.Watch. -func (s *store) Watch(ctx context.Context, key string, resourceVersion string, filter storage.FilterFunc) (watch.Interface, error) { - return s.watch(ctx, key, resourceVersion, filter, false) -} - -// WatchList implements storage.Interface.WatchList. -func (s *store) WatchList(ctx context.Context, key string, resourceVersion string, filter storage.FilterFunc) (watch.Interface, error) { - return s.watch(ctx, key, resourceVersion, filter, true) -} - -func (s *store) watch(ctx context.Context, key string, rv string, filter storage.FilterFunc, recursive bool) (watch.Interface, error) { - rev, err := storage.ParseWatchResourceVersion(rv) - if err != nil { - return nil, err - } - key = keyWithPrefix(s.pathPrefix, key) - return s.watcher.Watch(ctx, key, int64(rev), recursive, filter) -} - -func (s *store) getState(getResp *clientv3.GetResponse, key string, v reflect.Value, ignoreNotFound bool) (*objState, error) { - state := &objState{ - obj: reflect.New(v.Type()).Interface().(runtime.Object), - meta: &storage.ResponseMeta{}, - } - if len(getResp.Kvs) == 0 { - if !ignoreNotFound { - return nil, storage.NewKeyNotFoundError(key, 0) - } - if err := runtime.SetZeroValue(state.obj); err != nil { - return nil, err - } - } else { - state.rev = getResp.Kvs[0].ModRevision - state.meta.ResourceVersion = uint64(state.rev) - state.data = getResp.Kvs[0].Value - if err := decode(s.codec, s.versioner, state.data, state.obj, state.rev); err != nil { - return nil, err - } - } - return state, nil -} - -func (s *store) updateState(st *objState, userUpdate storage.UpdateFunc) (runtime.Object, uint64, error) { - ret, ttlPtr, err := userUpdate(st.obj, *st.meta) - if err != nil { - return nil, 0, err - } - - version, err := s.versioner.ObjectResourceVersion(ret) - if err != nil { - return nil, 0, err - } - if version != 0 { - // We cannot store object with resourceVersion in etcd. We need to reset it. - if err := s.versioner.UpdateObject(ret, 0); err != nil { - return nil, 0, fmt.Errorf("UpdateObject failed: %v", err) - } - } - var ttl uint64 - if ttlPtr != nil { - ttl = *ttlPtr - } - return ret, ttl, nil -} - -// ttlOpts returns client options based on given ttl. -// ttl: if ttl is non-zero, it will attach the key to a lease with ttl of roughly the same length -func (s *store) ttlOpts(ctx context.Context, ttl int64) ([]clientv3.OpOption, error) { - if ttl == 0 { - return nil, nil - } - // TODO: one lease per ttl key is expensive. Based on current use case, we can have a long window to - // put keys within into same lease. We shall benchmark this and optimize the performance. - lcr, err := s.client.Lease.Grant(ctx, ttl) - if err != nil { - return nil, err - } - return []clientv3.OpOption{clientv3.WithLease(clientv3.LeaseID(lcr.ID))}, nil -} - -func keyWithPrefix(prefix, key string) string { - if strings.HasPrefix(key, prefix) { - return key - } - return path.Join(prefix, key) -} - -// decode decodes value of bytes into object. It will also set the object resource version to rev. -// On success, objPtr would be set to the object. -func decode(codec runtime.Codec, versioner storage.Versioner, value []byte, objPtr runtime.Object, rev int64) error { - if _, err := conversion.EnforcePtr(objPtr); err != nil { - panic("unable to convert output object to pointer") - } - _, _, err := codec.Decode(value, nil, objPtr) - if err != nil { - return err - } - // being unable to set the version does not prevent the object from being extracted - versioner.UpdateObject(objPtr, uint64(rev)) - return nil -} - -// decodeList decodes a list of values into a list of objects, with resource version set to corresponding rev. -// On success, ListPtr would be set to the list of objects. -func decodeList(elems []*elemForDecode, filter storage.FilterFunc, ListPtr interface{}, codec runtime.Codec, versioner storage.Versioner) error { - v, err := conversion.EnforcePtr(ListPtr) - if err != nil || v.Kind() != reflect.Slice { - panic("need ptr to slice") - } - for _, elem := range elems { - obj, _, err := codec.Decode(elem.data, nil, reflect.New(v.Type().Elem()).Interface().(runtime.Object)) - if err != nil { - return err - } - // being unable to set the version does not prevent the object from being extracted - versioner.UpdateObject(obj, elem.rev) - if filter(obj) { - v.Set(reflect.Append(v, reflect.ValueOf(obj).Elem())) - } - } - return nil -} - -func checkPreconditions(key string, preconditions *storage.Preconditions, out runtime.Object) error { - if preconditions == nil { - return nil - } - objMeta, err := api.ObjectMetaFor(out) - if err != nil { - return storage.NewInternalErrorf("can't enforce preconditions %v on un-introspectable object %v, got error: %v", *preconditions, out, err) - } - if preconditions.UID != nil && *preconditions.UID != objMeta.UID { - errMsg := fmt.Sprintf("Precondition failed: UID in precondition: %v, UID in object meta: %v", preconditions.UID, objMeta.UID) - return storage.NewInvalidObjError(key, errMsg) - } - return nil -} - -func notFound(key string) clientv3.Cmp { - return clientv3.Compare(clientv3.ModRevision(key), "=", 0) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/store_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/store_test.go deleted file mode 100644 index 4da97f602..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/store_test.go +++ /dev/null @@ -1,554 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 etcd3 - -import ( - "fmt" - "reflect" - "sync" - "testing" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - - "github.com/coreos/etcd/integration" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/watch" -) - -func TestCreate(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - etcdClient := cluster.RandClient() - - key := "/testkey" - out := &api.Pod{} - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - - // verify that kv pair is empty before set - getResp, err := etcdClient.KV.Get(ctx, key) - if err != nil { - t.Fatalf("etcdClient.KV.Get failed: %v", err) - } - if len(getResp.Kvs) != 0 { - t.Fatalf("expecting empty result on key: %s", key) - } - - err = store.Create(ctx, key, obj, out, 0) - if err != nil { - t.Fatalf("Set failed: %v", err) - } - // basic tests of the output - if obj.ObjectMeta.Name != out.ObjectMeta.Name { - t.Errorf("pod name want=%s, get=%s", obj.ObjectMeta.Name, out.ObjectMeta.Name) - } - if out.ResourceVersion == "" { - t.Errorf("output should have non-empty resource version") - } - - // verify that kv pair is not empty after set - getResp, err = etcdClient.KV.Get(ctx, key) - if err != nil { - t.Fatalf("etcdClient.KV.Get failed: %v", err) - } - if len(getResp.Kvs) == 0 { - t.Fatalf("expecting non empty result on key: %s", key) - } -} - -func TestCreateWithTTL(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - - input := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - key := "/somekey" - - out := &api.Pod{} - if err := store.Create(ctx, key, input, out, 1); err != nil { - t.Fatalf("Create failed: %v", err) - } - - w, err := store.Watch(ctx, key, out.ResourceVersion, storage.Everything) - if err != nil { - t.Fatalf("Watch failed: %v", err) - } - testCheckResult(t, 0, watch.Deleted, w, nil) -} - -func TestCreateWithKeyExist(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - obj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - key, _ := testPropogateStore(t, store, ctx, obj) - out := &api.Pod{} - err := store.Create(ctx, key, obj, out, 0) - if err == nil || !storage.IsNodeExist(err) { - t.Errorf("expecting key exists error, but get: %s", err) - } -} - -func TestGet(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, storedObj := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - - tests := []struct { - key string - ignoreNotFound bool - expectNotFoundErr bool - expectedOut *api.Pod - }{{ // test get on existing item - key: key, - ignoreNotFound: false, - expectNotFoundErr: false, - expectedOut: storedObj, - }, { // test get on non-existing item with ignoreNotFound=false - key: "/non-existing", - ignoreNotFound: false, - expectNotFoundErr: true, - }, { // test get on non-existing item with ignoreNotFound=true - key: "/non-existing", - ignoreNotFound: true, - expectNotFoundErr: false, - expectedOut: &api.Pod{}, - }} - - for i, tt := range tests { - out := &api.Pod{} - err := store.Get(ctx, tt.key, out, tt.ignoreNotFound) - if tt.expectNotFoundErr { - if err == nil || !storage.IsNotFound(err) { - t.Errorf("#%d: expecting not found error, but get: %s", i, err) - } - continue - } - if err != nil { - t.Fatalf("Get failed: %v", err) - } - if !reflect.DeepEqual(tt.expectedOut, out) { - t.Errorf("#%d: pod want=%#v, get=%#v", i, tt.expectedOut, out) - } - } -} - -func TestUnconditionalDelete(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, storedObj := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - - tests := []struct { - key string - expectedObj *api.Pod - expectNotFoundErr bool - }{{ // test unconditional delete on existing key - key: key, - expectedObj: storedObj, - expectNotFoundErr: false, - }, { // test unconditional delete on non-existing key - key: "/non-existing", - expectedObj: nil, - expectNotFoundErr: true, - }} - - for i, tt := range tests { - out := &api.Pod{} // reset - err := store.Delete(ctx, tt.key, out, nil) - if tt.expectNotFoundErr { - if err == nil || !storage.IsNotFound(err) { - t.Errorf("#%d: expecting not found error, but get: %s", i, err) - } - continue - } - if err != nil { - t.Fatalf("Delete failed: %v", err) - } - if !reflect.DeepEqual(tt.expectedObj, out) { - t.Errorf("#%d: pod want=%#v, get=%#v", i, tt.expectedObj, out) - } - } -} - -func TestConditionalDelete(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, storedObj := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", UID: "A"}}) - - tests := []struct { - precondition *storage.Preconditions - expectInvalidObjErr bool - }{{ // test conditional delete with UID match - precondition: storage.NewUIDPreconditions("A"), - expectInvalidObjErr: false, - }, { // test conditional delete with UID mismatch - precondition: storage.NewUIDPreconditions("B"), - expectInvalidObjErr: true, - }} - - for i, tt := range tests { - out := &api.Pod{} - err := store.Delete(ctx, key, out, tt.precondition) - if tt.expectInvalidObjErr { - if err == nil || !storage.IsInvalidObj(err) { - t.Errorf("#%d: expecting invalid UID error, but get: %s", i, err) - } - continue - } - if err != nil { - t.Fatalf("Delete failed: %v", err) - } - if !reflect.DeepEqual(storedObj, out) { - t.Errorf("#%d: pod want=%#v, get=%#v", i, storedObj, out) - } - key, storedObj = testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", UID: "A"}}) - } -} - -func TestGetToList(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, storedObj := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - - tests := []struct { - key string - filter storage.FilterFunc - expectedOut []*api.Pod - }{{ // test GetToList on existing key - key: key, - filter: storage.Everything, - expectedOut: []*api.Pod{storedObj}, - }, { // test GetToList on non-existing key - key: "/non-existing", - filter: storage.Everything, - expectedOut: nil, - }, { // test GetToList with filter to reject the pod - key: "/non-existing", - filter: func(obj runtime.Object) bool { - pod, ok := obj.(*api.Pod) - if !ok { - t.Fatal("It should be able to convert obj to *api.Pod") - } - return pod.Name != storedObj.Name - }, - expectedOut: nil, - }} - - for i, tt := range tests { - out := &api.PodList{} - err := store.GetToList(ctx, tt.key, tt.filter, out) - if err != nil { - t.Fatalf("GetToList failed: %v", err) - } - if len(out.Items) != len(tt.expectedOut) { - t.Errorf("#%d: length of list want=%d, get=%d", i, len(tt.expectedOut), len(out.Items)) - continue - } - for j, wantPod := range tt.expectedOut { - getPod := &out.Items[j] - if !reflect.DeepEqual(wantPod, getPod) { - t.Errorf("#%d: pod want=%#v, get=%#v", i, wantPod, getPod) - } - } - } -} - -func TestGuaranteedUpdate(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, storeObj := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo", UID: "A"}}) - - tests := []struct { - key string - name string - ignoreNotFound bool - precondition *storage.Preconditions - expectNotFoundErr bool - expectInvalidObjErr bool - expectNoUpdate bool - }{{ // GuaranteedUpdate on non-existing key with ignoreNotFound=false - key: "/non-existing", - ignoreNotFound: false, - precondition: nil, - expectNotFoundErr: true, - expectInvalidObjErr: false, - expectNoUpdate: false, - }, { // GuaranteedUpdate on non-existing key with ignoreNotFound=true - key: "/non-existing", - ignoreNotFound: true, - precondition: nil, - expectNotFoundErr: false, - expectInvalidObjErr: false, - expectNoUpdate: false, - }, { // GuaranteedUpdate on existing key - key: key, - ignoreNotFound: false, - precondition: nil, - expectNotFoundErr: false, - expectInvalidObjErr: false, - expectNoUpdate: false, - }, { // GuaranteedUpdate with same data - key: key, - ignoreNotFound: false, - precondition: nil, - expectNotFoundErr: false, - expectInvalidObjErr: false, - expectNoUpdate: true, - }, { // GuaranteedUpdate with UID match - key: key, - ignoreNotFound: false, - precondition: storage.NewUIDPreconditions("A"), - expectNotFoundErr: false, - expectInvalidObjErr: false, - expectNoUpdate: true, - }, { // GuaranteedUpdate with UID mismatch - key: key, - ignoreNotFound: false, - precondition: storage.NewUIDPreconditions("B"), - expectNotFoundErr: false, - expectInvalidObjErr: true, - expectNoUpdate: true, - }} - - for i, tt := range tests { - out := &api.Pod{} - name := fmt.Sprintf("foo-%d", i) - if tt.expectNoUpdate { - name = storeObj.Name - } - version := storeObj.ResourceVersion - err := store.GuaranteedUpdate(ctx, tt.key, out, tt.ignoreNotFound, tt.precondition, - storage.SimpleUpdate(func(obj runtime.Object) (runtime.Object, error) { - if tt.expectNotFoundErr && tt.ignoreNotFound { - if pod := obj.(*api.Pod); pod.Name != "" { - t.Errorf("#%d: expecting zero value, but get=%#v", i, pod) - } - } - pod := *storeObj - pod.Name = name - return &pod, nil - })) - - if tt.expectNotFoundErr { - if err == nil || !storage.IsNotFound(err) { - t.Errorf("#%d: expecting not found error, but get: %v", i, err) - } - continue - } - if tt.expectInvalidObjErr { - if err == nil || !storage.IsInvalidObj(err) { - t.Errorf("#%d: expecting invalid UID error, but get: %s", i, err) - } - continue - } - if err != nil { - t.Fatalf("GuaranteedUpdate failed: %v", err) - } - if out.ObjectMeta.Name != name { - t.Errorf("#%d: pod name want=%s, get=%s", i, name, out.ObjectMeta.Name) - } - switch tt.expectNoUpdate { - case true: - if version != out.ResourceVersion { - t.Errorf("#%d: expect no version change, before=%s, after=%s", i, version, out.ResourceVersion) - } - case false: - if version == out.ResourceVersion { - t.Errorf("#%d: expect version change, but get the same version=%s", i, version) - } - } - storeObj = out - } -} - -func TestGuaranteedUpdateWithTTL(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - - input := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - key := "/somekey" - - out := &api.Pod{} - err := store.GuaranteedUpdate(ctx, key, out, true, nil, - func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) { - ttl := uint64(1) - return input, &ttl, nil - }) - if err != nil { - t.Fatalf("Create failed: %v", err) - } - - w, err := store.Watch(ctx, key, out.ResourceVersion, storage.Everything) - if err != nil { - t.Fatalf("Watch failed: %v", err) - } - testCheckResult(t, 0, watch.Deleted, w, nil) -} - -func TestGuaranteedUpdateWithConflict(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, _ := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - - errChan := make(chan error, 1) - var firstToFinish sync.WaitGroup - var secondToEnter sync.WaitGroup - firstToFinish.Add(1) - secondToEnter.Add(1) - - go func() { - err := store.GuaranteedUpdate(ctx, key, &api.Pod{}, false, nil, - storage.SimpleUpdate(func(obj runtime.Object) (runtime.Object, error) { - pod := obj.(*api.Pod) - pod.Name = "foo-1" - secondToEnter.Wait() - return pod, nil - })) - firstToFinish.Done() - errChan <- err - }() - - updateCount := 0 - err := store.GuaranteedUpdate(ctx, key, &api.Pod{}, false, nil, - storage.SimpleUpdate(func(obj runtime.Object) (runtime.Object, error) { - if updateCount == 0 { - secondToEnter.Done() - firstToFinish.Wait() - } - updateCount++ - pod := obj.(*api.Pod) - pod.Name = "foo-2" - return pod, nil - })) - if err != nil { - t.Fatalf("Second GuaranteedUpdate error %#v", err) - } - if err := <-errChan; err != nil { - t.Fatalf("First GuaranteedUpdate error %#v", err) - } - - if updateCount != 2 { - t.Errorf("Should have conflict and called update func twice") - } -} - -func TestList(t *testing.T) { - cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) - defer cluster.Terminate(t) - store := newStore(cluster.RandClient(), testapi.Default.Codec(), "") - ctx := context.Background() - - // Setup storage with the following structure: - // / - // - one-level/ - // | - test - // | - // - two-level/ - // - 1/ - // | - test - // | - // - 2/ - // - test - preset := []struct { - key string - obj *api.Pod - storedObj *api.Pod - }{{ - key: "/one-level/test", - obj: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, - }, { - key: "/two-level/1/test", - obj: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, - }, { - key: "/two-level/2/test", - obj: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}}, - }} - - for i, ps := range preset { - preset[i].storedObj = &api.Pod{} - err := store.Create(ctx, ps.key, ps.obj, preset[i].storedObj, 0) - if err != nil { - t.Fatalf("Set failed: %v", err) - } - } - - tests := []struct { - prefix string - filter storage.FilterFunc - expectedOut []*api.Pod - }{{ // test List on existing key - prefix: "/one-level/", - filter: storage.Everything, - expectedOut: []*api.Pod{preset[0].storedObj}, - }, { // test List on non-existing key - prefix: "/non-existing/", - filter: storage.Everything, - expectedOut: nil, - }, { // test List with filter - prefix: "/one-level/", - filter: func(obj runtime.Object) bool { - pod, ok := obj.(*api.Pod) - if !ok { - t.Fatal("It should be able to convert obj to *api.Pod") - } - return pod.Name != preset[0].storedObj.Name - }, - expectedOut: nil, - }, { // test List with multiple levels of directories and expect flattened result - prefix: "/two-level/", - filter: storage.Everything, - expectedOut: []*api.Pod{preset[1].storedObj, preset[2].storedObj}, - }} - - for i, tt := range tests { - out := &api.PodList{} - err := store.List(ctx, tt.prefix, "0", tt.filter, out) - if err != nil { - t.Fatalf("List failed: %v", err) - } - if len(tt.expectedOut) != len(out.Items) { - t.Errorf("#%d: length of list want=%d, get=%d", i, len(tt.expectedOut), len(out.Items)) - continue - } - for j, wantPod := range tt.expectedOut { - getPod := &out.Items[j] - if !reflect.DeepEqual(wantPod, getPod) { - t.Errorf("#%d: pod want=%#v, get=%#v", i, wantPod, getPod) - } - } - } -} - -func testSetup(t *testing.T) (context.Context, *store, *integration.ClusterV3) { - cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) - store := newStore(cluster.RandClient(), testapi.Default.Codec(), "") - ctx := context.Background() - return ctx, store, cluster -} - -// testPropogateStore helps propogates store with objects, automates key generation, and returns -// keys and stored objects. -func testPropogateStore(t *testing.T, store *store, ctx context.Context, obj *api.Pod) (string, *api.Pod) { - // Setup store with a key and grab the output for returning. - key := "/testkey" - setOutput := &api.Pod{} - err := store.Create(ctx, key, obj, setOutput, 0) - if err != nil { - t.Fatalf("Set failed: %v", err) - } - return key, setOutput -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/watcher.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/watcher.go deleted file mode 100644 index 6d1490c01..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/watcher.go +++ /dev/null @@ -1,340 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 etcd3 - -import ( - "fmt" - "net/http" - "strings" - "sync" - - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/watch" - - "github.com/coreos/etcd/clientv3" - etcdrpc "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" - "github.com/golang/glog" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" -) - -const ( - // We have set a buffer in order to reduce times of context switches. - incomingBufSize = 100 - outgoingBufSize = 100 -) - -type watcher struct { - client *clientv3.Client - codec runtime.Codec - versioner storage.Versioner -} - -// watchChan implements watch.Interface. -type watchChan struct { - watcher *watcher - key string - initialRev int64 - recursive bool - filter storage.FilterFunc - ctx context.Context - cancel context.CancelFunc - incomingEventChan chan *event - resultChan chan watch.Event - errChan chan error -} - -func newWatcher(client *clientv3.Client, codec runtime.Codec, versioner storage.Versioner) *watcher { - return &watcher{ - client: client, - codec: codec, - versioner: versioner, - } -} - -// Watch watches on a key and returns a watch.Interface that transfers relevant notifications. -// If rev is zero, it will return the existing object(s) and then start watching from -// the maximum revision+1 from returned objects. -// If rev is non-zero, it will watch events happened after given revision. -// If recursive is false, it watches on given key. -// If recursive is true, it watches any children and directories under the key, excluding the root key itself. -// filter must be non-nil. Only if filter returns true will the changes be returned. -func (w *watcher) Watch(ctx context.Context, key string, rev int64, recursive bool, filter storage.FilterFunc) (watch.Interface, error) { - if recursive && !strings.HasSuffix(key, "/") { - key += "/" - } - wc := w.createWatchChan(ctx, key, rev, recursive, filter) - go wc.run() - return wc, nil -} - -func (w *watcher) createWatchChan(ctx context.Context, key string, rev int64, recursive bool, filter storage.FilterFunc) *watchChan { - wc := &watchChan{ - watcher: w, - key: key, - initialRev: rev, - recursive: recursive, - filter: filter, - incomingEventChan: make(chan *event, incomingBufSize), - resultChan: make(chan watch.Event, outgoingBufSize), - errChan: make(chan error, 1), - } - wc.ctx, wc.cancel = context.WithCancel(ctx) - return wc -} - -func (wc *watchChan) run() { - go wc.startWatching() - - var resultChanWG sync.WaitGroup - resultChanWG.Add(1) - go wc.processEvent(&resultChanWG) - - select { - case err := <-wc.errChan: - errResult := parseError(err) - wc.cancel() - // error result is guaranteed to be received by user before closing ResultChan. - if errResult != nil { - wc.resultChan <- *errResult - } - case <-wc.ctx.Done(): - } - // we need to wait until resultChan wouldn't be sent to anymore - resultChanWG.Wait() - close(wc.resultChan) -} - -func (wc *watchChan) Stop() { - wc.cancel() -} - -func (wc *watchChan) ResultChan() <-chan watch.Event { - return wc.resultChan -} - -// sync tries to retrieve existing data and send them to process. -// The revision to watch will be set to the revision in response. -func (wc *watchChan) sync() error { - opts := []clientv3.OpOption{} - if wc.recursive { - opts = append(opts, clientv3.WithPrefix()) - } - getResp, err := wc.watcher.client.Get(wc.ctx, wc.key, opts...) - if err != nil { - return err - } - wc.initialRev = getResp.Header.Revision - - for _, kv := range getResp.Kvs { - wc.sendEvent(parseKV(kv)) - } - return nil -} - -// startWatching does: -// - get current objects if initialRev=0; set initialRev to current rev -// - watch on given key and send events to process. -func (wc *watchChan) startWatching() { - if wc.initialRev == 0 { - if err := wc.sync(); err != nil { - wc.sendError(err) - return - } - } - opts := []clientv3.OpOption{clientv3.WithRev(wc.initialRev + 1)} - if wc.recursive { - opts = append(opts, clientv3.WithPrefix()) - } - wch := wc.watcher.client.Watch(wc.ctx, wc.key, opts...) - for wres := range wch { - if wres.Err() != nil { - // If there is an error on server (e.g. compaction), the channel will return it before closed. - wc.sendError(wres.Err()) - return - } - for _, e := range wres.Events { - wc.sendEvent(parseEvent(e)) - } - } -} - -// processEvent processes events from etcd watcher and sends results to resultChan. -func (wc *watchChan) processEvent(wg *sync.WaitGroup) { - defer wg.Done() - - for { - select { - case e := <-wc.incomingEventChan: - res := wc.transform(e) - if res == nil { - continue - } - // If user couldn't receive results fast enough, we also block incoming events from watcher. - // Because storing events in local will cause more memory usage. - // The worst case would be closing the fast watcher. - select { - case wc.resultChan <- *res: - case <-wc.ctx.Done(): - return - } - case <-wc.ctx.Done(): - return - } - } -} - -// transform transforms an event into a result for user if not filtered. -// TODO (Optimization): -// - Save remote round-trip. -// Currently, DELETE and PUT event don't contain the previous value. -// We need to do another Get() in order to get previous object and have logic upon it. -// We could potentially do some optimizations: -// - For PUT, we can save current and previous objects into the value. -// - For DELETE, See https://github.com/coreos/etcd/issues/4620 -func (wc *watchChan) transform(e *event) (res *watch.Event) { - curObj, oldObj, err := prepareObjs(wc.ctx, e, wc.watcher.client, wc.watcher.codec, wc.watcher.versioner) - if err != nil { - wc.sendError(err) - return nil - } - - switch { - case e.isDeleted: - if !wc.filter(oldObj) { - return nil - } - res = &watch.Event{ - Type: watch.Deleted, - Object: oldObj, - } - case e.isCreated: - if !wc.filter(curObj) { - return nil - } - res = &watch.Event{ - Type: watch.Added, - Object: curObj, - } - default: - curObjPasses := wc.filter(curObj) - oldObjPasses := wc.filter(oldObj) - switch { - case curObjPasses && oldObjPasses: - res = &watch.Event{ - Type: watch.Modified, - Object: curObj, - } - case curObjPasses && !oldObjPasses: - res = &watch.Event{ - Type: watch.Added, - Object: curObj, - } - case !curObjPasses && oldObjPasses: - res = &watch.Event{ - Type: watch.Deleted, - Object: oldObj, - } - } - } - return res -} - -func parseError(err error) *watch.Event { - var status *unversioned.Status - switch { - case err == etcdrpc.ErrCompacted: - status = &unversioned.Status{ - Status: unversioned.StatusFailure, - Message: err.Error(), - Code: http.StatusGone, - Reason: unversioned.StatusReasonExpired, - } - default: - status = &unversioned.Status{ - Status: unversioned.StatusFailure, - Message: err.Error(), - Code: http.StatusInternalServerError, - Reason: unversioned.StatusReasonInternalError, - } - } - - return &watch.Event{ - Type: watch.Error, - Object: status, - } -} - -func (wc *watchChan) sendError(err error) { - // Context.canceled is an expected behavior. - // We should just stop all goroutines in watchChan without returning error. - // TODO: etcd client should return context.Canceled instead of grpc specific error. - if grpc.Code(err) == codes.Canceled || err == context.Canceled { - return - } - select { - case wc.errChan <- err: - case <-wc.ctx.Done(): - } -} - -func (wc *watchChan) sendEvent(e *event) { - if len(wc.incomingEventChan) == incomingBufSize { - glog.V(2).Infof("Fast watcher, slow processing. Number of buffered events: %d."+ - "Probably caused by slow decoding, user not receiving fast, or other processing logic", - incomingBufSize) - } - select { - case wc.incomingEventChan <- e: - case <-wc.ctx.Done(): - } -} - -func prepareObjs(ctx context.Context, e *event, client *clientv3.Client, codec runtime.Codec, versioner storage.Versioner) (curObj runtime.Object, oldObj runtime.Object, err error) { - if !e.isDeleted { - curObj, err = decodeObj(codec, versioner, e.value, e.rev) - if err != nil { - return nil, nil, err - } - } - if e.isDeleted || !e.isCreated { - getResp, err := client.Get(ctx, e.key, clientv3.WithRev(e.rev-1)) - if err != nil { - return nil, nil, err - } - oldObj, err = decodeObj(codec, versioner, getResp.Kvs[0].Value, getResp.Kvs[0].ModRevision) - if err != nil { - return nil, nil, err - } - } - return curObj, oldObj, nil -} - -func decodeObj(codec runtime.Codec, versioner storage.Versioner, data []byte, rev int64) (runtime.Object, error) { - obj, err := runtime.Decode(codec, []byte(data)) - if err != nil { - return nil, err - } - // ensure resource version is set on the object we load from etcd - if err := versioner.UpdateObject(obj, uint64(rev)); err != nil { - return nil, fmt.Errorf("failure to version api object (%d) %#v: %v", rev, obj, err) - } - return obj, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/watcher_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/watcher_test.go deleted file mode 100644 index 66578e56c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/etcd3/watcher_test.go +++ /dev/null @@ -1,235 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 etcd3 - -import ( - "errors" - "reflect" - "testing" - "time" - - "github.com/coreos/etcd/integration" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/testapi" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" -) - -func TestWatch(t *testing.T) { - testWatch(t, false) -} - -func TestWatchList(t *testing.T) { - testWatch(t, true) -} - -// It tests that -// - first occurrence of objects should notify Add event -// - -func testWatch(t *testing.T, recursive bool) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - - podFoo := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} - podBar := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}} - - tests := []struct { - key string - filter storage.FilterFunc - watchTests []*testWatchStruct - }{{ // create a key - key: "/somekey-1", - watchTests: []*testWatchStruct{{podFoo, true, watch.Added}}, - filter: storage.Everything, - }, { // create a key but obj gets filtered - key: "/somekey-2", - watchTests: []*testWatchStruct{{podFoo, false, ""}}, - filter: func(runtime.Object) bool { return false }, - }, { // create a key but obj gets filtered. Then update it with unfiltered obj - key: "/somekey-3", - watchTests: []*testWatchStruct{{podFoo, false, ""}, {podBar, true, watch.Added}}, - filter: func(obj runtime.Object) bool { - pod := obj.(*api.Pod) - return pod.Name == "bar" - }, - }, { // update - key: "/somekey-4", - watchTests: []*testWatchStruct{{podFoo, true, watch.Added}, {podBar, true, watch.Modified}}, - filter: storage.Everything, - }, { // delete because of being filtered - key: "/somekey-5", - watchTests: []*testWatchStruct{{podFoo, true, watch.Added}, {podBar, true, watch.Deleted}}, - filter: func(obj runtime.Object) bool { - pod := obj.(*api.Pod) - return pod.Name != "bar" - }, - }} - for i, tt := range tests { - w, err := store.watch(ctx, tt.key, "0", tt.filter, recursive) - if err != nil { - t.Fatalf("Watch failed: %v", err) - } - for _, watchTest := range tt.watchTests { - out := &api.Pod{} - key := tt.key - if recursive { - key = key + "/item" - } - err := store.GuaranteedUpdate(ctx, key, out, true, nil, storage.SimpleUpdate( - func(runtime.Object) (runtime.Object, error) { - return watchTest.obj, nil - })) - if err != nil { - t.Fatalf("GuaranteedUpdate failed: %v", err) - } - if watchTest.expectEvent { - testCheckResult(t, i, watchTest.watchType, w, nil) - } - } - w.Stop() - testCheckStop(t, i, w) - } -} - -func TestDeleteTriggerWatch(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, storedObj := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - w, err := store.Watch(ctx, key, storedObj.ResourceVersion, storage.Everything) - if err != nil { - t.Fatalf("Watch failed: %v", err) - } - if err := store.Delete(ctx, key, &api.Pod{}, nil); err != nil { - t.Fatalf("Delete failed: %v", err) - } - testCheckResult(t, 0, watch.Deleted, w, storedObj) -} - -// TestWatchSync tests that -// - watch from 0 should sync up and grab the object added before -// - watch from non-0 should just watch changes after given version -func TestWatchFromZeroAndNoneZero(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - key, storedObj := testPropogateStore(t, store, ctx, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}) - - w, err := store.Watch(ctx, key, "0", storage.Everything) - if err != nil { - t.Fatalf("Watch failed: %v", err) - } - testCheckResult(t, 0, watch.Added, w, storedObj) - w.Stop() - testCheckStop(t, 0, w) - - w, err = store.Watch(ctx, key, storedObj.ResourceVersion, storage.Everything) - if err != nil { - t.Fatalf("Watch failed: %v", err) - } - out := &api.Pod{} - store.GuaranteedUpdate(ctx, key, out, true, nil, storage.SimpleUpdate( - func(runtime.Object) (runtime.Object, error) { - return &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}}, err - })) - testCheckResult(t, 0, watch.Modified, w, out) -} - -func TestWatchError(t *testing.T) { - cluster := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) - defer cluster.Terminate(t) - invalidStore := newStore(cluster.RandClient(), &testCodec{testapi.Default.Codec()}, "") - ctx := context.Background() - w, err := invalidStore.Watch(ctx, "/abc", "0", storage.Everything) - if err != nil { - t.Fatalf("Watch failed: %v", err) - } - validStore := newStore(cluster.RandClient(), testapi.Default.Codec(), "") - validStore.GuaranteedUpdate(ctx, "/abc", &api.Pod{}, true, nil, storage.SimpleUpdate( - func(runtime.Object) (runtime.Object, error) { - return &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, nil - })) - testCheckResult(t, 0, watch.Error, w, nil) -} - -func TestWatchContextCancel(t *testing.T) { - ctx, store, cluster := testSetup(t) - defer cluster.Terminate(t) - canceledCtx, cancel := context.WithCancel(ctx) - cancel() - w := store.watcher.createWatchChan(canceledCtx, "/abc", 0, false, storage.Everything) - // When we do a client.Get with a canceled context, it will return error. - // Nonetheless, when we try to send it over internal errChan, we should detect - // it's context canceled and not send it. - err := w.sync() - w.ctx = ctx - w.sendError(err) - select { - case err := <-w.errChan: - t.Errorf("cancelling context shouldn't return any error. Err: %v", err) - default: - } -} - -type testWatchStruct struct { - obj *api.Pod - expectEvent bool - watchType watch.EventType -} - -type testCodec struct { - runtime.Codec -} - -func (c *testCodec) Decode(data []byte, defaults *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) { - return nil, nil, errors.New("Expected decoding failure") -} - -func testCheckResult(t *testing.T, i int, expectEventType watch.EventType, w watch.Interface, expectObj *api.Pod) { - select { - case res := <-w.ResultChan(): - if res.Type != expectEventType { - t.Errorf("#%d: event type want=%v, get=%v", i, expectEventType, res.Type) - return - } - if expectObj != nil && !reflect.DeepEqual(expectObj, res.Object) { - t.Errorf("#%d: obj want=\n%#v\nget=\n%#v", i, expectObj, res.Object) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("#%d: time out after waiting %v on ResultChan", i, wait.ForeverTestTimeout) - } -} - -func testCheckStop(t *testing.T, i int, w watch.Interface) { - select { - case e, ok := <-w.ResultChan(): - if ok { - var obj string - switch e.Object.(type) { - case *api.Pod: - obj = e.Object.(*api.Pod).Name - case *unversioned.Status: - obj = e.Object.(*unversioned.Status).Message - } - t.Errorf("#%d: ResultChan should have been closed. Event: %s. Object: %s", i, e.Type, obj) - } - case <-time.After(wait.ForeverTestTimeout): - t.Errorf("#%d: time out after waiting 1s on ResultChan", i) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/config.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/config.go deleted file mode 100644 index 6d3b127e7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/config.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 storagebackend - -import ( - "fmt" - - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" -) - -const ( - StorageTypeUnset = "" - StorageTypeETCD2 = "etcd2" - StorageTypeETCD3 = "etcd3" -) - -// Config is configuration for creating a storage backend. -type Config struct { - // Type defines the type of storage backend, e.g. "etcd2", etcd3". Default ("") is "etcd2". - Type string - // Codec is used to serialize/deserialize objects. - Codec runtime.Codec - // Prefix is the prefix to all keys passed to storage.Interface methods. - Prefix string - // ServerList is the list of storage servers to connect with. - ServerList []string - // TLS credentials - KeyFile string - CertFile string - CAFile string - // Quorum indicates that whether read operations should be quorum-level consistent. - Quorum bool - // DeserializationCacheSize is the size of cache of deserialized objects. - // Currently this is only supported in etcd2. - // We will drop the cache once using protobuf. - DeserializationCacheSize int -} - -// Create creates a storage backend based on given config. -func Create(c Config) (storage.Interface, error) { - switch c.Type { - case StorageTypeUnset, StorageTypeETCD2: - return newETCD2Storage(c) - case StorageTypeETCD3: - // TODO: We have the following features to implement: - // - Support secure connection by using key, cert, and CA files. - // - Honor "https" scheme to support secure connection in gRPC. - // - Support non-quorum read. - return newETCD3Storage(c) - default: - return nil, fmt.Errorf("unknown storage type: %s", c.Type) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/etcd3.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/etcd3.go deleted file mode 100644 index 7699eec7b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/etcd3.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 storagebackend - -import ( - "strings" - - "github.com/coreos/etcd/clientv3" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/storage/etcd3" -) - -func newETCD3Storage(c Config) (storage.Interface, error) { - endpoints := c.ServerList - for i, s := range endpoints { - endpoints[i] = strings.TrimLeft(s, "http://") - } - cfg := clientv3.Config{ - Endpoints: endpoints, - } - client, err := clientv3.New(cfg) - if err != nil { - return nil, err - } - etcd3.StartCompactor(context.Background(), client) - return etcd3.New(client, c.Codec, c.Prefix), nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/etdc2.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/etdc2.go deleted file mode 100644 index b1176042e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/storagebackend/etdc2.go +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 storagebackend - -import ( - "net" - "net/http" - "time" - - etcd2client "github.com/coreos/etcd/client" - "github.com/coreos/etcd/pkg/transport" - "k8s.io/kubernetes/pkg/storage" - "k8s.io/kubernetes/pkg/storage/etcd" - utilnet "k8s.io/kubernetes/pkg/util/net" -) - -func newETCD2Storage(c Config) (storage.Interface, error) { - tr, err := newTransportForETCD2(c.CertFile, c.KeyFile, c.CAFile) - if err != nil { - return nil, err - } - client, err := newETCD2Client(tr, c.ServerList) - if err != nil { - return nil, err - } - return etcd.NewEtcdStorage(client, c.Codec, c.Prefix, c.Quorum, c.DeserializationCacheSize), nil -} - -func newETCD2Client(tr *http.Transport, serverList []string) (etcd2client.Client, error) { - cli, err := etcd2client.New(etcd2client.Config{ - Endpoints: serverList, - Transport: tr, - }) - if err != nil { - return nil, err - } - - return cli, nil -} - -func newTransportForETCD2(certFile, keyFile, caFile string) (*http.Transport, error) { - info := transport.TLSInfo{ - CertFile: certFile, - KeyFile: keyFile, - CAFile: caFile, - } - cfg, err := info.ClientConfig() - if err != nil { - return nil, err - } - // Copied from etcd.DefaultTransport declaration. - // TODO: Determine if transport needs optimization - tr := utilnet.SetTransportDefaults(&http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - TLSHandshakeTimeout: 10 * time.Second, - MaxIdleConnsPerHost: 500, - TLSClientConfig: cfg, - }) - return tr, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/types.generated.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/types.generated.go deleted file mode 100644 index 0bdb64f47..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/types.generated.go +++ /dev/null @@ -1,365 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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. -*/ - -// ************************************************************ -// DO NOT EDIT. -// THIS FILE IS AUTO-GENERATED BY codecgen. -// ************************************************************ - -package testing - -import ( - "errors" - "fmt" - codec1978 "github.com/ugorji/go/codec" - pkg2_api "k8s.io/kubernetes/pkg/api" - pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned" - pkg3_types "k8s.io/kubernetes/pkg/types" - "reflect" - "runtime" - time "time" -) - -const ( - // ----- content types ---- - codecSelferC_UTF81234 = 1 - codecSelferC_RAW1234 = 0 - // ----- value types used ---- - codecSelferValueTypeArray1234 = 10 - codecSelferValueTypeMap1234 = 9 - // ----- containerStateValues ---- - codecSelfer_containerMapKey1234 = 2 - codecSelfer_containerMapValue1234 = 3 - codecSelfer_containerMapEnd1234 = 4 - codecSelfer_containerArrayElem1234 = 6 - codecSelfer_containerArrayEnd1234 = 7 -) - -var ( - codecSelferBitsize1234 = uint8(reflect.TypeOf(uint(0)).Bits()) - codecSelferOnlyMapOrArrayEncodeToStructErr1234 = errors.New(`only encoded map or array can be decoded into a struct`) -) - -type codecSelfer1234 struct{} - -func init() { - if codec1978.GenVersion != 5 { - _, file, _, _ := runtime.Caller(0) - err := fmt.Errorf("codecgen version mismatch: current: %v, need %v. Re-generate file: %v", - 5, codec1978.GenVersion, file) - panic(err) - } - if false { // reference the types, but skip this branch at build/run time - var v0 pkg2_api.ObjectMeta - var v1 pkg1_unversioned.TypeMeta - var v2 pkg3_types.UID - var v3 time.Time - _, _, _, _ = v0, v1, v2, v3 - } -} - -func (x *TestResource) CodecEncodeSelf(e *codec1978.Encoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperEncoder(e) - _, _, _ = h, z, r - if x == nil { - r.EncodeNil() - } else { - yym1 := z.EncBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.EncExt(x) { - } else { - yysep2 := !z.EncBinary() - yy2arr2 := z.EncBasicHandle().StructToArray - var yyq2 [4]bool - _, _, _ = yysep2, yyq2, yy2arr2 - const yyr2 bool = false - yyq2[2] = x.Kind != "" - yyq2[3] = x.APIVersion != "" - var yynn2 int - if yyr2 || yy2arr2 { - r.EncodeArrayStart(4) - } else { - yynn2 = 2 - for _, b := range yyq2 { - if b { - yynn2++ - } - } - r.EncodeMapStart(yynn2) - yynn2 = 0 - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yy4 := &x.ObjectMeta - yy4.CodecEncodeSelf(e) - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("metadata")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yy6 := &x.ObjectMeta - yy6.CodecEncodeSelf(e) - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - yym9 := z.EncBinary() - _ = yym9 - if false { - } else { - r.EncodeInt(int64(x.Value)) - } - } else { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("value")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym10 := z.EncBinary() - _ = yym10 - if false { - } else { - r.EncodeInt(int64(x.Value)) - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[2] { - yym12 := z.EncBinary() - _ = yym12 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) - } - } else { - r.EncodeString(codecSelferC_UTF81234, "") - } - } else { - if yyq2[2] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("kind")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym13 := z.EncBinary() - _ = yym13 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.Kind)) - } - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayElem1234) - if yyq2[3] { - yym15 := z.EncBinary() - _ = yym15 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) - } - } else { - r.EncodeString(codecSelferC_UTF81234, "") - } - } else { - if yyq2[3] { - z.EncSendContainerState(codecSelfer_containerMapKey1234) - r.EncodeString(codecSelferC_UTF81234, string("apiVersion")) - z.EncSendContainerState(codecSelfer_containerMapValue1234) - yym16 := z.EncBinary() - _ = yym16 - if false { - } else { - r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion)) - } - } - } - if yyr2 || yy2arr2 { - z.EncSendContainerState(codecSelfer_containerArrayEnd1234) - } else { - z.EncSendContainerState(codecSelfer_containerMapEnd1234) - } - } - } -} - -func (x *TestResource) CodecDecodeSelf(d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - yym1 := z.DecBinary() - _ = yym1 - if false { - } else if z.HasExtensions() && z.DecExt(x) { - } else { - yyct2 := r.ContainerType() - if yyct2 == codecSelferValueTypeMap1234 { - yyl2 := r.ReadMapStart() - if yyl2 == 0 { - z.DecSendContainerState(codecSelfer_containerMapEnd1234) - } else { - x.codecDecodeSelfFromMap(yyl2, d) - } - } else if yyct2 == codecSelferValueTypeArray1234 { - yyl2 := r.ReadArrayStart() - if yyl2 == 0 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - } else { - x.codecDecodeSelfFromArray(yyl2, d) - } - } else { - panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234) - } - } -} - -func (x *TestResource) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - var yys3Slc = z.DecScratchBuffer() // default slice to decode into - _ = yys3Slc - var yyhl3 bool = l >= 0 - for yyj3 := 0; ; yyj3++ { - if yyhl3 { - if yyj3 >= l { - break - } - } else { - if r.CheckBreak() { - break - } - } - z.DecSendContainerState(codecSelfer_containerMapKey1234) - yys3Slc = r.DecodeBytes(yys3Slc, true, true) - yys3 := string(yys3Slc) - z.DecSendContainerState(codecSelfer_containerMapValue1234) - switch yys3 { - case "metadata": - if r.TryDecodeAsNil() { - x.ObjectMeta = pkg2_api.ObjectMeta{} - } else { - yyv4 := &x.ObjectMeta - yyv4.CodecDecodeSelf(d) - } - case "value": - if r.TryDecodeAsNil() { - x.Value = 0 - } else { - x.Value = int(r.DecodeInt(codecSelferBitsize1234)) - } - case "kind": - if r.TryDecodeAsNil() { - x.Kind = "" - } else { - x.Kind = string(r.DecodeString()) - } - case "apiVersion": - if r.TryDecodeAsNil() { - x.APIVersion = "" - } else { - x.APIVersion = string(r.DecodeString()) - } - default: - z.DecStructFieldNotFound(-1, yys3) - } // end switch yys3 - } // end for yyj3 - z.DecSendContainerState(codecSelfer_containerMapEnd1234) -} - -func (x *TestResource) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) { - var h codecSelfer1234 - z, r := codec1978.GenHelperDecoder(d) - _, _, _ = h, z, r - var yyj8 int - var yyb8 bool - var yyhl8 bool = l >= 0 - yyj8++ - if yyhl8 { - yyb8 = yyj8 > l - } else { - yyb8 = r.CheckBreak() - } - if yyb8 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.ObjectMeta = pkg2_api.ObjectMeta{} - } else { - yyv9 := &x.ObjectMeta - yyv9.CodecDecodeSelf(d) - } - yyj8++ - if yyhl8 { - yyb8 = yyj8 > l - } else { - yyb8 = r.CheckBreak() - } - if yyb8 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Value = 0 - } else { - x.Value = int(r.DecodeInt(codecSelferBitsize1234)) - } - yyj8++ - if yyhl8 { - yyb8 = yyj8 > l - } else { - yyb8 = r.CheckBreak() - } - if yyb8 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.Kind = "" - } else { - x.Kind = string(r.DecodeString()) - } - yyj8++ - if yyhl8 { - yyb8 = yyj8 > l - } else { - yyb8 = r.CheckBreak() - } - if yyb8 { - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) - return - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - if r.TryDecodeAsNil() { - x.APIVersion = "" - } else { - x.APIVersion = string(r.DecodeString()) - } - for { - yyj8++ - if yyhl8 { - yyb8 = yyj8 > l - } else { - yyb8 = r.CheckBreak() - } - if yyb8 { - break - } - z.DecSendContainerState(codecSelfer_containerArrayElem1234) - z.DecStructFieldNotFound(yyj8-1, "") - } - z.DecSendContainerState(codecSelfer_containerArrayEnd1234) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/types.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/types.go deleted file mode 100644 index a1377aa04..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/types.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import ( - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" -) - -type TestResource struct { - unversioned.TypeMeta `json:",inline"` - api.ObjectMeta `json:"metadata"` - Value int `json:"value"` -} - -func (obj *TestResource) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta } diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/utils.go deleted file mode 100644 index 8858e3300..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/testing/utils.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import ( - "path" - - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/api/meta" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/storage" -) - -// CreateObj will create a single object using the storage interface -func CreateObj(helper storage.Interface, name string, obj, out runtime.Object, ttl uint64) error { - return helper.Create(context.TODO(), name, obj, out, ttl) -} - -//CreateObjList will create a list from the array of objects -func CreateObjList(prefix string, helper storage.Interface, items []runtime.Object) error { - for i := range items { - obj := items[i] - meta, err := meta.Accessor(obj) - if err != nil { - return err - } - err = CreateObj(helper, path.Join(prefix, meta.GetName()), obj, obj, 0) - if err != nil { - return err - } - items[i] = obj - } - return nil -} - -// CreateList will properly create a list using the storage interface -func CreateList(prefix string, helper storage.Interface, list runtime.Object) error { - items, err := meta.ExtractList(list) - if err != nil { - return err - } - err = CreateObjList(prefix, helper, items) - if err != nil { - return err - } - return meta.SetList(list, items) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/util_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/util_test.go deleted file mode 100644 index 7d0675cce..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/util_test.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 storage - -import "testing" - -func TestEtcdParseWatchResourceVersion(t *testing.T) { - testCases := []struct { - Version string - ExpectVersion uint64 - Err bool - }{ - {Version: "", ExpectVersion: 0}, - {Version: "a", Err: true}, - {Version: " ", Err: true}, - {Version: "1", ExpectVersion: 1}, - {Version: "10", ExpectVersion: 10}, - } - for _, testCase := range testCases { - version, err := ParseWatchResourceVersion(testCase.Version) - switch { - case testCase.Err: - if err == nil { - t.Errorf("%s: unexpected non-error", testCase.Version) - continue - } - if !IsInvalidError(err) { - t.Errorf("%s: unexpected error: %v", testCase.Version, err) - continue - } - case !testCase.Err && err != nil: - t.Errorf("%s: unexpected error: %v", testCase.Version, err) - continue - } - if version != testCase.ExpectVersion { - t.Errorf("%s: expected version %d but was %d", testCase.Version, testCase.ExpectVersion, version) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/watch_cache_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/watch_cache_test.go deleted file mode 100644 index 8d9327e3c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/storage/watch_cache_test.go +++ /dev/null @@ -1,334 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 storage - -import ( - "strconv" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/client/cache" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util" - "k8s.io/kubernetes/pkg/util/sets" - "k8s.io/kubernetes/pkg/util/wait" - "k8s.io/kubernetes/pkg/watch" -) - -func makeTestPod(name string, resourceVersion uint64) *api.Pod { - return &api.Pod{ - ObjectMeta: api.ObjectMeta{ - Namespace: "ns", - Name: name, - ResourceVersion: strconv.FormatUint(resourceVersion, 10), - }, - } -} - -// newTestWatchCache just adds a fake clock. -func newTestWatchCache(capacity int) *watchCache { - wc := newWatchCache(capacity) - wc.clock = util.NewFakeClock(time.Now()) - return wc -} - -func TestWatchCacheBasic(t *testing.T) { - store := newTestWatchCache(2) - - // Test Add/Update/Delete. - pod1 := makeTestPod("pod", 1) - if err := store.Add(pod1); err != nil { - t.Errorf("unexpected error: %v", err) - } - if item, ok, _ := store.Get(pod1); !ok { - t.Errorf("didn't find pod") - } else { - if !api.Semantic.DeepEqual(pod1, item) { - t.Errorf("expected %v, got %v", pod1, item) - } - } - pod2 := makeTestPod("pod", 2) - if err := store.Update(pod2); err != nil { - t.Errorf("unexpected error: %v", err) - } - if item, ok, _ := store.Get(pod2); !ok { - t.Errorf("didn't find pod") - } else { - if !api.Semantic.DeepEqual(pod2, item) { - t.Errorf("expected %v, got %v", pod1, item) - } - } - pod3 := makeTestPod("pod", 3) - if err := store.Delete(pod3); err != nil { - t.Errorf("unexpected error: %v", err) - } - if _, ok, _ := store.Get(pod3); ok { - t.Errorf("found pod") - } - - // Test List. - store.Add(makeTestPod("pod1", 4)) - store.Add(makeTestPod("pod2", 5)) - store.Add(makeTestPod("pod3", 6)) - { - podNames := sets.String{} - for _, item := range store.List() { - podNames.Insert(item.(*api.Pod).ObjectMeta.Name) - } - if !podNames.HasAll("pod1", "pod2", "pod3") { - t.Errorf("missing pods, found %v", podNames) - } - if len(podNames) != 3 { - t.Errorf("found missing/extra items") - } - } - - // Test Replace. - store.Replace([]interface{}{ - makeTestPod("pod4", 7), - makeTestPod("pod5", 8), - }, "8") - { - podNames := sets.String{} - for _, item := range store.List() { - podNames.Insert(item.(*api.Pod).ObjectMeta.Name) - } - if !podNames.HasAll("pod4", "pod5") { - t.Errorf("missing pods, found %v", podNames) - } - if len(podNames) != 2 { - t.Errorf("found missing/extra items") - } - } -} - -func TestEvents(t *testing.T) { - store := newTestWatchCache(5) - - store.Add(makeTestPod("pod", 3)) - - // Test for Added event. - { - _, err := store.GetAllEventsSince(1) - if err == nil { - t.Errorf("expected error too old") - } - if _, ok := err.(*errors.StatusError); !ok { - t.Errorf("expected error to be of type StatusError") - } - } - { - result, err := store.GetAllEventsSince(2) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(result) != 1 { - t.Fatalf("unexpected events: %v", result) - } - if result[0].Type != watch.Added { - t.Errorf("unexpected event type: %v", result[0].Type) - } - pod := makeTestPod("pod", uint64(3)) - if !api.Semantic.DeepEqual(pod, result[0].Object) { - t.Errorf("unexpected item: %v, expected: %v", result[0].Object, pod) - } - if result[0].PrevObject != nil { - t.Errorf("unexpected item: %v", result[0].PrevObject) - } - } - - store.Update(makeTestPod("pod", 4)) - store.Update(makeTestPod("pod", 5)) - - // Test with not full cache. - { - _, err := store.GetAllEventsSince(1) - if err == nil { - t.Errorf("expected error too old") - } - } - { - result, err := store.GetAllEventsSince(3) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(result) != 2 { - t.Fatalf("unexpected events: %v", result) - } - for i := 0; i < 2; i++ { - if result[i].Type != watch.Modified { - t.Errorf("unexpected event type: %v", result[i].Type) - } - pod := makeTestPod("pod", uint64(i+4)) - if !api.Semantic.DeepEqual(pod, result[i].Object) { - t.Errorf("unexpected item: %v, expected: %v", result[i].Object, pod) - } - prevPod := makeTestPod("pod", uint64(i+3)) - if !api.Semantic.DeepEqual(prevPod, result[i].PrevObject) { - t.Errorf("unexpected item: %v, expected: %v", result[i].PrevObject, prevPod) - } - } - } - - for i := 6; i < 10; i++ { - store.Update(makeTestPod("pod", uint64(i))) - } - - // Test with full cache - there should be elements from 5 to 9. - { - _, err := store.GetAllEventsSince(3) - if err == nil { - t.Errorf("expected error too old") - } - } - { - result, err := store.GetAllEventsSince(4) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(result) != 5 { - t.Fatalf("unexpected events: %v", result) - } - for i := 0; i < 5; i++ { - pod := makeTestPod("pod", uint64(i+5)) - if !api.Semantic.DeepEqual(pod, result[i].Object) { - t.Errorf("unexpected item: %v, expected: %v", result[i].Object, pod) - } - } - } - - // Test for delete event. - store.Delete(makeTestPod("pod", uint64(10))) - - { - result, err := store.GetAllEventsSince(9) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if len(result) != 1 { - t.Fatalf("unexpected events: %v", result) - } - if result[0].Type != watch.Deleted { - t.Errorf("unexpected event type: %v", result[0].Type) - } - pod := makeTestPod("pod", uint64(10)) - if !api.Semantic.DeepEqual(pod, result[0].Object) { - t.Errorf("unexpected item: %v, expected: %v", result[0].Object, pod) - } - prevPod := makeTestPod("pod", uint64(9)) - if !api.Semantic.DeepEqual(prevPod, result[0].PrevObject) { - t.Errorf("unexpected item: %v, expected: %v", result[0].PrevObject, prevPod) - } - } -} - -func TestWaitUntilFreshAndList(t *testing.T) { - store := newTestWatchCache(3) - - // In background, update the store. - go func() { - store.Add(makeTestPod("foo", 2)) - store.Add(makeTestPod("bar", 5)) - }() - - list, resourceVersion, err := store.WaitUntilFreshAndList(5) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if resourceVersion != 5 { - t.Errorf("unexpected resourceVersion: %v, expected: 5", resourceVersion) - } - if len(list) != 2 { - t.Errorf("unexpected list returned: %#v", list) - } -} - -func TestWaitUntilFreshAndListTimeout(t *testing.T) { - store := newTestWatchCache(3) - fc := store.clock.(*util.FakeClock) - - // In background, step clock after the below call starts the timer. - go func() { - for !fc.HasWaiters() { - time.Sleep(time.Millisecond) - } - fc.Step(MaximumListWait) - - // Add an object to make sure the test would - // eventually fail instead of just waiting - // forever. - time.Sleep(30 * time.Second) - store.Add(makeTestPod("bar", 5)) - }() - - _, _, err := store.WaitUntilFreshAndList(5) - if err == nil { - t.Fatalf("unexpected lack of timeout error") - } -} - -type testLW struct { - ListFunc func(options api.ListOptions) (runtime.Object, error) - WatchFunc func(options api.ListOptions) (watch.Interface, error) -} - -func (t *testLW) List(options api.ListOptions) (runtime.Object, error) { - return t.ListFunc(options) -} -func (t *testLW) Watch(options api.ListOptions) (watch.Interface, error) { - return t.WatchFunc(options) -} - -func TestReflectorForWatchCache(t *testing.T) { - store := newTestWatchCache(5) - - { - _, version, err := store.WaitUntilFreshAndList(0) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != 0 { - t.Errorf("unexpected resource version: %d", version) - } - } - - lw := &testLW{ - WatchFunc: func(options api.ListOptions) (watch.Interface, error) { - fw := watch.NewFake() - go fw.Stop() - return fw, nil - }, - ListFunc: func(options api.ListOptions) (runtime.Object, error) { - return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "10"}}, nil - }, - } - r := cache.NewReflector(lw, &api.Pod{}, store, 0) - r.ListAndWatch(wait.NeverStop) - - { - _, version, err := store.WaitUntilFreshAndList(10) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if version != 10 { - t.Errorf("unexpected resource version: %d", version) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/atomic/value.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/atomic/value.go deleted file mode 100644 index a9bc8cd81..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/atomic/value.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 atomic - -import ( - "sync" -) - -// TODO(ArtfulCoder) -// sync/atomic/Value was added in golang 1.4 -// Once support is dropped for go 1.3, this type must be deprecated in favor of sync/atomic/Value. -// The functions are named Load/Store to match sync/atomic/Value function names. -type Value struct { - value interface{} - valueMutex sync.RWMutex -} - -func (at *Value) Store(val interface{}) { - at.valueMutex.Lock() - defer at.valueMutex.Unlock() - at.value = val -} - -func (at *Value) Load() interface{} { - at.valueMutex.RLock() - defer at.valueMutex.RUnlock() - return at.value -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/atomic/value_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/atomic/value_test.go deleted file mode 100644 index 052b35082..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/atomic/value_test.go +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 atomic - -import ( - "testing" - "time" - - "k8s.io/kubernetes/pkg/util/wait" -) - -func ExpectValue(t *testing.T, atomicValue *Value, expectedValue interface{}) { - actualValue := atomicValue.Load() - if actualValue != expectedValue { - t.Errorf("Expected to find %v, found %v", expectedValue, actualValue) - } - ch := make(chan interface{}) - go func() { - ch <- atomicValue.Load() - }() - select { - case actualValue = <-ch: - if actualValue != expectedValue { - t.Errorf("Expected to find %v, found %v", expectedValue, actualValue) - return - } - case <-time.After(wait.ForeverTestTimeout): - t.Error("Value could not be read") - return - } -} - -func TestAtomicValue(t *testing.T) { - atomicValue := &Value{} - ExpectValue(t, atomicValue, nil) - atomicValue.Store(10) - ExpectValue(t, atomicValue, 10) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/doc.go deleted file mode 100644 index 5ae73e8be..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 bandwidth provides utilities for bandwidth shaping -package bandwidth diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/fake_shaper.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/fake_shaper.go deleted file mode 100644 index 12798bde1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/fake_shaper.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 bandwidth - -import ( - "errors" - - "k8s.io/kubernetes/pkg/api/resource" -) - -type FakeShaper struct { - CIDRs []string - ResetCIDRs []string -} - -func (f *FakeShaper) Limit(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -func (f *FakeShaper) Reset(cidr string) error { - f.ResetCIDRs = append(f.ResetCIDRs, cidr) - return nil -} - -func (f *FakeShaper) ReconcileInterface() error { - return errors.New("unimplemented") -} - -func (f *FakeShaper) ReconcileCIDR(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -func (f *FakeShaper) GetCIDRs() ([]string, error) { - return f.CIDRs, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/interfaces.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/interfaces.go deleted file mode 100644 index 62b20d87d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/interfaces.go +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 bandwidth - -import "k8s.io/kubernetes/pkg/api/resource" - -type BandwidthShaper interface { - // Limit the bandwidth for a particular CIDR on a particular interface - // * ingress and egress are in bits/second - // * cidr is expected to be a valid network CIDR (e.g. '1.2.3.4/32' or '10.20.0.1/16') - // 'egress' bandwidth limit applies to all packets on the interface whose source matches 'cidr' - // 'ingress' bandwidth limit applies to all packets on the interface whose destination matches 'cidr' - // Limits are aggregate limits for the CIDR, not per IP address. CIDRs must be unique, but can be overlapping, traffic - // that matches multiple CIDRs counts against all limits. - Limit(cidr string, egress, ingress *resource.Quantity) error - // Remove a bandwidth limit for a particular CIDR on a particular network interface - Reset(cidr string) error - // Reconcile the interface managed by this shaper with the state on the ground. - ReconcileInterface() error - // Reconcile a CIDR managed by this shaper with the state on the ground - ReconcileCIDR(cidr string, egress, ingress *resource.Quantity) error - // GetCIDRs returns the set of CIDRs that are being managed by this shaper - GetCIDRs() ([]string, error) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/linux.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/linux.go deleted file mode 100644 index edb480c69..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/linux.go +++ /dev/null @@ -1,322 +0,0 @@ -// +build linux - -/* -Copyright 2015 The Kubernetes Authors 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 bandwidth - -import ( - "bufio" - "bytes" - "encoding/hex" - "fmt" - "net" - "strings" - - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/util/exec" - "k8s.io/kubernetes/pkg/util/sets" - - "github.com/golang/glog" -) - -// tcShaper provides an implementation of the BandwidthShaper interface on Linux using the 'tc' tool. -// In general, using this requires that the caller posses the NET_CAP_ADMIN capability, though if you -// do this within an container, it only requires the NS_CAPABLE capability for manipulations to that -// container's network namespace. -// Uses the hierarchical token bucket queuing discipline (htb), this requires Linux 2.4.20 or newer -// or a custom kernel with that queuing discipline backported. -type tcShaper struct { - e exec.Interface - iface string -} - -func NewTCShaper(iface string) BandwidthShaper { - shaper := &tcShaper{ - e: exec.New(), - iface: iface, - } - return shaper -} - -func (t *tcShaper) execAndLog(cmdStr string, args ...string) error { - glog.V(6).Infof("Running: %s %s", cmdStr, strings.Join(args, " ")) - cmd := t.e.Command(cmdStr, args...) - out, err := cmd.CombinedOutput() - glog.V(6).Infof("Output from tc: %s", string(out)) - return err -} - -func (t *tcShaper) nextClassID() (int, error) { - data, err := t.e.Command("tc", "class", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return -1, err - } - - scanner := bufio.NewScanner(bytes.NewBuffer(data)) - classes := sets.String{} - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - // skip empty lines - if len(line) == 0 { - continue - } - parts := strings.Split(line, " ") - // expected tc line: - // class htb 1:1 root prio 0 rate 1000Kbit ceil 1000Kbit burst 1600b cburst 1600b - if len(parts) != 14 { - return -1, fmt.Errorf("unexpected output from tc: %s (%v)", scanner.Text(), parts) - } - classes.Insert(parts[2]) - } - - // Make sure it doesn't go forever - for nextClass := 1; nextClass < 10000; nextClass++ { - if !classes.Has(fmt.Sprintf("1:%d", nextClass)) { - return nextClass, nil - } - } - // This should really never happen - return -1, fmt.Errorf("exhausted class space, please try again") -} - -// Convert a CIDR from text to a hex representation -// Strips any masked parts of the IP, so 1.2.3.4/16 becomes hex(1.2.0.0)/ffffffff -func hexCIDR(cidr string) (string, error) { - ip, ipnet, err := net.ParseCIDR(cidr) - if err != nil { - return "", err - } - ip = ip.Mask(ipnet.Mask) - hexIP := hex.EncodeToString([]byte(ip.To4())) - hexMask := ipnet.Mask.String() - return hexIP + "/" + hexMask, nil -} - -// Convert a CIDR from hex representation to text, opposite of the above. -func asciiCIDR(cidr string) (string, error) { - parts := strings.Split(cidr, "/") - if len(parts) != 2 { - return "", fmt.Errorf("unexpected CIDR format: %s", cidr) - } - ipData, err := hex.DecodeString(parts[0]) - if err != nil { - return "", err - } - ip := net.IP(ipData) - - maskData, err := hex.DecodeString(parts[1]) - mask := net.IPMask(maskData) - size, _ := mask.Size() - - return fmt.Sprintf("%s/%d", ip.String(), size), nil -} - -func (t *tcShaper) findCIDRClass(cidr string) (class, handle string, found bool, err error) { - data, err := t.e.Command("tc", "filter", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return "", "", false, err - } - - hex, err := hexCIDR(cidr) - if err != nil { - return "", "", false, err - } - spec := fmt.Sprintf("match %s", hex) - - scanner := bufio.NewScanner(bytes.NewBuffer(data)) - filter := "" - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if len(line) == 0 { - continue - } - if strings.HasPrefix(line, "filter") { - filter = line - continue - } - if strings.Contains(line, spec) { - parts := strings.Split(filter, " ") - // expected tc line: - // filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 - if len(parts) != 19 { - return "", "", false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(parts), parts) - } - return parts[18], parts[9], true, nil - } - } - return "", "", false, nil -} - -func makeKBitString(rsrc *resource.Quantity) string { - return fmt.Sprintf("%dkbit", (rsrc.Value() / 1000)) -} - -func (t *tcShaper) makeNewClass(rate string) (int, error) { - class, err := t.nextClassID() - if err != nil { - return -1, err - } - if err := t.execAndLog("tc", "class", "add", - "dev", t.iface, - "parent", "1:", - "classid", fmt.Sprintf("1:%d", class), - "htb", "rate", rate); err != nil { - return -1, err - } - return class, nil -} - -func (t *tcShaper) Limit(cidr string, upload, download *resource.Quantity) (err error) { - var downloadClass, uploadClass int - if download != nil { - if downloadClass, err = t.makeNewClass(makeKBitString(download)); err != nil { - return err - } - if err := t.execAndLog("tc", "filter", "add", - "dev", t.iface, - "protocol", "ip", - "parent", "1:0", - "prio", "1", "u32", - "match", "ip", "dst", cidr, - "flowid", fmt.Sprintf("1:%d", downloadClass)); err != nil { - return err - } - } - if upload != nil { - if uploadClass, err = t.makeNewClass(makeKBitString(upload)); err != nil { - return err - } - if err := t.execAndLog("tc", "filter", "add", - "dev", t.iface, - "protocol", "ip", - "parent", "1:0", - "prio", "1", "u32", - "match", "ip", "src", cidr, - "flowid", fmt.Sprintf("1:%d", uploadClass)); err != nil { - return err - } - } - return nil -} - -// tests to see if an interface exists, if it does, return true and the status line for the interface -// returns false, "", if an error occurs. -func (t *tcShaper) interfaceExists() (bool, string, error) { - data, err := t.e.Command("tc", "qdisc", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return false, "", err - } - value := strings.TrimSpace(string(data)) - if len(value) == 0 { - return false, "", nil - } - // Newer versions of tc and/or the kernel return the following instead of nothing: - // qdisc noqueue 0: root refcnt 2 - fields := strings.Fields(value) - if len(fields) > 1 && fields[1] == "noqueue" { - return false, "", nil - } - return true, value, nil -} - -func (t *tcShaper) ReconcileCIDR(cidr string, upload, download *resource.Quantity) error { - _, _, found, err := t.findCIDRClass(cidr) - if err != nil { - return err - } - if !found { - return t.Limit(cidr, upload, download) - } - // TODO: actually check bandwidth limits here - return nil -} - -func (t *tcShaper) ReconcileInterface() error { - exists, output, err := t.interfaceExists() - if err != nil { - return err - } - if !exists { - glog.V(4).Info("Didn't find bandwidth interface, creating") - return t.initializeInterface() - } - fields := strings.Split(output, " ") - if len(fields) != 12 || fields[1] != "htb" || fields[2] != "1:" { - if err := t.deleteInterface(fields[2]); err != nil { - return err - } - return t.initializeInterface() - } - return nil -} - -func (t *tcShaper) initializeInterface() error { - return t.execAndLog("tc", "qdisc", "add", "dev", t.iface, "root", "handle", "1:", "htb", "default", "30") -} - -func (t *tcShaper) Reset(cidr string) error { - class, handle, found, err := t.findCIDRClass(cidr) - if err != nil { - return err - } - if !found { - return fmt.Errorf("Failed to find cidr: %s on interface: %s", cidr, t.iface) - } - if err := t.execAndLog("tc", "filter", "del", - "dev", t.iface, - "parent", "1:", - "proto", "ip", - "prio", "1", - "handle", handle, "u32"); err != nil { - return err - } - return t.execAndLog("tc", "class", "del", "dev", t.iface, "parent", "1:", "classid", class) -} - -func (t *tcShaper) deleteInterface(class string) error { - return t.execAndLog("tc", "qdisc", "delete", "dev", t.iface, "root", "handle", class) -} - -func (t *tcShaper) GetCIDRs() ([]string, error) { - data, err := t.e.Command("tc", "filter", "show", "dev", t.iface).CombinedOutput() - if err != nil { - return nil, err - } - - result := []string{} - scanner := bufio.NewScanner(bytes.NewBuffer(data)) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if len(line) == 0 { - continue - } - if strings.Contains(line, "match") { - parts := strings.Split(line, " ") - // expected tc line: - // match at - if len(parts) != 4 { - return nil, fmt.Errorf("unexpected output: %v", parts) - } - cidr, err := asciiCIDR(parts[1]) - if err != nil { - return nil, err - } - result = append(result, cidr) - } - } - return result, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/linux_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/linux_test.go deleted file mode 100644 index b6d2b559c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/linux_test.go +++ /dev/null @@ -1,634 +0,0 @@ -// +build linux - -/* -Copyright 2015 The Kubernetes Authors 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 bandwidth - -import ( - "errors" - "reflect" - "strings" - "testing" - - "k8s.io/kubernetes/pkg/api/resource" - "k8s.io/kubernetes/pkg/util/exec" -) - -var tcClassOutput = `class htb 1:1 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -class htb 1:2 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -class htb 1:3 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -class htb 1:4 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -` - -var tcClassOutput2 = `class htb 1:1 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -class htb 1:2 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -class htb 1:3 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -class htb 1:4 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -class htb 1:5 root prio 0 rate 10000bit ceil 10000bit burst 1600b cburst 1600b -` - -func TestNextClassID(t *testing.T) { - tests := []struct { - output string - expectErr bool - expected int - err error - }{ - { - output: tcClassOutput, - expected: 5, - }, - { - output: "\n", - expected: 1, - }, - { - expected: -1, - expectErr: true, - err: errors.New("test error"), - }, - } - for _, test := range tests { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(test.output), test.err }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { - return exec.InitFakeCmd(&fcmd, cmd, args...) - }, - }, - } - shaper := &tcShaper{e: &fexec} - class, err := shaper.nextClassID() - if test.expectErr { - if err == nil { - t.Errorf("unexpected non-error") - } - } else { - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if class != test.expected { - t.Errorf("expected: %d, found %d", test.expected, class) - } - } - } -} - -func TestHexCIDR(t *testing.T) { - tests := []struct { - input string - output string - expectErr bool - }{ - { - input: "1.2.0.0/16", - output: "01020000/ffff0000", - }, - { - input: "172.17.0.2/32", - output: "ac110002/ffffffff", - }, - { - input: "foo", - expectErr: true, - }, - } - for _, test := range tests { - output, err := hexCIDR(test.input) - if test.expectErr { - if err == nil { - t.Error("unexpected non-error") - } - } else { - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if output != test.output { - t.Errorf("expected: %s, saw: %s", test.output, output) - } - input, err := asciiCIDR(output) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if input != test.input { - t.Errorf("expected: %s, saw: %s", test.input, input) - } - } - } -} - -var tcFilterOutput = `filter parent 1: protocol ip pref 1 u32 -filter parent 1: protocol ip pref 1 u32 fh 800: ht divisor 1 -filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 - match ac110002/ffffffff at 16 -filter parent 1: protocol ip pref 1 u32 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:2 - match 01020000/ffff0000 at 16 -` - -func TestFindCIDRClass(t *testing.T) { - tests := []struct { - cidr string - output string - expectErr bool - expectNotFound bool - expectedClass string - expectedHandle string - err error - }{ - { - cidr: "172.17.0.2/32", - output: tcFilterOutput, - expectedClass: "1:1", - expectedHandle: "800::800", - }, - { - cidr: "1.2.3.4/16", - output: tcFilterOutput, - expectedClass: "1:2", - expectedHandle: "800::801", - }, - { - cidr: "2.2.3.4/16", - output: tcFilterOutput, - expectNotFound: true, - }, - { - err: errors.New("test error"), - expectErr: true, - }, - } - for _, test := range tests { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(test.output), test.err }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { - return exec.InitFakeCmd(&fcmd, cmd, args...) - }, - }, - } - shaper := &tcShaper{e: &fexec} - class, handle, found, err := shaper.findCIDRClass(test.cidr) - if test.expectErr { - if err == nil { - t.Errorf("unexpected non-error") - } - } else { - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if test.expectNotFound { - if found { - t.Errorf("unexpectedly found an interface: %s %s", class, handle) - } - } else { - if class != test.expectedClass { - t.Errorf("expected: %s, found %s", test.expectedClass, class) - } - if handle != test.expectedHandle { - t.Errorf("expected: %s, found %s", test.expectedHandle, handle) - } - } - } - } -} - -func TestGetCIDRs(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(tcFilterOutput), nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { - return exec.InitFakeCmd(&fcmd, cmd, args...) - }, - }, - } - shaper := &tcShaper{e: &fexec} - cidrs, err := shaper.GetCIDRs() - if err != nil { - t.Errorf("unexpected error: %v", err) - } - expectedCidrs := []string{"172.17.0.2/32", "1.2.0.0/16"} - if !reflect.DeepEqual(cidrs, expectedCidrs) { - t.Errorf("expected: %v, saw: %v", expectedCidrs, cidrs) - } -} - -func TestLimit(t *testing.T) { - tests := []struct { - cidr string - ingress *resource.Quantity - egress *resource.Quantity - expectErr bool - expectedCalls int - err error - }{ - { - cidr: "1.2.3.4/32", - ingress: resource.NewQuantity(10, resource.DecimalSI), - egress: resource.NewQuantity(20, resource.DecimalSI), - expectedCalls: 6, - }, - { - cidr: "1.2.3.4/32", - ingress: resource.NewQuantity(10, resource.DecimalSI), - egress: nil, - expectedCalls: 3, - }, - { - cidr: "1.2.3.4/32", - ingress: nil, - egress: resource.NewQuantity(20, resource.DecimalSI), - expectedCalls: 3, - }, - { - cidr: "1.2.3.4/32", - ingress: nil, - egress: nil, - expectedCalls: 0, - }, - { - err: errors.New("test error"), - ingress: resource.NewQuantity(10, resource.DecimalSI), - egress: resource.NewQuantity(20, resource.DecimalSI), - expectErr: true, - }, - } - - for _, test := range tests { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(tcClassOutput), test.err }, - func() ([]byte, error) { return []byte{}, test.err }, - func() ([]byte, error) { return []byte{}, test.err }, - func() ([]byte, error) { return []byte(tcClassOutput2), test.err }, - func() ([]byte, error) { return []byte{}, test.err }, - func() ([]byte, error) { return []byte{}, test.err }, - }, - } - - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - iface := "cbr0" - shaper := &tcShaper{e: &fexec, iface: iface} - if err := shaper.Limit(test.cidr, test.ingress, test.egress); err != nil && !test.expectErr { - t.Errorf("unexpected error: %v", err) - return - } else if err == nil && test.expectErr { - t.Error("unexpected non-error") - return - } - // No more testing in the error case - if test.expectErr { - if fcmd.CombinedOutputCalls != 1 { - t.Errorf("unexpected number of calls: %d, expected: 1", fcmd.CombinedOutputCalls) - } - return - } - - if fcmd.CombinedOutputCalls != test.expectedCalls { - t.Errorf("unexpected number of calls: %d, expected: %d", fcmd.CombinedOutputCalls, test.expectedCalls) - } - - for ix := range fcmd.CombinedOutputLog { - output := fcmd.CombinedOutputLog[ix] - if output[0] != "tc" { - t.Errorf("unexpected command: %s, expected tc", output[0]) - } - if output[4] != iface { - t.Errorf("unexpected interface: %s, expected %s (%v)", output[4], iface, output) - } - if ix == 1 { - var expectedRate string - if test.ingress != nil { - expectedRate = makeKBitString(test.ingress) - } else { - expectedRate = makeKBitString(test.egress) - } - if output[11] != expectedRate { - t.Errorf("unexpected ingress: %s, expected: %s", output[11], expectedRate) - } - if output[8] != "1:5" { - t.Errorf("unexpected class: %s, expected: %s", output[8], "1:5") - } - } - if ix == 2 { - if output[15] != test.cidr { - t.Errorf("unexpected cidr: %s, expected: %s", output[15], test.cidr) - } - if output[17] != "1:5" { - t.Errorf("unexpected class: %s, expected: %s", output[17], "1:5") - } - } - if ix == 4 { - if output[11] != makeKBitString(test.egress) { - t.Errorf("unexpected egress: %s, expected: %s", output[11], makeKBitString(test.egress)) - } - if output[8] != "1:6" { - t.Errorf("unexpected class: %s, expected: %s", output[8], "1:6") - } - } - if ix == 5 { - if output[15] != test.cidr { - t.Errorf("unexpected cidr: %s, expected: %s", output[15], test.cidr) - } - if output[17] != "1:6" { - t.Errorf("unexpected class: %s, expected: %s", output[17], "1:5") - } - } - } - } -} - -func TestReset(t *testing.T) { - tests := []struct { - cidr string - err error - expectErr bool - expectedHandle string - expectedClass string - }{ - { - cidr: "1.2.3.4/16", - expectedHandle: "800::801", - expectedClass: "1:2", - }, - { - cidr: "172.17.0.2/32", - expectedHandle: "800::800", - expectedClass: "1:1", - }, - { - err: errors.New("test error"), - expectErr: true, - }, - } - for _, test := range tests { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(tcFilterOutput), test.err }, - func() ([]byte, error) { return []byte{}, test.err }, - func() ([]byte, error) { return []byte{}, test.err }, - }, - } - - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - iface := "cbr0" - shaper := &tcShaper{e: &fexec, iface: iface} - - if err := shaper.Reset(test.cidr); err != nil && !test.expectErr { - t.Errorf("unexpected error: %v", err) - return - } else if test.expectErr && err == nil { - t.Error("unexpected non-error") - return - } - - // No more testing in the error case - if test.expectErr { - if fcmd.CombinedOutputCalls != 1 { - t.Errorf("unexpected number of calls: %d, expected: 1", fcmd.CombinedOutputCalls) - } - return - } - - if fcmd.CombinedOutputCalls != 3 { - t.Errorf("unexpected number of calls: %d, expected: 3", fcmd.CombinedOutputCalls) - } - - for ix := range fcmd.CombinedOutputLog { - output := fcmd.CombinedOutputLog[ix] - if output[0] != "tc" { - t.Errorf("unexpected command: %s, expected tc", output[0]) - } - if output[4] != iface { - t.Errorf("unexpected interface: %s, expected %s (%v)", output[4], iface, output) - } - if ix == 1 && output[12] != test.expectedHandle { - t.Errorf("unexpected handle: %s, expected: %s", output[12], test.expectedHandle) - } - if ix == 2 && output[8] != test.expectedClass { - t.Errorf("unexpected class: %s, expected: %s", output[8], test.expectedClass) - } - } - } -} - -var tcQdisc = "qdisc htb 1: root refcnt 2 r2q 10 default 30 direct_packets_stat 0\n" - -func TestReconcileInterfaceExists(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(tcQdisc), nil }, - }, - } - - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - iface := "cbr0" - shaper := &tcShaper{e: &fexec, iface: iface} - err := shaper.ReconcileInterface() - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if fcmd.CombinedOutputCalls != 1 { - t.Errorf("unexpected number of calls: %d", fcmd.CombinedOutputCalls) - } - - output := fcmd.CombinedOutputLog[0] - if len(output) != 5 { - t.Errorf("unexpected command: %v", output) - } - if output[0] != "tc" { - t.Errorf("unexpected command: %s", output[0]) - } - if output[4] != iface { - t.Errorf("unexpected interface: %s, expected %s", output[4], iface) - } - if output[2] != "show" { - t.Errorf("unexpected action: %s", output[2]) - } -} - -func testReconcileInterfaceHasNoData(t *testing.T, output string) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(output), nil }, - func() ([]byte, error) { return []byte(output), nil }, - }, - } - - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - iface := "cbr0" - shaper := &tcShaper{e: &fexec, iface: iface} - err := shaper.ReconcileInterface() - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("unexpected number of calls: %d", fcmd.CombinedOutputCalls) - } - - for ix, output := range fcmd.CombinedOutputLog { - if output[0] != "tc" { - t.Errorf("unexpected command: %s", output[0]) - } - if output[4] != iface { - t.Errorf("unexpected interface: %s, expected %s", output[4], iface) - } - if ix == 0 { - if len(output) != 5 { - t.Errorf("unexpected command: %v", output) - } - if output[2] != "show" { - t.Errorf("unexpected action: %s", output[2]) - } - } - if ix == 1 { - if len(output) != 11 { - t.Errorf("unexpected command: %v", output) - } - if output[2] != "add" { - t.Errorf("unexpected action: %s", output[2]) - } - if output[7] != "1:" { - t.Errorf("unexpected root class: %s", output[7]) - } - if output[8] != "htb" { - t.Errorf("unexpected qdisc algo: %s", output[8]) - } - } - } -} - -func TestReconcileInterfaceDoesntExist(t *testing.T) { - testReconcileInterfaceHasNoData(t, "\n") -} - -var tcQdiscNoqueue = "qdisc noqueue 0: root refcnt 2 \n" - -func TestReconcileInterfaceExistsWithNoqueue(t *testing.T) { - testReconcileInterfaceHasNoData(t, tcQdiscNoqueue) -} - -var tcQdiscWrong = []string{ - "qdisc htb 2: root refcnt 2 r2q 10 default 30 direct_packets_stat 0\n", - "qdisc foo 1: root refcnt 2 r2q 10 default 30 direct_packets_stat 0\n", -} - -func TestReconcileInterfaceIsWrong(t *testing.T) { - for _, test := range tcQdiscWrong { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(test), nil }, - func() ([]byte, error) { return []byte("\n"), nil }, - func() ([]byte, error) { return []byte("\n"), nil }, - }, - } - - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - iface := "cbr0" - shaper := &tcShaper{e: &fexec, iface: iface} - err := shaper.ReconcileInterface() - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if fcmd.CombinedOutputCalls != 3 { - t.Errorf("unexpected number of calls: %d", fcmd.CombinedOutputCalls) - } - - for ix, output := range fcmd.CombinedOutputLog { - if output[0] != "tc" { - t.Errorf("unexpected command: %s", output[0]) - } - if output[4] != iface { - t.Errorf("unexpected interface: %s, expected %s", output[4], iface) - } - if ix == 0 { - if len(output) != 5 { - t.Errorf("unexpected command: %v", output) - } - if output[2] != "show" { - t.Errorf("unexpected action: %s", output[2]) - } - } - if ix == 1 { - if len(output) != 8 { - t.Errorf("unexpected command: %v", output) - } - if output[2] != "delete" { - t.Errorf("unexpected action: %s", output[2]) - } - if output[7] != strings.Split(test, " ")[2] { - t.Errorf("unexpected class: %s, expected: %s", output[7], strings.Split(test, " ")[2]) - } - } - if ix == 2 { - if len(output) != 11 { - t.Errorf("unexpected command: %v", output) - } - if output[7] != "1:" { - t.Errorf("unexpected root class: %s", output[7]) - } - if output[8] != "htb" { - t.Errorf("unexpected qdisc algo: %s", output[8]) - } - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/unsupported.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/unsupported.go deleted file mode 100644 index 7f980a265..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/unsupported.go +++ /dev/null @@ -1,52 +0,0 @@ -// +build !linux - -/* -Copyright 2015 The Kubernetes Authors 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 bandwidth - -import ( - "errors" - - "k8s.io/kubernetes/pkg/api/resource" -) - -type unsupportedShaper struct { -} - -func NewTCShaper(iface string) BandwidthShaper { - return &unsupportedShaper{} -} - -func (f *unsupportedShaper) Limit(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -func (f *unsupportedShaper) Reset(cidr string) error { - return nil -} - -func (f *unsupportedShaper) ReconcileInterface() error { - return errors.New("unimplemented") -} - -func (f *unsupportedShaper) ReconcileCIDR(cidr string, egress, ingress *resource.Quantity) error { - return errors.New("unimplemented") -} - -func (f *unsupportedShaper) GetCIDRs() ([]string, error) { - return []string{}, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/utils.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/utils.go deleted file mode 100644 index 989096f93..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/bandwidth/utils.go +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 bandwidth - -import ( - "fmt" - - "k8s.io/kubernetes/pkg/api/resource" -) - -var minRsrc = resource.MustParse("1k") -var maxRsrc = resource.MustParse("1P") - -func validateBandwidthIsReasonable(rsrc *resource.Quantity) error { - if rsrc.Value() < minRsrc.Value() { - return fmt.Errorf("resource is unreasonably small (< 1kbit)") - } - if rsrc.Value() > maxRsrc.Value() { - return fmt.Errorf("resoruce is unreasonably large (> 1Pbit)") - } - return nil -} - -func ExtractPodBandwidthResources(podAnnotations map[string]string) (ingress, egress *resource.Quantity, err error) { - str, found := podAnnotations["kubernetes.io/ingress-bandwidth"] - if found { - if ingress, err = resource.ParseQuantity(str); err != nil { - return nil, nil, err - } - if err := validateBandwidthIsReasonable(ingress); err != nil { - return nil, nil, err - } - } - str, found = podAnnotations["kubernetes.io/egress-bandwidth"] - if found { - if egress, err = resource.ParseQuantity(str); err != nil { - return nil, nil, err - } - if err := validateBandwidthIsReasonable(egress); err != nil { - return nil, nil, err - } - } - return ingress, egress, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/cache/cache.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/cache/cache.go deleted file mode 100644 index 1f96c9b9a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/cache/cache.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cache - -import ( - "sync" -) - -const ( - shardsCount int = 32 -) - -type Cache []*cacheShard - -func NewCache(maxSize int) Cache { - if maxSize < shardsCount { - maxSize = shardsCount - } - cache := make(Cache, shardsCount) - for i := 0; i < shardsCount; i++ { - cache[i] = &cacheShard{ - items: make(map[uint64]interface{}), - maxSize: maxSize / shardsCount, - } - } - return cache -} - -func (c Cache) getShard(index uint64) *cacheShard { - return c[index%uint64(shardsCount)] -} - -// Returns true if object already existed, false otherwise. -func (c *Cache) Add(index uint64, obj interface{}) bool { - return c.getShard(index).add(index, obj) -} - -func (c *Cache) Get(index uint64) (obj interface{}, found bool) { - return c.getShard(index).get(index) -} - -type cacheShard struct { - items map[uint64]interface{} - sync.RWMutex - maxSize int -} - -// Returns true if object already existed, false otherwise. -func (s *cacheShard) add(index uint64, obj interface{}) bool { - s.Lock() - defer s.Unlock() - _, isOverwrite := s.items[index] - if !isOverwrite && len(s.items) >= s.maxSize { - var randomKey uint64 - for randomKey = range s.items { - break - } - delete(s.items, randomKey) - } - s.items[index] = obj - return isOverwrite -} - -func (s *cacheShard) get(index uint64) (obj interface{}, found bool) { - s.RLock() - defer s.RUnlock() - obj, found = s.items[index] - return -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/cache/cache_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/cache/cache_test.go deleted file mode 100644 index e08c27911..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/cache/cache_test.go +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 cache - -import ( - "testing" -) - -const ( - maxTestCacheSize int = shardsCount * 2 -) - -func ExpectEntry(t *testing.T, cache Cache, index uint64, expectedValue interface{}) bool { - elem, found := cache.Get(index) - if !found { - t.Errorf("Expected to find entry with key %d", index) - return false - } else if elem != expectedValue { - t.Errorf("Expected to find %v, got %v", expectedValue, elem) - return false - } - return true -} - -func TestBasic(t *testing.T) { - cache := NewCache(maxTestCacheSize) - cache.Add(1, "xxx") - ExpectEntry(t, cache, 1, "xxx") -} - -func TestOverflow(t *testing.T) { - cache := NewCache(maxTestCacheSize) - for i := 0; i < maxTestCacheSize+1; i++ { - cache.Add(uint64(i), "xxx") - } - foundIndexes := make([]uint64, 0) - for i := 0; i < maxTestCacheSize+1; i++ { - _, found := cache.Get(uint64(i)) - if found { - foundIndexes = append(foundIndexes, uint64(i)) - } - } - if len(foundIndexes) != maxTestCacheSize { - t.Errorf("Expect to find %d elements, got %d %v", maxTestCacheSize, len(foundIndexes), foundIndexes) - } -} - -func TestOverwrite(t *testing.T) { - cache := NewCache(maxTestCacheSize) - cache.Add(1, "xxx") - ExpectEntry(t, cache, 1, "xxx") - cache.Add(1, "yyy") - ExpectEntry(t, cache, 1, "yyy") -} - -// TestEvict this test will fail sporatically depending on what add() -// selects for the randomKey to be evicted. Ensure that randomKey -// is never the key we most recently added. Since the chance of failure -// on each evict is 50%, if we do it 7 times, it should catch the problem -// if it exists >99% of the time. -func TestEvict(t *testing.T) { - cache := NewCache(shardsCount) - var found bool - for retry := 0; retry < 7; retry++ { - cache.Add(uint64(shardsCount), "xxx") - found = ExpectEntry(t, cache, uint64(shardsCount), "xxx") - if !found { - break - } - cache.Add(0, "xxx") - found = ExpectEntry(t, cache, 0, "xxx") - if !found { - break - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chmod/chmod.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chmod/chmod.go deleted file mode 100644 index 5b646c95b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chmod/chmod.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 chmod - -import ( - "os" -) - -// Interface is something that knows how to run the chmod system call. -// It is non-recursive. -type Interface interface { - // Chmod changes the mode of the given file, implementing the same - // semantics as os.Chmod. - Chmod(path string, filemode os.FileMode) error -} - -func New() Interface { - return &chmodRunner{} -} - -type chmodRunner struct{} - -func (_ *chmodRunner) Chmod(path string, mode os.FileMode) error { - return os.Chmod(path, mode) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chmod/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chmod/doc.go deleted file mode 100644 index a230e98fd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chmod/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 chown provides an interface and implementations -// for things that run run the chmod system call. -package chmod diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chown/chown.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chown/chown.go deleted file mode 100644 index 0d90629de..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chown/chown.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 chown - -import ( - "os" -) - -// Interface is something that knows how to run the chown system call. -// It is non-recursive. -type Interface interface { - // Chown changes the owning UID and GID of a file, implementing - // the exact same semantics as os.Chown. - Chown(path string, uid, gid int) error -} - -func New() Interface { - return &chownRunner{} -} - -type chownRunner struct{} - -func (_ *chownRunner) Chown(path string, uid, gid int) error { - return os.Chown(path, uid, gid) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chown/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chown/doc.go deleted file mode 100644 index 3c41f5ed3..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/chown/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 chown provides utilities to chown a path -package chown diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/clock_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/clock_test.go deleted file mode 100644 index ee60fcb0d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/clock_test.go +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 util - -import ( - "testing" - "time" -) - -func TestFakeClock(t *testing.T) { - startTime := time.Now() - tc := NewFakeClock(startTime) - tc.Step(time.Second) - now := tc.Now() - if now.Sub(startTime) != time.Second { - t.Errorf("input: %s now=%s gap=%s expected=%s", startTime, now, now.Sub(startTime), time.Second) - } - - tt := tc.Now() - tc.SetTime(tt.Add(time.Hour)) - if tc.Now().Sub(tt) != time.Hour { - t.Errorf("input: %s now=%s gap=%s expected=%s", tt, tc.Now(), tc.Now().Sub(tt), time.Hour) - } -} - -func TestFakeClockSleep(t *testing.T) { - startTime := time.Now() - tc := NewFakeClock(startTime) - tc.Sleep(time.Duration(1) * time.Hour) - now := tc.Now() - if now.Sub(startTime) != time.Hour { - t.Errorf("Fake sleep failed, expected time to advance by one hour, instead, its %v", now.Sub(startTime)) - } -} - -func TestFakeAfter(t *testing.T) { - tc := NewFakeClock(time.Now()) - if tc.HasWaiters() { - t.Errorf("unexpected waiter?") - } - oneSec := tc.After(time.Second) - if !tc.HasWaiters() { - t.Errorf("unexpected lack of waiter?") - } - - oneOhOneSec := tc.After(time.Second + time.Millisecond) - twoSec := tc.After(2 * time.Second) - select { - case <-oneSec: - t.Errorf("unexpected channel read") - case <-oneOhOneSec: - t.Errorf("unexpected channel read") - case <-twoSec: - t.Errorf("unexpected channel read") - default: - } - - tc.Step(999 * time.Millisecond) - select { - case <-oneSec: - t.Errorf("unexpected channel read") - case <-oneOhOneSec: - t.Errorf("unexpected channel read") - case <-twoSec: - t.Errorf("unexpected channel read") - default: - } - - tc.Step(time.Millisecond) - select { - case <-oneSec: - // Expected! - case <-oneOhOneSec: - t.Errorf("unexpected channel read") - case <-twoSec: - t.Errorf("unexpected channel read") - default: - t.Errorf("unexpected non-channel read") - } - tc.Step(time.Millisecond) - select { - case <-oneSec: - // should not double-trigger! - t.Errorf("unexpected channel read") - case <-oneOhOneSec: - // Expected! - case <-twoSec: - t.Errorf("unexpected channel read") - default: - t.Errorf("unexpected non-channel read") - } -} - -func TestFakeTick(t *testing.T) { - tc := NewFakeClock(time.Now()) - if tc.HasWaiters() { - t.Errorf("unexpected waiter?") - } - oneSec := tc.Tick(time.Second) - if !tc.HasWaiters() { - t.Errorf("unexpected lack of waiter?") - } - - oneOhOneSec := tc.Tick(time.Second + time.Millisecond) - twoSec := tc.Tick(2 * time.Second) - select { - case <-oneSec: - t.Errorf("unexpected channel read") - case <-oneOhOneSec: - t.Errorf("unexpected channel read") - case <-twoSec: - t.Errorf("unexpected channel read") - default: - } - - tc.Step(999 * time.Millisecond) // t=.999 - select { - case <-oneSec: - t.Errorf("unexpected channel read") - case <-oneOhOneSec: - t.Errorf("unexpected channel read") - case <-twoSec: - t.Errorf("unexpected channel read") - default: - } - - tc.Step(time.Millisecond) // t=1.000 - select { - case <-oneSec: - // Expected! - case <-oneOhOneSec: - t.Errorf("unexpected channel read") - case <-twoSec: - t.Errorf("unexpected channel read") - default: - t.Errorf("unexpected non-channel read") - } - tc.Step(time.Millisecond) // t=1.001 - select { - case <-oneSec: - // should not double-trigger! - t.Errorf("unexpected channel read") - case <-oneOhOneSec: - // Expected! - case <-twoSec: - t.Errorf("unexpected channel read") - default: - t.Errorf("unexpected non-channel read") - } - - tc.Step(time.Second) // t=2.001 - tc.Step(time.Second) // t=3.001 - tc.Step(time.Second) // t=4.001 - tc.Step(time.Second) // t=5.001 - - // The one second ticker should not accumulate ticks - accumulatedTicks := 0 - drained := false - for !drained { - select { - case <-oneSec: - accumulatedTicks++ - default: - drained = true - } - } - if accumulatedTicks != 1 { - t.Errorf("unexpected number of accumulated ticks: %d", accumulatedTicks) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/codeinspector/codeinspector.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/codeinspector/codeinspector.go deleted file mode 100644 index 6ec21be71..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/codeinspector/codeinspector.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 codeinspector - -import ( - "fmt" - "go/ast" - "go/parser" - "go/token" - "io/ioutil" - "strings" - "unicode" -) - -// GetPublicFunctions lists all public functions (not methods) from a golang source file. -func GetPublicFunctions(filePath string) ([]string, error) { - var functionNames []string - - // Create the AST by parsing src. - fset := token.NewFileSet() // positions are relative to fset - f, err := parser.ParseFile(fset, filePath, nil, 0) - if err != nil { - return nil, fmt.Errorf("failed parse file to list functions: %v", err) - } - - // Inspect the AST and print all identifiers and literals. - ast.Inspect(f, func(n ast.Node) bool { - var s string - switch x := n.(type) { - case *ast.FuncDecl: - s = x.Name.Name - // It's a function (not method), and is public, record it. - if x.Recv == nil && isPublic(s) { - functionNames = append(functionNames, s) - } - } - return true - }) - - return functionNames, nil -} - -// isPublic checks if a given string is a public function name. -func isPublic(myString string) bool { - a := []rune(myString) - a[0] = unicode.ToUpper(a[0]) - return myString == string(a) -} - -// GetSourceCodeFiles lists golang source code files from directory, excluding sub-directory and tests files. -func GetSourceCodeFiles(dir string) ([]string, error) { - files, err := ioutil.ReadDir(dir) - if err != nil { - return nil, err - } - - var filenames []string - - for _, file := range files { - if strings.HasSuffix(file.Name(), ".go") && !strings.HasSuffix(file.Name(), "_test.go") { - filenames = append(filenames, file.Name()) - } - } - - return filenames, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/config.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/config.go deleted file mode 100644 index 37f6f6ab1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/config.go +++ /dev/null @@ -1,140 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "sync" - - "k8s.io/kubernetes/pkg/util/wait" -) - -type Merger interface { - // Invoked when a change from a source is received. May also function as an incremental - // merger if you wish to consume changes incrementally. Must be reentrant when more than - // one source is defined. - Merge(source string, update interface{}) error -} - -// MergeFunc implements the Merger interface -type MergeFunc func(source string, update interface{}) error - -func (f MergeFunc) Merge(source string, update interface{}) error { - return f(source, update) -} - -// Mux is a class for merging configuration from multiple sources. Changes are -// pushed via channels and sent to the merge function. -type Mux struct { - // Invoked when an update is sent to a source. - merger Merger - - // Sources and their lock. - sourceLock sync.RWMutex - // Maps source names to channels - sources map[string]chan interface{} -} - -// NewMux creates a new mux that can merge changes from multiple sources. -func NewMux(merger Merger) *Mux { - mux := &Mux{ - sources: make(map[string]chan interface{}), - merger: merger, - } - return mux -} - -// Channel returns a channel where a configuration source -// can send updates of new configurations. Multiple calls with the same -// source will return the same channel. This allows change and state based sources -// to use the same channel. Different source names however will be treated as a -// union. -func (m *Mux) Channel(source string) chan interface{} { - if len(source) == 0 { - panic("Channel given an empty name") - } - m.sourceLock.Lock() - defer m.sourceLock.Unlock() - channel, exists := m.sources[source] - if exists { - return channel - } - newChannel := make(chan interface{}) - m.sources[source] = newChannel - go wait.Until(func() { m.listen(source, newChannel) }, 0, wait.NeverStop) - return newChannel -} - -func (m *Mux) listen(source string, listenChannel <-chan interface{}) { - for update := range listenChannel { - m.merger.Merge(source, update) - } -} - -// Accessor is an interface for retrieving the current merge state. -type Accessor interface { - // MergedState returns a representation of the current merge state. - // Must be reentrant when more than one source is defined. - MergedState() interface{} -} - -// AccessorFunc implements the Accessor interface. -type AccessorFunc func() interface{} - -func (f AccessorFunc) MergedState() interface{} { - return f() -} - -type Listener interface { - // OnUpdate is invoked when a change is made to an object. - OnUpdate(instance interface{}) -} - -// ListenerFunc receives a representation of the change or object. -type ListenerFunc func(instance interface{}) - -func (f ListenerFunc) OnUpdate(instance interface{}) { - f(instance) -} - -type Broadcaster struct { - // Listeners for changes and their lock. - listenerLock sync.RWMutex - listeners []Listener -} - -// NewBroadcaster registers a set of listeners that support the Listener interface -// and notifies them all on changes. -func NewBroadcaster() *Broadcaster { - return &Broadcaster{} -} - -// Add registers listener to receive updates of changes. -func (b *Broadcaster) Add(listener Listener) { - b.listenerLock.Lock() - defer b.listenerLock.Unlock() - b.listeners = append(b.listeners, listener) -} - -// Notify notifies all listeners. -func (b *Broadcaster) Notify(instance interface{}) { - b.listenerLock.RLock() - listeners := b.listeners - b.listenerLock.RUnlock() - for _, listener := range listeners { - listener.OnUpdate(instance) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/config_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/config_test.go deleted file mode 100644 index 4ebab7bf9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/config_test.go +++ /dev/null @@ -1,120 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "reflect" - "testing" -) - -func TestConfigurationChannels(t *testing.T) { - mux := NewMux(nil) - channelOne := mux.Channel("one") - if channelOne != mux.Channel("one") { - t.Error("Didn't get the same muxuration channel back with the same name") - } - channelTwo := mux.Channel("two") - if channelOne == channelTwo { - t.Error("Got back the same muxuration channel for different names") - } -} - -type MergeMock struct { - source string - update interface{} - t *testing.T -} - -func (m MergeMock) Merge(source string, update interface{}) error { - if m.source != source { - m.t.Errorf("Expected %s, Got %s", m.source, source) - } - if !reflect.DeepEqual(m.update, update) { - m.t.Errorf("Expected %s, Got %s", m.update, update) - } - return nil -} - -func TestMergeInvoked(t *testing.T) { - merger := MergeMock{"one", "test", t} - mux := NewMux(&merger) - mux.Channel("one") <- "test" -} - -func TestMergeFuncInvoked(t *testing.T) { - ch := make(chan bool) - mux := NewMux(MergeFunc(func(source string, update interface{}) error { - if source != "one" { - t.Errorf("Expected %s, Got %s", "one", source) - } - if update.(string) != "test" { - t.Errorf("Expected %s, Got %s", "test", update) - } - ch <- true - return nil - })) - mux.Channel("one") <- "test" - <-ch -} - -func TestSimultaneousMerge(t *testing.T) { - ch := make(chan bool, 2) - mux := NewMux(MergeFunc(func(source string, update interface{}) error { - switch source { - case "one": - if update.(string) != "test" { - t.Errorf("Expected %s, Got %s", "test", update) - } - case "two": - if update.(string) != "test2" { - t.Errorf("Expected %s, Got %s", "test2", update) - } - default: - t.Errorf("Unexpected source, Got %s", update) - } - ch <- true - return nil - })) - source := mux.Channel("one") - source2 := mux.Channel("two") - source <- "test" - source2 <- "test2" - <-ch - <-ch -} - -func TestBroadcaster(t *testing.T) { - b := NewBroadcaster() - b.Notify(struct{}{}) - - ch := make(chan bool, 2) - b.Add(ListenerFunc(func(object interface{}) { - if object != "test" { - t.Errorf("Expected %s, Got %s", "test", object) - } - ch <- true - })) - b.Add(ListenerFunc(func(object interface{}) { - if object != "test" { - t.Errorf("Expected %s, Got %s", "test", object) - } - ch <- true - })) - b.Notify("test") - <-ch - <-ch -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/configuration_map.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/configuration_map.go deleted file mode 100644 index e7ad4fadb..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/configuration_map.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config - -import ( - "fmt" - "sort" - "strings" -) - -type ConfigurationMap map[string]string - -func (m *ConfigurationMap) String() string { - pairs := []string{} - for k, v := range *m { - pairs = append(pairs, fmt.Sprintf("%s=%s", k, v)) - } - sort.Strings(pairs) - return strings.Join(pairs, ",") -} - -func (m *ConfigurationMap) Set(value string) error { - for _, s := range strings.Split(value, ",") { - if len(s) == 0 { - continue - } - arr := strings.SplitN(s, "=", 2) - if len(arr) == 2 { - (*m)[strings.TrimSpace(arr[0])] = strings.TrimSpace(arr[1]) - } else { - (*m)[strings.TrimSpace(arr[0])] = "" - } - } - return nil -} - -func (*ConfigurationMap) Type() string { - return "mapStringString" -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/doc.go deleted file mode 100644 index 697f3ab56..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/config/doc.go +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 config provides utility objects for decoupling sources of configuration and the -// actual configuration state. Consumers must implement the Merger interface to unify -// the sources of change into an object. -package config diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/configz/configz.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/configz/configz.go deleted file mode 100644 index e8954a4a8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/configz/configz.go +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 configz - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "sync" -) - -var ( - configsGuard sync.RWMutex - configs = map[string]*Config{} -) - -type Config struct { - val interface{} -} - -func InstallHandler(m mux) { - m.Handle("/configz", http.HandlerFunc(handle)) -} - -type mux interface { - Handle(string, http.Handler) -} - -func New(name string) (*Config, error) { - configsGuard.Lock() - defer configsGuard.Unlock() - if _, found := configs[name]; found { - return nil, fmt.Errorf("register config %q twice", name) - } - newConfig := Config{} - configs[name] = &newConfig - return &newConfig, nil -} - -func Delete(name string) { - configsGuard.Lock() - defer configsGuard.Unlock() - delete(configs, name) -} - -func (v *Config) Set(val interface{}) { - configsGuard.Lock() - defer configsGuard.Unlock() - v.val = val -} - -func (v *Config) MarshalJSON() ([]byte, error) { - return json.Marshal(v.val) -} - -func handle(w http.ResponseWriter, r *http.Request) { - if err := write(w); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } -} - -func write(w io.Writer) error { - configsGuard.Lock() - defer configsGuard.Unlock() - b, err := json.Marshal(configs) - if err != nil { - return fmt.Errorf("error marshaling json: %v", err) - } - _, err = w.Write(b) - return err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/configz/configz_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/configz/configz_test.go deleted file mode 100644 index 7e5202050..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/configz/configz_test.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 configz - -import ( - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" -) - -func TestConfigz(t *testing.T) { - v, err := New("testing") - if err != nil { - t.Fatalf("err: %v", err) - } - - v.Set("blah") - - s := httptest.NewServer(http.HandlerFunc(handle)) - defer s.Close() - - resp, err := http.Get(s.URL + "/configz") - if err != nil { - t.Fatalf("err: %v", err) - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("err: %v", err) - } - if string(body) != `{"testing":"blah"}` { - t.Fatalf("unexpected output: %v", err) - } - - v.Set("bing") - resp, err = http.Get(s.URL + "/configz") - if err != nil { - t.Fatalf("err: %v", err) - } - - body, err = ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("err: %v", err) - } - if string(body) != `{"testing":"bing"}` { - t.Fatalf("unexpected output: %v", err) - } - - Delete("testing") - resp, err = http.Get(s.URL + "/configz") - if err != nil { - t.Fatalf("err: %v", err) - } - - body, err = ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatalf("err: %v", err) - } - if string(body) != `{}` { - t.Fatalf("unexpected output: %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/crlf/crlf.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/crlf/crlf.go deleted file mode 100644 index e098e8600..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/crlf/crlf.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 crlf - -import ( - "bytes" - "io" -) - -type crlfWriter struct { - io.Writer -} - -// NewCRLFWriter implements a CR/LF line ending writer used for normalizing -// text for Windows platforms. -func NewCRLFWriter(w io.Writer) io.Writer { - return crlfWriter{w} -} - -func (w crlfWriter) Write(b []byte) (n int, err error) { - for i, written := 0, 0; ; { - next := bytes.Index(b[i:], []byte("\n")) - if next == -1 { - n, err := w.Writer.Write(b[i:]) - return written + n, err - } - next = next + i - n, err := w.Writer.Write(b[i:next]) - if err != nil { - return written + n, err - } - written += n - n, err = w.Writer.Write([]byte("\r\n")) - if err != nil { - if n > 1 { - n = 1 - } - return written + n, err - } - written += 1 - i = next + 1 - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/dbus.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/dbus.go deleted file mode 100644 index 13da1469e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/dbus.go +++ /dev/null @@ -1,133 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 dbus - -import ( - godbus "github.com/godbus/dbus" -) - -// Interface is an interface that presents a subset of the godbus/dbus API. Use this -// when you want to inject fakeable/mockable D-Bus behavior. -type Interface interface { - // SystemBus returns a connection to the system bus, connecting to it - // first if necessary - SystemBus() (Connection, error) - // SessionBus returns a connection to the session bus, connecting to it - // first if necessary - SessionBus() (Connection, error) -} - -// Connection represents a D-Bus connection -type Connection interface { - // Returns an Object representing the bus itself - BusObject() Object - - // Object creates a representation of a remote D-Bus object - Object(name, path string) Object - - // Signal registers or unregisters a channel to receive D-Bus signals - Signal(ch chan<- *godbus.Signal) -} - -// Object represents a remote D-Bus object -type Object interface { - // Call synchronously calls a D-Bus method - Call(method string, flags godbus.Flags, args ...interface{}) Call -} - -// Call represents a pending or completed D-Bus method call -type Call interface { - // Store returns a completed call's return values, or an error - Store(retvalues ...interface{}) error -} - -// Implements Interface in terms of actually talking to D-Bus -type dbusImpl struct { - systemBus *connImpl - sessionBus *connImpl -} - -// Implements Connection as a godbus.Conn -type connImpl struct { - conn *godbus.Conn -} - -// Implements Object as a godbus.Object -type objectImpl struct { - object godbus.BusObject -} - -// Implements Call as a godbus.Call -type callImpl struct { - call *godbus.Call -} - -// New returns a new Interface which will use godbus to talk to D-Bus -func New() Interface { - return &dbusImpl{} -} - -// SystemBus is part of Interface -func (db *dbusImpl) SystemBus() (Connection, error) { - if db.systemBus == nil { - bus, err := godbus.SystemBus() - if err != nil { - return nil, err - } - db.systemBus = &connImpl{bus} - } - - return db.systemBus, nil -} - -// SessionBus is part of Interface -func (db *dbusImpl) SessionBus() (Connection, error) { - if db.sessionBus == nil { - bus, err := godbus.SessionBus() - if err != nil { - return nil, err - } - db.sessionBus = &connImpl{bus} - } - - return db.sessionBus, nil -} - -// BusObject is part of the Connection interface -func (conn *connImpl) BusObject() Object { - return &objectImpl{conn.conn.BusObject()} -} - -// Object is part of the Connection interface -func (conn *connImpl) Object(name, path string) Object { - return &objectImpl{conn.conn.Object(name, godbus.ObjectPath(path))} -} - -// Signal is part of the Connection interface -func (conn *connImpl) Signal(ch chan<- *godbus.Signal) { - conn.conn.Signal(ch) -} - -// Call is part of the Object interface -func (obj *objectImpl) Call(method string, flags godbus.Flags, args ...interface{}) Call { - return &callImpl{obj.object.Call(method, flags, args...)} -} - -// Store is part of the Call interface -func (call *callImpl) Store(retvalues ...interface{}) error { - return call.call.Store(retvalues...) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/dbus_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/dbus_test.go deleted file mode 100644 index 96670373b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/dbus_test.go +++ /dev/null @@ -1,249 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 dbus - -import ( - "fmt" - "os" - "testing" - - godbus "github.com/godbus/dbus" -) - -const ( - DBusNameFlagAllowReplacement uint32 = 1 << (iota + 1) - DBusNameFlagReplaceExisting - DBusNameFlagDoNotQueue -) - -const ( - DBusRequestNameReplyPrimaryOwner uint32 = iota + 1 - DBusRequestNameReplyInQueue - DBusRequestNameReplyExists - DBusRequestNameReplyAlreadyOwner -) - -const ( - DBusReleaseNameReplyReleased uint32 = iota + 1 - DBusReleaseNameReplyNonExistent - DBusReleaseNameReplyNotOwner -) - -func doDBusTest(t *testing.T, dbus Interface, real bool) { - bus, err := dbus.SystemBus() - if err != nil { - if !real { - t.Errorf("dbus.SystemBus() failed with fake Interface") - } - t.Skipf("D-Bus is not running: %v", err) - } - busObj := bus.BusObject() - - id := "" - err = busObj.Call("org.freedesktop.DBus.GetId", 0).Store(&id) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if len(id) == 0 { - t.Errorf("expected non-empty Id, got \"\"") - } - - // Switch to the session bus for the rest, since the system bus is more - // locked down (and thus harder to trick into emitting signals). - - bus, err = dbus.SessionBus() - if err != nil { - if !real { - t.Errorf("dbus.SystemBus() failed with fake Interface") - } - t.Skipf("D-Bus session bus is not available: %v", err) - } - busObj = bus.BusObject() - - name := fmt.Sprintf("io.kubernetes.dbus_test_%d", os.Getpid()) - owner := "" - err = busObj.Call("org.freedesktop.DBus.GetNameOwner", 0, name).Store(&owner) - if err == nil { - t.Errorf("expected '%s' to be un-owned, but found owner %s", name, owner) - } - dbuserr, ok := err.(godbus.Error) - if !ok { - t.Errorf("expected godbus.Error, but got %#v", err) - } - if dbuserr.Name != "org.freedesktop.DBus.Error.NameHasNoOwner" { - t.Errorf("expected NameHasNoOwner error but got %v", err) - } - - sigchan := make(chan *godbus.Signal, 10) - bus.Signal(sigchan) - - rule := fmt.Sprintf("type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',sender='org.freedesktop.DBus',arg0='%s'", name) - err = busObj.Call("org.freedesktop.DBus.AddMatch", 0, rule).Store() - if err != nil { - t.Errorf("expected success, got %v", err) - } - - var ret uint32 - err = busObj.Call("org.freedesktop.DBus.RequestName", 0, name, DBusNameFlagDoNotQueue).Store(&ret) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if ret != DBusRequestNameReplyPrimaryOwner { - t.Errorf("expected %v, got %v", DBusRequestNameReplyPrimaryOwner, ret) - } - - err = busObj.Call("org.freedesktop.DBus.GetNameOwner", 0, name).Store(&owner) - if err != nil { - t.Errorf("expected success, got %v", err) - } - - var changedSignal, acquiredSignal, lostSignal *godbus.Signal - - sig1 := <-sigchan - sig2 := <-sigchan - // We get two signals, but the order isn't guaranteed - if sig1.Name == "org.freedesktop.DBus.NameOwnerChanged" { - changedSignal = sig1 - acquiredSignal = sig2 - } else { - acquiredSignal = sig1 - changedSignal = sig2 - } - - if acquiredSignal.Sender != "org.freedesktop.DBus" || acquiredSignal.Name != "org.freedesktop.DBus.NameAcquired" { - t.Errorf("expected NameAcquired signal, got %v", acquiredSignal) - } - acquiredName := acquiredSignal.Body[0].(string) - if acquiredName != name { - t.Errorf("unexpected NameAcquired arguments: %v", acquiredSignal) - } - - if changedSignal.Sender != "org.freedesktop.DBus" || changedSignal.Name != "org.freedesktop.DBus.NameOwnerChanged" { - t.Errorf("expected NameOwnerChanged signal, got %v", changedSignal) - } - - changedName := changedSignal.Body[0].(string) - oldOwner := changedSignal.Body[1].(string) - newOwner := changedSignal.Body[2].(string) - if changedName != name || oldOwner != "" || newOwner != owner { - t.Errorf("unexpected NameOwnerChanged arguments: %v", changedSignal) - } - - err = busObj.Call("org.freedesktop.DBus.ReleaseName", 0, name).Store(&ret) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if ret != DBusReleaseNameReplyReleased { - t.Errorf("expected %v, got %v", DBusReleaseNameReplyReleased, ret) - } - - sig1 = <-sigchan - sig2 = <-sigchan - if sig1.Name == "org.freedesktop.DBus.NameOwnerChanged" { - changedSignal = sig1 - lostSignal = sig2 - } else { - lostSignal = sig1 - changedSignal = sig2 - } - - if lostSignal.Sender != "org.freedesktop.DBus" || lostSignal.Name != "org.freedesktop.DBus.NameLost" { - t.Errorf("expected NameLost signal, got %v", lostSignal) - } - lostName := lostSignal.Body[0].(string) - if lostName != name { - t.Errorf("unexpected NameLost arguments: %v", lostSignal) - } - - if changedSignal.Sender != "org.freedesktop.DBus" || changedSignal.Name != "org.freedesktop.DBus.NameOwnerChanged" { - t.Errorf("expected NameOwnerChanged signal, got %v", changedSignal) - } - - changedName = changedSignal.Body[0].(string) - oldOwner = changedSignal.Body[1].(string) - newOwner = changedSignal.Body[2].(string) - if changedName != name || oldOwner != owner || newOwner != "" { - t.Errorf("unexpected NameOwnerChanged arguments: %v", changedSignal) - } - - if len(sigchan) != 0 { - t.Errorf("unexpected extra signals (%d)", len(sigchan)) - } - - // Unregister sigchan - bus.Signal(sigchan) -} - -func TestRealDBus(t *testing.T) { - dbus := New() - doDBusTest(t, dbus, true) -} - -func TestFakeDBus(t *testing.T) { - uniqueName := ":1.1" - ownedName := "" - - fakeSystem := NewFakeConnection() - fakeSystem.SetBusObject( - func(method string, args ...interface{}) ([]interface{}, error) { - if method == "org.freedesktop.DBus.GetId" { - return []interface{}{"foo"}, nil - } - return nil, fmt.Errorf("unexpected method call '%s'", method) - }, - ) - - fakeSession := NewFakeConnection() - fakeSession.SetBusObject( - func(method string, args ...interface{}) ([]interface{}, error) { - if method == "org.freedesktop.DBus.GetNameOwner" { - checkName := args[0].(string) - if checkName != ownedName { - return nil, godbus.Error{Name: "org.freedesktop.DBus.Error.NameHasNoOwner", Body: nil} - } else { - return []interface{}{uniqueName}, nil - } - } else if method == "org.freedesktop.DBus.RequestName" { - reqName := args[0].(string) - _ = args[1].(uint32) - if ownedName != "" { - return []interface{}{DBusRequestNameReplyAlreadyOwner}, nil - } - ownedName = reqName - fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameAcquired", reqName) - fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged", reqName, "", uniqueName) - return []interface{}{DBusRequestNameReplyPrimaryOwner}, nil - } else if method == "org.freedesktop.DBus.ReleaseName" { - reqName := args[0].(string) - if reqName != ownedName { - return []interface{}{DBusReleaseNameReplyNotOwner}, nil - } - ownedName = "" - fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged", reqName, uniqueName, "") - fakeSession.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameLost", reqName) - return []interface{}{DBusReleaseNameReplyReleased}, nil - } else if method == "org.freedesktop.DBus.AddMatch" { - return nil, nil - } else { - return nil, fmt.Errorf("unexpected method call '%s'", method) - } - }, - ) - - dbus := NewFake(fakeSystem, fakeSession) - doDBusTest(t, dbus, false) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/doc.go deleted file mode 100644 index 59bec0e56..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 dbus provides an injectable interface and implementations for D-Bus communication -package dbus diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/fake_dbus.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/fake_dbus.go deleted file mode 100644 index eb97febae..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/dbus/fake_dbus.go +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 dbus - -import ( - "fmt" - - godbus "github.com/godbus/dbus" -) - -// DBusFake is a simple fake Interface type. -type DBusFake struct { - systemBus *DBusFakeConnection - sessionBus *DBusFakeConnection -} - -// DBusFakeConnection represents a fake D-Bus connection -type DBusFakeConnection struct { - busObject *fakeObject - objects map[string]*fakeObject - signalHandlers []chan<- *godbus.Signal -} - -// DBusFakeHandler is used to handle fake D-Bus method calls -type DBusFakeHandler func(method string, args ...interface{}) ([]interface{}, error) - -type fakeObject struct { - handler DBusFakeHandler -} - -type fakeCall struct { - ret []interface{} - err error -} - -// NewFake returns a new Interface which will fake talking to D-Bus -func NewFake(systemBus *DBusFakeConnection, sessionBus *DBusFakeConnection) *DBusFake { - return &DBusFake{systemBus, sessionBus} -} - -func NewFakeConnection() *DBusFakeConnection { - return &DBusFakeConnection{ - objects: make(map[string]*fakeObject), - } -} - -// SystemBus is part of Interface -func (db *DBusFake) SystemBus() (Connection, error) { - if db.systemBus != nil { - return db.systemBus, nil - } else { - return nil, fmt.Errorf("DBus is not running") - } -} - -// SessionBus is part of Interface -func (db *DBusFake) SessionBus() (Connection, error) { - if db.sessionBus != nil { - return db.sessionBus, nil - } else { - return nil, fmt.Errorf("DBus is not running") - } -} - -// BusObject is part of the Connection interface -func (conn *DBusFakeConnection) BusObject() Object { - return conn.busObject -} - -// Object is part of the Connection interface -func (conn *DBusFakeConnection) Object(name, path string) Object { - return conn.objects[name+path] -} - -// Signal is part of the Connection interface -func (conn *DBusFakeConnection) Signal(ch chan<- *godbus.Signal) { - for i := range conn.signalHandlers { - if conn.signalHandlers[i] == ch { - conn.signalHandlers = append(conn.signalHandlers[:i], conn.signalHandlers[i+1:]...) - return - } - } - conn.signalHandlers = append(conn.signalHandlers, ch) -} - -// SetBusObject sets the handler for the BusObject of conn -func (conn *DBusFakeConnection) SetBusObject(handler DBusFakeHandler) { - conn.busObject = &fakeObject{handler} -} - -// AddObject adds a handler for the Object at name and path -func (conn *DBusFakeConnection) AddObject(name, path string, handler DBusFakeHandler) { - conn.objects[name+path] = &fakeObject{handler} -} - -// EmitSignal emits a signal on conn -func (conn *DBusFakeConnection) EmitSignal(name, path, iface, signal string, args ...interface{}) { - sig := &godbus.Signal{ - Sender: name, - Path: godbus.ObjectPath(path), - Name: iface + "." + signal, - Body: args, - } - for _, ch := range conn.signalHandlers { - ch <- sig - } -} - -// Call is part of the Object interface -func (obj *fakeObject) Call(method string, flags godbus.Flags, args ...interface{}) Call { - ret, err := obj.handler(method, args...) - return &fakeCall{ret, err} -} - -// Store is part of the Call interface -func (call *fakeCall) Store(retvalues ...interface{}) error { - if call.err != nil { - return call.err - } - return godbus.Store(call.ret, retvalues...) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/deployment/deployment_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/deployment/deployment_test.go deleted file mode 100644 index 31d23d2c1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/deployment/deployment_test.go +++ /dev/null @@ -1,409 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 deployment - -import ( - "fmt" - "reflect" - "testing" - "time" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/apis/extensions" - "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" - "k8s.io/kubernetes/pkg/client/testing/core" - "k8s.io/kubernetes/pkg/client/unversioned/testclient" - "k8s.io/kubernetes/pkg/runtime" -) - -func addListRSReactor(fakeClient *fake.Clientset, obj runtime.Object) *fake.Clientset { - fakeClient.AddReactor("list", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { - return true, obj, nil - }) - return fakeClient -} - -func addListPodsReactor(fakeClient *fake.Clientset, obj runtime.Object) *fake.Clientset { - fakeClient.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { - return true, obj, nil - }) - return fakeClient -} - -func addGetRSReactor(fakeClient *fake.Clientset, obj runtime.Object) *fake.Clientset { - rsList, ok := obj.(*extensions.ReplicaSetList) - fakeClient.AddReactor("get", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { - name := action.(testclient.GetAction).GetName() - if ok { - for _, rs := range rsList.Items { - if rs.Name == name { - return true, &rs, nil - } - } - } - return false, nil, fmt.Errorf("could not find the requested replica set: %s", name) - - }) - return fakeClient -} - -func addUpdateRSReactor(fakeClient *fake.Clientset) *fake.Clientset { - fakeClient.AddReactor("update", "replicasets", func(action core.Action) (handled bool, ret runtime.Object, err error) { - obj := action.(testclient.UpdateAction).GetObject().(*extensions.ReplicaSet) - return true, obj, nil - }) - return fakeClient -} - -func addUpdatePodsReactor(fakeClient *fake.Clientset) *fake.Clientset { - fakeClient.AddReactor("update", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) { - obj := action.(testclient.UpdateAction).GetObject().(*api.Pod) - return true, obj, nil - }) - return fakeClient -} - -func newPod(now time.Time, ready bool, beforeSec int) api.Pod { - conditionStatus := api.ConditionFalse - if ready { - conditionStatus = api.ConditionTrue - } - return api.Pod{ - Status: api.PodStatus{ - Conditions: []api.PodCondition{ - { - Type: api.PodReady, - LastTransitionTime: unversioned.NewTime(now.Add(-1 * time.Duration(beforeSec) * time.Second)), - Status: conditionStatus, - }, - }, - }, - } -} - -func TestGetReadyPodsCount(t *testing.T) { - now := time.Now() - tests := []struct { - pods []api.Pod - minReadySeconds int - expected int - }{ - { - []api.Pod{ - newPod(now, true, 0), - newPod(now, true, 2), - newPod(now, false, 1), - }, - 1, - 1, - }, - { - []api.Pod{ - newPod(now, true, 2), - newPod(now, true, 11), - newPod(now, true, 5), - }, - 10, - 1, - }, - } - - for _, test := range tests { - if count := getReadyPodsCount(test.pods, int32(test.minReadySeconds)); int(count) != test.expected { - t.Errorf("Pods = %#v, minReadySeconds = %d, expected %d, got %d", test.pods, test.minReadySeconds, test.expected, count) - } - } -} - -// generatePodFromRS creates a pod, with the input ReplicaSet's selector and its template -func generatePodFromRS(rs extensions.ReplicaSet) api.Pod { - return api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: rs.Labels, - }, - Spec: rs.Spec.Template.Spec, - } -} - -func generatePod(labels map[string]string, image string) api.Pod { - return api.Pod{ - ObjectMeta: api.ObjectMeta{ - Labels: labels, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: image, - Image: image, - ImagePullPolicy: api.PullAlways, - TerminationMessagePath: api.TerminationMessagePathDefault, - }, - }, - }, - } -} - -func generateRSWithLabel(labels map[string]string, image string) extensions.ReplicaSet { - return extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: api.SimpleNameGenerator.GenerateName("replicaset"), - Labels: labels, - }, - Spec: extensions.ReplicaSetSpec{ - Replicas: 1, - Selector: &unversioned.LabelSelector{MatchLabels: labels}, - Template: api.PodTemplateSpec{ - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: image, - Image: image, - ImagePullPolicy: api.PullAlways, - TerminationMessagePath: api.TerminationMessagePathDefault, - }, - }, - }, - }, - }, - } -} - -// generateRS creates a replica set, with the input deployment's template as its template -func generateRS(deployment extensions.Deployment) extensions.ReplicaSet { - template := GetNewReplicaSetTemplate(&deployment) - return extensions.ReplicaSet{ - ObjectMeta: api.ObjectMeta{ - Name: api.SimpleNameGenerator.GenerateName("replicaset"), - Labels: template.Labels, - }, - Spec: extensions.ReplicaSetSpec{ - Template: template, - Selector: &unversioned.LabelSelector{MatchLabels: template.Labels}, - }, - } -} - -// generateDeployment creates a deployment, with the input image as its template -func generateDeployment(image string) extensions.Deployment { - podLabels := map[string]string{"name": image} - terminationSec := int64(30) - return extensions.Deployment{ - ObjectMeta: api.ObjectMeta{ - Name: image, - }, - Spec: extensions.DeploymentSpec{ - Replicas: 1, - Selector: &unversioned.LabelSelector{MatchLabels: podLabels}, - Template: api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: podLabels, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: image, - Image: image, - ImagePullPolicy: api.PullAlways, - TerminationMessagePath: api.TerminationMessagePathDefault, - }, - }, - DNSPolicy: api.DNSClusterFirst, - TerminationGracePeriodSeconds: &terminationSec, - RestartPolicy: api.RestartPolicyAlways, - SecurityContext: &api.PodSecurityContext{}, - }, - }, - }, - } -} - -func TestGetNewRC(t *testing.T) { - newDeployment := generateDeployment("nginx") - newRC := generateRS(newDeployment) - - tests := []struct { - test string - objs []runtime.Object - expected *extensions.ReplicaSet - }{ - { - "No new ReplicaSet", - []runtime.Object{ - &api.PodList{}, - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ - generateRS(generateDeployment("foo")), - generateRS(generateDeployment("bar")), - }, - }, - }, - nil, - }, - { - "Has new ReplicaSet", - []runtime.Object{ - &api.PodList{}, - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ - generateRS(generateDeployment("foo")), - generateRS(generateDeployment("bar")), - generateRS(generateDeployment("abc")), - newRC, - generateRS(generateDeployment("xyz")), - }, - }, - }, - &newRC, - }, - } - - for _, test := range tests { - fakeClient := &fake.Clientset{} - fakeClient = addListPodsReactor(fakeClient, test.objs[0]) - fakeClient = addListRSReactor(fakeClient, test.objs[1]) - fakeClient = addUpdatePodsReactor(fakeClient) - fakeClient = addUpdateRSReactor(fakeClient) - rs, err := GetNewReplicaSet(&newDeployment, fakeClient) - if err != nil { - t.Errorf("In test case %s, got unexpected error %v", test.test, err) - } - if !api.Semantic.DeepEqual(rs, test.expected) { - t.Errorf("In test case %s, expected %+v, got %+v", test.test, test.expected, rs) - } - } -} - -func TestGetOldRCs(t *testing.T) { - newDeployment := generateDeployment("nginx") - newRS := generateRS(newDeployment) - newRS.Status.FullyLabeledReplicas = newRS.Spec.Replicas - newPod := generatePodFromRS(newRS) - - // create 2 old deployments and related replica sets/pods, with the same labels but different template - oldDeployment := generateDeployment("nginx") - oldDeployment.Spec.Template.Spec.Containers[0].Name = "nginx-old-1" - oldRS := generateRS(oldDeployment) - oldRS.Status.FullyLabeledReplicas = oldRS.Spec.Replicas - oldPod := generatePodFromRS(oldRS) - oldDeployment2 := generateDeployment("nginx") - oldDeployment2.Spec.Template.Spec.Containers[0].Name = "nginx-old-2" - oldRS2 := generateRS(oldDeployment2) - oldRS2.Status.FullyLabeledReplicas = oldRS2.Spec.Replicas - oldPod2 := generatePodFromRS(oldRS2) - - // create 1 ReplicaSet that existed before the deployment, with the same labels as the deployment - existedPod := generatePod(newDeployment.Spec.Template.Labels, "foo") - existedRS := generateRSWithLabel(newDeployment.Spec.Template.Labels, "foo") - existedRS.Status.FullyLabeledReplicas = existedRS.Spec.Replicas - - tests := []struct { - test string - objs []runtime.Object - expected []*extensions.ReplicaSet - }{ - { - "No old ReplicaSets", - []runtime.Object{ - &api.PodList{ - Items: []api.Pod{ - generatePod(newDeployment.Spec.Template.Labels, "foo"), - generatePod(newDeployment.Spec.Template.Labels, "bar"), - newPod, - }, - }, - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ - generateRS(generateDeployment("foo")), - newRS, - generateRS(generateDeployment("bar")), - }, - }, - }, - []*extensions.ReplicaSet{}, - }, - { - "Has old ReplicaSet", - []runtime.Object{ - &api.PodList{ - Items: []api.Pod{ - oldPod, - oldPod2, - generatePod(map[string]string{"name": "bar"}, "bar"), - generatePod(map[string]string{"name": "xyz"}, "xyz"), - existedPod, - generatePod(newDeployment.Spec.Template.Labels, "abc"), - }, - }, - &extensions.ReplicaSetList{ - Items: []extensions.ReplicaSet{ - oldRS2, - oldRS, - existedRS, - newRS, - generateRSWithLabel(map[string]string{"name": "xyz"}, "xyz"), - generateRSWithLabel(map[string]string{"name": "bar"}, "bar"), - }, - }, - }, - []*extensions.ReplicaSet{&oldRS, &oldRS2, &existedRS}, - }, - } - - for _, test := range tests { - fakeClient := &fake.Clientset{} - fakeClient = addListPodsReactor(fakeClient, test.objs[0]) - fakeClient = addListRSReactor(fakeClient, test.objs[1]) - fakeClient = addGetRSReactor(fakeClient, test.objs[1]) - fakeClient = addUpdatePodsReactor(fakeClient) - fakeClient = addUpdateRSReactor(fakeClient) - rss, _, err := GetOldReplicaSets(&newDeployment, fakeClient) - if err != nil { - t.Errorf("In test case %s, got unexpected error %v", test.test, err) - } - if !equal(rss, test.expected) { - t.Errorf("In test case %q, expected:", test.test) - for _, rs := range test.expected { - t.Errorf("rs = %+v", rs) - } - t.Errorf("In test case %q, got:", test.test) - for _, rs := range rss { - t.Errorf("rs = %+v", rs) - } - } - } -} - -// equal compares the equality of two ReplicaSet slices regardless of their ordering -func equal(rss1, rss2 []*extensions.ReplicaSet) bool { - if reflect.DeepEqual(rss1, rss2) { - return true - } - if rss1 == nil || rss2 == nil || len(rss1) != len(rss2) { - return false - } - count := 0 - for _, rs1 := range rss1 { - for _, rs2 := range rss2 { - if reflect.DeepEqual(rs1, rs2) { - count++ - break - } - } - } - return count == len(rss1) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/diff/diff.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/diff/diff.go deleted file mode 100644 index e907f7f7b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/diff/diff.go +++ /dev/null @@ -1,121 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 diff - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - "text/tabwriter" - - "github.com/davecgh/go-spew/spew" -) - -// StringDiff diffs a and b and returns a human readable diff. -func StringDiff(a, b string) string { - ba := []byte(a) - bb := []byte(b) - out := []byte{} - i := 0 - for ; i < len(ba) && i < len(bb); i++ { - if ba[i] != bb[i] { - break - } - out = append(out, ba[i]) - } - out = append(out, []byte("\n\nA: ")...) - out = append(out, ba[i:]...) - out = append(out, []byte("\n\nB: ")...) - out = append(out, bb[i:]...) - out = append(out, []byte("\n\n")...) - return string(out) -} - -// ObjectDiff writes the two objects out as JSON and prints out the identical part of -// the objects followed by the remaining part of 'a' and finally the remaining part of 'b'. -// For debugging tests. -func ObjectDiff(a, b interface{}) string { - ab, err := json.Marshal(a) - if err != nil { - panic(fmt.Sprintf("a: %v", err)) - } - bb, err := json.Marshal(b) - if err != nil { - panic(fmt.Sprintf("b: %v", err)) - } - return StringDiff(string(ab), string(bb)) -} - -// ObjectGoPrintDiff is like ObjectDiff, but uses go-spew to print the objects, -// which shows absolutely everything by recursing into every single pointer -// (go's %#v formatters OTOH stop at a certain point). This is needed when you -// can't figure out why reflect.DeepEqual is returning false and nothing is -// showing you differences. This will. -func ObjectGoPrintDiff(a, b interface{}) string { - s := spew.ConfigState{DisableMethods: true} - return StringDiff( - s.Sprintf("%#v", a), - s.Sprintf("%#v", b), - ) -} - -// ObjectGoPrintSideBySide prints a and b as textual dumps side by side, -// enabling easy visual scanning for mismatches. -func ObjectGoPrintSideBySide(a, b interface{}) string { - s := spew.ConfigState{ - Indent: " ", - // Extra deep spew. - DisableMethods: true, - } - sA := s.Sdump(a) - sB := s.Sdump(b) - - linesA := strings.Split(sA, "\n") - linesB := strings.Split(sB, "\n") - width := 0 - for _, s := range linesA { - l := len(s) - if l > width { - width = l - } - } - for _, s := range linesB { - l := len(s) - if l > width { - width = l - } - } - buf := &bytes.Buffer{} - w := tabwriter.NewWriter(buf, width, 0, 1, ' ', 0) - max := len(linesA) - if len(linesB) > max { - max = len(linesB) - } - for i := 0; i < max; i++ { - var a, b string - if i < len(linesA) { - a = linesA[i] - } - if i < len(linesB) { - b = linesB[i] - } - fmt.Fprintf(w, "%s\t%s\n", a, b) - } - w.Flush() - return buf.String() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/env/env.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/env/env.go deleted file mode 100644 index ad4310c25..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/env/env.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 env - -import ( - "os" - "strconv" -) - -func GetEnvAsStringOrFallback(key, defaultValue string) string { - if v := os.Getenv(key); v != "" { - return v - } - return defaultValue -} - -func GetEnvAsIntOrFallback(key string, defaultValue int) (int, error) { - if v := os.Getenv(key); v != "" { - value, err := strconv.Atoi(v) - if err != nil { - return defaultValue, err - } - return value, nil - } - return defaultValue, nil -} - -func GetEnvAsFloat64OrFallback(key string, defaultValue float64) (float64, error) { - if v := os.Getenv(key); v != "" { - value, err := strconv.ParseFloat(v, 64) - if err != nil { - return defaultValue, err - } - return value, nil - } - return defaultValue, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/env/env_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/env/env_test.go deleted file mode 100644 index f7ff0a235..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/env/env_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 env - -import ( - "os" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestGetEnvAsStringOrFallback(t *testing.T) { - const expected = "foo" - - assert := assert.New(t) - - key := "FLOCKER_SET_VAR" - os.Setenv(key, expected) - assert.Equal(expected, GetEnvAsStringOrFallback(key, "~"+expected)) - - key = "FLOCKER_UNSET_VAR" - assert.Equal(expected, GetEnvAsStringOrFallback(key, expected)) -} - -func TestGetEnvAsIntOrFallback(t *testing.T) { - const expected = 1 - - assert := assert.New(t) - - key := "FLOCKER_SET_VAR" - os.Setenv(key, strconv.Itoa(expected)) - returnVal, _ := GetEnvAsIntOrFallback(key, 1) - assert.Equal(expected, returnVal) - - key = "FLOCKER_UNSET_VAR" - returnVal, _ = GetEnvAsIntOrFallback(key, expected) - assert.Equal(expected, returnVal) -} - -func TestGetEnvAsFloat64OrFallback(t *testing.T) { - const expected = 1.0 - - assert := assert.New(t) - - key := "FLOCKER_SET_VAR" - os.Setenv(key, "1.0") - returnVal, _ := GetEnvAsFloat64OrFallback(key, 2.0) - assert.Equal(expected, returnVal) - - key = "FLOCKER_UNSET_VAR" - returnVal, _ = GetEnvAsFloat64OrFallback(key, 1.0) - assert.Equal(expected, returnVal) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/errors/errors_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/errors/errors_test.go deleted file mode 100644 index 7ecf919ff..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/errors/errors_test.go +++ /dev/null @@ -1,286 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 errors - -import ( - "fmt" - "reflect" - "testing" -) - -func TestEmptyAggregate(t *testing.T) { - var slice []error - var agg Aggregate - var err error - - agg = NewAggregate(slice) - if agg != nil { - t.Errorf("expected nil, got %#v", agg) - } - err = NewAggregate(slice) - if err != nil { - t.Errorf("expected nil, got %#v", err) - } - - // This is not normally possible, but pedantry demands I test it. - agg = aggregate(slice) // empty aggregate - if s := agg.Error(); s != "" { - t.Errorf("expected empty string, got %q", s) - } - if s := agg.Errors(); len(s) != 0 { - t.Errorf("expected empty slice, got %#v", s) - } - err = agg.(error) - if s := err.Error(); s != "" { - t.Errorf("expected empty string, got %q", s) - } -} - -func TestSingularAggregate(t *testing.T) { - var slice []error = []error{fmt.Errorf("err")} - var agg Aggregate - var err error - - agg = NewAggregate(slice) - if agg == nil { - t.Errorf("expected non-nil") - } - if s := agg.Error(); s != "err" { - t.Errorf("expected 'err', got %q", s) - } - if s := agg.Errors(); len(s) != 1 { - t.Errorf("expected one-element slice, got %#v", s) - } - if s := agg.Errors()[0].Error(); s != "err" { - t.Errorf("expected 'err', got %q", s) - } - - err = agg.(error) - if err == nil { - t.Errorf("expected non-nil") - } - if s := err.Error(); s != "err" { - t.Errorf("expected 'err', got %q", s) - } -} - -func TestPluralAggregate(t *testing.T) { - var slice []error = []error{fmt.Errorf("abc"), fmt.Errorf("123")} - var agg Aggregate - var err error - - agg = NewAggregate(slice) - if agg == nil { - t.Errorf("expected non-nil") - } - if s := agg.Error(); s != "[abc, 123]" { - t.Errorf("expected '[abc, 123]', got %q", s) - } - if s := agg.Errors(); len(s) != 2 { - t.Errorf("expected two-elements slice, got %#v", s) - } - if s := agg.Errors()[0].Error(); s != "abc" { - t.Errorf("expected '[abc, 123]', got %q", s) - } - - err = agg.(error) - if err == nil { - t.Errorf("expected non-nil") - } - if s := err.Error(); s != "[abc, 123]" { - t.Errorf("expected '[abc, 123]', got %q", s) - } -} - -func TestFilterOut(t *testing.T) { - testCases := []struct { - err error - filter []Matcher - expected error - }{ - { - nil, - []Matcher{}, - nil, - }, - { - aggregate{}, - []Matcher{}, - nil, - }, - { - aggregate{fmt.Errorf("abc")}, - []Matcher{}, - aggregate{fmt.Errorf("abc")}, - }, - { - aggregate{fmt.Errorf("abc")}, - []Matcher{func(err error) bool { return false }}, - aggregate{fmt.Errorf("abc")}, - }, - { - aggregate{fmt.Errorf("abc")}, - []Matcher{func(err error) bool { return true }}, - nil, - }, - { - aggregate{fmt.Errorf("abc")}, - []Matcher{func(err error) bool { return false }, func(err error) bool { return false }}, - aggregate{fmt.Errorf("abc")}, - }, - { - aggregate{fmt.Errorf("abc")}, - []Matcher{func(err error) bool { return false }, func(err error) bool { return true }}, - nil, - }, - { - aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")}, - []Matcher{func(err error) bool { return err.Error() == "def" }}, - aggregate{fmt.Errorf("abc"), fmt.Errorf("ghi")}, - }, - { - aggregate{aggregate{fmt.Errorf("abc")}}, - []Matcher{}, - aggregate{aggregate{fmt.Errorf("abc")}}, - }, - { - aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}}, - []Matcher{}, - aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}}, - }, - { - aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}}, - []Matcher{func(err error) bool { return err.Error() == "def" }}, - aggregate{aggregate{fmt.Errorf("abc")}}, - }, - } - for i, testCase := range testCases { - err := FilterOut(testCase.err, testCase.filter...) - if !reflect.DeepEqual(testCase.expected, err) { - t.Errorf("%d: expected %v, got %v", i, testCase.expected, err) - } - } -} - -func TestFlatten(t *testing.T) { - testCases := []struct { - agg Aggregate - expected Aggregate - }{ - { - nil, - nil, - }, - { - aggregate{}, - nil, - }, - { - aggregate{fmt.Errorf("abc")}, - aggregate{fmt.Errorf("abc")}, - }, - { - aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")}, - aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")}, - }, - { - aggregate{aggregate{fmt.Errorf("abc")}}, - aggregate{fmt.Errorf("abc")}, - }, - { - aggregate{aggregate{aggregate{fmt.Errorf("abc")}}}, - aggregate{fmt.Errorf("abc")}, - }, - { - aggregate{aggregate{fmt.Errorf("abc"), aggregate{fmt.Errorf("def")}}}, - aggregate{fmt.Errorf("abc"), fmt.Errorf("def")}, - }, - { - aggregate{aggregate{aggregate{fmt.Errorf("abc")}, fmt.Errorf("def"), aggregate{fmt.Errorf("ghi")}}}, - aggregate{fmt.Errorf("abc"), fmt.Errorf("def"), fmt.Errorf("ghi")}, - }, - } - for i, testCase := range testCases { - agg := Flatten(testCase.agg) - if !reflect.DeepEqual(testCase.expected, agg) { - t.Errorf("%d: expected %v, got %v", i, testCase.expected, agg) - } - } -} - -func TestAggregateGoroutines(t *testing.T) { - testCases := []struct { - errs []error - expected map[string]bool // can't compare directly to Aggregate due to non-deterministic ordering - }{ - { - []error{}, - nil, - }, - { - []error{nil}, - nil, - }, - { - []error{nil, nil}, - nil, - }, - { - []error{fmt.Errorf("1")}, - map[string]bool{"1": true}, - }, - { - []error{fmt.Errorf("1"), nil}, - map[string]bool{"1": true}, - }, - { - []error{fmt.Errorf("1"), fmt.Errorf("267")}, - map[string]bool{"1": true, "267": true}, - }, - { - []error{fmt.Errorf("1"), nil, fmt.Errorf("1234")}, - map[string]bool{"1": true, "1234": true}, - }, - { - []error{nil, fmt.Errorf("1"), nil, fmt.Errorf("1234"), fmt.Errorf("22")}, - map[string]bool{"1": true, "1234": true, "22": true}, - }, - } - for i, testCase := range testCases { - funcs := make([]func() error, len(testCase.errs)) - for i := range testCase.errs { - err := testCase.errs[i] - funcs[i] = func() error { return err } - } - agg := AggregateGoroutines(funcs...) - if agg == nil { - if len(testCase.expected) > 0 { - t.Errorf("%d: expected %v, got nil", i, testCase.expected) - } - continue - } - if len(agg.Errors()) != len(testCase.expected) { - t.Errorf("%d: expected %d errors in aggregate, got %v", i, len(testCase.expected), agg) - continue - } - for _, err := range agg.Errors() { - if !testCase.expected[err.Error()] { - t.Errorf("%d: expected %v, got aggregate containing %v", i, testCase.expected, err) - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/doc.go deleted file mode 100644 index 64c1541bf..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 exec provides an injectable interface and implementations for running commands. -package exec diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/exec.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/exec.go deleted file mode 100644 index 80444a9d8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/exec.go +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 exec - -import ( - osexec "os/exec" - "syscall" -) - -// ErrExecutableNotFound is returned if the executable is not found. -var ErrExecutableNotFound = osexec.ErrNotFound - -// Interface is an interface that presents a subset of the os/exec API. Use this -// when you want to inject fakeable/mockable exec behavior. -type Interface interface { - // Command returns a Cmd instance which can be used to run a single command. - // This follows the pattern of package os/exec. - Command(cmd string, args ...string) Cmd - - // LookPath wraps os/exec.LookPath - LookPath(file string) (string, error) -} - -// Cmd is an interface that presents an API that is very similar to Cmd from os/exec. -// As more functionality is needed, this can grow. Since Cmd is a struct, we will have -// to replace fields with get/set method pairs. -type Cmd interface { - // CombinedOutput runs the command and returns its combined standard output - // and standard error. This follows the pattern of package os/exec. - CombinedOutput() ([]byte, error) - // Output runs the command and returns standard output, but not standard err - Output() ([]byte, error) - SetDir(dir string) -} - -// ExitError is an interface that presents an API similar to os.ProcessState, which is -// what ExitError from os/exec is. This is designed to make testing a bit easier and -// probably loses some of the cross-platform properties of the underlying library. -type ExitError interface { - String() string - Error() string - Exited() bool - ExitStatus() int -} - -// Implements Interface in terms of really exec()ing. -type executor struct{} - -// New returns a new Interface which will os/exec to run commands. -func New() Interface { - return &executor{} -} - -// Command is part of the Interface interface. -func (executor *executor) Command(cmd string, args ...string) Cmd { - return (*cmdWrapper)(osexec.Command(cmd, args...)) -} - -// LookPath is part of the Interface interface -func (executor *executor) LookPath(file string) (string, error) { - return osexec.LookPath(file) -} - -// Wraps exec.Cmd so we can capture errors. -type cmdWrapper osexec.Cmd - -func (cmd *cmdWrapper) SetDir(dir string) { - cmd.Dir = dir -} - -// CombinedOutput is part of the Cmd interface. -func (cmd *cmdWrapper) CombinedOutput() ([]byte, error) { - out, err := (*osexec.Cmd)(cmd).CombinedOutput() - if err != nil { - return out, handleError(err) - } - return out, nil -} - -func (cmd *cmdWrapper) Output() ([]byte, error) { - out, err := (*osexec.Cmd)(cmd).Output() - if err != nil { - return out, handleError(err) - } - return out, nil -} - -func handleError(err error) error { - if ee, ok := err.(*osexec.ExitError); ok { - // Force a compile fail if exitErrorWrapper can't convert to ExitError. - var x ExitError = &exitErrorWrapper{ee} - return x - } - if ee, ok := err.(*osexec.Error); ok { - if ee.Err == osexec.ErrNotFound { - return ErrExecutableNotFound - } - } - return err -} - -// exitErrorWrapper is an implementation of ExitError in terms of os/exec ExitError. -// Note: standard exec.ExitError is type *os.ProcessState, which already implements Exited(). -type exitErrorWrapper struct { - *osexec.ExitError -} - -// ExitStatus is part of the ExitError interface. -func (eew exitErrorWrapper) ExitStatus() int { - ws, ok := eew.Sys().(syscall.WaitStatus) - if !ok { - panic("can't call ExitStatus() on a non-WaitStatus exitErrorWrapper") - } - return ws.ExitStatus() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/exec_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/exec_test.go deleted file mode 100644 index d24f9cc19..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/exec_test.go +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 exec - -import ( - osexec "os/exec" - "testing" -) - -func TestExecutorNoArgs(t *testing.T) { - ex := New() - - cmd := ex.Command("true") - out, err := cmd.CombinedOutput() - if err != nil { - t.Errorf("expected success, got %v", err) - } - if len(out) != 0 { - t.Errorf("expected no output, got %q", string(out)) - } - - cmd = ex.Command("false") - out, err = cmd.CombinedOutput() - if err == nil { - t.Errorf("expected failure, got nil error") - } - if len(out) != 0 { - t.Errorf("expected no output, got %q", string(out)) - } - ee, ok := err.(ExitError) - if !ok { - t.Errorf("expected an ExitError, got %+v", err) - } - if ee.Exited() { - if code := ee.ExitStatus(); code != 1 { - t.Errorf("expected exit status 1, got %d", code) - } - } - - cmd = ex.Command("/does/not/exist") - out, err = cmd.CombinedOutput() - if err == nil { - t.Errorf("expected failure, got nil error") - } - if ee, ok := err.(ExitError); ok { - t.Errorf("expected non-ExitError, got %+v", ee) - } -} - -func TestExecutorWithArgs(t *testing.T) { - ex := New() - - cmd := ex.Command("/bin/echo", "stdout") - out, err := cmd.CombinedOutput() - if err != nil { - t.Errorf("expected success, got %+v", err) - } - if string(out) != "stdout\n" { - t.Errorf("unexpected output: %q", string(out)) - } - - cmd = ex.Command("/bin/sh", "-c", "echo stderr > /dev/stderr") - out, err = cmd.CombinedOutput() - if err != nil { - t.Errorf("expected success, got %+v", err) - } - if string(out) != "stderr\n" { - t.Errorf("unexpected output: %q", string(out)) - } -} - -func TestLookPath(t *testing.T) { - ex := New() - - shExpected, _ := osexec.LookPath("sh") - sh, _ := ex.LookPath("sh") - if sh != shExpected { - t.Errorf("unexpected result for LookPath: got %s, expected %s", sh, shExpected) - } -} - -func TestExecutableNotFound(t *testing.T) { - exec := New() - cmd := exec.Command("fake_executable_name") - _, err := cmd.CombinedOutput() - if err != ErrExecutableNotFound { - t.Errorf("Expected error ErrExecutableNotFound but got %v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/fake_exec.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/fake_exec.go deleted file mode 100644 index 40df52921..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/exec/fake_exec.go +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 exec - -import ( - "fmt" -) - -// A simple scripted Interface type. -type FakeExec struct { - CommandScript []FakeCommandAction - CommandCalls int - LookPathFunc func(string) (string, error) -} - -type FakeCommandAction func(cmd string, args ...string) Cmd - -func (fake *FakeExec) Command(cmd string, args ...string) Cmd { - if fake.CommandCalls > len(fake.CommandScript)-1 { - panic(fmt.Sprintf("ran out of Command() actions. Could not handle command [%d]: %s args: %v", fake.CommandCalls, cmd, args)) - } - i := fake.CommandCalls - fake.CommandCalls++ - return fake.CommandScript[i](cmd, args...) -} - -func (fake *FakeExec) LookPath(file string) (string, error) { - return fake.LookPathFunc(file) -} - -// A simple scripted Cmd type. -type FakeCmd struct { - Argv []string - CombinedOutputScript []FakeCombinedOutputAction - CombinedOutputCalls int - CombinedOutputLog [][]string - Dirs []string -} - -func InitFakeCmd(fake *FakeCmd, cmd string, args ...string) Cmd { - fake.Argv = append([]string{cmd}, args...) - return fake -} - -type FakeCombinedOutputAction func() ([]byte, error) - -func (fake *FakeCmd) SetDir(dir string) { - fake.Dirs = append(fake.Dirs, dir) -} - -func (fake *FakeCmd) CombinedOutput() ([]byte, error) { - if fake.CombinedOutputCalls > len(fake.CombinedOutputScript)-1 { - panic("ran out of CombinedOutput() actions") - } - if fake.CombinedOutputLog == nil { - fake.CombinedOutputLog = [][]string{} - } - i := fake.CombinedOutputCalls - fake.CombinedOutputLog = append(fake.CombinedOutputLog, append([]string{}, fake.Argv...)) - fake.CombinedOutputCalls++ - return fake.CombinedOutputScript[i]() -} - -func (fake *FakeCmd) Output() ([]byte, error) { - return nil, fmt.Errorf("unimplemented") -} - -// A simple fake ExitError type. -type FakeExitError struct { - Status int -} - -func (fake *FakeExitError) String() string { - return fmt.Sprintf("exit %d", fake.Status) -} - -func (fake *FakeExitError) Error() string { - return fake.String() -} - -func (fake *FakeExitError) Exited() bool { - return true -} - -func (fake *FakeExitError) ExitStatus() int { - return fake.Status -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flock/flock_other.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flock/flock_other.go deleted file mode 100644 index b80981882..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flock/flock_other.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build !linux,!darwin,!freebsd,!openbsd,!netbsd,!dragonfly - -/* -Copyright 2016 The Kubernetes Authors 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 flock - -// Acquire is not implemented on non-unix systems. -func Acquire(path string) error { - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flock/flock_unix.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flock/flock_unix.go deleted file mode 100644 index 88ca8d700..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flock/flock_unix.go +++ /dev/null @@ -1,51 +0,0 @@ -// +build linux darwin freebsd openbsd netbsd dragonfly - -/* -Copyright 2016 The Kubernetes Authors 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 flock - -import ( - "os" - "sync" - - "golang.org/x/sys/unix" -) - -var ( - // lock guards lockfile. Assignment is not atomic. - lock sync.Mutex - // os.File has a runtime.Finalizer so the fd will be closed if the struct - // is garbage collected. Let's hold onto a reference so that doesn't happen. - lockfile *os.File -) - -// Acquire acquires a lock on a file for the duration of the process. This method -// is reentrant. -func Acquire(path string) error { - lock.Lock() - defer lock.Unlock() - var err error - if lockfile, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0600); err != nil { - return err - } - - opts := unix.Flock_t{Type: unix.F_WRLCK} - if err := unix.FcntlFlock(lockfile.Fd(), unix.F_SETLKW, &opts); err != nil { - return err - } - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flowcontrol/backoff_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flowcontrol/backoff_test.go deleted file mode 100644 index 350c5b790..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flowcontrol/backoff_test.go +++ /dev/null @@ -1,194 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 flowcontrol - -import ( - "k8s.io/kubernetes/pkg/util" - "testing" - "time" -) - -func TestSlowBackoff(t *testing.T) { - id := "_idSlow" - tc := util.NewFakeClock(time.Now()) - step := time.Second - maxDuration := 50 * step - - b := NewFakeBackOff(step, maxDuration, tc) - cases := []time.Duration{0, 1, 2, 4, 8, 16, 32, 50, 50, 50} - for ix, c := range cases { - tc.Step(step) - w := b.Get(id) - if w != c*step { - t.Errorf("input: '%d': expected %s, got %s", ix, c*step, w) - } - b.Next(id, tc.Now()) - } - - //Now confirm that the Reset cancels backoff. - b.Next(id, tc.Now()) - b.Reset(id) - if b.Get(id) != 0 { - t.Errorf("Reset didn't clear the backoff.") - } - -} - -func TestBackoffReset(t *testing.T) { - id := "_idReset" - tc := util.NewFakeClock(time.Now()) - step := time.Second - maxDuration := step * 5 - b := NewFakeBackOff(step, maxDuration, tc) - startTime := tc.Now() - - // get to backoff = maxDuration - for i := 0; i <= int(maxDuration/step); i++ { - tc.Step(step) - b.Next(id, tc.Now()) - } - - // backoff should be capped at maxDuration - if !b.IsInBackOffSince(id, tc.Now()) { - t.Errorf("expected to be in Backoff got %s", b.Get(id)) - } - - lastUpdate := tc.Now() - tc.Step(2*maxDuration + step) // time += 11s, 11 > 2*maxDuration - if b.IsInBackOffSince(id, lastUpdate) { - t.Errorf("expected to not be in Backoff after reset (start=%s, now=%s, lastUpdate=%s), got %s", startTime, tc.Now(), lastUpdate, b.Get(id)) - } -} - -func TestBackoffHightWaterMark(t *testing.T) { - id := "_idHiWaterMark" - tc := util.NewFakeClock(time.Now()) - step := time.Second - maxDuration := 5 * step - b := NewFakeBackOff(step, maxDuration, tc) - - // get to backoff = maxDuration - for i := 0; i <= int(maxDuration/step); i++ { - tc.Step(step) - b.Next(id, tc.Now()) - } - - // backoff high watermark expires after 2*maxDuration - tc.Step(maxDuration + step) - b.Next(id, tc.Now()) - - if b.Get(id) != maxDuration { - t.Errorf("expected Backoff to stay at high watermark %s got %s", maxDuration, b.Get(id)) - } -} - -func TestBackoffGC(t *testing.T) { - id := "_idGC" - tc := util.NewFakeClock(time.Now()) - step := time.Second - maxDuration := 5 * step - - b := NewFakeBackOff(step, maxDuration, tc) - - for i := 0; i <= int(maxDuration/step); i++ { - tc.Step(step) - b.Next(id, tc.Now()) - } - lastUpdate := tc.Now() - tc.Step(maxDuration + step) - b.GC() - _, found := b.perItemBackoff[id] - if !found { - t.Errorf("expected GC to skip entry, elapsed time=%s maxDuration=%s", tc.Now().Sub(lastUpdate), maxDuration) - } - - tc.Step(maxDuration + step) - b.GC() - r, found := b.perItemBackoff[id] - if found { - t.Errorf("expected GC of entry after %s got entry %v", tc.Now().Sub(lastUpdate), r) - } -} - -func TestIsInBackOffSinceUpdate(t *testing.T) { - id := "_idIsInBackOffSinceUpdate" - tc := util.NewFakeClock(time.Now()) - step := time.Second - maxDuration := 10 * step - b := NewFakeBackOff(step, maxDuration, tc) - startTime := tc.Now() - - cases := []struct { - tick time.Duration - inBackOff bool - value int - }{ - {tick: 0, inBackOff: false, value: 0}, - {tick: 1, inBackOff: false, value: 1}, - {tick: 2, inBackOff: true, value: 2}, - {tick: 3, inBackOff: false, value: 2}, - {tick: 4, inBackOff: true, value: 4}, - {tick: 5, inBackOff: true, value: 4}, - {tick: 6, inBackOff: true, value: 4}, - {tick: 7, inBackOff: false, value: 4}, - {tick: 8, inBackOff: true, value: 8}, - {tick: 9, inBackOff: true, value: 8}, - {tick: 10, inBackOff: true, value: 8}, - {tick: 11, inBackOff: true, value: 8}, - {tick: 12, inBackOff: true, value: 8}, - {tick: 13, inBackOff: true, value: 8}, - {tick: 14, inBackOff: true, value: 8}, - {tick: 15, inBackOff: false, value: 8}, - {tick: 16, inBackOff: true, value: 10}, - {tick: 17, inBackOff: true, value: 10}, - {tick: 18, inBackOff: true, value: 10}, - {tick: 19, inBackOff: true, value: 10}, - {tick: 20, inBackOff: true, value: 10}, - {tick: 21, inBackOff: true, value: 10}, - {tick: 22, inBackOff: true, value: 10}, - {tick: 23, inBackOff: true, value: 10}, - {tick: 24, inBackOff: true, value: 10}, - {tick: 25, inBackOff: false, value: 10}, - {tick: 26, inBackOff: true, value: 10}, - {tick: 27, inBackOff: true, value: 10}, - {tick: 28, inBackOff: true, value: 10}, - {tick: 29, inBackOff: true, value: 10}, - {tick: 30, inBackOff: true, value: 10}, - {tick: 31, inBackOff: true, value: 10}, - {tick: 32, inBackOff: true, value: 10}, - {tick: 33, inBackOff: true, value: 10}, - {tick: 34, inBackOff: true, value: 10}, - {tick: 35, inBackOff: false, value: 10}, - {tick: 56, inBackOff: false, value: 0}, - {tick: 57, inBackOff: false, value: 1}, - } - - for _, c := range cases { - tc.SetTime(startTime.Add(c.tick * step)) - if c.inBackOff != b.IsInBackOffSinceUpdate(id, tc.Now()) { - t.Errorf("expected IsInBackOffSinceUpdate %v got %v at tick %s", c.inBackOff, b.IsInBackOffSinceUpdate(id, tc.Now()), c.tick*step) - } - - if c.inBackOff && (time.Duration(c.value)*step != b.Get(id)) { - t.Errorf("expected backoff value=%s got %s at tick %s", time.Duration(c.value)*step, b.Get(id), c.tick*step) - } - - if !c.inBackOff { - b.Next(id, tc.Now()) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flowcontrol/throttle_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flowcontrol/throttle_test.go deleted file mode 100644 index 30b792ec0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flowcontrol/throttle_test.go +++ /dev/null @@ -1,127 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 flowcontrol - -import ( - "math" - "sync" - "testing" - "time" -) - -func TestBasicThrottle(t *testing.T) { - r := NewTokenBucketRateLimiter(1, 3) - for i := 0; i < 3; i++ { - if !r.TryAccept() { - t.Error("unexpected false accept") - } - } - if r.TryAccept() { - t.Error("unexpected true accept") - } -} - -func TestIncrementThrottle(t *testing.T) { - r := NewTokenBucketRateLimiter(1, 1) - if !r.TryAccept() { - t.Error("unexpected false accept") - } - if r.TryAccept() { - t.Error("unexpected true accept") - } - - // Allow to refill - time.Sleep(2 * time.Second) - - if !r.TryAccept() { - t.Error("unexpected false accept") - } -} - -func TestThrottle(t *testing.T) { - r := NewTokenBucketRateLimiter(10, 5) - - // Should consume 5 tokens immediately, then - // the remaining 11 should take at least 1 second (0.1s each) - expectedFinish := time.Now().Add(time.Second * 1) - for i := 0; i < 16; i++ { - r.Accept() - } - if time.Now().Before(expectedFinish) { - t.Error("rate limit was not respected, finished too early") - } -} - -func TestRateLimiterSaturation(t *testing.T) { - const e = 0.000001 - tests := []struct { - capacity int - take int - - expectedSaturation float64 - }{ - {1, 1, 1}, - {10, 3, 0.3}, - } - for i, tt := range tests { - rl := NewTokenBucketRateLimiter(1, tt.capacity) - for i := 0; i < tt.take; i++ { - rl.Accept() - } - if math.Abs(rl.Saturation()-tt.expectedSaturation) > e { - t.Fatalf("#%d: Saturation rate difference isn't within tolerable range\n want=%f, get=%f", - i, tt.expectedSaturation, rl.Saturation()) - } - } -} - -func TestAlwaysFake(t *testing.T) { - rl := NewFakeAlwaysRateLimiter() - if !rl.TryAccept() { - t.Error("TryAccept in AlwaysFake should return true.") - } - // If this will block the test will timeout - rl.Accept() -} - -func TestNeverFake(t *testing.T) { - rl := NewFakeNeverRateLimiter() - if rl.TryAccept() { - t.Error("TryAccept in NeverFake should return false.") - } - - finished := false - wg := sync.WaitGroup{} - wg.Add(1) - go func() { - rl.Accept() - finished = true - wg.Done() - }() - - // Wait some time to make sure it never finished. - time.Sleep(time.Second) - if finished { - t.Error("Accept should block forever in NeverFake.") - } - - rl.Stop() - wg.Wait() - if !finished { - t.Error("Stop should make Accept unblock in NeverFake.") - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/doc.go deleted file mode 100644 index 485b99926..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 flushwriter implements a wrapper for a writer that flushes on every -// write if that writer implements the io.Flusher interface -package flushwriter diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/writer.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/writer.go deleted file mode 100644 index 0a9d88a78..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/writer.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 flushwriter - -import ( - "io" - "net/http" -) - -// Wrap wraps an io.Writer into a writer that flushes after every write if -// the writer implements the Flusher interface. -func Wrap(w io.Writer) io.Writer { - fw := &flushWriter{ - writer: w, - } - if flusher, ok := w.(http.Flusher); ok { - fw.flusher = flusher - } - return fw -} - -// flushWriter provides wrapper for responseWriter with HTTP streaming capabilities -type flushWriter struct { - flusher http.Flusher - writer io.Writer -} - -// Write is a FlushWriter implementation of the io.Writer that sends any buffered -// data to the client. -func (fw *flushWriter) Write(p []byte) (n int, err error) { - n, err = fw.writer.Write(p) - if err != nil { - return - } - if fw.flusher != nil { - fw.flusher.Flush() - } - return -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/writer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/writer_test.go deleted file mode 100644 index d40b0bb00..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/flushwriter/writer_test.go +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 flushwriter - -import ( - "fmt" - "testing" -) - -type writerWithFlush struct { - writeCount, flushCount int - err error -} - -func (w *writerWithFlush) Flush() { - w.flushCount++ -} - -func (w *writerWithFlush) Write(p []byte) (n int, err error) { - w.writeCount++ - return len(p), w.err -} - -type writerWithNoFlush struct { - writeCount int -} - -func (w *writerWithNoFlush) Write(p []byte) (n int, err error) { - w.writeCount++ - return len(p), nil -} - -func TestWriteWithFlush(t *testing.T) { - w := &writerWithFlush{} - fw := Wrap(w) - for i := 0; i < 10; i++ { - _, err := fw.Write([]byte("Test write")) - if err != nil { - t.Errorf("Unexpected error while writing with flush writer: %v", err) - } - } - if w.flushCount != 10 { - t.Errorf("Flush not called the expected number of times. Actual: %d", w.flushCount) - } - if w.writeCount != 10 { - t.Errorf("Write not called the expected number of times. Actual: %d", w.writeCount) - } -} - -func TestWriteWithoutFlush(t *testing.T) { - w := &writerWithNoFlush{} - fw := Wrap(w) - for i := 0; i < 10; i++ { - _, err := fw.Write([]byte("Test write")) - if err != nil { - t.Errorf("Unexpected error while writing with flush writer: %v", err) - } - } - if w.writeCount != 10 { - t.Errorf("Write not called the expected number of times. Actual: %d", w.writeCount) - } -} - -func TestWriteError(t *testing.T) { - e := fmt.Errorf("Error") - w := &writerWithFlush{err: e} - fw := Wrap(w) - _, err := fw.Write([]byte("Test write")) - if err != e { - t.Errorf("Did not get expected error. Got: %#v", err) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/framer/framer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/framer/framer_test.go deleted file mode 100644 index c5e4ba874..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/framer/framer_test.go +++ /dev/null @@ -1,176 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 framer - -import ( - "bytes" - "io" - "io/ioutil" - "testing" -) - -func TestRead(t *testing.T) { - data := []byte{ - 0x00, 0x00, 0x00, 0x04, - 0x01, 0x02, 0x03, 0x04, - 0x00, 0x00, 0x00, 0x03, - 0x05, 0x06, 0x07, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x08, - } - b := bytes.NewBuffer(data) - r := NewLengthDelimitedFrameReader(ioutil.NopCloser(b)) - buf := make([]byte, 1) - if n, err := r.Read(buf); err != io.ErrShortBuffer && n != 1 && bytes.Equal(buf, []byte{0x01}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - if n, err := r.Read(buf); err != io.ErrShortBuffer && n != 1 && bytes.Equal(buf, []byte{0x02}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read the remaining frame - buf = make([]byte, 2) - if n, err := r.Read(buf); err != nil && n != 2 && bytes.Equal(buf, []byte{0x03, 0x04}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read with buffer equal to frame - buf = make([]byte, 3) - if n, err := r.Read(buf); err != nil && n != 3 && bytes.Equal(buf, []byte{0x05, 0x06, 0x07}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read empty frame - buf = make([]byte, 3) - if n, err := r.Read(buf); err != nil && n != 0 && bytes.Equal(buf, []byte{}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read with larger buffer than frame - buf = make([]byte, 3) - if n, err := r.Read(buf); err != nil && n != 1 && bytes.Equal(buf, []byte{0x08}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read EOF - if n, err := r.Read(buf); err != io.EOF && n != 0 { - t.Fatalf("unexpected: %v %d", err, n) - } -} - -func TestReadLarge(t *testing.T) { - data := []byte{ - 0x00, 0x00, 0x00, 0x04, - 0x01, 0x02, 0x03, 0x04, - 0x00, 0x00, 0x00, 0x03, - 0x05, 0x06, 0x07, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, - 0x08, - } - b := bytes.NewBuffer(data) - r := NewLengthDelimitedFrameReader(ioutil.NopCloser(b)) - buf := make([]byte, 40) - if n, err := r.Read(buf); err != nil && n != 4 && bytes.Equal(buf, []byte{0x01, 0x02, 0x03, 0x04}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - if n, err := r.Read(buf); err != nil && n != 3 && bytes.Equal(buf, []byte{0x05, 0x06, 0x7}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - if n, err := r.Read(buf); err != nil && n != 0 && bytes.Equal(buf, []byte{}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - if n, err := r.Read(buf); err != nil && n != 1 && bytes.Equal(buf, []byte{0x08}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read EOF - if n, err := r.Read(buf); err != io.EOF && n != 0 { - t.Fatalf("unexpected: %v %d", err, n) - } -} -func TestReadInvalidFrame(t *testing.T) { - data := []byte{ - 0x00, 0x00, 0x00, 0x04, - 0x01, 0x02, - } - b := bytes.NewBuffer(data) - r := NewLengthDelimitedFrameReader(ioutil.NopCloser(b)) - buf := make([]byte, 1) - if n, err := r.Read(buf); err != io.ErrShortBuffer && n != 1 && bytes.Equal(buf, []byte{0x01}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read the remaining frame - buf = make([]byte, 3) - if n, err := r.Read(buf); err != io.ErrUnexpectedEOF && n != 1 && bytes.Equal(buf, []byte{0x02}) { - t.Fatalf("unexpected: %v %d %v", err, n, buf) - } - // read EOF - if n, err := r.Read(buf); err != io.EOF && n != 0 { - t.Fatalf("unexpected: %v %d", err, n) - } -} - -func TestJSONFrameReader(t *testing.T) { - b := bytes.NewBufferString("{\"test\":true}\n1\n[\"a\"]") - r := NewJSONFramedReader(ioutil.NopCloser(b)) - buf := make([]byte, 20) - if n, err := r.Read(buf); err != nil || n != 13 || string(buf[:n]) != `{"test":true}` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != nil || n != 1 || string(buf[:n]) != `1` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != nil || n != 5 || string(buf[:n]) != `["a"]` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != io.EOF || n != 0 { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } -} - -func TestJSONFrameReaderShortBuffer(t *testing.T) { - b := bytes.NewBufferString("{\"test\":true}\n1\n[\"a\"]") - r := NewJSONFramedReader(ioutil.NopCloser(b)) - buf := make([]byte, 3) - - if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `{"t` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `est` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `":t` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `rue` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != nil || n != 1 || string(buf[:n]) != `}` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - - if n, err := r.Read(buf); err != nil || n != 1 || string(buf[:n]) != `1` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - - if n, err := r.Read(buf); err != io.ErrShortBuffer || n != 3 || string(buf[:n]) != `["a` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - if n, err := r.Read(buf); err != nil || n != 2 || string(buf[:n]) != `"]` { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } - - if n, err := r.Read(buf); err != io.EOF || n != 0 { - t.Fatalf("unexpected: %v %d %q", err, n, buf) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/hash/hash_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/hash/hash_test.go deleted file mode 100644 index 3bba3b074..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/hash/hash_test.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 hash - -import ( - "fmt" - "hash/adler32" - "testing" - - "github.com/davecgh/go-spew/spew" -) - -type A struct { - x int - y string -} - -type B struct { - x []int - y map[string]bool -} - -type C struct { - x int - y string -} - -func (c C) String() string { - return fmt.Sprintf("%d:%s", c.x, c.y) -} - -func TestDeepHashObject(t *testing.T) { - successCases := []func() interface{}{ - func() interface{} { return 8675309 }, - func() interface{} { return "Jenny, I got your number" }, - func() interface{} { return []string{"eight", "six", "seven"} }, - func() interface{} { return [...]int{5, 3, 0, 9} }, - func() interface{} { return map[int]string{8: "8", 6: "6", 7: "7"} }, - func() interface{} { return map[string]int{"5": 5, "3": 3, "0": 0, "9": 9} }, - func() interface{} { return A{867, "5309"} }, - func() interface{} { return &A{867, "5309"} }, - func() interface{} { - return B{[]int{8, 6, 7}, map[string]bool{"5": true, "3": true, "0": true, "9": true}} - }, - func() interface{} { return map[A]bool{A{8675309, "Jenny"}: true, A{9765683, "!Jenny"}: false} }, - func() interface{} { return map[C]bool{C{8675309, "Jenny"}: true, C{9765683, "!Jenny"}: false} }, - func() interface{} { return map[*A]bool{&A{8675309, "Jenny"}: true, &A{9765683, "!Jenny"}: false} }, - func() interface{} { return map[*C]bool{&C{8675309, "Jenny"}: true, &C{9765683, "!Jenny"}: false} }, - } - - for _, tc := range successCases { - hasher1 := adler32.New() - DeepHashObject(hasher1, tc()) - hash1 := hasher1.Sum32() - DeepHashObject(hasher1, tc()) - hash2 := hasher1.Sum32() - if hash1 != hash2 { - t.Fatalf("hash of the same object (%q) produced different results: %d vs %d", toString(tc()), hash1, hash2) - } - for i := 0; i < 100; i++ { - hasher2 := adler32.New() - - DeepHashObject(hasher1, tc()) - hash1a := hasher1.Sum32() - DeepHashObject(hasher2, tc()) - hash2a := hasher2.Sum32() - - if hash1a != hash1 { - t.Errorf("repeated hash of the same object (%q) produced different results: %d vs %d", toString(tc()), hash1, hash1a) - } - if hash2a != hash2 { - t.Errorf("repeated hash of the same object (%q) produced different results: %d vs %d", toString(tc()), hash2, hash2a) - } - if hash1a != hash2a { - t.Errorf("hash of the same object produced (%q) different results: %d vs %d", toString(tc()), hash1a, hash2a) - } - } - } -} - -func toString(obj interface{}) string { - return spew.Sprintf("%#v", obj) -} - -type wheel struct { - radius uint32 -} - -type unicycle struct { - primaryWheel *wheel - licencePlateID string - tags map[string]string -} - -func TestDeepObjectPointer(t *testing.T) { - // Arrange - wheel1 := wheel{radius: 17} - wheel2 := wheel{radius: 22} - wheel3 := wheel{radius: 17} - - myUni1 := unicycle{licencePlateID: "blah", primaryWheel: &wheel1, tags: map[string]string{"color": "blue", "name": "john"}} - myUni2 := unicycle{licencePlateID: "blah", primaryWheel: &wheel2, tags: map[string]string{"color": "blue", "name": "john"}} - myUni3 := unicycle{licencePlateID: "blah", primaryWheel: &wheel3, tags: map[string]string{"color": "blue", "name": "john"}} - - // Run it more than once to verify determinism of hasher. - for i := 0; i < 100; i++ { - hasher1 := adler32.New() - hasher2 := adler32.New() - hasher3 := adler32.New() - // Act - DeepHashObject(hasher1, myUni1) - hash1 := hasher1.Sum32() - DeepHashObject(hasher1, myUni1) - hash1a := hasher1.Sum32() - DeepHashObject(hasher2, myUni2) - hash2 := hasher2.Sum32() - DeepHashObject(hasher3, myUni3) - hash3 := hasher3.Sum32() - - // Assert - if hash1 != hash1a { - t.Errorf("repeated hash of the same object produced different results: %d vs %d", hash1, hash1a) - } - - if hash1 == hash2 { - t.Errorf("hash1 (%d) and hash2(%d) must be different because they have different values for wheel size", hash1, hash2) - } - - if hash1 != hash3 { - t.Errorf("hash1 (%d) and hash3(%d) must be the same because although they point to different objects, they have the same values for wheel size", hash1, hash3) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/doc.go deleted file mode 100644 index b474fc572..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 httpstream adds multiplexed streaming support to HTTP requests and -// responses via connection upgrades. -package httpstream diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/httpstream.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/httpstream.go deleted file mode 100644 index 3ce3b02a0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/httpstream.go +++ /dev/null @@ -1,149 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 httpstream - -import ( - "fmt" - "io" - "net/http" - "strings" - "time" -) - -const ( - HeaderConnection = "Connection" - HeaderUpgrade = "Upgrade" - HeaderProtocolVersion = "X-Stream-Protocol-Version" - HeaderAcceptedProtocolVersions = "X-Accepted-Stream-Protocol-Versions" -) - -// NewStreamHandler defines a function that is called when a new Stream is -// received. If no error is returned, the Stream is accepted; otherwise, -// the stream is rejected. After the reply frame has been sent, replySent is closed. -type NewStreamHandler func(stream Stream, replySent <-chan struct{}) error - -// NoOpNewStreamHandler is a stream handler that accepts a new stream and -// performs no other logic. -func NoOpNewStreamHandler(stream Stream, replySent <-chan struct{}) error { return nil } - -// Dialer knows how to open a streaming connection to a server. -type Dialer interface { - - // Dial opens a streaming connection to a server using one of the protocols - // specified (in order of most preferred to least preferred). - Dial(protocols ...string) (Connection, string, error) -} - -// UpgradeRoundTripper is a type of http.RoundTripper that is able to upgrade -// HTTP requests to support multiplexed bidirectional streams. After RoundTrip() -// is invoked, if the upgrade is successful, clients may retrieve the upgraded -// connection by calling UpgradeRoundTripper.Connection(). -type UpgradeRoundTripper interface { - http.RoundTripper - // NewConnection validates the response and creates a new Connection. - NewConnection(resp *http.Response) (Connection, error) -} - -// ResponseUpgrader knows how to upgrade HTTP requests and responses to -// add streaming support to them. -type ResponseUpgrader interface { - // UpgradeResponse upgrades an HTTP response to one that supports multiplexed - // streams. newStreamHandler will be called asynchronously whenever the - // other end of the upgraded connection creates a new stream. - UpgradeResponse(w http.ResponseWriter, req *http.Request, newStreamHandler NewStreamHandler) Connection -} - -// Connection represents an upgraded HTTP connection. -type Connection interface { - // CreateStream creates a new Stream with the supplied headers. - CreateStream(headers http.Header) (Stream, error) - // Close resets all streams and closes the connection. - Close() error - // CloseChan returns a channel that is closed when the underlying connection is closed. - CloseChan() <-chan bool - // SetIdleTimeout sets the amount of time the connection may remain idle before - // it is automatically closed. - SetIdleTimeout(timeout time.Duration) -} - -// Stream represents a bidirectional communications channel that is part of an -// upgraded connection. -type Stream interface { - io.ReadWriteCloser - // Reset closes both directions of the stream, indicating that neither client - // or server can use it any more. - Reset() error - // Headers returns the headers used to create the stream. - Headers() http.Header - // Identifier returns the stream's ID. - Identifier() uint32 -} - -// IsUpgradeRequest returns true if the given request is a connection upgrade request -func IsUpgradeRequest(req *http.Request) bool { - for _, h := range req.Header[http.CanonicalHeaderKey(HeaderConnection)] { - if strings.Contains(strings.ToLower(h), strings.ToLower(HeaderUpgrade)) { - return true - } - } - return false -} - -func negotiateProtocol(clientProtocols, serverProtocols []string) string { - for i := range clientProtocols { - for j := range serverProtocols { - if clientProtocols[i] == serverProtocols[j] { - return clientProtocols[i] - } - } - } - return "" -} - -// Handshake performs a subprotocol negotiation. If the client did request a -// subprotocol, Handshake will select the first common value found in -// serverProtocols. If a match is found, Handshake adds a response header -// indicating the chosen subprotocol. If no match is found, HTTP forbidden is -// returned, along with a response header containing the list of protocols the -// server can accept. -func Handshake(req *http.Request, w http.ResponseWriter, serverProtocols []string) (string, error) { - clientProtocols := req.Header[http.CanonicalHeaderKey(HeaderProtocolVersion)] - if len(clientProtocols) == 0 { - // Kube 1.0 clients didn't support subprotocol negotiation. - // TODO require clientProtocols once Kube 1.0 is no longer supported - return "", nil - } - - if len(serverProtocols) == 0 { - // Kube 1.0 servers didn't support subprotocol negotiation. This is mainly for testing. - // TODO require serverProtocols once Kube 1.0 is no longer supported - return "", nil - } - - negotiatedProtocol := negotiateProtocol(clientProtocols, serverProtocols) - if len(negotiatedProtocol) == 0 { - w.WriteHeader(http.StatusForbidden) - for i := range serverProtocols { - w.Header().Add(HeaderAcceptedProtocolVersions, serverProtocols[i]) - } - fmt.Fprintf(w, "unable to upgrade: unable to negotiate protocol: client supports %v, server accepts %v", clientProtocols, serverProtocols) - return "", fmt.Errorf("unable to upgrade: unable to negotiate protocol: client supports %v, server supports %v", clientProtocols, serverProtocols) - } - - w.Header().Add(HeaderProtocolVersion, negotiatedProtocol) - return negotiatedProtocol, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/httpstream_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/httpstream_test.go deleted file mode 100644 index d21e60c0e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/httpstream_test.go +++ /dev/null @@ -1,127 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 httpstream - -import ( - "net/http" - "reflect" - "testing" - - "k8s.io/kubernetes/pkg/api" -) - -type responseWriter struct { - header http.Header - statusCode *int -} - -func newResponseWriter() *responseWriter { - return &responseWriter{ - header: make(http.Header), - } -} - -func (r *responseWriter) Header() http.Header { - return r.header -} - -func (r *responseWriter) WriteHeader(code int) { - r.statusCode = &code -} - -func (r *responseWriter) Write([]byte) (int, error) { - return 0, nil -} - -func TestHandshake(t *testing.T) { - tests := map[string]struct { - clientProtocols []string - serverProtocols []string - expectedProtocol string - expectError bool - }{ - "no client protocols": { - clientProtocols: []string{}, - serverProtocols: []string{"a", "b"}, - expectedProtocol: "", - }, - "no common protocol": { - clientProtocols: []string{"c"}, - serverProtocols: []string{"a", "b"}, - expectedProtocol: "", - expectError: true, - }, - "common protocol": { - clientProtocols: []string{"b"}, - serverProtocols: []string{"a", "b"}, - expectedProtocol: "b", - }, - } - - for name, test := range tests { - req, err := http.NewRequest("GET", "http://www.example.com/", nil) - if err != nil { - t.Fatalf("%s: error creating request: %v", name, err) - } - - for _, p := range test.clientProtocols { - req.Header.Add(HeaderProtocolVersion, p) - } - - w := newResponseWriter() - negotiated, err := Handshake(req, w, test.serverProtocols) - - // verify negotiated protocol - if e, a := test.expectedProtocol, negotiated; e != a { - t.Errorf("%s: protocol: expected %q, got %q", name, e, a) - } - - if test.expectError { - if err == nil { - t.Errorf("%s: expected error but did not get one", name) - } - if w.statusCode == nil { - t.Errorf("%s: expected w.statusCode to be set", name) - } else if e, a := http.StatusForbidden, *w.statusCode; e != a { - t.Errorf("%s: w.statusCode: expected %d, got %d", name, e, a) - } - if e, a := test.serverProtocols, w.Header()[HeaderAcceptedProtocolVersions]; !reflect.DeepEqual(e, a) { - t.Errorf("%s: accepted server protocols: expected %v, got %v", name, e, a) - } - continue - } - if !test.expectError && err != nil { - t.Errorf("%s: unexpected error: %v", name, err) - continue - } - if w.statusCode != nil { - t.Errorf("%s: unexpected non-nil w.statusCode: %d", name, w.statusCode) - } - - if len(test.expectedProtocol) == 0 { - if len(w.Header()[HeaderProtocolVersion]) > 0 { - t.Errorf("%s: unexpected protocol version response header: %s", name, w.Header()[HeaderProtocolVersion]) - } - continue - } - - // verify response headers - if e, a := []string{test.expectedProtocol}, w.Header()[HeaderProtocolVersion]; !api.Semantic.DeepEqual(e, a) { - t.Errorf("%s: protocol response header: expected %v, got %v", name, e, a) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/connection.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/connection.go deleted file mode 100644 index 0330e2038..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/connection.go +++ /dev/null @@ -1,145 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 spdy - -import ( - "net" - "net/http" - "sync" - "time" - - "github.com/docker/spdystream" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/util/httpstream" -) - -// connection maintains state about a spdystream.Connection and its associated -// streams. -type connection struct { - conn *spdystream.Connection - streams []httpstream.Stream - streamLock sync.Mutex - newStreamHandler httpstream.NewStreamHandler -} - -// NewClientConnection creates a new SPDY client connection. -func NewClientConnection(conn net.Conn) (httpstream.Connection, error) { - spdyConn, err := spdystream.NewConnection(conn, false) - if err != nil { - defer conn.Close() - return nil, err - } - - return newConnection(spdyConn, httpstream.NoOpNewStreamHandler), nil -} - -// NewServerConnection creates a new SPDY server connection. newStreamHandler -// will be invoked when the server receives a newly created stream from the -// client. -func NewServerConnection(conn net.Conn, newStreamHandler httpstream.NewStreamHandler) (httpstream.Connection, error) { - spdyConn, err := spdystream.NewConnection(conn, true) - if err != nil { - defer conn.Close() - return nil, err - } - - return newConnection(spdyConn, newStreamHandler), nil -} - -// newConnection returns a new connection wrapping conn. newStreamHandler -// will be invoked when the server receives a newly created stream from the -// client. -func newConnection(conn *spdystream.Connection, newStreamHandler httpstream.NewStreamHandler) httpstream.Connection { - c := &connection{conn: conn, newStreamHandler: newStreamHandler} - go conn.Serve(c.newSpdyStream) - return c -} - -// createStreamResponseTimeout indicates how long to wait for the other side to -// acknowledge the new stream before timing out. -const createStreamResponseTimeout = 30 * time.Second - -// Close first sends a reset for all of the connection's streams, and then -// closes the underlying spdystream.Connection. -func (c *connection) Close() error { - c.streamLock.Lock() - for _, s := range c.streams { - // calling Reset instead of Close ensures that all streams are fully torn down - s.Reset() - } - c.streams = make([]httpstream.Stream, 0) - c.streamLock.Unlock() - - // now that all streams are fully torn down, it's safe to call close on the underlying connection, - // which should be able to terminate immediately at this point, instead of waiting for any - // remaining graceful stream termination. - return c.conn.Close() -} - -// CreateStream creates a new stream with the specified headers and registers -// it with the connection. -func (c *connection) CreateStream(headers http.Header) (httpstream.Stream, error) { - stream, err := c.conn.CreateStream(headers, nil, false) - if err != nil { - return nil, err - } - if err = stream.WaitTimeout(createStreamResponseTimeout); err != nil { - return nil, err - } - - c.registerStream(stream) - return stream, nil -} - -// registerStream adds the stream s to the connection's list of streams that -// it owns. -func (c *connection) registerStream(s httpstream.Stream) { - c.streamLock.Lock() - c.streams = append(c.streams, s) - c.streamLock.Unlock() -} - -// CloseChan returns a channel that, when closed, indicates that the underlying -// spdystream.Connection has been closed. -func (c *connection) CloseChan() <-chan bool { - return c.conn.CloseChan() -} - -// newSpdyStream is the internal new stream handler used by spdystream.Connection.Serve. -// It calls connection's newStreamHandler, giving it the opportunity to accept or reject -// the stream. If newStreamHandler returns an error, the stream is rejected. If not, the -// stream is accepted and registered with the connection. -func (c *connection) newSpdyStream(stream *spdystream.Stream) { - replySent := make(chan struct{}) - err := c.newStreamHandler(stream, replySent) - rejectStream := (err != nil) - if rejectStream { - glog.Warningf("Stream rejected: %v", err) - stream.Reset() - return - } - - c.registerStream(stream) - stream.SendReply(http.Header{}, rejectStream) - close(replySent) -} - -// SetIdleTimeout sets the amount of time the connection may remain idle before -// it is automatically closed. -func (c *connection) SetIdleTimeout(timeout time.Duration) { - c.conn.SetIdleTimeout(timeout) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/connection_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/connection_test.go deleted file mode 100644 index 36b096402..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/connection_test.go +++ /dev/null @@ -1,163 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 spdy - -import ( - "io" - "net" - "net/http" - "sync" - "testing" - "time" - - "k8s.io/kubernetes/pkg/util/httpstream" -) - -func runProxy(t *testing.T, backendUrl string, proxyUrl chan<- string, proxyDone chan<- struct{}) { - listener, err := net.Listen("tcp4", "localhost:0") - if err != nil { - t.Fatalf("error listening: %v", err) - } - defer listener.Close() - - proxyUrl <- listener.Addr().String() - - clientConn, err := listener.Accept() - if err != nil { - t.Errorf("proxy: error accepting client connection: %v", err) - return - } - - backendConn, err := net.Dial("tcp4", backendUrl) - if err != nil { - t.Errorf("proxy: error dialing backend: %v", err) - return - } - defer backendConn.Close() - - var wg sync.WaitGroup - wg.Add(2) - - go func() { - defer wg.Done() - io.Copy(backendConn, clientConn) - }() - - go func() { - defer wg.Done() - io.Copy(clientConn, backendConn) - }() - - wg.Wait() - - proxyDone <- struct{}{} -} - -func runServer(t *testing.T, backendUrl chan<- string, serverDone chan<- struct{}) { - listener, err := net.Listen("tcp4", "localhost:0") - if err != nil { - t.Fatalf("server: error listening: %v", err) - } - defer listener.Close() - - backendUrl <- listener.Addr().String() - - conn, err := listener.Accept() - if err != nil { - t.Errorf("server: error accepting connection: %v", err) - return - } - - streamChan := make(chan httpstream.Stream) - replySentChan := make(chan (<-chan struct{})) - spdyConn, err := NewServerConnection(conn, func(stream httpstream.Stream, replySent <-chan struct{}) error { - streamChan <- stream - replySentChan <- replySent - return nil - }) - if err != nil { - t.Errorf("server: error creating spdy connection: %v", err) - return - } - - stream := <-streamChan - replySent := <-replySentChan - <-replySent - - buf := make([]byte, 1) - _, err = stream.Read(buf) - if err != io.EOF { - t.Errorf("server: unexpected read error: %v", err) - return - } - - <-spdyConn.CloseChan() - raw := spdyConn.(*connection).conn - if err := raw.Wait(15 * time.Second); err != nil { - t.Errorf("server: timed out waiting for connection closure: %v", err) - } - - serverDone <- struct{}{} -} - -func TestConnectionCloseIsImmediateThroughAProxy(t *testing.T) { - serverDone := make(chan struct{}) - backendUrlChan := make(chan string) - go runServer(t, backendUrlChan, serverDone) - backendUrl := <-backendUrlChan - - proxyDone := make(chan struct{}) - proxyUrlChan := make(chan string) - go runProxy(t, backendUrl, proxyUrlChan, proxyDone) - proxyUrl := <-proxyUrlChan - - conn, err := net.Dial("tcp4", proxyUrl) - if err != nil { - t.Fatalf("client: error connecting to proxy: %v", err) - } - - spdyConn, err := NewClientConnection(conn) - if err != nil { - t.Fatalf("client: error creating spdy connection: %v", err) - } - - if _, err := spdyConn.CreateStream(http.Header{}); err != nil { - t.Fatalf("client: error creating stream: %v", err) - } - - spdyConn.Close() - raw := spdyConn.(*connection).conn - if err := raw.Wait(15 * time.Second); err != nil { - t.Fatalf("client: timed out waiting for connection closure: %v", err) - } - - expired := time.NewTimer(15 * time.Second) - i := 0 - for { - select { - case <-expired.C: - t.Fatalf("timed out waiting for proxy and/or server closure") - case <-serverDone: - i++ - case <-proxyDone: - i++ - } - if i == 2 { - break - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/roundtripper.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/roundtripper.go deleted file mode 100644 index ca7e9370e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/roundtripper.go +++ /dev/null @@ -1,258 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 spdy - -import ( - "bufio" - "crypto/tls" - "encoding/base64" - "fmt" - "io/ioutil" - "net" - "net/http" - "net/http/httputil" - "net/url" - "strings" - - "k8s.io/kubernetes/pkg/api" - apierrors "k8s.io/kubernetes/pkg/api/errors" - "k8s.io/kubernetes/pkg/api/unversioned" - "k8s.io/kubernetes/pkg/util/httpstream" - "k8s.io/kubernetes/third_party/golang/netutil" -) - -// SpdyRoundTripper knows how to upgrade an HTTP request to one that supports -// multiplexed streams. After RoundTrip() is invoked, Conn will be set -// and usable. SpdyRoundTripper implements the UpgradeRoundTripper interface. -type SpdyRoundTripper struct { - //tlsConfig holds the TLS configuration settings to use when connecting - //to the remote server. - tlsConfig *tls.Config - - /* TODO according to http://golang.org/pkg/net/http/#RoundTripper, a RoundTripper - must be safe for use by multiple concurrent goroutines. If this is absolutely - necessary, we could keep a map from http.Request to net.Conn. In practice, - a client will create an http.Client, set the transport to a new insteace of - SpdyRoundTripper, and use it a single time, so this hopefully won't be an issue. - */ - // conn is the underlying network connection to the remote server. - conn net.Conn - - // Dialer is the dialer used to connect. Used if non-nil. - Dialer *net.Dialer - - // proxier knows which proxy to use given a request, defaults to http.ProxyFromEnvironment - // Used primarily for mocking the proxy discovery in tests. - proxier func(req *http.Request) (*url.URL, error) -} - -// NewRoundTripper creates a new SpdyRoundTripper that will use -// the specified tlsConfig. -func NewRoundTripper(tlsConfig *tls.Config) httpstream.UpgradeRoundTripper { - return NewSpdyRoundTripper(tlsConfig) -} - -// NewSpdyRoundTripper creates a new SpdyRoundTripper that will use -// the specified tlsConfig. This function is mostly meant for unit tests. -func NewSpdyRoundTripper(tlsConfig *tls.Config) *SpdyRoundTripper { - return &SpdyRoundTripper{tlsConfig: tlsConfig} -} - -// dial dials the host specified by req, using TLS if appropriate, optionally -// using a proxy server if one is configured via environment variables. -func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { - proxier := s.proxier - if proxier == nil { - proxier = http.ProxyFromEnvironment - } - proxyURL, err := proxier(req) - if err != nil { - return nil, err - } - - if proxyURL == nil { - return s.dialWithoutProxy(req.URL) - } - - // ensure we use a canonical host with proxyReq - targetHost := netutil.CanonicalAddr(req.URL) - - // proxying logic adapted from http://blog.h6t.eu/post/74098062923/golang-websocket-with-http-proxy-support - proxyReq := http.Request{ - Method: "CONNECT", - URL: &url.URL{}, - Host: targetHost, - } - - if pa := s.proxyAuth(proxyURL); pa != "" { - proxyReq.Header = http.Header{} - proxyReq.Header.Set("Proxy-Authorization", pa) - } - - proxyDialConn, err := s.dialWithoutProxy(proxyURL) - if err != nil { - return nil, err - } - - proxyClientConn := httputil.NewProxyClientConn(proxyDialConn, nil) - _, err = proxyClientConn.Do(&proxyReq) - if err != nil && err != httputil.ErrPersistEOF { - return nil, err - } - - rwc, _ := proxyClientConn.Hijack() - - if req.URL.Scheme != "https" { - return rwc, nil - } - - host, _, err := net.SplitHostPort(targetHost) - if err != nil { - return nil, err - } - - if len(s.tlsConfig.ServerName) == 0 { - s.tlsConfig.ServerName = host - } - - tlsConn := tls.Client(rwc, s.tlsConfig) - - // need to manually call Handshake() so we can call VerifyHostname() below - if err := tlsConn.Handshake(); err != nil { - return nil, err - } - - // Return if we were configured to skip validation - if s.tlsConfig != nil && s.tlsConfig.InsecureSkipVerify { - return tlsConn, nil - } - - if err := tlsConn.VerifyHostname(host); err != nil { - return nil, err - } - - return tlsConn, nil -} - -// dialWithoutProxy dials the host specified by url, using TLS if appropriate. -func (s *SpdyRoundTripper) dialWithoutProxy(url *url.URL) (net.Conn, error) { - dialAddr := netutil.CanonicalAddr(url) - - if url.Scheme == "http" { - if s.Dialer == nil { - return net.Dial("tcp", dialAddr) - } else { - return s.Dialer.Dial("tcp", dialAddr) - } - } - - // TODO validate the TLSClientConfig is set up? - var conn *tls.Conn - var err error - if s.Dialer == nil { - conn, err = tls.Dial("tcp", dialAddr, s.tlsConfig) - } else { - conn, err = tls.DialWithDialer(s.Dialer, "tcp", dialAddr, s.tlsConfig) - } - if err != nil { - return nil, err - } - - // Return if we were configured to skip validation - if s.tlsConfig != nil && s.tlsConfig.InsecureSkipVerify { - return conn, nil - } - - host, _, err := net.SplitHostPort(dialAddr) - if err != nil { - return nil, err - } - err = conn.VerifyHostname(host) - if err != nil { - return nil, err - } - - return conn, nil -} - -// proxyAuth returns, for a given proxy URL, the value to be used for the Proxy-Authorization header -func (s *SpdyRoundTripper) proxyAuth(proxyURL *url.URL) string { - if proxyURL == nil || proxyURL.User == nil { - return "" - } - credentials := proxyURL.User.String() - encodedAuth := base64.StdEncoding.EncodeToString([]byte(credentials)) - return fmt.Sprintf("Basic %s", encodedAuth) -} - -// RoundTrip executes the Request and upgrades it. After a successful upgrade, -// clients may call SpdyRoundTripper.Connection() to retrieve the upgraded -// connection. -func (s *SpdyRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - // TODO what's the best way to clone the request? - r := *req - req = &r - req.Header.Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade) - req.Header.Add(httpstream.HeaderUpgrade, HeaderSpdy31) - - conn, err := s.dial(req) - if err != nil { - return nil, err - } - - err = req.Write(conn) - if err != nil { - return nil, err - } - - resp, err := http.ReadResponse(bufio.NewReader(conn), req) - if err != nil { - return nil, err - } - - s.conn = conn - - return resp, nil -} - -// NewConnection validates the upgrade response, creating and returning a new -// httpstream.Connection if there were no errors. -func (s *SpdyRoundTripper) NewConnection(resp *http.Response) (httpstream.Connection, error) { - connectionHeader := strings.ToLower(resp.Header.Get(httpstream.HeaderConnection)) - upgradeHeader := strings.ToLower(resp.Header.Get(httpstream.HeaderUpgrade)) - if (resp.StatusCode != http.StatusSwitchingProtocols) || !strings.Contains(connectionHeader, strings.ToLower(httpstream.HeaderUpgrade)) || !strings.Contains(upgradeHeader, strings.ToLower(HeaderSpdy31)) { - defer resp.Body.Close() - responseError := "" - responseErrorBytes, err := ioutil.ReadAll(resp.Body) - if err != nil { - responseError = "unable to read error from server response" - } else { - // TODO: I don't belong here, I should be abstracted from this class - if obj, _, err := api.Codecs.UniversalDecoder().Decode(responseErrorBytes, nil, &unversioned.Status{}); err == nil { - if status, ok := obj.(*unversioned.Status); ok { - return nil, &apierrors.StatusError{ErrStatus: *status} - } - } - responseError = string(responseErrorBytes) - responseError = strings.TrimSpace(responseError) - } - - return nil, fmt.Errorf("unable to upgrade connection: %s", responseError) - } - - return NewClientConnection(s.conn) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/roundtripper_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/roundtripper_test.go deleted file mode 100644 index c80a24a69..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/roundtripper_test.go +++ /dev/null @@ -1,423 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 spdy - -import ( - "crypto/tls" - "crypto/x509" - "encoding/base64" - "io" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/elazarl/goproxy" - "k8s.io/kubernetes/pkg/util/httpstream" -) - -func TestRoundTripAndNewConnection(t *testing.T) { - localhostPool := x509.NewCertPool() - if !localhostPool.AppendCertsFromPEM(localhostCert) { - t.Errorf("error setting up localhostCert pool") - } - - httpsServerInvalidHostname := func(h http.Handler) *httptest.Server { - cert, err := tls.X509KeyPair(exampleCert, exampleKey) - if err != nil { - t.Errorf("https (invalid hostname): proxy_test: %v", err) - } - ts := httptest.NewUnstartedServer(h) - ts.TLS = &tls.Config{ - Certificates: []tls.Certificate{cert}, - } - ts.StartTLS() - return ts - } - - httpsServerValidHostname := func(h http.Handler) *httptest.Server { - cert, err := tls.X509KeyPair(localhostCert, localhostKey) - if err != nil { - t.Errorf("https (valid hostname): proxy_test: %v", err) - } - ts := httptest.NewUnstartedServer(h) - ts.TLS = &tls.Config{ - Certificates: []tls.Certificate{cert}, - } - ts.StartTLS() - return ts - } - - testCases := map[string]struct { - serverFunc func(http.Handler) *httptest.Server - proxyServerFunc func(http.Handler) *httptest.Server - proxyAuth *url.Userinfo - clientTLS *tls.Config - serverConnectionHeader string - serverUpgradeHeader string - serverStatusCode int - shouldError bool - }{ - "no headers": { - serverFunc: httptest.NewServer, - serverConnectionHeader: "", - serverUpgradeHeader: "", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: true, - }, - "no upgrade header": { - serverFunc: httptest.NewServer, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: true, - }, - "no connection header": { - serverFunc: httptest.NewServer, - serverConnectionHeader: "", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: true, - }, - "no switching protocol status code": { - serverFunc: httptest.NewServer, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusForbidden, - shouldError: true, - }, - "http": { - serverFunc: httptest.NewServer, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "https (invalid hostname + InsecureSkipVerify)": { - serverFunc: httpsServerInvalidHostname, - clientTLS: &tls.Config{InsecureSkipVerify: true}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "https (invalid hostname + hostname verification)": { - serverFunc: httpsServerInvalidHostname, - clientTLS: &tls.Config{InsecureSkipVerify: false}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: true, - }, - "https (valid hostname + RootCAs)": { - serverFunc: httpsServerValidHostname, - clientTLS: &tls.Config{RootCAs: localhostPool}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "proxied http->http": { - serverFunc: httptest.NewServer, - proxyServerFunc: httptest.NewServer, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "proxied https (invalid hostname + InsecureSkipVerify) -> http": { - serverFunc: httptest.NewServer, - proxyServerFunc: httpsServerInvalidHostname, - clientTLS: &tls.Config{InsecureSkipVerify: true}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "proxied https with auth (invalid hostname + InsecureSkipVerify) -> http": { - serverFunc: httptest.NewServer, - proxyServerFunc: httpsServerInvalidHostname, - proxyAuth: url.UserPassword("proxyuser", "proxypasswd"), - clientTLS: &tls.Config{InsecureSkipVerify: true}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "proxied https (invalid hostname + hostname verification) -> http": { - serverFunc: httptest.NewServer, - proxyServerFunc: httpsServerInvalidHostname, - clientTLS: &tls.Config{InsecureSkipVerify: false}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: true, // fails because the client doesn't trust the proxy - }, - "proxied https (valid hostname + RootCAs) -> http": { - serverFunc: httptest.NewServer, - proxyServerFunc: httpsServerValidHostname, - clientTLS: &tls.Config{RootCAs: localhostPool}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "proxied https with auth (valid hostname + RootCAs) -> http": { - serverFunc: httptest.NewServer, - proxyServerFunc: httpsServerValidHostname, - proxyAuth: url.UserPassword("proxyuser", "proxypasswd"), - clientTLS: &tls.Config{RootCAs: localhostPool}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "proxied https (invalid hostname + InsecureSkipVerify) -> https (invalid hostname)": { - serverFunc: httpsServerInvalidHostname, - proxyServerFunc: httpsServerInvalidHostname, - clientTLS: &tls.Config{InsecureSkipVerify: true}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, // works because the test proxy ignores TLS errors - }, - "proxied https with auth (invalid hostname + InsecureSkipVerify) -> https (invalid hostname)": { - serverFunc: httpsServerInvalidHostname, - proxyServerFunc: httpsServerInvalidHostname, - proxyAuth: url.UserPassword("proxyuser", "proxypasswd"), - clientTLS: &tls.Config{InsecureSkipVerify: true}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, // works because the test proxy ignores TLS errors - }, - "proxied https (invalid hostname + hostname verification) -> https (invalid hostname)": { - serverFunc: httpsServerInvalidHostname, - proxyServerFunc: httpsServerInvalidHostname, - clientTLS: &tls.Config{InsecureSkipVerify: false}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: true, // fails because the client doesn't trust the proxy - }, - "proxied https (valid hostname + RootCAs) -> https (valid hostname + RootCAs)": { - serverFunc: httpsServerValidHostname, - proxyServerFunc: httpsServerValidHostname, - clientTLS: &tls.Config{RootCAs: localhostPool}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - "proxied https with auth (valid hostname + RootCAs) -> https (valid hostname + RootCAs)": { - serverFunc: httpsServerValidHostname, - proxyServerFunc: httpsServerValidHostname, - proxyAuth: url.UserPassword("proxyuser", "proxypasswd"), - clientTLS: &tls.Config{RootCAs: localhostPool}, - serverConnectionHeader: "Upgrade", - serverUpgradeHeader: "SPDY/3.1", - serverStatusCode: http.StatusSwitchingProtocols, - shouldError: false, - }, - } - - for k, testCase := range testCases { - server := testCase.serverFunc(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if testCase.shouldError { - if e, a := httpstream.HeaderUpgrade, req.Header.Get(httpstream.HeaderConnection); e != a { - t.Fatalf("%s: Expected connection=upgrade header, got '%s", k, a) - } - - w.Header().Set(httpstream.HeaderConnection, testCase.serverConnectionHeader) - w.Header().Set(httpstream.HeaderUpgrade, testCase.serverUpgradeHeader) - w.WriteHeader(testCase.serverStatusCode) - - return - } - - streamCh := make(chan httpstream.Stream) - - responseUpgrader := NewResponseUpgrader() - spdyConn := responseUpgrader.UpgradeResponse(w, req, func(s httpstream.Stream, replySent <-chan struct{}) error { - streamCh <- s - return nil - }) - if spdyConn == nil { - t.Fatalf("%s: unexpected nil spdyConn", k) - } - defer spdyConn.Close() - - stream := <-streamCh - io.Copy(stream, stream) - })) - defer server.Close() - - serverURL, err := url.Parse(server.URL) - if err != nil { - t.Fatalf("%s: Error creating request: %s", k, err) - } - req, err := http.NewRequest("GET", server.URL, nil) - if err != nil { - t.Fatalf("%s: Error creating request: %s", k, err) - } - - spdyTransport := NewSpdyRoundTripper(testCase.clientTLS) - - var proxierCalled bool - var proxyCalledWithHost string - var proxyCalledWithAuth bool - var proxyCalledWithAuthHeader string - if testCase.proxyServerFunc != nil { - proxyHandler := goproxy.NewProxyHttpServer() - - proxyHandler.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) { - proxyCalledWithHost = host - - proxyAuthHeaderName := "Proxy-Authorization" - _, proxyCalledWithAuth = ctx.Req.Header[proxyAuthHeaderName] - proxyCalledWithAuthHeader = ctx.Req.Header.Get(proxyAuthHeaderName) - return goproxy.OkConnect, host - }) - - proxy := testCase.proxyServerFunc(proxyHandler) - - spdyTransport.proxier = func(proxierReq *http.Request) (*url.URL, error) { - proxierCalled = true - proxyURL, err := url.Parse(proxy.URL) - if err != nil { - return nil, err - } - proxyURL.User = testCase.proxyAuth - return proxyURL, nil - } - defer proxy.Close() - } - - client := &http.Client{Transport: spdyTransport} - - resp, err := client.Do(req) - var conn httpstream.Connection - if err == nil { - conn, err = spdyTransport.NewConnection(resp) - } - haveErr := err != nil - if e, a := testCase.shouldError, haveErr; e != a { - t.Fatalf("%s: shouldError=%t, got %t: %v", k, e, a, err) - } - if testCase.shouldError { - continue - } - defer conn.Close() - - if resp.StatusCode != http.StatusSwitchingProtocols { - t.Fatalf("%s: expected http 101 switching protocols, got %d", k, resp.StatusCode) - } - - stream, err := conn.CreateStream(http.Header{}) - if err != nil { - t.Fatalf("%s: error creating client stream: %s", k, err) - } - - n, err := stream.Write([]byte("hello")) - if err != nil { - t.Fatalf("%s: error writing to stream: %s", k, err) - } - if n != 5 { - t.Fatalf("%s: Expected to write 5 bytes, but actually wrote %d", k, n) - } - - b := make([]byte, 5) - n, err = stream.Read(b) - if err != nil { - t.Fatalf("%s: error reading from stream: %s", k, err) - } - if n != 5 { - t.Fatalf("%s: Expected to read 5 bytes, but actually read %d", k, n) - } - if e, a := "hello", string(b[0:n]); e != a { - t.Fatalf("%s: expected '%s', got '%s'", k, e, a) - } - - if testCase.proxyServerFunc != nil { - if !proxierCalled { - t.Fatalf("%s: Expected to use a proxy but proxier in SpdyRoundTripper wasn't called", k) - } - if proxyCalledWithHost != serverURL.Host { - t.Fatalf("%s: Expected to see a call to the proxy for backend %q, got %q", k, serverURL.Host, proxyCalledWithHost) - } - } - - var expectedProxyAuth string - if testCase.proxyAuth != nil { - encodedCredentials := base64.StdEncoding.EncodeToString([]byte(testCase.proxyAuth.String())) - expectedProxyAuth = "Basic " + encodedCredentials - } - if len(expectedProxyAuth) == 0 && proxyCalledWithAuth { - t.Fatalf("%s: Proxy authorization unexpected, got %q", k, proxyCalledWithAuthHeader) - } - if proxyCalledWithAuthHeader != expectedProxyAuth { - t.Fatalf("%s: Expected to see a call to the proxy with credentials %q, got %q", k, testCase.proxyAuth, proxyCalledWithAuthHeader) - } - } -} - -// exampleCert was generated from crypto/tls/generate_cert.go with the following command: -// go run generate_cert.go --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h -var exampleCert = []byte(`-----BEGIN CERTIFICATE----- -MIIBcjCCAR6gAwIBAgIQBOUTYowZaENkZi0faI9DgTALBgkqhkiG9w0BAQswEjEQ -MA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2MDAw -MFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCZ -xfR3sgeHBraGFfF/24tTn4PRVAHOf2UOOxSQRs+aYjNqimFqf/SRIblQgeXdBJDR -gVK5F1Js2zwlehw0bHxRAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIApDATBgNVHSUE -DDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4YW1w -bGUuY29tMAsGCSqGSIb3DQEBCwNBAI/mfBB8dm33IpUl+acSyWfL6gX5Wc0FFyVj -dKeesE1XBuPX1My/rzU6Oy/YwX7LOL4FaeNUS6bbL4axSLPKYSs= ------END CERTIFICATE-----`) - -var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBOgIBAAJBAJnF9HeyB4cGtoYV8X/bi1Ofg9FUAc5/ZQ47FJBGz5piM2qKYWp/ -9JEhuVCB5d0EkNGBUrkXUmzbPCV6HDRsfFECAwEAAQJBAJLH9yPuButniACTn5L5 -IJQw1mWQt6zBw9eCo41YWkA0866EgjC53aPZaRjXMp0uNJGdIsys2V5rCOOLWN2C -ODECIQDICHsi8QQQ9wpuJy8X5l8MAfxHL+DIqI84wQTeVM91FQIhAMTME8A18/7h -1Ad6drdnxAkuC0tX6Sx0LDozrmen+HFNAiAlcEDrt0RVkIcpOrg7tuhPLQf0oudl -Zvb3Xlj069awSQIgcT15E/43w2+RASifzVNhQ2MCTr1sSA8lL+xzK+REmnUCIBhQ -j4139pf8Re1J50zBxS/JlQfgDQi9sO9pYeiHIxNs ------END RSA PRIVATE KEY-----`) - -// localhostCert was generated from crypto/tls/generate_cert.go with the following command: -// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h -var localhostCert = []byte(`-----BEGIN CERTIFICATE----- -MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD -bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj -bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa -IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA -AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud -EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA -AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk -Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA== ------END CERTIFICATE-----`) - -// localhostKey is the private key for localhostCert. -var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY----- -MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0 -0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV -NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d -AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW -MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD -EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA -1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE= ------END RSA PRIVATE KEY-----`) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/upgrade.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/upgrade.go deleted file mode 100644 index b7d126a5d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/upgrade.go +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 spdy - -import ( - "fmt" - "net/http" - "strings" - - "k8s.io/kubernetes/pkg/util/httpstream" - "k8s.io/kubernetes/pkg/util/runtime" -) - -const HeaderSpdy31 = "SPDY/3.1" - -// responseUpgrader knows how to upgrade HTTP responses. It -// implements the httpstream.ResponseUpgrader interface. -type responseUpgrader struct { -} - -// NewResponseUpgrader returns a new httpstream.ResponseUpgrader that is -// capable of upgrading HTTP responses using SPDY/3.1 via the -// spdystream package. -func NewResponseUpgrader() httpstream.ResponseUpgrader { - return responseUpgrader{} -} - -// UpgradeResponse upgrades an HTTP response to one that supports multiplexed -// streams. newStreamHandler will be called synchronously whenever the -// other end of the upgraded connection creates a new stream. -func (u responseUpgrader) UpgradeResponse(w http.ResponseWriter, req *http.Request, newStreamHandler httpstream.NewStreamHandler) httpstream.Connection { - connectionHeader := strings.ToLower(req.Header.Get(httpstream.HeaderConnection)) - upgradeHeader := strings.ToLower(req.Header.Get(httpstream.HeaderUpgrade)) - if !strings.Contains(connectionHeader, strings.ToLower(httpstream.HeaderUpgrade)) || !strings.Contains(upgradeHeader, strings.ToLower(HeaderSpdy31)) { - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintf(w, "unable to upgrade: missing upgrade headers in request: %#v", req.Header) - return nil - } - - hijacker, ok := w.(http.Hijacker) - if !ok { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "unable to upgrade: unable to hijack response") - return nil - } - - w.Header().Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade) - w.Header().Add(httpstream.HeaderUpgrade, HeaderSpdy31) - w.WriteHeader(http.StatusSwitchingProtocols) - - conn, _, err := hijacker.Hijack() - if err != nil { - runtime.HandleError(fmt.Errorf("unable to upgrade: error hijacking response: %v", err)) - return nil - } - - spdyConn, err := NewServerConnection(conn, newStreamHandler) - if err != nil { - runtime.HandleError(fmt.Errorf("unable to upgrade: error creating SPDY server connection: %v", err)) - return nil - } - - return spdyConn -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/upgrade_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/upgrade_test.go deleted file mode 100644 index 4e111407e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/httpstream/spdy/upgrade_test.go +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 spdy - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -func TestUpgradeResponse(t *testing.T) { - testCases := []struct { - connectionHeader string - upgradeHeader string - shouldError bool - }{ - { - connectionHeader: "", - upgradeHeader: "", - shouldError: true, - }, - { - connectionHeader: "Upgrade", - upgradeHeader: "", - shouldError: true, - }, - { - connectionHeader: "", - upgradeHeader: "SPDY/3.1", - shouldError: true, - }, - { - connectionHeader: "Upgrade", - upgradeHeader: "SPDY/3.1", - shouldError: false, - }, - } - - for i, testCase := range testCases { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - upgrader := NewResponseUpgrader() - conn := upgrader.UpgradeResponse(w, req, nil) - haveErr := conn == nil - if e, a := testCase.shouldError, haveErr; e != a { - t.Fatalf("%d: expected shouldErr=%t, got %t", i, testCase.shouldError, haveErr) - } - if haveErr { - return - } - if conn == nil { - t.Fatalf("%d: unexpected nil conn", i) - } - defer conn.Close() - })) - defer server.Close() - - req, err := http.NewRequest("GET", server.URL, nil) - if err != nil { - t.Fatalf("%d: error creating request: %s", i, err) - } - - req.Header.Set("Connection", testCase.connectionHeader) - req.Header.Set("Upgrade", testCase.upgradeHeader) - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - t.Fatalf("%d: unexpected non-nil err from client.Do: %s", i, err) - } - - if testCase.shouldError { - continue - } - - if resp.StatusCode != http.StatusSwitchingProtocols { - t.Fatalf("%d: expected status 101 switching protocols, got %d", i, resp.StatusCode) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/integer/integer_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/integer/integer_test.go deleted file mode 100644 index 0f8856738..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/integer/integer_test.go +++ /dev/null @@ -1,143 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 integer - -import "testing" - -func TestIntMax(t *testing.T) { - tests := []struct { - nums []int - expectedMax int - }{ - { - nums: []int{-1, 0}, - expectedMax: 0, - }, - { - nums: []int{-1, -2}, - expectedMax: -1, - }, - { - nums: []int{0, 1}, - expectedMax: 1, - }, - { - nums: []int{1, 2}, - expectedMax: 2, - }, - } - - for i, test := range tests { - t.Logf("executing scenario %d", i) - if max := IntMax(test.nums[0], test.nums[1]); max != test.expectedMax { - t.Errorf("expected %v, got %v", test.expectedMax, max) - } - } -} - -func TestIntMin(t *testing.T) { - tests := []struct { - nums []int - expectedMin int - }{ - { - nums: []int{-1, 0}, - expectedMin: -1, - }, - { - nums: []int{-1, -2}, - expectedMin: -2, - }, - { - nums: []int{0, 1}, - expectedMin: 0, - }, - { - nums: []int{1, 2}, - expectedMin: 1, - }, - } - - for i, test := range tests { - t.Logf("executing scenario %d", i) - if min := IntMin(test.nums[0], test.nums[1]); min != test.expectedMin { - t.Errorf("expected %v, got %v", test.expectedMin, min) - } - } -} - -func TestInt64Max(t *testing.T) { - tests := []struct { - nums []int64 - expectedMax int64 - }{ - { - nums: []int64{-1, 0}, - expectedMax: 0, - }, - { - nums: []int64{-1, -2}, - expectedMax: -1, - }, - { - nums: []int64{0, 1}, - expectedMax: 1, - }, - { - nums: []int64{1, 2}, - expectedMax: 2, - }, - } - - for i, test := range tests { - t.Logf("executing scenario %d", i) - if max := Int64Max(test.nums[0], test.nums[1]); max != test.expectedMax { - t.Errorf("expected %v, got %v", test.expectedMax, max) - } - } -} - -func TestInt64Min(t *testing.T) { - tests := []struct { - nums []int64 - expectedMin int64 - }{ - { - nums: []int64{-1, 0}, - expectedMin: -1, - }, - { - nums: []int64{-1, -2}, - expectedMin: -2, - }, - { - nums: []int64{0, 1}, - expectedMin: 0, - }, - { - nums: []int64{1, 2}, - expectedMin: 1, - }, - } - - for i, test := range tests { - t.Logf("executing scenario %d", i) - if min := Int64Min(test.nums[0], test.nums[1]); min != test.expectedMin { - t.Errorf("expected %v, got %v", test.expectedMin, min) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/interrupt/interrupt.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/interrupt/interrupt.go deleted file mode 100644 index 0f4da7d4c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/interrupt/interrupt.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 interrupt - -import ( - "os" - "os/signal" - "sync" - "syscall" -) - -// terminationSignals are signals that cause the program to exit in the -// supported platforms (linux, darwin, windows). -var terminationSignals = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT} - -// Handler guarantees execution of notifications after a critical section (the function passed -// to a Run method), even in the presence of process termination. It guarantees exactly once -// invocation of the provided notify functions. -type Handler struct { - notify []func() - final func(os.Signal) - once sync.Once -} - -// Chain creates a new handler that invokes all notify functions when the critical section exits -// and then invokes the optional handler's notifications. This allows critical sections to be -// nested without losing exactly once invocations. Notify functions can invoke any cleanup needed -// but should not exit (which is the responsibility of the parent handler). -func Chain(handler *Handler, notify ...func()) *Handler { - if handler == nil { - return New(nil, notify...) - } - return New(handler.Signal, append(notify, handler.Close)...) -} - -// New creates a new handler that guarantees all notify functions are run after the critical -// section exits (or is interrupted by the OS), then invokes the final handler. If no final -// handler is specified, the default final is `os.Exit(0)`. A handler can only be used for -// one critical section. -func New(final func(os.Signal), notify ...func()) *Handler { - return &Handler{ - final: final, - notify: notify, - } -} - -// Close executes all the notification handlers if they have not yet been executed. -func (h *Handler) Close() { - h.once.Do(func() { - for _, fn := range h.notify { - fn() - } - }) -} - -// Signal is called when an os.Signal is received, and guarantees that all notifications -// are executed, then the final handler is executed. This function should only be called once -// per Handler instance. -func (h *Handler) Signal(s os.Signal) { - h.once.Do(func() { - for _, fn := range h.notify { - fn() - } - if h.final == nil { - os.Exit(0) - } - h.final(s) - }) -} - -// Run ensures that any notifications are invoked after the provided fn exits (even if the -// process is interrupted by an OS termination signal). Notifications are only invoked once -// per Handler instance, so calling Run more than once will not behave as the user expects. -func (h *Handler) Run(fn func() error) error { - ch := make(chan os.Signal, 1) - signal.Notify(ch, terminationSignals...) - defer func() { - signal.Stop(ch) - close(ch) - }() - go func() { - sig, ok := <-ch - if !ok { - return - } - h.Signal(sig) - }() - defer h.Close() - return fn() -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/intstr/intstr_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/intstr/intstr_test.go deleted file mode 100644 index d4ccb6d28..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/intstr/intstr_test.go +++ /dev/null @@ -1,176 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 intstr - -import ( - "encoding/json" - "reflect" - "testing" - - "github.com/ghodss/yaml" -) - -func TestFromInt(t *testing.T) { - i := FromInt(93) - if i.Type != Int || i.IntVal != 93 { - t.Errorf("Expected IntVal=93, got %+v", i) - } -} - -func TestFromString(t *testing.T) { - i := FromString("76") - if i.Type != String || i.StrVal != "76" { - t.Errorf("Expected StrVal=\"76\", got %+v", i) - } -} - -type IntOrStringHolder struct { - IOrS IntOrString `json:"val"` -} - -func TestIntOrStringUnmarshalJSON(t *testing.T) { - cases := []struct { - input string - result IntOrString - }{ - {"{\"val\": 123}", FromInt(123)}, - {"{\"val\": \"123\"}", FromString("123")}, - } - - for _, c := range cases { - var result IntOrStringHolder - if err := json.Unmarshal([]byte(c.input), &result); err != nil { - t.Errorf("Failed to unmarshal input '%v': %v", c.input, err) - } - if result.IOrS != c.result { - t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result) - } - } -} - -func TestIntOrStringMarshalJSON(t *testing.T) { - cases := []struct { - input IntOrString - result string - }{ - {FromInt(123), "{\"val\":123}"}, - {FromString("123"), "{\"val\":\"123\"}"}, - } - - for _, c := range cases { - input := IntOrStringHolder{c.input} - result, err := json.Marshal(&input) - if err != nil { - t.Errorf("Failed to marshal input '%v': %v", input, err) - } - if string(result) != c.result { - t.Errorf("Failed to marshal input '%v': expected: %+v, got %q", input, c.result, string(result)) - } - } -} - -func TestIntOrStringMarshalJSONUnmarshalYAML(t *testing.T) { - cases := []struct { - input IntOrString - }{ - {FromInt(123)}, - {FromString("123")}, - } - - for _, c := range cases { - input := IntOrStringHolder{c.input} - jsonMarshalled, err := json.Marshal(&input) - if err != nil { - t.Errorf("1: Failed to marshal input: '%v': %v", input, err) - } - - var result IntOrStringHolder - err = yaml.Unmarshal(jsonMarshalled, &result) - if err != nil { - t.Errorf("2: Failed to unmarshal '%+v': %v", string(jsonMarshalled), err) - } - - if !reflect.DeepEqual(input, result) { - t.Errorf("3: Failed to marshal input '%+v': got %+v", input, result) - } - } -} - -func TestGetValueFromIntOrPercent(t *testing.T) { - tests := []struct { - input IntOrString - total int - roundUp bool - expectErr bool - expectVal int - }{ - { - input: FromInt(123), - expectErr: false, - expectVal: 123, - }, - { - input: FromString("90%"), - total: 100, - roundUp: true, - expectErr: false, - expectVal: 90, - }, - { - input: FromString("90%"), - total: 95, - roundUp: true, - expectErr: false, - expectVal: 86, - }, - { - input: FromString("90%"), - total: 95, - roundUp: false, - expectErr: false, - expectVal: 85, - }, - { - input: FromString("%"), - expectErr: true, - }, - { - input: FromString("90#"), - expectErr: true, - }, - { - input: FromString("#%"), - expectErr: true, - }, - } - - for i, test := range tests { - t.Logf("test case %d", i) - value, err := GetValueFromIntOrPercent(&test.input, test.total, test.roundUp) - if test.expectErr && err == nil { - t.Errorf("expected error, but got none") - continue - } - if !test.expectErr && err != nil { - t.Errorf("unexpected err: %v", err) - continue - } - if test.expectVal != value { - t.Errorf("expected %v, but got %v", test.expectVal, value) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/io.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/io.go deleted file mode 100644 index d600c08c1..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/io.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 io - -import ( - "fmt" - "io/ioutil" - "os" - - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/runtime" -) - -// LoadPodFromFile will read, decode, and return a Pod from a file. -func LoadPodFromFile(filePath string) (*api.Pod, error) { - if filePath == "" { - return nil, fmt.Errorf("file path not specified") - } - podDef, err := ioutil.ReadFile(filePath) - if err != nil { - return nil, fmt.Errorf("failed to read file path %s: %+v", filePath, err) - } - if len(podDef) == 0 { - return nil, fmt.Errorf("file was empty: %s", filePath) - } - pod := &api.Pod{} - - codec := api.Codecs.LegacyCodec(registered.GroupOrDie(api.GroupName).GroupVersion) - if err := runtime.DecodeInto(codec, podDef, pod); err != nil { - return nil, fmt.Errorf("failed decoding file: %v", err) - } - return pod, nil -} - -// SavePodToFile will encode and save a pod to a given path & permissions -func SavePodToFile(pod *api.Pod, filePath string, perm os.FileMode) error { - if filePath == "" { - return fmt.Errorf("file path not specified") - } - codec := api.Codecs.LegacyCodec(registered.GroupOrDie(api.GroupName).GroupVersion) - data, err := runtime.Encode(codec, pod) - if err != nil { - return fmt.Errorf("failed encoding pod: %v", err) - } - return ioutil.WriteFile(filePath, data, perm) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/io_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/io_test.go deleted file mode 100644 index 1b9d4c67a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/io_test.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 io_test - -import ( - "fmt" - "os" - "testing" - - "github.com/pborman/uuid" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/apimachinery/registered" - "k8s.io/kubernetes/pkg/runtime" - "k8s.io/kubernetes/pkg/util/io" - utiltesting "k8s.io/kubernetes/pkg/util/testing" - "k8s.io/kubernetes/pkg/volume" -) - -func TestSavePodToFile(t *testing.T) { - pod := volume.NewPersistentVolumeRecyclerPodTemplate() - - // sets all default values on a pod for equality comparison after decoding from file - codec := api.Codecs.LegacyCodec(registered.GroupOrDie(api.GroupName).GroupVersion) - encoded, err := runtime.Encode(codec, pod) - runtime.DecodeInto(codec, encoded, pod) - - tmpDir := utiltesting.MkTmpdirOrDie("kube-io-test") - defer os.RemoveAll(tmpDir) - path := fmt.Sprintf("/%s/kube-io-test-%s", tmpDir, uuid.New()) - - if err := io.SavePodToFile(pod, path, 777); err != nil { - t.Fatalf("failed to save pod to file: %v", err) - } - - podFromFile, err := io.LoadPodFromFile(path) - if err != nil { - t.Fatalf("failed to load pod from file: %v", err) - } - if !api.Semantic.DeepEqual(pod, podFromFile) { - t.Errorf("\nexpected %#v\ngot %#v\n", pod, podFromFile) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/writer.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/writer.go deleted file mode 100644 index 3046c4d9b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/io/writer.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 io - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "os/exec" - - "github.com/golang/glog" -) - -// Writer is an interface which allows to write data to a file. -type Writer interface { - WriteFile(filename string, data []byte, perm os.FileMode) error -} - -// StdWriter implements Writer interface and uses standard libraries -// for writing data to files. -type StdWriter struct { -} - -func (writer *StdWriter) WriteFile(filename string, data []byte, perm os.FileMode) error { - return ioutil.WriteFile(filename, data, perm) -} - -// Alternative implementation of Writer interface that allows writing data to file -// using nsenter command. -// If a program (e.g. kubelet) runs in a container it may want to write data to -// a mounted device. Since in Docker, mount propagation mode is set to private, -// it will not see the mounted device in its own namespace. To work around this -// limitaion one has to first enter hosts namespace (by using 'nsenter') and only -// then write data. -type NsenterWriter struct { -} - -// TODO: should take a writer, not []byte -func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.FileMode) error { - cmd := "nsenter" - base_args := []string{ - "--mount=/rootfs/proc/1/ns/mnt", - "--", - } - - echo_args := append(base_args, "sh", "-c", fmt.Sprintf("cat > %s", filename)) - glog.V(5).Infof("Command to write data to file: %v %v", cmd, echo_args) - command := exec.Command(cmd, echo_args...) - command.Stdin = bytes.NewBuffer(data) - outputBytes, err := command.CombinedOutput() - if err != nil { - glog.Errorf("Output from writing to %q: %v", filename, string(outputBytes)) - return err - } - - chmod_args := append(base_args, "chmod", fmt.Sprintf("%o", perm), filename) - glog.V(5).Infof("Command to change permissions to file: %v %v", cmd, chmod_args) - outputBytes, err = exec.Command(cmd, chmod_args...).CombinedOutput() - if err != nil { - glog.Errorf("Output from chmod command: %v", string(outputBytes)) - return err - } - - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/doc.go deleted file mode 100644 index 5824f3b4e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 iptables provides an interface and implementations for running iptables commands. -package iptables diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/iptables.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/iptables.go deleted file mode 100644 index 801cc8bf7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/iptables.go +++ /dev/null @@ -1,595 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 iptables - -import ( - "fmt" - "io/ioutil" - "os" - "regexp" - "strings" - "sync" - - "github.com/coreos/go-semver/semver" - godbus "github.com/godbus/dbus" - "github.com/golang/glog" - utildbus "k8s.io/kubernetes/pkg/util/dbus" - utilexec "k8s.io/kubernetes/pkg/util/exec" - "k8s.io/kubernetes/pkg/util/sets" -) - -type RulePosition string - -const ( - Prepend RulePosition = "-I" - Append RulePosition = "-A" -) - -// An injectable interface for running iptables commands. Implementations must be goroutine-safe. -type Interface interface { - // GetVersion returns the "X.Y.Z" semver string for iptables. - GetVersion() (string, error) - // EnsureChain checks if the specified chain exists and, if not, creates it. If the chain existed, return true. - EnsureChain(table Table, chain Chain) (bool, error) - // FlushChain clears the specified chain. If the chain did not exist, return error. - FlushChain(table Table, chain Chain) error - // DeleteChain deletes the specified chain. If the chain did not exist, return error. - DeleteChain(table Table, chain Chain) error - // EnsureRule checks if the specified rule is present and, if not, creates it. If the rule existed, return true. - EnsureRule(position RulePosition, table Table, chain Chain, args ...string) (bool, error) - // DeleteRule checks if the specified rule is present and, if so, deletes it. - DeleteRule(table Table, chain Chain, args ...string) error - // IsIpv6 returns true if this is managing ipv6 tables - IsIpv6() bool - // TODO: (BenTheElder) Unit-Test Save/SaveAll, Restore/RestoreAll - // Save calls `iptables-save` for table. - Save(table Table) ([]byte, error) - // SaveAll calls `iptables-save`. - SaveAll() ([]byte, error) - // Restore runs `iptables-restore` passing data through a temporary file. - // table is the Table to restore - // data should be formatted like the output of Save() - // flush sets the presence of the "--noflush" flag. see: FlushFlag - // counters sets the "--counters" flag. see: RestoreCountersFlag - Restore(table Table, data []byte, flush FlushFlag, counters RestoreCountersFlag) error - // RestoreAll is the same as Restore except that no table is specified. - RestoreAll(data []byte, flush FlushFlag, counters RestoreCountersFlag) error - // AddReloadFunc adds a function to call on iptables reload - AddReloadFunc(reloadFunc func()) - // Destroy cleans up resources used by the Interface - Destroy() -} - -type Protocol byte - -const ( - ProtocolIpv4 Protocol = iota + 1 - ProtocolIpv6 -) - -type Table string - -const ( - TableNAT Table = "nat" - TableFilter Table = "filter" -) - -type Chain string - -const ( - ChainPostrouting Chain = "POSTROUTING" - ChainPrerouting Chain = "PREROUTING" - ChainOutput Chain = "OUTPUT" - ChainInput Chain = "INPUT" -) - -const ( - cmdIptablesSave string = "iptables-save" - cmdIptablesRestore string = "iptables-restore" - cmdIptables string = "iptables" - cmdIp6tables string = "ip6tables" -) - -// Option flag for Restore -type RestoreCountersFlag bool - -const RestoreCounters RestoreCountersFlag = true -const NoRestoreCounters RestoreCountersFlag = false - -// Option flag for Flush -type FlushFlag bool - -const FlushTables FlushFlag = true -const NoFlushTables FlushFlag = false - -// Versions of iptables less than this do not support the -C / --check flag -// (test whether a rule exists). -const MinCheckVersion = "1.4.11" - -// Minimum iptables versions supporting the -w and -w2 flags -const MinWaitVersion = "1.4.20" -const MinWait2Version = "1.4.22" - -// runner implements Interface in terms of exec("iptables"). -type runner struct { - mu sync.Mutex - exec utilexec.Interface - dbus utildbus.Interface - protocol Protocol - hasCheck bool - waitFlag []string - - reloadFuncs []func() - signal chan *godbus.Signal -} - -// New returns a new Interface which will exec iptables. -func New(exec utilexec.Interface, dbus utildbus.Interface, protocol Protocol) Interface { - vstring, err := getIptablesVersionString(exec) - if err != nil { - glog.Warningf("Error checking iptables version, assuming version at least %s: %v", MinCheckVersion, err) - vstring = MinCheckVersion - } - runner := &runner{ - exec: exec, - dbus: dbus, - protocol: protocol, - hasCheck: getIptablesHasCheckCommand(vstring), - waitFlag: getIptablesWaitFlag(vstring), - } - runner.connectToFirewallD() - return runner -} - -// Destroy is part of Interface. -func (runner *runner) Destroy() { - if runner.signal != nil { - runner.signal <- nil - } -} - -const ( - firewalldName = "org.fedoraproject.FirewallD1" - firewalldPath = "/org/fedoraproject/FirewallD1" - firewalldInterface = "org.fedoraproject.FirewallD1" -) - -// Connects to D-Bus and listens for FirewallD start/restart. (On non-FirewallD-using -// systems, this is effectively a no-op; we listen for the signals, but they will never be -// emitted, so reload() will never be called.) -func (runner *runner) connectToFirewallD() { - bus, err := runner.dbus.SystemBus() - if err != nil { - glog.V(1).Infof("Could not connect to D-Bus system bus: %s", err) - return - } - - rule := fmt.Sprintf("type='signal',sender='%s',path='%s',interface='%s',member='Reloaded'", firewalldName, firewalldPath, firewalldInterface) - bus.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule) - - rule = fmt.Sprintf("type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',sender='org.freedesktop.DBus',arg0='%s'", firewalldName) - bus.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule) - - runner.signal = make(chan *godbus.Signal, 10) - bus.Signal(runner.signal) - - go runner.dbusSignalHandler(bus) -} - -// GetVersion returns the version string. -func (runner *runner) GetVersion() (string, error) { - return getIptablesVersionString(runner.exec) -} - -// EnsureChain is part of Interface. -func (runner *runner) EnsureChain(table Table, chain Chain) (bool, error) { - fullArgs := makeFullArgs(table, chain) - - runner.mu.Lock() - defer runner.mu.Unlock() - - out, err := runner.run(opCreateChain, fullArgs) - if err != nil { - if ee, ok := err.(utilexec.ExitError); ok { - if ee.Exited() && ee.ExitStatus() == 1 { - return true, nil - } - } - return false, fmt.Errorf("error creating chain %q: %v: %s", chain, err, out) - } - return false, nil -} - -// FlushChain is part of Interface. -func (runner *runner) FlushChain(table Table, chain Chain) error { - fullArgs := makeFullArgs(table, chain) - - runner.mu.Lock() - defer runner.mu.Unlock() - - out, err := runner.run(opFlushChain, fullArgs) - if err != nil { - return fmt.Errorf("error flushing chain %q: %v: %s", chain, err, out) - } - return nil -} - -// DeleteChain is part of Interface. -func (runner *runner) DeleteChain(table Table, chain Chain) error { - fullArgs := makeFullArgs(table, chain) - - runner.mu.Lock() - defer runner.mu.Unlock() - - // TODO: we could call iptables -S first, ignore the output and check for non-zero return (more like DeleteRule) - out, err := runner.run(opDeleteChain, fullArgs) - if err != nil { - return fmt.Errorf("error deleting chain %q: %v: %s", chain, err, out) - } - return nil -} - -// EnsureRule is part of Interface. -func (runner *runner) EnsureRule(position RulePosition, table Table, chain Chain, args ...string) (bool, error) { - fullArgs := makeFullArgs(table, chain, args...) - - runner.mu.Lock() - defer runner.mu.Unlock() - - exists, err := runner.checkRule(table, chain, args...) - if err != nil { - return false, err - } - if exists { - return true, nil - } - out, err := runner.run(operation(position), fullArgs) - if err != nil { - return false, fmt.Errorf("error appending rule: %v: %s", err, out) - } - return false, nil -} - -// DeleteRule is part of Interface. -func (runner *runner) DeleteRule(table Table, chain Chain, args ...string) error { - fullArgs := makeFullArgs(table, chain, args...) - - runner.mu.Lock() - defer runner.mu.Unlock() - - exists, err := runner.checkRule(table, chain, args...) - if err != nil { - return err - } - if !exists { - return nil - } - out, err := runner.run(opDeleteRule, fullArgs) - if err != nil { - return fmt.Errorf("error deleting rule: %v: %s", err, out) - } - return nil -} - -func (runner *runner) IsIpv6() bool { - return runner.protocol == ProtocolIpv6 -} - -// Save is part of Interface. -func (runner *runner) Save(table Table) ([]byte, error) { - runner.mu.Lock() - defer runner.mu.Unlock() - - // run and return - args := []string{"-t", string(table)} - glog.V(4).Infof("running iptables-save %v", args) - return runner.exec.Command(cmdIptablesSave, args...).CombinedOutput() -} - -// SaveAll is part of Interface. -func (runner *runner) SaveAll() ([]byte, error) { - runner.mu.Lock() - defer runner.mu.Unlock() - - // run and return - glog.V(4).Infof("running iptables-save") - return runner.exec.Command(cmdIptablesSave, []string{}...).CombinedOutput() -} - -// Restore is part of Interface. -func (runner *runner) Restore(table Table, data []byte, flush FlushFlag, counters RestoreCountersFlag) error { - // setup args - args := []string{"-T", string(table)} - return runner.restoreInternal(args, data, flush, counters) -} - -// RestoreAll is part of Interface. -func (runner *runner) RestoreAll(data []byte, flush FlushFlag, counters RestoreCountersFlag) error { - // setup args - args := make([]string, 0) - return runner.restoreInternal(args, data, flush, counters) -} - -// restoreInternal is the shared part of Restore/RestoreAll -func (runner *runner) restoreInternal(args []string, data []byte, flush FlushFlag, counters RestoreCountersFlag) error { - runner.mu.Lock() - defer runner.mu.Unlock() - - if !flush { - args = append(args, "--noflush") - } - if counters { - args = append(args, "--counters") - } - // create temp file through which to pass data - temp, err := ioutil.TempFile("", "kube-temp-iptables-restore-") - if err != nil { - return err - } - // make sure we delete the temp file - defer os.Remove(temp.Name()) - // Put the filename at the end of args. - // NOTE: the filename must be at the end. - // See: https://git.netfilter.org/iptables/commit/iptables-restore.c?id=e6869a8f59d779ff4d5a0984c86d80db70784962 - args = append(args, temp.Name()) - if err != nil { - return err - } - // write data to the file - _, err = temp.Write(data) - temp.Close() - if err != nil { - return err - } - // run the command and return the output or an error including the output and error - glog.V(4).Infof("running iptables-restore %v", args) - b, err := runner.exec.Command(cmdIptablesRestore, args...).CombinedOutput() - if err != nil { - return fmt.Errorf("%v (%s)", err, b) - } - return nil -} - -func (runner *runner) iptablesCommand() string { - if runner.IsIpv6() { - return cmdIp6tables - } else { - return cmdIptables - } -} - -func (runner *runner) run(op operation, args []string) ([]byte, error) { - iptablesCmd := runner.iptablesCommand() - - fullArgs := append(runner.waitFlag, string(op)) - fullArgs = append(fullArgs, args...) - glog.V(4).Infof("running iptables %s %v", string(op), args) - return runner.exec.Command(iptablesCmd, fullArgs...).CombinedOutput() - // Don't log err here - callers might not think it is an error. -} - -// Returns (bool, nil) if it was able to check the existence of the rule, or -// (, error) if the process of checking failed. -func (runner *runner) checkRule(table Table, chain Chain, args ...string) (bool, error) { - if runner.hasCheck { - return runner.checkRuleUsingCheck(makeFullArgs(table, chain, args...)) - } else { - return runner.checkRuleWithoutCheck(table, chain, args...) - } -} - -// Executes the rule check without using the "-C" flag, instead parsing iptables-save. -// Present for compatibility with <1.4.11 versions of iptables. This is full -// of hack and half-measures. We should nix this ASAP. -func (runner *runner) checkRuleWithoutCheck(table Table, chain Chain, args ...string) (bool, error) { - glog.V(1).Infof("running iptables-save -t %s", string(table)) - out, err := runner.exec.Command(cmdIptablesSave, "-t", string(table)).CombinedOutput() - if err != nil { - return false, fmt.Errorf("error checking rule: %v", err) - } - - // Sadly, iptables has inconsistent quoting rules for comments. Just remove all quotes. - // Also, quoted multi-word comments (which are counted as a single arg) - // will be unpacked into multiple args, - // in order to compare against iptables-save output (which will be split at whitespace boundary) - // e.g. a single arg('"this must be before the NodePort rules"') will be unquoted and unpacked into 7 args. - var argsCopy []string - for i := range args { - tmpField := strings.Trim(args[i], "\"") - argsCopy = append(argsCopy, strings.Fields(tmpField)...) - } - argset := sets.NewString(argsCopy...) - - for _, line := range strings.Split(string(out), "\n") { - var fields = strings.Fields(line) - - // Check that this is a rule for the correct chain, and that it has - // the correct number of argument (+2 for "-A ") - if !strings.HasPrefix(line, fmt.Sprintf("-A %s", string(chain))) || len(fields) != len(argsCopy)+2 { - continue - } - - // Sadly, iptables has inconsistent quoting rules for comments. - // Just remove all quotes. - for i := range fields { - fields[i] = strings.Trim(fields[i], "\"") - } - - // TODO: This misses reorderings e.g. "-x foo ! -y bar" will match "! -x foo -y bar" - if sets.NewString(fields...).IsSuperset(argset) { - return true, nil - } - glog.V(5).Infof("DBG: fields is not a superset of args: fields=%v args=%v", fields, args) - } - - return false, nil -} - -// Executes the rule check using the "-C" flag -func (runner *runner) checkRuleUsingCheck(args []string) (bool, error) { - out, err := runner.run(opCheckRule, args) - if err == nil { - return true, nil - } - if ee, ok := err.(utilexec.ExitError); ok { - // iptables uses exit(1) to indicate a failure of the operation, - // as compared to a malformed commandline, for example. - if ee.Exited() && ee.ExitStatus() == 1 { - return false, nil - } - } - return false, fmt.Errorf("error checking rule: %v: %s", err, out) -} - -type operation string - -const ( - opCreateChain operation = "-N" - opFlushChain operation = "-F" - opDeleteChain operation = "-X" - opAppendRule operation = "-A" - opCheckRule operation = "-C" - opDeleteRule operation = "-D" -) - -func makeFullArgs(table Table, chain Chain, args ...string) []string { - return append([]string{string(chain), "-t", string(table)}, args...) -} - -// Checks if iptables has the "-C" flag -func getIptablesHasCheckCommand(vstring string) bool { - minVersion, err := semver.NewVersion(MinCheckVersion) - if err != nil { - glog.Errorf("MinCheckVersion (%s) is not a valid version string: %v", MinCheckVersion, err) - return true - } - version, err := semver.NewVersion(vstring) - if err != nil { - glog.Errorf("vstring (%s) is not a valid version string: %v", vstring, err) - return true - } - if version.LessThan(*minVersion) { - return false - } - return true -} - -// Checks if iptables version has a "wait" flag -func getIptablesWaitFlag(vstring string) []string { - version, err := semver.NewVersion(vstring) - if err != nil { - glog.Errorf("vstring (%s) is not a valid version string: %v", vstring, err) - return nil - } - - minVersion, err := semver.NewVersion(MinWaitVersion) - if err != nil { - glog.Errorf("MinWaitVersion (%s) is not a valid version string: %v", MinWaitVersion, err) - return nil - } - if version.LessThan(*minVersion) { - return nil - } - - minVersion, err = semver.NewVersion(MinWait2Version) - if err != nil { - glog.Errorf("MinWait2Version (%s) is not a valid version string: %v", MinWait2Version, err) - return nil - } - if version.LessThan(*minVersion) { - return []string{"-w"} - } else { - return []string{"-w2"} - } -} - -// getIptablesVersionString runs "iptables --version" to get the version string -// in the form "X.X.X" -func getIptablesVersionString(exec utilexec.Interface) (string, error) { - // this doesn't access mutable state so we don't need to use the interface / runner - bytes, err := exec.Command(cmdIptables, "--version").CombinedOutput() - if err != nil { - return "", err - } - versionMatcher := regexp.MustCompile("v([0-9]+\\.[0-9]+\\.[0-9]+)") - match := versionMatcher.FindStringSubmatch(string(bytes)) - if match == nil { - return "", fmt.Errorf("no iptables version found in string: %s", bytes) - } - return match[1], nil -} - -// goroutine to listen for D-Bus signals -func (runner *runner) dbusSignalHandler(bus utildbus.Connection) { - firewalld := bus.Object(firewalldName, firewalldPath) - - for s := range runner.signal { - if s == nil { - // Unregister - bus.Signal(runner.signal) - return - } - - switch s.Name { - case "org.freedesktop.DBus.NameOwnerChanged": - name := s.Body[0].(string) - new_owner := s.Body[2].(string) - - if name != firewalldName || len(new_owner) == 0 { - continue - } - - // FirewallD startup (specifically the part where it deletes - // all existing iptables rules) may not yet be complete when - // we get this signal, so make a dummy request to it to - // synchronize. - firewalld.Call(firewalldInterface+".getDefaultZone", 0) - - runner.reload() - case firewalldInterface + ".Reloaded": - runner.reload() - } - } -} - -// AddReloadFunc is part of Interface -func (runner *runner) AddReloadFunc(reloadFunc func()) { - runner.reloadFuncs = append(runner.reloadFuncs, reloadFunc) -} - -// runs all reload funcs to re-sync iptables rules -func (runner *runner) reload() { - glog.V(1).Infof("reloading iptables rules") - - for _, f := range runner.reloadFuncs { - f() - } -} - -// IsNotFoundError returns true if the error indicates "not found". It parses -// the error string looking for known values, which is imperfect but works in -// practice. -func IsNotFoundError(err error) bool { - es := err.Error() - if strings.Contains(es, "No such file or directory") { - return true - } - if strings.Contains(es, "No chain/target/match by that name") { - return true - } - return false -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/iptables_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/iptables_test.go deleted file mode 100644 index d5bb34691..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/iptables_test.go +++ /dev/null @@ -1,768 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 iptables - -import ( - "strings" - "testing" - "time" - - "k8s.io/kubernetes/pkg/util/dbus" - "k8s.io/kubernetes/pkg/util/exec" - "k8s.io/kubernetes/pkg/util/sets" -) - -func getIptablesCommand(protocol Protocol) string { - if protocol == ProtocolIpv4 { - return cmdIptables - } - if protocol == ProtocolIpv6 { - return cmdIp6tables - } - panic("Unknown protocol") -} - -func testEnsureChain(t *testing.T, protocol Protocol) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Success. - func() ([]byte, error) { return []byte{}, nil }, - // Exists. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - // Failure. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 2} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), protocol) - defer runner.Destroy() - // Success. - exists, err := runner.EnsureChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if exists { - t.Errorf("expected exists = false") - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - cmd := getIptablesCommand(protocol) - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll(cmd, "-t", "nat", "-N", "FOOBAR") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } - // Exists. - exists, err = runner.EnsureChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if !exists { - t.Errorf("expected exists = true") - } - // Failure. - _, err = runner.EnsureChain(TableNAT, Chain("FOOBAR")) - if err == nil { - t.Errorf("expected failure") - } -} - -func TestEnsureChainIpv4(t *testing.T) { - testEnsureChain(t, ProtocolIpv4) -} - -func TestEnsureChainIpv6(t *testing.T) { - testEnsureChain(t, ProtocolIpv6) -} - -func TestFlushChain(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Success. - func() ([]byte, error) { return []byte{}, nil }, - // Failure. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - // Success. - err := runner.FlushChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-F", "FOOBAR") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } - // Failure. - err = runner.FlushChain(TableNAT, Chain("FOOBAR")) - if err == nil { - t.Errorf("expected failure") - } -} - -func TestDeleteChain(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Success. - func() ([]byte, error) { return []byte{}, nil }, - // Failure. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - // Success. - err := runner.DeleteChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-X", "FOOBAR") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } - // Failure. - err = runner.DeleteChain(TableNAT, Chain("FOOBAR")) - if err == nil { - t.Errorf("expected failure") - } -} - -func TestEnsureRuleAlreadyExists(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Success. - func() ([]byte, error) { return []byte{}, nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Success of that exec means "done". - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - exists, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if !exists { - t.Errorf("expected exists = true") - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-C", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } -} - -func TestEnsureRuleNew(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Status 1 on the first call. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - // Success on the second call. - func() ([]byte, error) { return []byte{}, nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Failure of that means create it. - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - exists, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if exists { - t.Errorf("expected exists = false") - } - if fcmd.CombinedOutputCalls != 3 { - t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[2]...).HasAll("iptables", "-t", "nat", "-A", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2]) - } -} - -func TestEnsureRuleErrorChecking(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Status 2 on the first call. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 2} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Failure of that means create it. - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - _, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123") - if err == nil { - t.Errorf("expected failure") - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } -} - -func TestEnsureRuleErrorCreating(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Status 1 on the first call. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - // Status 1 on the second call. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Failure of that means create it. - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - _, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123") - if err == nil { - t.Errorf("expected failure") - } - if fcmd.CombinedOutputCalls != 3 { - t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } -} - -func TestDeleteRuleAlreadyExists(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Status 1 on the first call. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Failure of that exec means "does not exist". - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-C", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } -} - -func TestDeleteRuleNew(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Success on the first call. - func() ([]byte, error) { return []byte{}, nil }, - // Success on the second call. - func() ([]byte, error) { return []byte{}, nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Success of that means delete it. - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 3 { - t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[2]...).HasAll("iptables", "-t", "nat", "-D", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2]) - } -} - -func TestDeleteRuleErrorChecking(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Status 2 on the first call. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 2} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Failure of that means create it. - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123") - if err == nil { - t.Errorf("expected failure") - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } -} - -func TestDeleteRuleErrorCreating(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, - // Success on the first call. - func() ([]byte, error) { return []byte{}, nil }, - // Status 1 on the second call. - func() ([]byte, error) { return nil, &exec.FakeExitError{Status: 1} }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // iptables version check - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - // The second Command() call is checking the rule. Success of that means delete it. - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123") - if err == nil { - t.Errorf("expected failure") - } - if fcmd.CombinedOutputCalls != 3 { - t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } -} - -func TestGetIptablesHasCheckCommand(t *testing.T) { - testCases := []struct { - Version string - Err bool - Expected bool - }{ - {"iptables v1.4.7", false, false}, - {"iptables v1.4.11", false, true}, - {"iptables v1.4.19.1", false, true}, - {"iptables v2.0.0", false, true}, - {"total junk", true, false}, - } - - for _, testCase := range testCases { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(testCase.Version), nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - version, err := getIptablesVersionString(&fexec) - if (err != nil) != testCase.Err { - t.Errorf("Expected error: %v, Got error: %v", testCase.Err, err) - } - if err == nil { - check := getIptablesHasCheckCommand(version) - if testCase.Expected != check { - t.Errorf("Expected result: %v, Got result: %v", testCase.Expected, check) - } - } - } -} - -func TestCheckRuleWithoutCheckPresent(t *testing.T) { - iptables_save_output := `# Generated by iptables-save v1.4.7 on Wed Oct 29 14:56:01 2014 -*nat -:PREROUTING ACCEPT [2136997:197881818] -:POSTROUTING ACCEPT [4284525:258542680] -:OUTPUT ACCEPT [5901660:357267963] --A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER -COMMIT -# Completed on Wed Oct 29 14:56:01 2014` - - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // Success. - func() ([]byte, error) { return []byte(iptables_save_output), nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // The first Command() call is checking the rule. Success of that exec means "done". - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := &runner{exec: &fexec} - exists, err := runner.checkRuleWithoutCheck(TableNAT, ChainPrerouting, "-m", "addrtype", "-j", "DOCKER", "--dst-type", "LOCAL") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if !exists { - t.Errorf("expected exists = true") - } - if fcmd.CombinedOutputCalls != 1 { - t.Errorf("expected 1 CombinedOutput() call, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll("iptables-save", "-t", "nat") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) - } -} - -func TestCheckRuleWithoutCheckAbsent(t *testing.T) { - iptables_save_output := `# Generated by iptables-save v1.4.7 on Wed Oct 29 14:56:01 2014 -*nat -:PREROUTING ACCEPT [2136997:197881818] -:POSTROUTING ACCEPT [4284525:258542680] -:OUTPUT ACCEPT [5901660:357267963] --A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER -COMMIT -# Completed on Wed Oct 29 14:56:01 2014` - - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // Success. - func() ([]byte, error) { return []byte(iptables_save_output), nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - // The first Command() call is checking the rule. Success of that exec means "done". - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := &runner{exec: &fexec} - exists, err := runner.checkRuleWithoutCheck(TableNAT, ChainPrerouting, "-m", "addrtype", "-j", "DOCKER") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if exists { - t.Errorf("expected exists = false") - } - if fcmd.CombinedOutputCalls != 1 { - t.Errorf("expected 1 CombinedOutput() call, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll("iptables-save", "-t", "nat") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) - } -} - -func TestIptablesWaitFlag(t *testing.T) { - testCases := []struct { - Version string - Result string - }{ - {"0.55.55", ""}, - {"1.0.55", ""}, - {"1.4.19", ""}, - {"1.4.20", "-w"}, - {"1.4.21", "-w"}, - {"1.4.22", "-w2"}, - {"1.5.0", "-w2"}, - {"2.0.0", "-w2"}, - } - - for _, testCase := range testCases { - result := getIptablesWaitFlag(testCase.Version) - if strings.Join(result, "") != testCase.Result { - t.Errorf("For %s expected %v got %v", testCase.Version, testCase.Result, result) - } - } -} - -func TestWaitFlagUnavailable(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.4.19"), nil }, - // Success. - func() ([]byte, error) { return []byte{}, nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - err := runner.DeleteChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if sets.NewString(fcmd.CombinedOutputLog[1]...).HasAny("-w", "-w2") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } -} - -func TestWaitFlagOld(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.4.20"), nil }, - // Success. - func() ([]byte, error) { return []byte{}, nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - err := runner.DeleteChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-w") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } - if sets.NewString(fcmd.CombinedOutputLog[1]...).HasAny("-w2") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } -} - -func TestWaitFlagNew(t *testing.T) { - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.4.22"), nil }, - // Success. - func() ([]byte, error) { return []byte{}, nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - runner := New(&fexec, dbus.NewFake(nil, nil), ProtocolIpv4) - defer runner.Destroy() - err := runner.DeleteChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if fcmd.CombinedOutputCalls != 2 { - t.Errorf("expected 2 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-w2") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } - if sets.NewString(fcmd.CombinedOutputLog[1]...).HasAny("-w") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } -} - -func TestReload(t *testing.T) { - dbusConn := dbus.NewFakeConnection() - dbusConn.SetBusObject(func(method string, args ...interface{}) ([]interface{}, error) { return nil, nil }) - dbusConn.AddObject(firewalldName, firewalldPath, func(method string, args ...interface{}) ([]interface{}, error) { return nil, nil }) - fdbus := dbus.NewFake(dbusConn, nil) - - reloaded := make(chan bool, 2) - - fcmd := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - // iptables version check - func() ([]byte, error) { return []byte("iptables v1.4.22"), nil }, - - // first reload - // EnsureChain - func() ([]byte, error) { return []byte{}, nil }, - // EnsureRule abc check - func() ([]byte, error) { return []byte{}, &exec.FakeExitError{Status: 1} }, - // EnsureRule abc - func() ([]byte, error) { return []byte{}, nil }, - - // second reload - // EnsureChain - func() ([]byte, error) { return []byte{}, nil }, - // EnsureRule abc check - func() ([]byte, error) { return []byte{}, &exec.FakeExitError{Status: 1} }, - // EnsureRule abc - func() ([]byte, error) { return []byte{}, nil }, - }, - } - fexec := exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{ - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, - }, - } - - runner := New(&fexec, fdbus, ProtocolIpv4) - defer runner.Destroy() - - runner.AddReloadFunc(func() { - exists, err := runner.EnsureChain(TableNAT, Chain("FOOBAR")) - if err != nil { - t.Errorf("expected success, got %v", err) - } - if exists { - t.Errorf("expected exists = false") - } - reloaded <- true - }) - - runner.AddReloadFunc(func() { - exists, err := runner.EnsureRule(Append, TableNAT, ChainOutput, "abc", "123") - if err != nil { - t.Errorf("expected success, got %v", err) - } - if exists { - t.Errorf("expected exists = false") - } - reloaded <- true - }) - - dbusConn.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged", firewalldName, "", ":1.1") - <-reloaded - <-reloaded - - if fcmd.CombinedOutputCalls != 4 { - t.Errorf("expected 4 CombinedOutput() calls total, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-N", "FOOBAR") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) - } - if !sets.NewString(fcmd.CombinedOutputLog[2]...).HasAll("iptables", "-t", "nat", "-C", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[2]) - } - if !sets.NewString(fcmd.CombinedOutputLog[3]...).HasAll("iptables", "-t", "nat", "-A", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[3]) - } - - go func() { time.Sleep(time.Second / 100); reloaded <- true }() - dbusConn.EmitSignal(firewalldName, firewalldPath, firewalldInterface, "DefaultZoneChanged", "public") - dbusConn.EmitSignal("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "NameOwnerChanged", "io.k8s.Something", "", ":1.1") - <-reloaded - - if fcmd.CombinedOutputCalls != 4 { - t.Errorf("Incorrect signal caused a reload") - } - - dbusConn.EmitSignal(firewalldName, firewalldPath, firewalldInterface, "Reloaded") - <-reloaded - <-reloaded - - if fcmd.CombinedOutputCalls != 7 { - t.Errorf("expected 7 CombinedOutput() calls total, got %d", fcmd.CombinedOutputCalls) - } - if !sets.NewString(fcmd.CombinedOutputLog[4]...).HasAll("iptables", "-t", "nat", "-N", "FOOBAR") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[4]) - } - if !sets.NewString(fcmd.CombinedOutputLog[5]...).HasAll("iptables", "-t", "nat", "-C", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[5]) - } - if !sets.NewString(fcmd.CombinedOutputLog[6]...).HasAll("iptables", "-t", "nat", "-A", "OUTPUT", "abc", "123") { - t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[6]) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/testing/fake.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/testing/fake.go deleted file mode 100644 index ac9967727..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/iptables/testing/fake.go +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 testing - -import "k8s.io/kubernetes/pkg/util/iptables" - -// no-op implemenatation of iptables Interface -type fake struct{} - -func NewFake() *fake { - return &fake{} -} - -func (*fake) GetVersion() (string, error) { - return "0.0.0", nil -} - -func (*fake) EnsureChain(table iptables.Table, chain iptables.Chain) (bool, error) { - return true, nil -} - -func (*fake) FlushChain(table iptables.Table, chain iptables.Chain) error { - return nil -} - -func (*fake) DeleteChain(table iptables.Table, chain iptables.Chain) error { - return nil -} - -func (*fake) EnsureRule(position iptables.RulePosition, table iptables.Table, chain iptables.Chain, args ...string) (bool, error) { - return true, nil -} - -func (*fake) DeleteRule(table iptables.Table, chain iptables.Chain, args ...string) error { - return nil -} - -func (*fake) IsIpv6() bool { - return false -} - -func (*fake) Save(table iptables.Table) ([]byte, error) { - return make([]byte, 0), nil -} - -func (*fake) SaveAll() ([]byte, error) { - return make([]byte, 0), nil -} - -func (*fake) Restore(table iptables.Table, data []byte, flush iptables.FlushFlag, counters iptables.RestoreCountersFlag) error { - return nil -} - -func (*fake) RestoreAll(data []byte, flush iptables.FlushFlag, counters iptables.RestoreCountersFlag) error { - return nil -} -func (*fake) AddReloadFunc(reloadFunc func()) {} - -func (*fake) Destroy() {} - -var _ = iptables.Interface(&fake{}) diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/json/json_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/json/json_test.go deleted file mode 100644 index e41f6ce04..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/json/json_test.go +++ /dev/null @@ -1,317 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 json - -import ( - "fmt" - "math" - "reflect" - "strconv" - "strings" - "testing" -) - -func TestEvaluateTypes(t *testing.T) { - testCases := []struct { - In string - Data interface{} - Out string - Err bool - }{ - // Invalid syntaxes - { - In: `x`, - Err: true, - }, - { - In: ``, - Err: true, - }, - - // Null - { - In: `null`, - Data: nil, - Out: `null`, - }, - // Booleans - { - In: `true`, - Data: true, - Out: `true`, - }, - { - In: `false`, - Data: false, - Out: `false`, - }, - - // Integers - { - In: `0`, - Data: int64(0), - Out: `0`, - }, - { - In: `-0`, - Data: int64(-0), - Out: `0`, - }, - { - In: `1`, - Data: int64(1), - Out: `1`, - }, - { - In: `2147483647`, - Data: int64(math.MaxInt32), - Out: `2147483647`, - }, - { - In: `-2147483648`, - Data: int64(math.MinInt32), - Out: `-2147483648`, - }, - { - In: `9223372036854775807`, - Data: int64(math.MaxInt64), - Out: `9223372036854775807`, - }, - { - In: `-9223372036854775808`, - Data: int64(math.MinInt64), - Out: `-9223372036854775808`, - }, - - // Int overflow - { - In: `9223372036854775808`, // MaxInt64 + 1 - Data: float64(9223372036854775808), - Out: strconv.FormatFloat(9223372036854775808, 'g', -1, 64), - }, - { - In: `-9223372036854775809`, // MinInt64 - 1 - Data: float64(math.MinInt64), - Out: strconv.FormatFloat(-9223372036854775809, 'g', -1, 64), - }, - - // Floats - { - In: `0.0`, - Data: float64(0), - Out: `0`, - }, - { - In: `-0.0`, - Data: float64(-0.0), - Out: `-0`, - }, - { - In: `0.5`, - Data: float64(0.5), - Out: `0.5`, - }, - { - In: `1e3`, - Data: float64(1e3), - Out: `1000`, - }, - { - In: `1.5`, - Data: float64(1.5), - Out: `1.5`, - }, - { - In: `-0.3`, - Data: float64(-.3), - Out: `-0.3`, - }, - { - // Largest representable float32 - In: `3.40282346638528859811704183484516925440e+38`, - Data: float64(math.MaxFloat32), - Out: strconv.FormatFloat(math.MaxFloat32, 'g', -1, 64), - }, - { - // Smallest float32 without losing precision - In: `1.175494351e-38`, - Data: float64(1.175494351e-38), - Out: `1.175494351e-38`, - }, - { - // float32 closest to zero - In: `1.401298464324817070923729583289916131280e-45`, - Data: float64(math.SmallestNonzeroFloat32), - Out: strconv.FormatFloat(math.SmallestNonzeroFloat32, 'g', -1, 64), - }, - { - // Largest representable float64 - In: `1.797693134862315708145274237317043567981e+308`, - Data: float64(math.MaxFloat64), - Out: strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64), - }, - { - // Closest to zero without losing precision - In: `2.2250738585072014e-308`, - Data: float64(2.2250738585072014e-308), - Out: `2.2250738585072014e-308`, - }, - - { - // float64 closest to zero - In: `4.940656458412465441765687928682213723651e-324`, - Data: float64(math.SmallestNonzeroFloat64), - Out: strconv.FormatFloat(math.SmallestNonzeroFloat64, 'g', -1, 64), - }, - - { - // math.MaxFloat64 + 2 overflow - In: `1.7976931348623159e+308`, - Err: true, - }, - - // Strings - { - In: `""`, - Data: string(""), - Out: `""`, - }, - { - In: `"0"`, - Data: string("0"), - Out: `"0"`, - }, - { - In: `"A"`, - Data: string("A"), - Out: `"A"`, - }, - { - In: `"Iñtërnâtiônàlizætiøn"`, - Data: string("Iñtërnâtiônàlizætiøn"), - Out: `"Iñtërnâtiônàlizætiøn"`, - }, - - // Arrays - { - In: `[]`, - Data: []interface{}{}, - Out: `[]`, - }, - { - In: `[` + strings.Join([]string{ - `null`, - `true`, - `false`, - `0`, - `9223372036854775807`, - `0.0`, - `0.5`, - `1.0`, - `1.797693134862315708145274237317043567981e+308`, - `"0"`, - `"A"`, - `"Iñtërnâtiônàlizætiøn"`, - `[null,true,1,1.0,1.5]`, - `{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`, - }, ",") + `]`, - Data: []interface{}{ - nil, - true, - false, - int64(0), - int64(math.MaxInt64), - float64(0.0), - float64(0.5), - float64(1.0), - float64(math.MaxFloat64), - string("0"), - string("A"), - string("Iñtërnâtiônàlizætiøn"), - []interface{}{nil, true, int64(1), float64(1.0), float64(1.5)}, - map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)}, - }, - Out: `[` + strings.Join([]string{ - `null`, - `true`, - `false`, - `0`, - `9223372036854775807`, - `0`, - `0.5`, - `1`, - strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64), - `"0"`, - `"A"`, - `"Iñtërnâtiônàlizætiøn"`, - `[null,true,1,1,1.5]`, - `{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`, // gets alphabetized by Marshal - }, ",") + `]`, - }, - - // Maps - { - In: `{}`, - Data: map[string]interface{}{}, - Out: `{}`, - }, - { - In: `{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`, - Data: map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)}, - Out: `{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`, // gets alphabetized by Marshal - }, - } - - for _, tc := range testCases { - inputJSON := fmt.Sprintf(`{"data":%s}`, tc.In) - expectedJSON := fmt.Sprintf(`{"data":%s}`, tc.Out) - m := map[string]interface{}{} - err := Unmarshal([]byte(inputJSON), &m) - if tc.Err && err != nil { - // Expected error - continue - } - if err != nil { - t.Errorf("%s: error decoding: %v", tc.In, err) - continue - } - if tc.Err { - t.Errorf("%s: expected error, got none", tc.In) - continue - } - data, ok := m["data"] - if !ok { - t.Errorf("%s: decoded object missing data key: %#v", tc.In, m) - continue - } - if !reflect.DeepEqual(tc.Data, data) { - t.Errorf("%s: expected\n\t%#v (%v), got\n\t%#v (%v)", tc.In, tc.Data, reflect.TypeOf(tc.Data), data, reflect.TypeOf(data)) - continue - } - - outputJSON, err := Marshal(m) - if err != nil { - t.Errorf("%s: error encoding: %v", tc.In, err) - continue - } - - if expectedJSON != string(outputJSON) { - t.Errorf("%s: expected\n\t%s, got\n\t%s", tc.In, expectedJSON, string(outputJSON)) - continue - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/jsonpath/jsonpath_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/jsonpath/jsonpath_test.go deleted file mode 100644 index e01a9a458..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/jsonpath/jsonpath_test.go +++ /dev/null @@ -1,264 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 jsonpath - -import ( - "bytes" - "encoding/json" - "fmt" - "reflect" - "sort" - "strings" - "testing" -) - -type jsonpathTest struct { - name string - template string - input interface{} - expect string -} - -func testJSONPath(tests []jsonpathTest, t *testing.T) { - for _, test := range tests { - j := New(test.name) - err := j.Parse(test.template) - if err != nil { - t.Errorf("in %s, parse %s error %v", test.name, test.template, err) - } - buf := new(bytes.Buffer) - err = j.Execute(buf, test.input) - if err != nil { - t.Errorf("in %s, execute error %v", test.name, err) - } - out := buf.String() - if out != test.expect { - t.Errorf(`in %s, expect to get "%s", got "%s"`, test.name, test.expect, out) - } - } -} - -// testJSONPathSortOutput test cases related to map, the results may print in random order -func testJSONPathSortOutput(tests []jsonpathTest, t *testing.T) { - for _, test := range tests { - j := New(test.name) - err := j.Parse(test.template) - if err != nil { - t.Errorf("in %s, parse %s error %v", test.name, test.template, err) - } - buf := new(bytes.Buffer) - err = j.Execute(buf, test.input) - if err != nil { - t.Errorf("in %s, execute error %v", test.name, err) - } - out := buf.String() - //since map is visited in random order, we need to sort the results. - sortedOut := strings.Fields(out) - sort.Strings(sortedOut) - sortedExpect := strings.Fields(test.expect) - sort.Strings(sortedExpect) - if !reflect.DeepEqual(sortedOut, sortedExpect) { - t.Errorf(`in %s, expect to get "%s", got "%s"`, test.name, test.expect, out) - } - } -} - -func testFailJSONPath(tests []jsonpathTest, t *testing.T) { - for _, test := range tests { - j := New(test.name) - err := j.Parse(test.template) - if err != nil { - t.Errorf("in %s, parse %s error %v", test.name, test.template, err) - } - buf := new(bytes.Buffer) - err = j.Execute(buf, test.input) - var out string - if err == nil { - out = "nil" - } else { - out = err.Error() - } - if out != test.expect { - t.Errorf("in %s, expect to get error %q, got %q", test.name, test.expect, out) - } - } -} - -type book struct { - Category string - Author string - Title string - Price float32 -} - -func (b book) String() string { - return fmt.Sprintf("{Category: %s, Author: %s, Title: %s, Price: %v}", b.Category, b.Author, b.Title, b.Price) -} - -type bicycle struct { - Color string - Price float32 -} - -type empName string -type job string -type store struct { - Book []book - Bicycle bicycle - Name string - Labels map[string]int - Employees map[empName]job -} - -func TestStructInput(t *testing.T) { - - storeData := store{ - Name: "jsonpath", - Book: []book{ - {"reference", "Nigel Rees", "Sayings of the Centurey", 8.95}, - {"fiction", "Evelyn Waugh", "Sword of Honour", 12.99}, - {"fiction", "Herman Melville", "Moby Dick", 8.99}, - }, - Bicycle: bicycle{"red", 19.95}, - Labels: map[string]int{ - "engieer": 10, - "web/html": 15, - "k8s-app": 20, - }, - Employees: map[empName]job{ - "jason": "manager", - "dan": "clerk", - }, - } - - storeTests := []jsonpathTest{ - {"plain", "hello jsonpath", nil, "hello jsonpath"}, - {"recursive", "{..}", []int{1, 2, 3}, "[1 2 3]"}, - {"filter", "{[?(@<5)]}", []int{2, 6, 3, 7}, "2 3"}, - {"quote", `{"{"}`, nil, "{"}, - {"union", "{[1,3,4]}", []int{0, 1, 2, 3, 4}, "1 3 4"}, - {"array", "{[0:2]}", []string{"Monday", "Tudesday"}, "Monday Tudesday"}, - {"variable", "hello {.Name}", storeData, "hello jsonpath"}, - {"dict/", "{$.Labels.web/html}", storeData, "15"}, - {"dict/", "{$.Employees.jason}", storeData, "manager"}, - {"dict/", "{$.Employees.dan}", storeData, "clerk"}, - {"dict-", "{.Labels.k8s-app}", storeData, "20"}, - {"nest", "{.Bicycle.Color}", storeData, "red"}, - {"allarray", "{.Book[*].Author}", storeData, "Nigel Rees Evelyn Waugh Herman Melville"}, - {"allfileds", "{.Bicycle.*}", storeData, "red 19.95"}, - {"recurfileds", "{..Price}", storeData, "8.95 12.99 8.99 19.95"}, - {"lastarray", "{.Book[-1:]}", storeData, - "{Category: fiction, Author: Herman Melville, Title: Moby Dick, Price: 8.99}"}, - {"recurarray", "{..Book[2]}", storeData, - "{Category: fiction, Author: Herman Melville, Title: Moby Dick, Price: 8.99}"}, - } - testJSONPath(storeTests, t) - - failStoreTests := []jsonpathTest{ - {"invalid identfier", "{hello}", storeData, "unrecognized identifier hello"}, - {"nonexistent field", "{.hello}", storeData, "hello is not found"}, - {"invalid array", "{.Labels[0]}", storeData, "map[string]int is not array or slice"}, - {"invalid filter operator", "{.Book[?(@.Price<>10)]}", storeData, "unrecognized filter operator <>"}, - {"redundent end", "{range .Labels.*}{@}{end}{end}", storeData, "not in range, nothing to end"}, - } - testFailJSONPath(failStoreTests, t) -} - -func TestJSONInput(t *testing.T) { - var pointsJSON = []byte(`[ - {"id": "i1", "x":4, "y":-5}, - {"id": "i2", "x":-2, "y":-5, "z":1}, - {"id": "i3", "x": 8, "y": 3 }, - {"id": "i4", "x": -6, "y": -1 }, - {"id": "i5", "x": 0, "y": 2, "z": 1 }, - {"id": "i6", "x": 1, "y": 4 } - ]`) - var pointsData interface{} - err := json.Unmarshal(pointsJSON, &pointsData) - if err != nil { - t.Error(err) - } - pointsTests := []jsonpathTest{ - {"exists filter", "{[?(@.z)].id}", pointsData, "i2 i5"}, - {"bracket key", "{[0]['id']}", pointsData, "i1"}, - } - testJSONPath(pointsTests, t) -} - -// TestKubernetes tests some use cases from kubernetes -func TestKubernetes(t *testing.T) { - var input = []byte(`{ - "kind": "List", - "items":[ - { - "kind":"None", - "metadata":{"name":"127.0.0.1"}, - "status":{ - "capacity":{"cpu":"4"}, - "addresses":[{"type": "LegacyHostIP", "address":"127.0.0.1"}] - } - }, - { - "kind":"None", - "metadata":{"name":"127.0.0.2"}, - "status":{ - "capacity":{"cpu":"8"}, - "addresses":[ - {"type": "LegacyHostIP", "address":"127.0.0.2"}, - {"type": "another", "address":"127.0.0.3"} - ] - } - } - ], - "users":[ - { - "name": "myself", - "user": {} - }, - { - "name": "e2e", - "user": {"username": "admin", "password": "secret"} - } - ] - }`) - var nodesData interface{} - err := json.Unmarshal(input, &nodesData) - if err != nil { - t.Error(err) - } - - nodesTests := []jsonpathTest{ - {"range item", `{range .items[*]}{.metadata.name}, {end}{.kind}`, nodesData, "127.0.0.1, 127.0.0.2, List"}, - {"range item with quote", `{range .items[*]}{.metadata.name}{"\t"}{end}`, nodesData, "127.0.0.1\t127.0.0.2\t"}, - {"range addresss", `{.items[*].status.addresses[*].address}`, nodesData, - "127.0.0.1 127.0.0.2 127.0.0.3"}, - {"double range", `{range .items[*]}{range .status.addresses[*]}{.address}, {end}{end}`, nodesData, - "127.0.0.1, 127.0.0.2, 127.0.0.3, "}, - {"item name", `{.items[*].metadata.name}`, nodesData, "127.0.0.1 127.0.0.2"}, - {"union nodes capacity", `{.items[*]['metadata.name', 'status.capacity']}`, nodesData, - "127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]"}, - {"range nodes capacity", `{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}`, nodesData, - "[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] "}, - {"user password", `{.users[?(@.name=="e2e")].user.password}`, &nodesData, "secret"}, - } - testJSONPath(nodesTests, t) - - randomPrintOrderTests := []jsonpathTest{ - {"recursive name", "{..name}", nodesData, `127.0.0.1 127.0.0.2 myself e2e`}, - } - testJSONPathSortOutput(randomPrintOrderTests, t) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/jsonpath/parser_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/jsonpath/parser_test.go deleted file mode 100644 index a061043b8..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/jsonpath/parser_test.go +++ /dev/null @@ -1,136 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 jsonpath - -import ( - "testing" -) - -type parserTest struct { - name string - text string - nodes []Node - shouldError bool -} - -var parserTests = []parserTest{ - {"plain", `hello jsonpath`, []Node{newText("hello jsonpath")}, false}, - {"variable", `hello {.jsonpath}`, - []Node{newText("hello "), newList(), newField("jsonpath")}, false}, - {"arrayfiled", `hello {['jsonpath']}`, - []Node{newText("hello "), newList(), newField("jsonpath")}, false}, - {"quote", `{"{"}`, []Node{newList(), newText("{")}, false}, - {"array", `{[1:3]}`, []Node{newList(), - newArray([3]ParamsEntry{{1, true}, {3, true}, {0, false}})}, false}, - {"allarray", `{.book[*].author}`, - []Node{newList(), newField("book"), - newArray([3]ParamsEntry{{0, false}, {0, false}, {0, false}}), newField("author")}, false}, - {"wildcard", `{.bicycle.*}`, - []Node{newList(), newField("bicycle"), newWildcard()}, false}, - {"filter", `{[?(@.price<3)]}`, - []Node{newList(), newFilter(newList(), newList(), "<"), - newList(), newField("price"), newList(), newInt(3)}, false}, - {"recursive", `{..}`, []Node{newList(), newRecursive()}, false}, - {"recurField", `{..price}`, - []Node{newList(), newRecursive(), newField("price")}, false}, - {"arraydict", `{['book.price']}`, []Node{newList(), - newField("book"), newField("price"), - }, false}, - {"union", `{['bicycle.price', 3, 'book.price']}`, []Node{newList(), newUnion([]*ListNode{}), - newList(), newField("bicycle"), newField("price"), - newList(), newArray([3]ParamsEntry{{3, true}, {4, true}, {0, false}}), - newList(), newField("book"), newField("price"), - }, false}, - {"range", `{range .items}{.name},{end}`, []Node{ - newList(), newIdentifier("range"), newField("items"), - newList(), newField("name"), newText(","), - newList(), newIdentifier("end"), - }, false}, - {"malformat input", `{\\\}`, []Node{}, true}, -} - -func collectNode(nodes []Node, cur Node) []Node { - nodes = append(nodes, cur) - switch cur.Type() { - case NodeList: - for _, node := range cur.(*ListNode).Nodes { - nodes = collectNode(nodes, node) - } - case NodeFilter: - nodes = collectNode(nodes, cur.(*FilterNode).Left) - nodes = collectNode(nodes, cur.(*FilterNode).Right) - case NodeUnion: - for _, node := range cur.(*UnionNode).Nodes { - nodes = collectNode(nodes, node) - } - } - return nodes -} - -func TestParser(t *testing.T) { - for _, test := range parserTests { - parser, err := Parse(test.name, test.text) - if test.shouldError { - if err == nil { - t.Errorf("unexpected non-error when parsing %s", test.name) - } - continue - } - if err != nil { - t.Errorf("parse %s error %v", test.name, err) - } - result := collectNode([]Node{}, parser.Root)[1:] - if len(result) != len(test.nodes) { - t.Errorf("in %s, expect to get %d nodes, got %d nodes", test.name, len(test.nodes), len(result)) - t.Error(result) - } - for i, expect := range test.nodes { - if result[i].String() != expect.String() { - t.Errorf("in %s, %dth node, expect %v, got %v", test.name, i, expect, result[i]) - } - } - } -} - -type failParserTest struct { - name string - text string - err string -} - -func TestFailParser(t *testing.T) { - failParserTests := []failParserTest{ - {"unclosed action", "{.hello", "unclosed action"}, - {"unrecognized character", "{*}", "unrecognized character in action: U+002A '*'"}, - {"invalid number", "{+12.3.0}", "cannot parse number +12.3.0"}, - {"unterminated array", "{[1}", "unterminated array"}, - {"invalid index", "{[::-1]}", "invalid array index ::-1"}, - {"unterminated filter", "{[?(.price]}", "unterminated filter"}, - } - for _, test := range failParserTests { - _, err := Parse(test.name, test.text) - var out string - if err == nil { - out = "nil" - } else { - out = err.Error() - } - if out != test.err { - t.Errorf("in %s, expect to get error %v, got %v", test.name, test.err, out) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/keymutex/keymutex.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/keymutex/keymutex.go deleted file mode 100644 index 2bcc95175..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/keymutex/keymutex.go +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 keymutex - -import ( - "fmt" - "github.com/golang/glog" - "sync" -) - -// KeyMutex is a thread-safe interface for acquiring locks on arbitrary strings. -type KeyMutex interface { - // Acquires a lock associated with the specified ID, creates the lock if one doesn't already exist. - LockKey(id string) - - // Releases the lock associated with the specified ID. - // Returns an error if the specified ID doesn't exist. - UnlockKey(id string) error -} - -// Returns a new instance of a key mutex. -func NewKeyMutex() KeyMutex { - return &keyMutex{ - mutexMap: make(map[string]*sync.Mutex), - } -} - -type keyMutex struct { - sync.RWMutex - mutexMap map[string]*sync.Mutex -} - -// Acquires a lock associated with the specified ID (creates the lock if one doesn't already exist). -func (km *keyMutex) LockKey(id string) { - glog.V(5).Infof("LockKey(...) called for id %q\r\n", id) - mutex := km.getOrCreateLock(id) - mutex.Lock() - glog.V(5).Infof("LockKey(...) for id %q completed.\r\n", id) -} - -// Releases the lock associated with the specified ID. -// Returns an error if the specified ID doesn't exist. -func (km *keyMutex) UnlockKey(id string) error { - glog.V(5).Infof("UnlockKey(...) called for id %q\r\n", id) - km.RLock() - defer km.RUnlock() - mutex, exists := km.mutexMap[id] - if !exists { - return fmt.Errorf("id %q not found", id) - } - glog.V(5).Infof("UnlockKey(...) for id. Mutex found, trying to unlock it. %q\r\n", id) - - mutex.Unlock() - glog.V(5).Infof("UnlockKey(...) for id %q completed.\r\n", id) - return nil -} - -// Returns lock associated with the specified ID, or creates the lock if one doesn't already exist. -func (km *keyMutex) getOrCreateLock(id string) *sync.Mutex { - km.Lock() - defer km.Unlock() - - if _, exists := km.mutexMap[id]; !exists { - km.mutexMap[id] = &sync.Mutex{} - } - - return km.mutexMap[id] -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/keymutex/keymutex_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/keymutex/keymutex_test.go deleted file mode 100644 index faa3be16a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/keymutex/keymutex_test.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 keymutex - -import ( - "testing" - "time" -) - -const ( - callbackTimeout = 1 * time.Second -) - -func Test_SingleLock_NoUnlock(t *testing.T) { - // Arrange - km := NewKeyMutex() - key := "fakeid" - callbackCh := make(chan interface{}) - - // Act - go lockAndCallback(km, key, callbackCh) - - // Assert - verifyCallbackHappens(t, callbackCh) -} - -func Test_SingleLock_SingleUnlock(t *testing.T) { - // Arrange - km := NewKeyMutex() - key := "fakeid" - callbackCh := make(chan interface{}) - - // Act & Assert - go lockAndCallback(km, key, callbackCh) - verifyCallbackHappens(t, callbackCh) - km.UnlockKey(key) -} - -func Test_DoubleLock_DoubleUnlock(t *testing.T) { - // Arrange - km := NewKeyMutex() - key := "fakeid" - callbackCh1stLock := make(chan interface{}) - callbackCh2ndLock := make(chan interface{}) - - // Act & Assert - go lockAndCallback(km, key, callbackCh1stLock) - verifyCallbackHappens(t, callbackCh1stLock) - go lockAndCallback(km, key, callbackCh2ndLock) - verifyCallbackDoesntHappens(t, callbackCh2ndLock) - km.UnlockKey(key) - verifyCallbackHappens(t, callbackCh2ndLock) - km.UnlockKey(key) -} - -func lockAndCallback(km KeyMutex, id string, callbackCh chan<- interface{}) { - km.LockKey(id) - callbackCh <- true -} - -func verifyCallbackHappens(t *testing.T, callbackCh <-chan interface{}) bool { - select { - case <-callbackCh: - return true - case <-time.After(callbackTimeout): - t.Fatalf("Timed out waiting for callback.") - return false - } -} - -func verifyCallbackDoesntHappens(t *testing.T, callbackCh <-chan interface{}) bool { - select { - case <-callbackCh: - t.Fatalf("Unexpected callback.") - return false - case <-time.After(callbackTimeout): - return true - } -} - -func verifyNoError(t *testing.T, err error, name string) { - if err != nil { - t.Fatalf("Unexpected response on %q. Expected: Actual: <%v>", name, err) - } -} - -func verifyError(t *testing.T, err error, name string) { - if err == nil { - t.Fatalf("Unexpected response on %q. Expected: Actual: ", name) - } -} - -func verifyMsg(t *testing.T, expected, actual string) { - if actual != expected { - t.Fatalf("Unexpected testMsg value. Expected: <%v> Actual: <%v>", expected, actual) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/labels/labels_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/labels/labels_test.go deleted file mode 100644 index 9adbd4554..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/labels/labels_test.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 labels - -import ( - "reflect" - "testing" -) - -func TestCloneAndAddLabel(t *testing.T) { - labels := map[string]string{ - "foo1": "bar1", - "foo2": "bar2", - "foo3": "bar3", - } - - cases := []struct { - labels map[string]string - labelKey string - labelValue uint32 - want map[string]string - }{ - { - labels: labels, - want: labels, - }, - { - labels: labels, - labelKey: "foo4", - labelValue: uint32(42), - want: map[string]string{ - "foo1": "bar1", - "foo2": "bar2", - "foo3": "bar3", - "foo4": "42", - }, - }, - } - - for _, tc := range cases { - got := CloneAndAddLabel(tc.labels, tc.labelKey, tc.labelValue) - if !reflect.DeepEqual(got, tc.want) { - t.Errorf("got %v, want %v", got, tc.want) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/limitwriter/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/limitwriter/doc.go deleted file mode 100644 index 7daff9c07..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/limitwriter/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 limitwriter provides a writer that only allows a certain number of bytes to be -// written. -package limitwriter diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/limitwriter/limitwriter.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/limitwriter/limitwriter.go deleted file mode 100644 index 88890a9fa..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/limitwriter/limitwriter.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 limitwriter - -import ( - "errors" - "io" -) - -// New creates a writer that is limited to writing at most n bytes to w. This writer is not -// thread safe. -func New(w io.Writer, n int64) io.Writer { - return &limitWriter{ - w: w, - n: n, - } -} - -// ErrMaximumWrite is returned when all bytes have been written. -var ErrMaximumWrite = errors.New("maximum write") - -type limitWriter struct { - w io.Writer - n int64 -} - -func (w *limitWriter) Write(p []byte) (n int, err error) { - if int64(len(p)) > w.n { - p = p[:w.n] - } - if len(p) > 0 { - n, err = w.w.Write(p) - w.n -= int64(n) - } - if w.n == 0 { - err = ErrMaximumWrite - } - return -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/line_delimiter_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/line_delimiter_test.go deleted file mode 100644 index 728d0abea..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/line_delimiter_test.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 util - -import ( - "fmt" - "os" -) - -func Example_trailingNewline() { - ld := NewLineDelimiter(os.Stdout, "|") - defer ld.Flush() - fmt.Fprint(ld, " Hello \n World \n") - // Output: - // | Hello | - // | World | - // || -} -func Example_noTrailingNewline() { - ld := NewLineDelimiter(os.Stdout, "|") - defer ld.Flush() - fmt.Fprint(ld, " Hello \n World ") - // Output: - // | Hello | - // | World | -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/metrics/util.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/metrics/util.go deleted file mode 100644 index ab74e35c4..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/metrics/util.go +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 metrics - -import ( - "fmt" - "sync" - "time" - - "k8s.io/kubernetes/pkg/util/flowcontrol" - "k8s.io/kubernetes/pkg/util/wait" - - "github.com/golang/glog" - "github.com/prometheus/client_golang/prometheus" -) - -const ( - updatePeriod = 5 * time.Second -) - -var ( - metricsLock sync.Mutex - rateLimiterMetrics map[string]prometheus.Gauge = make(map[string]prometheus.Gauge) -) - -func registerRateLimiterMetric(ownerName string) error { - metricsLock.Lock() - defer metricsLock.Unlock() - - if _, ok := rateLimiterMetrics[ownerName]; ok { - glog.Errorf("Metric for %v already registered", ownerName) - return fmt.Errorf("Metric for %v already registered", ownerName) - } - metric := prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "rate_limiter_use", - Subsystem: ownerName, - Help: fmt.Sprintf("A metric measuring the saturation of the rate limiter for %v", ownerName), - }) - rateLimiterMetrics[ownerName] = metric - prometheus.MustRegister(metric) - return nil -} - -// RegisterMetricAndTrackRateLimiterUsage registers a metric ownerName_rate_limiter_use in prometheus to track -// how much used rateLimiter is and starts a goroutine that updates this metric every updatePeriod -func RegisterMetricAndTrackRateLimiterUsage(ownerName string, rateLimiter flowcontrol.RateLimiter) error { - err := registerRateLimiterMetric(ownerName) - if err != nil { - return err - } - go wait.Forever(func() { - metricsLock.Lock() - defer metricsLock.Unlock() - rateLimiterMetrics[ownerName].Set(rateLimiter.Saturation()) - }, updatePeriod) - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/doc.go deleted file mode 100644 index 839c0a69a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 mount defines an interface to mounting filesystems. -package mount diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/fake.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/fake.go deleted file mode 100644 index 115293813..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/fake.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 mount - -import ( - "sync" - - "github.com/golang/glog" -) - -// FakeMounter implements mount.Interface for tests. -type FakeMounter struct { - MountPoints []MountPoint - Log []FakeAction - // Some tests run things in parallel, make sure the mounter does not produce - // any golang's DATA RACE warnings. - mutex sync.Mutex -} - -var _ Interface = &FakeMounter{} - -// Values for FakeAction.Action -const FakeActionMount = "mount" -const FakeActionUnmount = "unmount" - -// FakeAction objects are logged every time a fake mount or unmount is called. -type FakeAction struct { - Action string // "mount" or "unmount" - Target string // applies to both mount and unmount actions - Source string // applies only to "mount" actions - FSType string // applies only to "mount" actions -} - -func (f *FakeMounter) ResetLog() { - f.mutex.Lock() - defer f.mutex.Unlock() - - f.Log = []FakeAction{} -} - -func (f *FakeMounter) Mount(source string, target string, fstype string, options []string) error { - f.mutex.Lock() - defer f.mutex.Unlock() - - // find 'bind' option - for _, option := range options { - if option == "bind" { - // This is a bind-mount. In order to mimic linux behaviour, we must - // use the original device of the bind-mount as the real source. - // E.g. when mounted /dev/sda like this: - // $ mount /dev/sda /mnt/test - // $ mount -o bind /mnt/test /mnt/bound - // then /proc/mount contains: - // /dev/sda /mnt/test - // /dev/sda /mnt/bound - // (and not /mnt/test /mnt/bound) - // I.e. we must use /dev/sda as source instead of /mnt/test in the - // bind mount. - for _, mnt := range f.MountPoints { - if source == mnt.Path { - source = mnt.Device - break - } - } - break - } - } - - f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: target, Type: fstype}) - glog.V(5).Infof("Fake mounter: mouted %s to %s", source, target) - f.Log = append(f.Log, FakeAction{Action: FakeActionMount, Target: target, Source: source, FSType: fstype}) - return nil -} - -func (f *FakeMounter) Unmount(target string) error { - f.mutex.Lock() - defer f.mutex.Unlock() - - newMountpoints := []MountPoint{} - for _, mp := range f.MountPoints { - if mp.Path == target { - glog.V(5).Infof("Fake mounter: unmouted %s from %s", mp.Device, target) - // Don't copy it to newMountpoints - continue - } - newMountpoints = append(newMountpoints, MountPoint{Device: mp.Device, Path: mp.Path, Type: mp.Type}) - } - f.MountPoints = newMountpoints - f.Log = append(f.Log, FakeAction{Action: FakeActionUnmount, Target: target}) - return nil -} - -func (f *FakeMounter) List() ([]MountPoint, error) { - f.mutex.Lock() - defer f.mutex.Unlock() - - return f.MountPoints, nil -} - -func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) { - f.mutex.Lock() - defer f.mutex.Unlock() - - for _, mp := range f.MountPoints { - if mp.Path == file { - glog.V(5).Infof("isLikelyMountPoint for %s: monted %s, false", file, mp.Path) - return false, nil - } - } - glog.V(5).Infof("isLikelyMountPoint for %s: true", file) - return true, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount.go deleted file mode 100644 index 9c1d8d4f2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount.go +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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. -*/ - -// TODO(thockin): This whole pkg is pretty linux-centric. As soon as we have -// an alternate platform, we will need to abstract further. -package mount - -import ( - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/util/exec" - "path/filepath" -) - -type Interface interface { - // Mount mounts source to target as fstype with given options. - Mount(source string, target string, fstype string, options []string) error - // Unmount unmounts given target. - Unmount(target string) error - // List returns a list of all mounted filesystems. This can be large. - // On some platforms, reading mounts is not guaranteed consistent (i.e. - // it could change between chunked reads). This is guaranteed to be - // consistent. - List() ([]MountPoint, error) - // IsLikelyNotMountPoint determines if a directory is a mountpoint. - // It should return ErrNotExist when the directory does not exist. - IsLikelyNotMountPoint(file string) (bool, error) -} - -// This represents a single line in /proc/mounts or /etc/fstab. -type MountPoint struct { - Device string - Path string - Type string - Opts []string - Freq int - Pass int -} - -// SafeFormatAndMount probes a device to see if it is formatted. -// Namely it checks to see if a file system is present. If so it -// mounts it otherwise the device is formatted first then mounted. -type SafeFormatAndMount struct { - Interface - Runner exec.Interface -} - -// FormatAndMount formats the given disk, if needed, and mounts it. -// That is if the disk is not formatted and it is not being mounted as -// read-only it will format it first then mount it. Otherwise, if the -// disk is already formatted or it is being mounted as read-only, it -// will be mounted without formatting. -func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, fstype string, options []string) error { - // Don't attempt to format if mounting as readonly. Go straight to mounting. - for _, option := range options { - if option == "ro" { - return mounter.Interface.Mount(source, target, fstype, options) - } - } - return mounter.formatAndMount(source, target, fstype, options) -} - -// New returns a mount.Interface for the current system. -func New() Interface { - return &Mounter{} -} - -// GetMountRefs finds all other references to the device referenced -// by mountPath; returns a list of paths. -func GetMountRefs(mounter Interface, mountPath string) ([]string, error) { - mps, err := mounter.List() - if err != nil { - return nil, err - } - - // Find the device name. - deviceName := "" - // If mountPath is symlink, need get its target path. - slTarget, err := filepath.EvalSymlinks(mountPath) - if err != nil { - slTarget = mountPath - } - for i := range mps { - if mps[i].Path == slTarget { - deviceName = mps[i].Device - break - } - } - - // Find all references to the device. - var refs []string - if deviceName == "" { - glog.Warningf("could not determine device for path: %q", mountPath) - } else { - for i := range mps { - if mps[i].Device == deviceName && mps[i].Path != slTarget { - refs = append(refs, mps[i].Path) - } - } - } - return refs, nil -} - -// GetDeviceNameFromMount: given a mnt point, find the device from /proc/mounts -// returns the device name, reference count, and error code -func GetDeviceNameFromMount(mounter Interface, mountPath string) (string, int, error) { - mps, err := mounter.List() - if err != nil { - return "", 0, err - } - - // Find the device name. - // FIXME if multiple devices mounted on the same mount path, only the first one is returned - device := "" - // If mountPath is symlink, need get its target path. - slTarget, err := filepath.EvalSymlinks(mountPath) - if err != nil { - slTarget = mountPath - } - for i := range mps { - if mps[i].Path == slTarget { - device = mps[i].Device - break - } - } - - // Find all references to the device. - refCount := 0 - for i := range mps { - if mps[i].Device == device { - refCount++ - } - } - return device, refCount, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_linux.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_linux.go deleted file mode 100644 index 66959697c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_linux.go +++ /dev/null @@ -1,311 +0,0 @@ -// +build linux - -/* -Copyright 2014 The Kubernetes Authors 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 mount - -import ( - "bufio" - "fmt" - "hash/adler32" - "io" - "os" - "os/exec" - "strconv" - "strings" - "syscall" - - "github.com/golang/glog" - utilExec "k8s.io/kubernetes/pkg/util/exec" -) - -const ( - // How many times to retry for a consistent read of /proc/mounts. - maxListTries = 3 - // Number of fields per line in /proc/mounts as per the fstab man page. - expectedNumFieldsPerLine = 6 - // Location of the mount file to use - procMountsPath = "/proc/mounts" -) - -const ( - // 'fsck' found errors and corrected them - fsckErrorsCorrected = 1 - // 'fsck' found errors but exited without correcting them - fsckErrorsUncorrected = 4 -) - -// Mounter provides the default implementation of mount.Interface -// for the linux platform. This implementation assumes that the -// kubelet is running in the host's root mount namespace. -type Mounter struct{} - -var _ = Interface(&Mounter{}) - -// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must -// be an emtpy string in case it's not required, e.g. for remount, or for auto filesystem -// type, where kernel handles fs type for you. The mount 'options' is a list of options, -// currently come from mount(8), e.g. "ro", "remount", "bind", etc. If no more option is -// required, call Mount with an empty string list or nil. -func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error { - bind, bindRemountOpts := isBind(options) - - if bind { - err := doMount(source, target, fstype, []string{"bind"}) - if err != nil { - return err - } - return doMount(source, target, fstype, bindRemountOpts) - } else { - return doMount(source, target, fstype, options) - } -} - -// isBind detects whether a bind mount is being requested and makes the remount options to -// use in case of bind mount, due to the fact that bind mount doesn't respect mount options. -// The list equals: -// options - 'bind' + 'remount' (no duplicate) -func isBind(options []string) (bool, []string) { - bindRemountOpts := []string{"remount"} - bind := false - - if len(options) != 0 { - for _, option := range options { - switch option { - case "bind": - bind = true - break - case "remount": - break - default: - bindRemountOpts = append(bindRemountOpts, option) - } - } - } - - return bind, bindRemountOpts -} - -// doMount runs the mount command. -func doMount(source string, target string, fstype string, options []string) error { - glog.V(5).Infof("Mounting %s %s %s %v", source, target, fstype, options) - mountArgs := makeMountArgs(source, target, fstype, options) - command := exec.Command("mount", mountArgs...) - output, err := command.CombinedOutput() - if err != nil { - return fmt.Errorf("Mount failed: %v\nMounting arguments: %s %s %s %v\nOutput: %s\n", - err, source, target, fstype, options, string(output)) - } - return err -} - -// makeMountArgs makes the arguments to the mount(8) command. -func makeMountArgs(source, target, fstype string, options []string) []string { - // Build mount command as follows: - // mount [-t $fstype] [-o $options] [$source] $target - mountArgs := []string{} - if len(fstype) > 0 { - mountArgs = append(mountArgs, "-t", fstype) - } - if len(options) > 0 { - mountArgs = append(mountArgs, "-o", strings.Join(options, ",")) - } - if len(source) > 0 { - mountArgs = append(mountArgs, source) - } - mountArgs = append(mountArgs, target) - - return mountArgs -} - -// Unmount unmounts the target. -func (mounter *Mounter) Unmount(target string) error { - glog.V(5).Infof("Unmounting %s", target) - command := exec.Command("umount", target) - output, err := command.CombinedOutput() - if err != nil { - return fmt.Errorf("Unmount failed: %v\nUnmounting arguments: %s\nOutput: %s\n", err, target, string(output)) - } - return nil -} - -// List returns a list of all mounted filesystems. -func (*Mounter) List() ([]MountPoint, error) { - return listProcMounts(procMountsPath) -} - -// IsLikelyNotMountPoint determines if a directory is not a mountpoint. -// It is fast but not necessarily ALWAYS correct. If the path is in fact -// a bind mount from one part of a mount to another it will not be detected. -// mkdir /tmp/a /tmp/b; mount --bin /tmp/a /tmp/b; IsLikelyNotMountPoint("/tmp/b") -// will return true. When in fact /tmp/b is a mount point. If this situation -// if of interest to you, don't use this function... -func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { - stat, err := os.Stat(file) - if err != nil { - return true, err - } - rootStat, err := os.Lstat(file + "/..") - if err != nil { - return true, err - } - // If the directory has a different device as parent, then it is a mountpoint. - if stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev { - return false, nil - } - - return true, nil -} - -func listProcMounts(mountFilePath string) ([]MountPoint, error) { - hash1, err := readProcMounts(mountFilePath, nil) - if err != nil { - return nil, err - } - - for i := 0; i < maxListTries; i++ { - mps := []MountPoint{} - hash2, err := readProcMounts(mountFilePath, &mps) - if err != nil { - return nil, err - } - if hash1 == hash2 { - // Success - return mps, nil - } - hash1 = hash2 - } - return nil, fmt.Errorf("failed to get a consistent snapshot of %v after %d tries", mountFilePath, maxListTries) -} - -// readProcMounts reads the given mountFilePath (normally /proc/mounts) and produces a hash -// of the contents. If the out argument is not nil, this fills it with MountPoint structs. -func readProcMounts(mountFilePath string, out *[]MountPoint) (uint32, error) { - file, err := os.Open(mountFilePath) - if err != nil { - return 0, err - } - defer file.Close() - return readProcMountsFrom(file, out) -} - -func readProcMountsFrom(file io.Reader, out *[]MountPoint) (uint32, error) { - hash := adler32.New() - scanner := bufio.NewReader(file) - for { - line, err := scanner.ReadString('\n') - if err == io.EOF { - break - } - fields := strings.Fields(line) - if len(fields) != expectedNumFieldsPerLine { - return 0, fmt.Errorf("wrong number of fields (expected %d, got %d): %s", expectedNumFieldsPerLine, len(fields), line) - } - - fmt.Fprintf(hash, "%s", line) - - if out != nil { - mp := MountPoint{ - Device: fields[0], - Path: fields[1], - Type: fields[2], - Opts: strings.Split(fields[3], ","), - } - - freq, err := strconv.Atoi(fields[4]) - if err != nil { - return 0, err - } - mp.Freq = freq - - pass, err := strconv.Atoi(fields[5]) - if err != nil { - return 0, err - } - mp.Pass = pass - - *out = append(*out, mp) - } - } - return hash.Sum32(), nil -} - -// formatAndMount uses unix utils to format and mount the given disk -func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error { - options = append(options, "defaults") - - // Run fsck on the disk to fix repairable issues - args := []string{"-a", source} - cmd := mounter.Runner.Command("fsck", args...) - out, err := cmd.CombinedOutput() - if err != nil { - ee, isExitError := err.(utilExec.ExitError) - switch { - case err == utilExec.ErrExecutableNotFound: - glog.Warningf("'fsck' not found on system; continuing mount without running 'fsck'.") - case isExitError && ee.ExitStatus() == fsckErrorsCorrected: - glog.Infof("Device %s has errors which were corrected by fsck.", source) - case isExitError && ee.ExitStatus() == fsckErrorsUncorrected: - return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s.", source, string(out)) - case isExitError && ee.ExitStatus() > fsckErrorsUncorrected: - glog.Infof("`fsck` error %s", string(out)) - } - } - - // Try to mount the disk - err = mounter.Interface.Mount(source, target, fstype, options) - if err != nil { - // It is possible that this disk is not formatted. Double check using diskLooksUnformatted - notFormatted, err := mounter.diskLooksUnformatted(source) - if err == nil && notFormatted { - args = []string{source} - // Disk is unformatted so format it. - // Use 'ext4' as the default - if len(fstype) == 0 { - fstype = "ext4" - } - if fstype == "ext4" || fstype == "ext3" { - args = []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", source} - } - cmd := mounter.Runner.Command("mkfs."+fstype, args...) - _, err := cmd.CombinedOutput() - if err == nil { - // the disk has been formatted successfully try to mount it again. - return mounter.Interface.Mount(source, target, fstype, options) - } - return err - } - } - return err -} - -// diskLooksUnformatted uses 'lsblk' to see if the given disk is unformated -func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) { - args := []string{"-nd", "-o", "FSTYPE", disk} - cmd := mounter.Runner.Command("lsblk", args...) - dataOut, err := cmd.CombinedOutput() - output := strings.TrimSpace(string(dataOut)) - - // TODO (#13212): check if this disk has partitions and return false, and - // an error if so. - - if err != nil { - return false, err - } - - return output == "", nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go deleted file mode 100644 index cd802d774..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go +++ /dev/null @@ -1,182 +0,0 @@ -// +build linux - -/* -Copyright 2014 The Kubernetes Authors 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 mount - -import ( - "strings" - "testing" -) - -func TestReadProcMountsFrom(t *testing.T) { - successCase := - `/dev/0 /path/to/0 type0 flags 0 0 - /dev/1 /path/to/1 type1 flags 1 1 - /dev/2 /path/to/2 type2 flags,1,2=3 2 2 - ` - hash, err := readProcMountsFrom(strings.NewReader(successCase), nil) - if err != nil { - t.Errorf("expected success") - } - if hash != 0xa3522051 { - t.Errorf("expected 0xa3522051, got %#x", hash) - } - mounts := []MountPoint{} - hash, err = readProcMountsFrom(strings.NewReader(successCase), &mounts) - if err != nil { - t.Errorf("expected success") - } - if hash != 0xa3522051 { - t.Errorf("expected 0xa3522051, got %#x", hash) - } - if len(mounts) != 3 { - t.Fatalf("expected 3 mounts, got %d", len(mounts)) - } - mp := MountPoint{"/dev/0", "/path/to/0", "type0", []string{"flags"}, 0, 0} - if !mountPointsEqual(&mounts[0], &mp) { - t.Errorf("got unexpected MountPoint[0]: %#v", mounts[0]) - } - mp = MountPoint{"/dev/1", "/path/to/1", "type1", []string{"flags"}, 1, 1} - if !mountPointsEqual(&mounts[1], &mp) { - t.Errorf("got unexpected MountPoint[1]: %#v", mounts[1]) - } - mp = MountPoint{"/dev/2", "/path/to/2", "type2", []string{"flags", "1", "2=3"}, 2, 2} - if !mountPointsEqual(&mounts[2], &mp) { - t.Errorf("got unexpected MountPoint[2]: %#v", mounts[2]) - } - - errorCases := []string{ - "/dev/0 /path/to/mount\n", - "/dev/1 /path/to/mount type flags a 0\n", - "/dev/2 /path/to/mount type flags 0 b\n", - } - for _, ec := range errorCases { - _, err := readProcMountsFrom(strings.NewReader(ec), &mounts) - if err == nil { - t.Errorf("expected error") - } - } -} - -func mountPointsEqual(a, b *MountPoint) bool { - if a.Device != b.Device || a.Path != b.Path || a.Type != b.Type || !slicesEqual(a.Opts, b.Opts) || a.Pass != b.Pass || a.Freq != b.Freq { - return false - } - return true -} - -func slicesEqual(a, b []string) bool { - if len(a) != len(b) { - return false - } - for i := range a { - if a[i] != b[i] { - return false - } - } - return true -} - -func TestGetMountRefs(t *testing.T) { - fm := &FakeMounter{ - MountPoints: []MountPoint{ - {Device: "/dev/sdb", Path: "/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd"}, - {Device: "/dev/sdb", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd-in-pod"}, - {Device: "/dev/sdc", Path: "/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd2"}, - {Device: "/dev/sdc", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod"}, - {Device: "/dev/sdc", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod2"}, - }, - } - - tests := []struct { - mountPath string - expectedRefs []string - }{ - { - "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd-in-pod", - []string{ - "/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd", - }, - }, - { - "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod", - []string{ - "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod2", - "/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd2", - }, - }, - } - - for i, test := range tests { - if refs, err := GetMountRefs(fm, test.mountPath); err != nil || !setEquivalent(test.expectedRefs, refs) { - t.Errorf("%d. getMountRefs(%q) = %v, %v; expected %v, nil", i, test.mountPath, refs, err, test.expectedRefs) - } - } -} - -func setEquivalent(set1, set2 []string) bool { - map1 := make(map[string]bool) - map2 := make(map[string]bool) - for _, s := range set1 { - map1[s] = true - } - for _, s := range set2 { - map2[s] = true - } - - for s := range map1 { - if !map2[s] { - return false - } - } - for s := range map2 { - if !map1[s] { - return false - } - } - return true -} - -func TestGetDeviceNameFromMount(t *testing.T) { - fm := &FakeMounter{ - MountPoints: []MountPoint{ - {Device: "/dev/disk/by-path/prefix-lun-1", - Path: "/mnt/111"}, - {Device: "/dev/disk/by-path/prefix-lun-1", - Path: "/mnt/222"}, - }, - } - - tests := []struct { - mountPath string - expectedDevice string - expectedRefs int - }{ - { - "/mnt/222", - "/dev/disk/by-path/prefix-lun-1", - 2, - }, - } - - for i, test := range tests { - if device, refs, err := GetDeviceNameFromMount(fm, test.mountPath); err != nil || test.expectedRefs != refs || test.expectedDevice != device { - t.Errorf("%d. GetDeviceNameFromMount(%s) = (%s, %d), %v; expected (%s,%d), nil", i, test.mountPath, device, refs, err, test.expectedDevice, test.expectedRefs) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go deleted file mode 100644 index 8942c0036..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/mount_unsupported.go +++ /dev/null @@ -1,45 +0,0 @@ -// +build !linux - -/* -Copyright 2014 The Kubernetes Authors 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 mount - -type Mounter struct{} - -func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error { - return nil -} - -func (mounter *Mounter) Unmount(target string) error { - return nil -} - -func (mounter *Mounter) List() ([]MountPoint, error) { - return []MountPoint{}, nil -} - -func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) { - return true, nil -} - -func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error { - return nil -} - -func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) { - return true, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go deleted file mode 100644 index 9be0e551d..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go +++ /dev/null @@ -1,207 +0,0 @@ -// +build linux - -/* -Copyright 2014 The Kubernetes Authors 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 mount - -import ( - "os" - "path/filepath" - "strings" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/util/exec" -) - -// NsenterMounter is part of experimental support for running the kubelet -// in a container. Currently, all docker containers receive their own mount -// namespaces. NsenterMounter works by executing nsenter to run commands in -// the host's mount namespace. -// -// NsenterMounter requires: -// -// 1. Docker >= 1.6 due to the dependency on the slave propagation mode -// of the bind-mount of the kubelet root directory in the container. -// Docker 1.5 used a private propagation mode for bind-mounts, so mounts -// performed in the host's mount namespace do not propagate out to the -// bind-mount in this docker version. -// 2. The host's root filesystem must be available at /rootfs -// 3. The nsenter binary must be on the Kubelet process' PATH in the container's -// filesystem. -// 4. The Kubelet process must have CAP_SYS_ADMIN (required by nsenter); at -// the present, this effectively means that the kubelet is running in a -// privileged container. -// 5. The volume path used by the Kubelet must be the same inside and outside -// the container and be writable by the container (to initialize volume) -// contents. TODO: remove this requirement. -// 6. The host image must have mount, findmnt, and umount binaries in /bin, -// /usr/sbin, or /usr/bin -// -// For more information about mount propagation modes, see: -// https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt -type NsenterMounter struct { - // a map of commands to their paths on the host filesystem - paths map[string]string -} - -func NewNsenterMounter() *NsenterMounter { - m := &NsenterMounter{ - paths: map[string]string{ - "mount": "", - "findmnt": "", - "umount": "", - }, - } - // search for the mount command in other locations besides /usr/bin - for binary := range m.paths { - // default to root - m.paths[binary] = filepath.Join("/", binary) - for _, path := range []string{"/bin", "/usr/sbin", "/usr/bin"} { - binPath := filepath.Join(path, binary) - if _, err := os.Stat(filepath.Join(hostRootFsPath, binPath)); err != nil { - continue - } - m.paths[binary] = binPath - break - } - // TODO: error, so that the kubelet can stop if the mounts don't exist - } - return m -} - -// NsenterMounter implements mount.Interface -var _ = Interface(&NsenterMounter{}) - -const ( - hostRootFsPath = "/rootfs" - hostProcMountsPath = "/rootfs/proc/mounts" - nsenterPath = "nsenter" -) - -// Mount runs mount(8) in the host's root mount namespace. Aside from this -// aspect, Mount has the same semantics as the mounter returned by mount.New() -func (n *NsenterMounter) Mount(source string, target string, fstype string, options []string) error { - bind, bindRemountOpts := isBind(options) - - if bind { - err := n.doNsenterMount(source, target, fstype, []string{"bind"}) - if err != nil { - return err - } - return n.doNsenterMount(source, target, fstype, bindRemountOpts) - } - - return n.doNsenterMount(source, target, fstype, options) -} - -// doNsenterMount nsenters the host's mount namespace and performs the -// requested mount. -func (n *NsenterMounter) doNsenterMount(source, target, fstype string, options []string) error { - glog.V(5).Infof("nsenter Mounting %s %s %s %v", source, target, fstype, options) - args := n.makeNsenterArgs(source, target, fstype, options) - - glog.V(5).Infof("Mount command: %v %v", nsenterPath, args) - exec := exec.New() - outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput() - if len(outputBytes) != 0 { - glog.V(5).Infof("Output of mounting %s to %s: %v", source, target, string(outputBytes)) - } - - return err -} - -// makeNsenterArgs makes a list of argument to nsenter in order to do the -// requested mount. -func (n *NsenterMounter) makeNsenterArgs(source, target, fstype string, options []string) []string { - nsenterArgs := []string{ - "--mount=/rootfs/proc/1/ns/mnt", - "--", - n.absHostPath("mount"), - } - - args := makeMountArgs(source, target, fstype, options) - - return append(nsenterArgs, args...) -} - -// Unmount runs umount(8) in the host's mount namespace. -func (n *NsenterMounter) Unmount(target string) error { - args := []string{ - "--mount=/rootfs/proc/1/ns/mnt", - "--", - n.absHostPath("umount"), - target, - } - - glog.V(5).Infof("Unmount command: %v %v", nsenterPath, args) - exec := exec.New() - outputBytes, err := exec.Command(nsenterPath, args...).CombinedOutput() - if len(outputBytes) != 0 { - glog.V(5).Infof("Output of unmounting %s: %v", target, string(outputBytes)) - } - - return err -} - -// List returns a list of all mounted filesystems in the host's mount namespace. -func (*NsenterMounter) List() ([]MountPoint, error) { - return listProcMounts(hostProcMountsPath) -} - -// IsLikelyNotMountPoint determines whether a path is a mountpoint by calling findmnt -// in the host's root mount namespace. -func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { - file, err := filepath.Abs(file) - if err != nil { - return true, err - } - - // Check the directory exists - if _, err = os.Stat(file); os.IsNotExist(err) { - glog.V(5).Infof("findmnt: directory %s does not exist", file) - return true, err - } - - args := []string{"--mount=/rootfs/proc/1/ns/mnt", "--", n.absHostPath("findmnt"), "-o", "target", "--noheadings", "--target", file} - glog.V(5).Infof("findmnt command: %v %v", nsenterPath, args) - - exec := exec.New() - out, err := exec.Command(nsenterPath, args...).CombinedOutput() - if err != nil { - glog.V(2).Infof("Failed findmnt command for path %s: %v", file, err) - // Different operating systems behave differently for paths which are not mount points. - // On older versions (e.g. 2.20.1) we'd get error, on newer ones (e.g. 2.26.2) we'd get "/". - // It's safer to assume that it's not a mount point. - return true, nil - } - strOut := strings.TrimSuffix(string(out), "\n") - - glog.V(5).Infof("IsLikelyNotMountPoint findmnt output for path %s: %v", file, strOut) - if strOut == file { - return false, nil - } - - return true, nil -} - -func (n *NsenterMounter) absHostPath(command string) string { - path, ok := n.paths[command] - if !ok { - return command - } - return path -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go deleted file mode 100644 index 210fab851..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_unsupported.go +++ /dev/null @@ -1,43 +0,0 @@ -// +build !linux - -/* -Copyright 2014 The Kubernetes Authors 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 mount - -type NsenterMounter struct{} - -func NewNsenterMounter() *NsenterMounter { - return &NsenterMounter{} -} - -var _ = Interface(&NsenterMounter{}) - -func (*NsenterMounter) Mount(source string, target string, fstype string, options []string) error { - return nil -} - -func (*NsenterMounter) Unmount(target string) error { - return nil -} - -func (*NsenterMounter) List() ([]MountPoint, error) { - return []MountPoint{}, nil -} - -func (*NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) { - return true, nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go deleted file mode 100644 index 03c0b8442..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go +++ /dev/null @@ -1,224 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 mount - -import ( - "fmt" - "runtime" - "testing" - - "k8s.io/kubernetes/pkg/util/exec" -) - -type ErrorMounter struct { - *FakeMounter - errIndex int - err []error -} - -func (mounter *ErrorMounter) Mount(source string, target string, fstype string, options []string) error { - i := mounter.errIndex - mounter.errIndex++ - if mounter.err != nil && mounter.err[i] != nil { - return mounter.err[i] - } - return mounter.FakeMounter.Mount(source, target, fstype, options) -} - -type ExecArgs struct { - command string - args []string - output string - err error -} - -func TestSafeFormatAndMount(t *testing.T) { - if runtime.GOOS == "darwin" || runtime.GOOS == "windows" { - t.Skipf("not supported on GOOS=%s", runtime.GOOS) - } - tests := []struct { - description string - fstype string - mountOptions []string - execScripts []ExecArgs - mountErrs []error - expectedError error - }{ - { - description: "Test a read only mount", - fstype: "ext4", - mountOptions: []string{"ro"}, - }, - { - description: "Test a normal mount", - fstype: "ext4", - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", nil}, - }, - }, - { - description: "Test 'fsck' fails with exit status 4", - fstype: "ext4", - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", &exec.FakeExitError{Status: 4}}, - }, - expectedError: fmt.Errorf("'fsck' found errors on device /dev/foo but could not correct them: ."), - }, - { - description: "Test 'fsck' fails with exit status 1 (errors found and corrected)", - fstype: "ext4", - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", &exec.FakeExitError{Status: 1}}, - }, - }, - { - description: "Test 'fsck' fails with exit status other than 1 and 4 (likely unformatted device)", - fstype: "ext4", - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", &exec.FakeExitError{Status: 8}}, - }, - }, - { - description: "Test that 'lsblk' is called and fails", - fstype: "ext4", - mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")}, - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", nil}, - {"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "ext4", nil}, - }, - expectedError: fmt.Errorf("unknown filesystem type '(null)'"), - }, - { - description: "Test that 'lsblk' is called and confirms unformatted disk, format fails", - fstype: "ext4", - mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")}, - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", nil}, - {"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil}, - {"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")}, - }, - expectedError: fmt.Errorf("formatting failed"), - }, - { - description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount fails", - fstype: "ext4", - mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")}, - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", nil}, - {"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil}, - {"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil}, - }, - expectedError: fmt.Errorf("Still cannot mount"), - }, - { - description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes", - fstype: "ext4", - mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil}, - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", nil}, - {"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil}, - {"mkfs.ext4", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil}, - }, - expectedError: nil, - }, - { - description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes with ext3", - fstype: "ext3", - mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil}, - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", nil}, - {"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil}, - {"mkfs.ext3", []string{"-E", "lazy_itable_init=0,lazy_journal_init=0", "-F", "/dev/foo"}, "", nil}, - }, - expectedError: nil, - }, - { - description: "test that none ext4 fs does not get called with ext4 options.", - fstype: "xfs", - mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil}, - execScripts: []ExecArgs{ - {"fsck", []string{"-a", "/dev/foo"}, "", nil}, - {"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil}, - {"mkfs.xfs", []string{"/dev/foo"}, "", nil}, - }, - expectedError: nil, - }, - } - - for _, test := range tests { - commandScripts := []exec.FakeCommandAction{} - for _, expected := range test.execScripts { - ecmd := expected.command - eargs := expected.args - output := expected.output - err := expected.err - commandScript := func(cmd string, args ...string) exec.Cmd { - if cmd != ecmd { - t.Errorf("Unexpected command %s. Expecting %s", cmd, ecmd) - } - - for j := range args { - if args[j] != eargs[j] { - t.Errorf("Unexpected args %v. Expecting %v", args, eargs) - } - } - fake := exec.FakeCmd{ - CombinedOutputScript: []exec.FakeCombinedOutputAction{ - func() ([]byte, error) { return []byte(output), err }, - }, - } - return exec.InitFakeCmd(&fake, cmd, args...) - } - commandScripts = append(commandScripts, commandScript) - } - - fake := exec.FakeExec{ - CommandScript: commandScripts, - } - - fakeMounter := ErrorMounter{&FakeMounter{}, 0, test.mountErrs} - mounter := SafeFormatAndMount{ - Interface: &fakeMounter, - Runner: &fake, - } - - device := "/dev/foo" - dest := "/mnt/bar" - err := mounter.FormatAndMount(device, dest, test.fstype, test.mountOptions) - if test.expectedError == nil { - if err != nil { - t.Errorf("test \"%s\" unexpected non-error: %v", test.description, err) - } - - // Check that something was mounted on the directory - isNotMountPoint, err := fakeMounter.IsLikelyNotMountPoint(dest) - if err != nil || isNotMountPoint { - t.Errorf("test \"%s\" the directory was not mounted", test.description) - } - - //check that the correct device was mounted - mountedDevice, _, err := GetDeviceNameFromMount(fakeMounter.FakeMounter, dest) - if err != nil || mountedDevice != device { - t.Errorf("test \"%s\" the correct device was not mounted", test.description) - } - } else { - if err == nil || test.expectedError.Error() != err.Error() { - t.Errorf("test \"%s\" unexpected error: \n [%v]. \nExpecting [%v]", test.description, err, test.expectedError) - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/http_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/http_test.go deleted file mode 100644 index 1de67cade..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/http_test.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 net - -import ( - "net" - "net/http" - "net/url" - "os" - "reflect" - "testing" -) - -func TestGetClientIP(t *testing.T) { - ipString := "10.0.0.1" - ip := net.ParseIP(ipString) - invalidIPString := "invalidIPString" - testCases := []struct { - Request http.Request - ExpectedIP net.IP - }{ - { - Request: http.Request{}, - }, - { - Request: http.Request{ - Header: map[string][]string{ - "X-Real-Ip": {ipString}, - }, - }, - ExpectedIP: ip, - }, - { - Request: http.Request{ - Header: map[string][]string{ - "X-Real-Ip": {invalidIPString}, - }, - }, - }, - { - Request: http.Request{ - Header: map[string][]string{ - "X-Forwarded-For": {ipString}, - }, - }, - ExpectedIP: ip, - }, - { - Request: http.Request{ - Header: map[string][]string{ - "X-Forwarded-For": {invalidIPString}, - }, - }, - }, - { - Request: http.Request{ - Header: map[string][]string{ - "X-Forwarded-For": {invalidIPString + "," + ipString}, - }, - }, - ExpectedIP: ip, - }, - { - Request: http.Request{ - RemoteAddr: ipString, - }, - ExpectedIP: ip, - }, - { - Request: http.Request{ - RemoteAddr: invalidIPString, - }, - }, - { - Request: http.Request{ - Header: map[string][]string{ - "X-Forwarded-For": {invalidIPString}, - }, - RemoteAddr: ipString, - }, - ExpectedIP: ip, - }, - } - - for i, test := range testCases { - if a, e := GetClientIP(&test.Request), test.ExpectedIP; reflect.DeepEqual(e, a) != true { - t.Fatalf("test case %d failed. expected: %v, actual: %v", i+1, e, a) - } - } -} - -func TestProxierWithNoProxyCIDR(t *testing.T) { - testCases := []struct { - name string - noProxy string - url string - - expectedDelegated bool - }{ - { - name: "no env", - url: "https://192.168.143.1/api", - expectedDelegated: true, - }, - { - name: "no cidr", - noProxy: "192.168.63.1", - url: "https://192.168.143.1/api", - expectedDelegated: true, - }, - { - name: "hostname", - noProxy: "192.168.63.0/24,192.168.143.0/24", - url: "https://my-hostname/api", - expectedDelegated: true, - }, - { - name: "match second cidr", - noProxy: "192.168.63.0/24,192.168.143.0/24", - url: "https://192.168.143.1/api", - expectedDelegated: false, - }, - { - name: "match second cidr with host:port", - noProxy: "192.168.63.0/24,192.168.143.0/24", - url: "https://192.168.143.1:8443/api", - expectedDelegated: false, - }, - } - - for _, test := range testCases { - os.Setenv("NO_PROXY", test.noProxy) - actualDelegated := false - proxyFunc := NewProxierWithNoProxyCIDR(func(req *http.Request) (*url.URL, error) { - actualDelegated = true - return nil, nil - }) - - req, err := http.NewRequest("GET", test.url, nil) - if err != nil { - t.Errorf("%s: unexpected err: %v", test.name, err) - continue - } - if _, err := proxyFunc(req); err != nil { - t.Errorf("%s: unexpected err: %v", test.name, err) - continue - } - - if test.expectedDelegated != actualDelegated { - t.Errorf("%s: expected %v, got %v", test.name, test.expectedDelegated, actualDelegated) - continue - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/interface_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/interface_test.go deleted file mode 100644 index 9571e5b48..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/interface_test.go +++ /dev/null @@ -1,300 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 net - -import ( - "fmt" - "io" - "net" - "strings" - "testing" -) - -const gatewayfirst = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0 -eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0 -docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0 -virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 -` -const gatewaylast = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0 -virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 -eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0 -eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0 -` -const gatewaymiddle = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0 -docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0 -eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0 -virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 -` -const noInternetConnection = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0 -virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 -` -const nothing = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -` -const gatewayfirstIpv6_1 = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -eth3 00000000 0100FE0A 0003 0 0 1024 00000000 0 0 0 -eth3 0000FE0AA1 00000000 0001 0 0 0 0080FFFF 0 0 0 -docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0 -virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 -` -const gatewayfirstIpv6_2 = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -eth3 00000000 0100FE0AA1 0003 0 0 1024 00000000 0 0 0 -eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0 -docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0 -virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 -` -const route_Invalidhex = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -eth3 00000000 0100FE0AA 0003 0 0 1024 00000000 0 0 0 -eth3 0000FE0A 00000000 0001 0 0 0 0080FFFF 0 0 0 -docker0 000011AC 00000000 0001 0 0 0 0000FFFF 0 0 0 -virbr0 007AA8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 -` - -// Based on DigitalOcean COREOS -const gatewayfirstLinkLocal = `Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT -eth0 00000000 0120372D 0001 0 0 0 00000000 0 0 0 -eth0 00000000 00000000 0001 0 0 2048 00000000 0 0 0 -` - -func TestGetRoutes(t *testing.T) { - testCases := []struct { - tcase string - route string - expected int - }{ - {"gatewayfirst", gatewayfirst, 4}, - {"gatewaymiddle", gatewaymiddle, 4}, - {"gatewaylast", gatewaylast, 4}, - {"nothing", nothing, 0}, - {"gatewayfirstIpv6_1", gatewayfirstIpv6_1, 0}, - {"gatewayfirstIpv6_2", gatewayfirstIpv6_2, 0}, - {"route_Invalidhex", route_Invalidhex, 0}, - } - for _, tc := range testCases { - r := strings.NewReader(tc.route) - routes, err := getRoutes(r) - if len(routes) != tc.expected { - t.Errorf("case[%v]: expected %v, got %v .err : %v", tc.tcase, tc.expected, len(routes), err) - } - } -} - -func TestParseIP(t *testing.T) { - testCases := []struct { - tcase string - ip string - success bool - expected net.IP - }{ - {"empty", "", false, nil}, - {"too short", "AA", false, nil}, - {"too long", "0011223344", false, nil}, - {"invalid", "invalid!", false, nil}, - {"zero", "00000000", true, net.IP{0, 0, 0, 0}}, - {"ffff", "FFFFFFFF", true, net.IP{0xff, 0xff, 0xff, 0xff}}, - {"valid", "12345678", true, net.IP{120, 86, 52, 18}}, - } - for _, tc := range testCases { - ip, err := parseIP(tc.ip) - if !ip.Equal(tc.expected) { - t.Errorf("case[%v]: expected %q, got %q . err : %v", tc.tcase, tc.expected, ip, err) - } - } -} - -func TestIsInterfaceUp(t *testing.T) { - testCases := []struct { - tcase string - intf net.Interface - expected bool - }{ - {"up", net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp}, true}, - {"down", net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0}, false}, - {"nothing", net.Interface{}, false}, - } - for _, tc := range testCases { - it := isInterfaceUp(&tc.intf) - if it != tc.expected { - t.Errorf("case[%v]: expected %v, got %v .", tc.tcase, tc.expected, it) - } - } -} - -type addrStruct struct{ val string } - -func (a addrStruct) Network() string { - return a.val -} -func (a addrStruct) String() string { - return a.val -} - -func TestFinalIP(t *testing.T) { - testCases := []struct { - tcase string - addr []net.Addr - expected net.IP - }{ - {"ipv6", []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}}, nil}, - {"invalidCIDR", []net.Addr{addrStruct{val: "fe80::2f7:67fff:fe6e:2956/64"}}, nil}, - {"loopback", []net.Addr{addrStruct{val: "127.0.0.1/24"}}, nil}, - {"ip4", []net.Addr{addrStruct{val: "10.254.12.132/17"}}, net.ParseIP("10.254.12.132")}, - - {"nothing", []net.Addr{}, nil}, - } - for _, tc := range testCases { - ip, err := getFinalIP(tc.addr) - if !ip.Equal(tc.expected) { - t.Errorf("case[%v]: expected %v, got %v .err : %v", tc.tcase, tc.expected, ip, err) - } - } -} - -func TestAddrs(t *testing.T) { - var nw networkInterfacer = validNetworkInterface{} - intf := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: 0} - addrs, err := nw.Addrs(&intf) - if err != nil { - t.Errorf("expected no error got : %v", err) - } - if len(addrs) != 2 { - t.Errorf("expected addrs: 2 got null") - } -} - -type validNetworkInterface struct { -} - -func (_ validNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil -} -func (_ validNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { - var ifat []net.Addr - ifat = []net.Addr{ - addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}, addrStruct{val: "10.254.71.145/17"}} - return ifat, nil -} - -type validNetworkInterfaceWithLinkLocal struct { -} - -func (_ validNetworkInterfaceWithLinkLocal) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil -} -func (_ validNetworkInterfaceWithLinkLocal) Addrs(intf *net.Interface) ([]net.Addr, error) { - var ifat []net.Addr - ifat = []net.Addr{addrStruct{val: "169.254.162.166/16"}, addrStruct{val: "45.55.47.146/19"}} - return ifat, nil -} - -type validNetworkInterfacewithIpv6Only struct { -} - -func (_ validNetworkInterfacewithIpv6Only) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil -} -func (_ validNetworkInterfacewithIpv6Only) Addrs(intf *net.Interface) ([]net.Addr, error) { - var ifat []net.Addr - ifat = []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}} - return ifat, nil -} - -type noNetworkInterface struct { -} - -func (_ noNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) { - return nil, fmt.Errorf("unable get Interface") -} -func (_ noNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { - return nil, nil -} - -type networkInterfacewithNoAddrs struct { -} - -func (_ networkInterfacewithNoAddrs) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil -} -func (_ networkInterfacewithNoAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) { - return nil, fmt.Errorf("unable get Addrs") -} - -type networkInterfacewithIpv6addrs struct { -} - -func (_ networkInterfacewithIpv6addrs) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil -} -func (_ networkInterfacewithIpv6addrs) Addrs(intf *net.Interface) ([]net.Addr, error) { - var ifat []net.Addr - ifat = []net.Addr{addrStruct{val: "fe80::2f7:6ffff:fe6e:2956/64"}} - return ifat, nil -} - -func TestGetIPFromInterface(t *testing.T) { - testCases := []struct { - tcase string - nwname string - nw networkInterfacer - expected net.IP - }{ - {"valid", "eth3", validNetworkInterface{}, net.ParseIP("10.254.71.145")}, - {"ipv6", "eth3", validNetworkInterfacewithIpv6Only{}, nil}, - {"nothing", "eth3", noNetworkInterface{}, nil}, - } - for _, tc := range testCases { - ip, err := getIPFromInterface(tc.nwname, tc.nw) - if !ip.Equal(tc.expected) { - t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err) - } - } -} - -func TestChooseHostInterfaceFromRoute(t *testing.T) { - testCases := []struct { - tcase string - inFile io.Reader - nw networkInterfacer - expected net.IP - }{ - {"valid_routefirst", strings.NewReader(gatewayfirst), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, - {"valid_routelast", strings.NewReader(gatewaylast), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, - {"valid_routemiddle", strings.NewReader(gatewaymiddle), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, - {"valid_routemiddle_ipv6", strings.NewReader(gatewaymiddle), validNetworkInterfacewithIpv6Only{}, nil}, - {"no internet connection", strings.NewReader(noInternetConnection), validNetworkInterface{}, nil}, - {"no non-link-local ip", strings.NewReader(gatewayfirstLinkLocal), validNetworkInterfaceWithLinkLocal{}, net.ParseIP("45.55.47.146")}, - {"no route", strings.NewReader(nothing), validNetworkInterface{}, nil}, - {"no route file", nil, validNetworkInterface{}, nil}, - {"no interfaces", nil, noNetworkInterface{}, nil}, - {"no interface Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithNoAddrs{}, nil}, - {"Invalid Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithIpv6addrs{}, nil}, - } - for _, tc := range testCases { - ip, err := chooseHostInterfaceFromRoute(tc.inFile, tc.nw) - if !ip.Equal(tc.expected) { - t.Errorf("case[%v]: expected %v, got %+v .err : %v", tc.tcase, tc.expected, ip, err) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/port_range_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/port_range_test.go deleted file mode 100644 index 9eb081aa7..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/port_range_test.go +++ /dev/null @@ -1,66 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 net - -import ( - "testing" - - flag "github.com/spf13/pflag" -) - -func TestPortRange(t *testing.T) { - testCases := []struct { - input string - success bool - expected string - included int - excluded int - }{ - {"100-200", true, "100-200", 200, 201}, - {" 100-200 ", true, "100-200", 200, 201}, - {"0-0", true, "0-0", 0, 1}, - {"", true, "", -1, 0}, - {"100", false, "", -1, -1}, - {"100 - 200", false, "", -1, -1}, - {"-100", false, "", -1, -1}, - {"100-", false, "", -1, -1}, - } - - for i := range testCases { - tc := &testCases[i] - pr := &PortRange{} - var f flag.Value = pr - err := f.Set(tc.input) - if err != nil && tc.success == true { - t.Errorf("expected success, got %q", err) - continue - } else if err == nil && tc.success == false { - t.Errorf("expected failure") - continue - } else if tc.success { - if f.String() != tc.expected { - t.Errorf("expected %q, got %q", tc.expected, f.String()) - } - if tc.included >= 0 && !pr.Contains(tc.included) { - t.Errorf("expected %q to include %d", f.String(), tc.included) - } - if tc.excluded >= 0 && pr.Contains(tc.excluded) { - t.Errorf("expected %q to exclude %d", f.String(), tc.excluded) - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/port_split_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/port_split_test.go deleted file mode 100644 index 2e9e135c0..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/port_split_test.go +++ /dev/null @@ -1,111 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 net - -import ( - "testing" -) - -func TestSplitSchemeNamePort(t *testing.T) { - table := []struct { - in string - name, port, scheme string - valid bool - normalized bool - }{ - { - in: "aoeu:asdf", - name: "aoeu", - port: "asdf", - valid: true, - }, { - in: "http:aoeu:asdf", - scheme: "http", - name: "aoeu", - port: "asdf", - valid: true, - }, { - in: "https:aoeu:", - scheme: "https", - name: "aoeu", - port: "", - valid: true, - normalized: false, - }, { - in: "https:aoeu:asdf", - scheme: "https", - name: "aoeu", - port: "asdf", - valid: true, - }, { - in: "aoeu:", - name: "aoeu", - valid: true, - normalized: false, - }, { - in: ":asdf", - valid: false, - }, { - in: "aoeu:asdf:htns", - valid: false, - }, { - in: "aoeu", - name: "aoeu", - valid: true, - }, { - in: "", - valid: false, - }, - } - - for _, item := range table { - scheme, name, port, valid := SplitSchemeNamePort(item.in) - if e, a := item.scheme, scheme; e != a { - t.Errorf("%q: Wanted %q, got %q", item.in, e, a) - } - if e, a := item.name, name; e != a { - t.Errorf("%q: Wanted %q, got %q", item.in, e, a) - } - if e, a := item.port, port; e != a { - t.Errorf("%q: Wanted %q, got %q", item.in, e, a) - } - if e, a := item.valid, valid; e != a { - t.Errorf("%q: Wanted %t, got %t", item.in, e, a) - } - - // Make sure valid items round trip through JoinSchemeNamePort - if item.valid { - out := JoinSchemeNamePort(scheme, name, port) - if item.normalized && out != item.in { - t.Errorf("%q: Wanted %s, got %s", item.in, item.in, out) - } - scheme, name, port, valid := SplitSchemeNamePort(out) - if e, a := item.scheme, scheme; e != a { - t.Errorf("%q: Wanted %q, got %q", item.in, e, a) - } - if e, a := item.name, name; e != a { - t.Errorf("%q: Wanted %q, got %q", item.in, e, a) - } - if e, a := item.port, port; e != a { - t.Errorf("%q: Wanted %q, got %q", item.in, e, a) - } - if e, a := item.valid, valid; e != a { - t.Errorf("%q: Wanted %t, got %t", item.in, e, a) - } - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/sets/ipnet_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/sets/ipnet_test.go deleted file mode 100644 index 0223d1651..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/net/sets/ipnet_test.go +++ /dev/null @@ -1,155 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 sets - -import ( - "net" - "reflect" - "sort" - "testing" -) - -func parseIPNet(s string) *net.IPNet { - _, net, err := net.ParseCIDR(s) - if err != nil { - panic(err) - } - return net -} - -func TestIPNets(t *testing.T) { - s := IPNet{} - s2 := IPNet{} - if len(s) != 0 { - t.Errorf("Expected len=0: %d", len(s)) - } - a := parseIPNet("1.0.0.0/8") - b := parseIPNet("2.0.0.0/8") - c := parseIPNet("3.0.0.0/8") - d := parseIPNet("4.0.0.0/8") - - s.Insert(a, b) - if len(s) != 2 { - t.Errorf("Expected len=2: %d", len(s)) - } - s.Insert(c) - if s.Has(d) { - t.Errorf("Unexpected contents: %#v", s) - } - if !s.Has(a) { - t.Errorf("Missing contents: %#v", s) - } - s.Delete(a) - if s.Has(a) { - t.Errorf("Unexpected contents: %#v", s) - } - s.Insert(a) - if s.HasAll(a, b, d) { - t.Errorf("Unexpected contents: %#v", s) - } - if !s.HasAll(a, b) { - t.Errorf("Missing contents: %#v", s) - } - s2.Insert(a, b, d) - if s.IsSuperset(s2) { - t.Errorf("Unexpected contents: %#v", s) - } - s2.Delete(d) - if !s.IsSuperset(s2) { - t.Errorf("Missing contents: %#v", s) - } -} - -func TestIPNetSetDeleteMultiples(t *testing.T) { - s := IPNet{} - a := parseIPNet("1.0.0.0/8") - b := parseIPNet("2.0.0.0/8") - c := parseIPNet("3.0.0.0/8") - - s.Insert(a, b, c) - if len(s) != 3 { - t.Errorf("Expected len=3: %d", len(s)) - } - - s.Delete(a, c) - if len(s) != 1 { - t.Errorf("Expected len=1: %d", len(s)) - } - if s.Has(a) { - t.Errorf("Unexpected contents: %#v", s) - } - if s.Has(c) { - t.Errorf("Unexpected contents: %#v", s) - } - if !s.Has(b) { - t.Errorf("Missing contents: %#v", s) - } -} - -func TestNewIPSet(t *testing.T) { - s, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8") - if err != nil { - t.Errorf("error parsing IPNets: %v", err) - } - if len(s) != 3 { - t.Errorf("Expected len=3: %d", len(s)) - } - a := parseIPNet("1.0.0.0/8") - b := parseIPNet("2.0.0.0/8") - c := parseIPNet("3.0.0.0/8") - - if !s.Has(a) || !s.Has(b) || !s.Has(c) { - t.Errorf("Unexpected contents: %#v", s) - } -} - -func TestIPNetSetDifference(t *testing.T) { - l, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8") - if err != nil { - t.Errorf("error parsing IPNets: %v", err) - } - r, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "4.0.0.0/8", "5.0.0.0/8") - if err != nil { - t.Errorf("error parsing IPNets: %v", err) - } - c := l.Difference(r) - d := r.Difference(l) - if len(c) != 1 { - t.Errorf("Expected len=1: %d", len(c)) - } - if !c.Has(parseIPNet("3.0.0.0/8")) { - t.Errorf("Unexpected contents: %#v", c) - } - if len(d) != 2 { - t.Errorf("Expected len=2: %d", len(d)) - } - if !d.Has(parseIPNet("4.0.0.0/8")) || !d.Has(parseIPNet("5.0.0.0/8")) { - t.Errorf("Unexpected contents: %#v", d) - } -} - -func TestIPNetSetList(t *testing.T) { - s, err := ParseIPNets("3.0.0.0/8", "1.0.0.0/8", "2.0.0.0/8") - if err != nil { - t.Errorf("error parsing IPNets: %v", err) - } - l := s.StringSlice() - sort.Strings(l) - if !reflect.DeepEqual(l, []string{"1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8"}) { - t.Errorf("List gave unexpected result: %#v", l) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/node/node.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/node/node.go deleted file mode 100644 index cbc062fc9..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/node/node.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 node - -import ( - "fmt" - "net" - "os/exec" - "strings" - - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/api" -) - -func GetHostname(hostnameOverride string) string { - hostname := hostnameOverride - if string(hostname) == "" { - nodename, err := exec.Command("uname", "-n").Output() - if err != nil { - glog.Fatalf("Couldn't determine hostname: %v", err) - } - hostname = string(nodename) - } - return strings.ToLower(strings.TrimSpace(hostname)) -} - -// GetNodeHostIP returns the provided node's IP, based on the priority: -// 1. NodeInternalIP -// 2. NodeExternalIP -// 3. NodeLegacyHostIP -func GetNodeHostIP(node *api.Node) (net.IP, error) { - addresses := node.Status.Addresses - addressMap := make(map[api.NodeAddressType][]api.NodeAddress) - for i := range addresses { - addressMap[addresses[i].Type] = append(addressMap[addresses[i].Type], addresses[i]) - } - if addresses, ok := addressMap[api.NodeInternalIP]; ok { - return net.ParseIP(addresses[0].Address), nil - } - if addresses, ok := addressMap[api.NodeExternalIP]; ok { - return net.ParseIP(addresses[0].Address), nil - } - if addresses, ok := addressMap[api.NodeLegacyHostIP]; ok { - return net.ParseIP(addresses[0].Address), nil - } - return nil, fmt.Errorf("host IP unknown; known addresses: %v", addresses) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/doc.go deleted file mode 100644 index 539d6c43b..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 oom implements utility functions relating to out of memory management. -package oom diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom.go deleted file mode 100644 index c6d563ab2..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom.go +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 oom - -// This is a struct instead of an interface to allow injection of process ID listers and -// applying OOM score in tests. -// TODO: make this an interface, and inject a mock ioutil struct for testing. -type OOMAdjuster struct { - pidLister func(cgroupName string) ([]int, error) - ApplyOOMScoreAdj func(pid int, oomScoreAdj int) error - ApplyOOMScoreAdjContainer func(cgroupName string, oomScoreAdj, maxTries int) error -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_fake.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_fake.go deleted file mode 100644 index bd0bf6f45..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_fake.go +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 oom - -type FakeOOMAdjuster struct{} - -func NewFakeOOMAdjuster() *OOMAdjuster { - return &OOMAdjuster{ - pidLister: func(cgroupName string) ([]int, error) { return make([]int, 0), nil }, - ApplyOOMScoreAdj: fakeApplyOOMScoreAdj, - ApplyOOMScoreAdjContainer: fakeApplyOOMScoreAdjContainer, - } -} - -func fakeApplyOOMScoreAdj(pid int, oomScoreAdj int) error { - return nil -} - -func fakeApplyOOMScoreAdjContainer(cgroupName string, oomScoreAdj, maxTries int) error { - return nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_linux.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_linux.go deleted file mode 100644 index c054682bd..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_linux.go +++ /dev/null @@ -1,130 +0,0 @@ -// +build cgo,linux - -/* -Copyright 2015 The Kubernetes Authors 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 oom - -import ( - "fmt" - "os" - "path" - "strconv" - - "github.com/golang/glog" - "github.com/opencontainers/runc/libcontainer/cgroups/fs" - "github.com/opencontainers/runc/libcontainer/configs" -) - -func NewOOMAdjuster() *OOMAdjuster { - oomAdjuster := &OOMAdjuster{ - pidLister: getPids, - ApplyOOMScoreAdj: applyOOMScoreAdj, - } - oomAdjuster.ApplyOOMScoreAdjContainer = oomAdjuster.applyOOMScoreAdjContainer - return oomAdjuster -} - -func getPids(cgroupName string) ([]int, error) { - fsManager := fs.Manager{ - Cgroups: &configs.Cgroup{ - Parent: "/", - Name: cgroupName, - }, - } - return fsManager.GetPids() -} - -// Writes 'value' to /proc//oom_score_adj. PID = 0 means self -// Returns os.ErrNotExist if the `pid` does not exist. -func applyOOMScoreAdj(pid int, oomScoreAdj int) error { - if pid < 0 { - return fmt.Errorf("invalid PID %d specified for oom_score_adj", pid) - } - - var pidStr string - if pid == 0 { - pidStr = "self" - } else { - pidStr = strconv.Itoa(pid) - } - - maxTries := 2 - oomScoreAdjPath := path.Join("/proc", pidStr, "oom_score_adj") - value := strconv.Itoa(oomScoreAdj) - var err error - for i := 0; i < maxTries; i++ { - f, err := os.Open(oomScoreAdjPath) - if err != nil { - if os.IsNotExist(err) { - return os.ErrNotExist - } - err = fmt.Errorf("failed to apply oom-score-adj to pid %d (%v)", pid, err) - continue - } - if _, err := f.Write([]byte(value)); err != nil { - err = fmt.Errorf("failed to apply oom-score-adj to pid %d (%v)", pid, err) - continue - } - return nil - } - return err -} - -// Writes 'value' to /proc//oom_score_adj for all processes in cgroup cgroupName. -// Keeps trying to write until the process list of the cgroup stabilizes, or until maxTries tries. -func (oomAdjuster *OOMAdjuster) applyOOMScoreAdjContainer(cgroupName string, oomScoreAdj, maxTries int) error { - adjustedProcessSet := make(map[int]bool) - for i := 0; i < maxTries; i++ { - continueAdjusting := false - pidList, err := oomAdjuster.pidLister(cgroupName) - if err != nil { - if os.IsNotExist(err) { - // Nothing to do since the container doesn't exist anymore. - return os.ErrNotExist - } - continueAdjusting = true - glog.V(10).Infof("Error getting process list for cgroup %s: %+v", cgroupName, err) - } else if len(pidList) == 0 { - glog.V(10).Infof("Pid list is empty") - continueAdjusting = true - } else { - for _, pid := range pidList { - if !adjustedProcessSet[pid] { - glog.V(10).Infof("pid %d needs to be set", pid) - if err = oomAdjuster.ApplyOOMScoreAdj(pid, oomScoreAdj); err == nil { - adjustedProcessSet[pid] = true - } else if err == os.ErrNotExist { - continue - } else { - glog.V(10).Infof("cannot adjust oom score for pid %d - %v", pid, err) - continueAdjusting = true - } - // Processes can come and go while we try to apply oom score adjust value. So ignore errors here. - } - } - } - if !continueAdjusting { - return nil - } - // There's a slight race. A process might have forked just before we write its OOM score adjust. - // The fork might copy the parent process's old OOM score, then this function might execute and - // update the parent's OOM score, but the forked process id might not be reflected in cgroup.procs - // for a short amount of time. So this function might return without changing the forked process's - // OOM score. Very unlikely race, so ignoring this for now. - } - return fmt.Errorf("exceeded maxTries, some processes might not have desired OOM score") -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_linux_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_linux_test.go deleted file mode 100644 index 10e9f3d9e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_linux_test.go +++ /dev/null @@ -1,104 +0,0 @@ -// +build cgo,linux - -/* -Copyright 2015 The Kubernetes Authors 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 oom - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -// Converts a sequence of PID lists into a PID lister. -// The PID lister returns pidListSequence[i] on the ith call. If i >= length of pidListSequence -// then return the last element of pidListSequence (the sequence is considered to have) stabilized. -func sequenceToPidLister(pidListSequence [][]int) func(string) ([]int, error) { - var numCalls int - return func(cgroupName string) ([]int, error) { - numCalls++ - if len(pidListSequence) == 0 { - return []int{}, nil - } else if numCalls > len(pidListSequence) { - return pidListSequence[len(pidListSequence)-1], nil - } - return pidListSequence[numCalls-1], nil - } -} - -// Tests that applyOOMScoreAdjContainer correctly applies OOM scores to relevant processes, or -// returns the right error. -func applyOOMScoreAdjContainerTester(pidListSequence [][]int, maxTries int, appliedPids []int, expectedError bool, t *testing.T) { - pidOOMs := make(map[int]bool) - - // Mock ApplyOOMScoreAdj and pidLister. - oomAdjuster := NewOOMAdjuster() - oomAdjuster.ApplyOOMScoreAdj = func(pid int, oomScoreAdj int) error { - pidOOMs[pid] = true - return nil - } - oomAdjuster.pidLister = sequenceToPidLister(pidListSequence) - err := oomAdjuster.ApplyOOMScoreAdjContainer("", 100, maxTries) - - // Check error value. - if expectedError && err == nil { - t.Errorf("Expected error %+v when running ApplyOOMScoreAdjContainer but got no error", expectedError) - return - } else if !expectedError && err != nil { - t.Errorf("Expected no error but got error %+v when running ApplyOOMScoreAdjContainer", err) - return - } else if err != nil { - return - } - // Check that OOM scores were applied to the right processes. - if len(appliedPids) != len(pidOOMs) { - t.Errorf("Applied OOM scores to incorrect number of processes - %+v vs %v", appliedPids, pidOOMs) - return - } - for _, pid := range appliedPids { - if !pidOOMs[pid] { - t.Errorf("Failed to apply OOM scores to process %d", pid) - } - } -} - -func TestOOMScoreAdjContainer(t *testing.T) { - pidListSequenceEmpty := [][]int{} - applyOOMScoreAdjContainerTester(pidListSequenceEmpty, 3, nil, true, t) - - pidListSequence1 := [][]int{ - {1, 2}, - } - applyOOMScoreAdjContainerTester(pidListSequence1, 1, []int{1, 2}, false, t) - - pidListSequenceLag := [][]int{ - {}, - {}, - {}, - {1, 2, 4}, - } - for i := 1; i < 4; i++ { - applyOOMScoreAdjContainerTester(pidListSequenceLag, i, nil, true, t) - } - applyOOMScoreAdjContainerTester(pidListSequenceLag, 4, []int{1, 2, 4}, false, t) -} - -func TestPidListerFailure(t *testing.T) { - _, err := getPids("/does/not/exist") - assert.True(t, os.IsNotExist(err), "expected getPids to return not exists error. Got %v", err) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_unsupported.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_unsupported.go deleted file mode 100644 index 9c4473f7e..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/oom/oom_unsupported.go +++ /dev/null @@ -1,40 +0,0 @@ -// +build !cgo !linux - -/* -Copyright 2015 The Kubernetes Authors 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 oom - -import ( - "errors" -) - -var unsupportedErr = errors.New("setting OOM scores is unsupported in this build") - -func NewOOMAdjuster() *OOMAdjuster { - return &OOMAdjuster{ - ApplyOOMScoreAdj: unsupportedApplyOOMScoreAdj, - ApplyOOMScoreAdjContainer: unsupportedApplyOOMScoreAdjContainer, - } -} - -func unsupportedApplyOOMScoreAdj(pid int, oomScoreAdj int) error { - return unsupportedErr -} - -func unsupportedApplyOOMScoreAdjContainer(cgroupName string, oomScoreAdj, maxTries int) error { - return unsupportedErr -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/parsers/parsers_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/parsers/parsers_test.go deleted file mode 100644 index 371eee758..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/parsers/parsers_test.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors 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 parsers - -import ( - "testing" -) - -// Based on Docker test case removed in: -// https://github.com/docker/docker/commit/4352da7803d182a6013a5238ce20a7c749db979a -func TestParseImageName(t *testing.T) { - testCases := []struct { - Input string - Repo string - Tag string - Digest string - }{ - {Input: "root", Repo: "root", Tag: "latest"}, - {Input: "root:tag", Repo: "root", Tag: "tag"}, - {Input: "root@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Repo: "root", Digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, - {Input: "user/repo", Repo: "user/repo", Tag: "latest"}, - {Input: "user/repo:tag", Repo: "user/repo", Tag: "tag"}, - {Input: "user/repo@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Repo: "user/repo", Digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, - {Input: "url:5000/repo", Repo: "url:5000/repo", Tag: "latest"}, - {Input: "url:5000/repo:tag", Repo: "url:5000/repo", Tag: "tag"}, - {Input: "url:5000/repo@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Repo: "url:5000/repo", Digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, - } - for _, testCase := range testCases { - repo, tag, digest, err := ParseImageName(testCase.Input) - if err != nil { - t.Errorf("ParseImageName(%s) failed: %v", testCase.Input, err) - } else if repo != testCase.Repo || tag != testCase.Tag || digest != testCase.Digest { - t.Errorf("Expected repo: %q, tag: %q and digest: %q, got %q, %q and %q", testCase.Repo, testCase.Tag, testCase.Digest, - repo, tag, digest) - } - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/doc.go deleted file mode 100644 index d94e6687c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 procfs implements utility functions relating to the /proc mount. -package procfs diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/example_proc_cgroup b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/example_proc_cgroup deleted file mode 100644 index 3e42ce927..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/example_proc_cgroup +++ /dev/null @@ -1,10 +0,0 @@ -11:name=systemd:/user/1000.user/c1.session -10:hugetlb:/user/1000.user/c1.session -9:perf_event:/user/1000.user/c1.session -8:blkio:/user/1000.user/c1.session -7:freezer:/user/1000.user/c1.session -6:devices:/user/1000.user/c1.session -5:memory:/user/1000.user/c1.session -4:cpuacct:/user/1000.user/c1.session -3:cpu:/user/1000.user/c1.session -2:cpuset:/ \ No newline at end of file diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs.go deleted file mode 100644 index d0c38bf21..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs.go +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 procfs - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "strconv" - "strings" -) - -type ProcFS struct{} - -func NewProcFS() ProcFSInterface { - return &ProcFS{} -} - -func containerNameFromProcCgroup(content string) (string, error) { - lines := strings.Split(content, "\n") - for _, line := range lines { - entries := strings.SplitN(line, ":", 3) - if len(entries) == 3 && entries[1] == "devices" { - return strings.TrimSpace(entries[2]), nil - } - } - return "", fmt.Errorf("could not find devices cgroup location") -} - -// getFullContainerName gets the container name given the root process id of the container. -// Eg. If the devices cgroup for the container is stored in /sys/fs/cgroup/devices/docker/nginx, -// return docker/nginx. Assumes that the process is part of exactly one cgroup hierarchy. -func (pfs *ProcFS) GetFullContainerName(pid int) (string, error) { - filePath := path.Join("/proc", strconv.Itoa(pid), "cgroup") - content, err := ioutil.ReadFile(filePath) - if err != nil { - if os.IsNotExist(err) { - return "", os.ErrNotExist - } - return "", err - } - return containerNameFromProcCgroup(string(content)) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_fake.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_fake.go deleted file mode 100644 index 8d16aa53c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_fake.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 procfs - -type FakeProcFS struct{} - -func NewFakeProcFS() ProcFSInterface { - return &FakeProcFS{} -} - -// GetFullContainerName gets the container name given the root process id of the container. -// Eg. If the devices cgroup for the container is stored in /sys/fs/cgroup/devices/docker/nginx, -// return docker/nginx. Assumes that the process is part of exactly one cgroup hierarchy. -func (fakePfs *FakeProcFS) GetFullContainerName(pid int) (string, error) { - return "", nil -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_interface.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_interface.go deleted file mode 100644 index d3bf14f0c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_interface.go +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 procfs - -type ProcFSInterface interface { - // GetFullContainerName gets the container name given the root process id of the container. - GetFullContainerName(pid int) (string, error) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_test.go deleted file mode 100644 index 609543dca..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/procfs/procfs_test.go +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 procfs - -import ( - "io/ioutil" - "testing" -) - -func verifyContainerName(procCgroupText, expectedName string, expectedErr bool, t *testing.T) { - name, err := containerNameFromProcCgroup(procCgroupText) - if expectedErr && err == nil { - t.Errorf("Expected error but did not get error in verifyContainerName") - return - } else if !expectedErr && err != nil { - t.Errorf("Expected no error, but got error %+v in verifyContainerName", err) - return - } else if expectedErr { - return - } - if name != expectedName { - t.Errorf("Expected container name %s but got name %s", expectedName, name) - } -} - -func TestContainerNameFromProcCgroup(t *testing.T) { - procCgroupValid := "2:devices:docker/kubelet" - verifyContainerName(procCgroupValid, "docker/kubelet", false, t) - - procCgroupEmpty := "" - verifyContainerName(procCgroupEmpty, "", true, t) - - content, err := ioutil.ReadFile("example_proc_cgroup") - if err != nil { - t.Errorf("Could not read example /proc cgroup file") - } - verifyContainerName(string(content), "/user/1000.user/c1.session", false, t) - - procCgroupNoDevice := "2:freezer:docker/kubelet\n5:cpuacct:pkg/kubectl" - verifyContainerName(procCgroupNoDevice, "", true, t) - - procCgroupInvalid := "devices:docker/kubelet\ncpuacct:pkg/kubectl" - verifyContainerName(procCgroupInvalid, "", true, t) -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/dial.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/dial.go deleted file mode 100644 index 33cecb7ea..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/dial.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors 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 proxy - -import ( - "crypto/tls" - "fmt" - "net" - "net/http" - "net/url" - - "github.com/golang/glog" - - utilnet "k8s.io/kubernetes/pkg/util/net" - "k8s.io/kubernetes/third_party/golang/netutil" -) - -func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { - dialAddr := netutil.CanonicalAddr(url) - - dialer, _ := utilnet.Dialer(transport) - - switch url.Scheme { - case "http": - if dialer != nil { - return dialer("tcp", dialAddr) - } - return net.Dial("tcp", dialAddr) - case "https": - // Get the tls config from the transport if we recognize it - var tlsConfig *tls.Config - var tlsConn *tls.Conn - var err error - tlsConfig, _ = utilnet.TLSClientConfig(transport) - - if dialer != nil { - // We have a dialer; use it to open the connection, then - // create a tls client using the connection. - netConn, err := dialer("tcp", dialAddr) - if err != nil { - return nil, err - } - if tlsConfig == nil { - // tls.Client requires non-nil config - glog.Warningf("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify") - // tls.Handshake() requires ServerName or InsecureSkipVerify - tlsConfig = &tls.Config{ - InsecureSkipVerify: true, - } - } else if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify { - // tls.Handshake() requires ServerName or InsecureSkipVerify - // infer the ServerName from the hostname we're connecting to. - inferredHost := dialAddr - if host, _, err := net.SplitHostPort(dialAddr); err == nil { - inferredHost = host - } - // Make a copy to avoid polluting the provided config - tlsConfigCopy := *tlsConfig - tlsConfigCopy.ServerName = inferredHost - tlsConfig = &tlsConfigCopy - } - tlsConn = tls.Client(netConn, tlsConfig) - if err := tlsConn.Handshake(); err != nil { - netConn.Close() - return nil, err - } - - } else { - // Dial - tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig) - if err != nil { - return nil, err - } - } - - // Return if we were configured to skip validation - if tlsConfig != nil && tlsConfig.InsecureSkipVerify { - return tlsConn, nil - } - - // Verify - host, _, _ := net.SplitHostPort(dialAddr) - if err := tlsConn.VerifyHostname(host); err != nil { - tlsConn.Close() - return nil, err - } - - return tlsConn, nil - default: - return nil, fmt.Errorf("Unknown scheme: %s", url.Scheme) - } -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/doc.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/doc.go deleted file mode 100644 index 0d7519a0c..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 proxy provides transport and upgrade support for proxies -package proxy diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/transport.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/transport.go deleted file mode 100644 index 079670c0a..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/transport.go +++ /dev/null @@ -1,241 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 proxy - -import ( - "bytes" - "compress/gzip" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "path" - "strings" - - "github.com/golang/glog" - "golang.org/x/net/html" - "golang.org/x/net/html/atom" - - "k8s.io/kubernetes/pkg/util/net" - "k8s.io/kubernetes/pkg/util/sets" -) - -// atomsToAttrs states which attributes of which tags require URL substitution. -// Sources: http://www.w3.org/TR/REC-html40/index/attributes.html -// http://www.w3.org/html/wg/drafts/html/master/index.html#attributes-1 -var atomsToAttrs = map[atom.Atom]sets.String{ - atom.A: sets.NewString("href"), - atom.Applet: sets.NewString("codebase"), - atom.Area: sets.NewString("href"), - atom.Audio: sets.NewString("src"), - atom.Base: sets.NewString("href"), - atom.Blockquote: sets.NewString("cite"), - atom.Body: sets.NewString("background"), - atom.Button: sets.NewString("formaction"), - atom.Command: sets.NewString("icon"), - atom.Del: sets.NewString("cite"), - atom.Embed: sets.NewString("src"), - atom.Form: sets.NewString("action"), - atom.Frame: sets.NewString("longdesc", "src"), - atom.Head: sets.NewString("profile"), - atom.Html: sets.NewString("manifest"), - atom.Iframe: sets.NewString("longdesc", "src"), - atom.Img: sets.NewString("longdesc", "src", "usemap"), - atom.Input: sets.NewString("src", "usemap", "formaction"), - atom.Ins: sets.NewString("cite"), - atom.Link: sets.NewString("href"), - atom.Object: sets.NewString("classid", "codebase", "data", "usemap"), - atom.Q: sets.NewString("cite"), - atom.Script: sets.NewString("src"), - atom.Source: sets.NewString("src"), - atom.Video: sets.NewString("poster", "src"), - - // TODO: css URLs hidden in style elements. -} - -// Transport is a transport for text/html content that replaces URLs in html -// content with the prefix of the proxy server -type Transport struct { - Scheme string - Host string - PathPrepend string - - http.RoundTripper -} - -// RoundTrip implements the http.RoundTripper interface -func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { - // Add reverse proxy headers. - forwardedURI := path.Join(t.PathPrepend, req.URL.Path) - if strings.HasSuffix(req.URL.Path, "/") { - forwardedURI = forwardedURI + "/" - } - req.Header.Set("X-Forwarded-Uri", forwardedURI) - if len(t.Host) > 0 { - req.Header.Set("X-Forwarded-Host", t.Host) - } - if len(t.Scheme) > 0 { - req.Header.Set("X-Forwarded-Proto", t.Scheme) - } - - rt := t.RoundTripper - if rt == nil { - rt = http.DefaultTransport - } - resp, err := rt.RoundTrip(req) - - if err != nil { - message := fmt.Sprintf("Error: '%s'\nTrying to reach: '%v'", err.Error(), req.URL.String()) - resp = &http.Response{ - StatusCode: http.StatusServiceUnavailable, - Body: ioutil.NopCloser(strings.NewReader(message)), - } - return resp, nil - } - - if redirect := resp.Header.Get("Location"); redirect != "" { - resp.Header.Set("Location", t.rewriteURL(redirect, req.URL)) - return resp, nil - } - - cType := resp.Header.Get("Content-Type") - cType = strings.TrimSpace(strings.SplitN(cType, ";", 2)[0]) - if cType != "text/html" { - // Do nothing, simply pass through - return resp, nil - } - - return t.rewriteResponse(req, resp) -} - -var _ = net.RoundTripperWrapper(&Transport{}) - -func (rt *Transport) WrappedRoundTripper() http.RoundTripper { - return rt.RoundTripper -} - -// rewriteURL rewrites a single URL to go through the proxy, if the URL refers -// to the same host as sourceURL, which is the page on which the target URL -// occurred. If any error occurs (e.g. parsing), it returns targetURL. -func (t *Transport) rewriteURL(targetURL string, sourceURL *url.URL) string { - url, err := url.Parse(targetURL) - if err != nil { - return targetURL - } - - isDifferentHost := url.Host != "" && url.Host != sourceURL.Host - isRelative := !strings.HasPrefix(url.Path, "/") - if isDifferentHost || isRelative { - return targetURL - } - - url.Scheme = t.Scheme - url.Host = t.Host - origPath := url.Path - // Do not rewrite URL if the sourceURL already contains the necessary prefix. - if strings.HasPrefix(url.Path, t.PathPrepend) { - return url.String() - } - url.Path = path.Join(t.PathPrepend, url.Path) - if strings.HasSuffix(origPath, "/") { - // Add back the trailing slash, which was stripped by path.Join(). - url.Path += "/" - } - - return url.String() -} - -// rewriteHTML scans the HTML for tags with url-valued attributes, and updates -// those values with the urlRewriter function. The updated HTML is output to the -// writer. -func rewriteHTML(reader io.Reader, writer io.Writer, urlRewriter func(string) string) error { - // Note: This assumes the content is UTF-8. - tokenizer := html.NewTokenizer(reader) - - var err error - for err == nil { - tokenType := tokenizer.Next() - switch tokenType { - case html.ErrorToken: - err = tokenizer.Err() - case html.StartTagToken, html.SelfClosingTagToken: - token := tokenizer.Token() - if urlAttrs, ok := atomsToAttrs[token.DataAtom]; ok { - for i, attr := range token.Attr { - if urlAttrs.Has(attr.Key) { - token.Attr[i].Val = urlRewriter(attr.Val) - } - } - } - _, err = writer.Write([]byte(token.String())) - default: - _, err = writer.Write(tokenizer.Raw()) - } - } - if err != io.EOF { - return err - } - return nil -} - -// rewriteResponse modifies an HTML response by updating absolute links referring -// to the original host to instead refer to the proxy transport. -func (t *Transport) rewriteResponse(req *http.Request, resp *http.Response) (*http.Response, error) { - origBody := resp.Body - defer origBody.Close() - - newContent := &bytes.Buffer{} - var reader io.Reader = origBody - var writer io.Writer = newContent - encoding := resp.Header.Get("Content-Encoding") - switch encoding { - case "gzip": - var err error - reader, err = gzip.NewReader(reader) - if err != nil { - return nil, fmt.Errorf("errorf making gzip reader: %v", err) - } - gzw := gzip.NewWriter(writer) - defer gzw.Close() - writer = gzw - // TODO: support flate, other encodings. - case "": - // This is fine - default: - // Some encoding we don't understand-- don't try to parse this - glog.Errorf("Proxy encountered encoding %v for text/html; can't understand this so not fixing links.", encoding) - return resp, nil - } - - urlRewriter := func(targetUrl string) string { - return t.rewriteURL(targetUrl, req.URL) - } - err := rewriteHTML(reader, writer, urlRewriter) - if err != nil { - glog.Errorf("Failed to rewrite URLs: %v", err) - return resp, err - } - - resp.Body = ioutil.NopCloser(newContent) - // Update header node with new content-length - // TODO: Remove any hash/signature headers here? - resp.Header.Del("Content-Length") - resp.ContentLength = int64(newContent.Len()) - - return resp, err -} diff --git a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/transport_test.go b/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/transport_test.go deleted file mode 100644 index fca115526..000000000 --- a/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/proxy/transport_test.go +++ /dev/null @@ -1,261 +0,0 @@ -/* -Copyright 2014 The Kubernetes Authors 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 proxy - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "strings" - "testing" -) - -func parseURLOrDie(inURL string) *url.URL { - parsed, err := url.Parse(inURL) - if err != nil { - panic(err) - } - return parsed -} - -func TestProxyTransport(t *testing.T) { - testTransport := &Transport{ - Scheme: "http", - Host: "foo.com", - PathPrepend: "/proxy/minion/minion1:10250", - } - testTransport2 := &Transport{ - Scheme: "https", - Host: "foo.com", - PathPrepend: "/proxy/minion/minion1:8080", - } - emptyHostTransport := &Transport{ - Scheme: "https", - PathPrepend: "/proxy/minion/minion1:10250", - } - emptySchemeTransport := &Transport{ - Host: "foo.com", - PathPrepend: "/proxy/minion/minion1:10250", - } - type Item struct { - input string - sourceURL string - transport *Transport - output string - contentType string - forwardedURI string - redirect string - redirectWant string - } - - table := map[string]Item{ - "normal": { - input: `
kubelet.loggoogle.log
`, - sourceURL: "http://myminion.com/logs/log.log", - transport: testTransport, - output: `
kubelet.loggoogle.log
`, - contentType: "text/html", - forwardedURI: "/proxy/minion/minion1:10250/logs/log.log", - }, - "full document": { - input: `
kubelet.loggoogle.log
`, - sourceURL: "http://myminion.com/logs/log.log", - transport: testTransport, - output: `
kubelet.loggoogle.log
`, - contentType: "text/html", - forwardedURI: "/proxy/minion/minion1:10250/logs/log.log", - }, - "trailing slash": { - input: `
kubelet.loggoogle.log
`, - sourceURL: "http://myminion.com/logs/log.log", - transport: testTransport, - output: `
kubelet.loggoogle.log
`, - contentType: "text/html", - forwardedURI: "/proxy/minion/minion1:10250/logs/log.log", - }, - "content-type charset": { - input: `
kubelet.loggoogle.log
`, - sourceURL: "http://myminion.com/logs/log.log", - transport: testTransport, - output: `
kubelet.loggoogle.log
`, - contentType: "text/html; charset=utf-8", - forwardedURI: "/proxy/minion/minion1:10250/logs/log.log", - }, - "content-type passthrough": { - input: `
kubelet.loggoogle.log
`, - sourceURL: "http://myminion.com/logs/log.log", - transport: testTransport, - output: `
kubelet.loggoogle.log
`, - contentType: "text/plain", - forwardedURI: "/proxy/minion/minion1:10250/logs/log.log", - }, - "subdir": { - input: `kubelet.loggoogle.log`, - sourceURL: "http://myminion.com/whatever/apt/somelog.log", - transport: testTransport2, - output: `kubelet.loggoogle.log`, - contentType: "text/html", - forwardedURI: "/proxy/minion/minion1:8080/whatever/apt/somelog.log", - }, - "image": { - input: `
`, - sourceURL: "http://myminion.com/", - transport: testTransport, - output: `
`, - contentType: "text/html", - forwardedURI: "/proxy/minion/minion1:10250/", - }, - "abs": { - input: `