diff --git a/.gitignore b/.gitignore index 1b28f05..41e2aec 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ bin/ kconfig kube-scheduler vendor +Gopkg.lock \ No newline at end of file diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index 2d7a1f6..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,439 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - digest = "1:20da7140359cab99772431cbeb195bd8cbe76312fcf6509fd8125cf91ab2847b" - name = "github.com/docopt/docopt-go" - packages = ["."] - pruneopts = "" - revision = "ee0de3bc6815ee19d4a46c7eb90f829db0e014b1" - -[[projects]] - digest = "1:fd53b471edb4c28c7d297f617f4da0d33402755f58d6301e7ca1197ef0a90937" - name = "github.com/gogo/protobuf" - packages = [ - "proto", - "sortkeys", - ] - pruneopts = "" - revision = "ba06b47c162d49f2af050fb4c75bcbc86a159d5c" - version = "v1.2.1" - -[[projects]] - digest = "1:d3d38150b6d77b2aad42a9e105170538b6563518993d43df78a1add6e31cce62" - name = "github.com/golang/protobuf" - packages = [ - "proto", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/timestamp", - ] - pruneopts = "" - revision = "c823c79ea1570fb5ff454033735a8e68575d1d0f" - version = "v1.3.0" - -[[projects]] - branch = "master" - digest = "1:1e5b1e14524ed08301977b7b8e10c719ed853cbf3f24ecb66fae783a46f207a6" - name = "github.com/google/btree" - packages = ["."] - pruneopts = "" - revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" - -[[projects]] - branch = "master" - digest = "1:754f77e9c839b24778a4b64422236d38515301d2baeb63113aa3edc42e6af692" - name = "github.com/google/gofuzz" - packages = ["."] - pruneopts = "" - revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" - -[[projects]] - digest = "1:16b2837c8b3cf045fa2cdc82af0cf78b19582701394484ae76b2c3bc3c99ad73" - name = "github.com/googleapis/gnostic" - packages = [ - "OpenAPIv2", - "compiler", - "extensions", - ] - pruneopts = "" - revision = "7c663266750e7d82587642f65e60bc4083f1f84e" - version = "v0.2.0" - -[[projects]] - branch = "master" - digest = "1:326d7083af3723768cd8150db99b8ac730837b05ef290d5a042562905cc26210" - name = "github.com/gregjones/httpcache" - packages = [ - ".", - "diskcache", - ] - pruneopts = "" - revision = "3befbb6ad0cc97d4c25d851e9528915809e1a22f" - -[[projects]] - digest = "1:31bfd110d31505e9ffbc9478e31773bf05bf02adcaeb9b139af42684f9294c13" - name = "github.com/imdario/mergo" - packages = ["."] - pruneopts = "" - revision = "7c29201646fa3de8506f701213473dd407f19646" - version = "v0.3.7" - -[[projects]] - digest = "1:b79fc583e4dc7055ed86742e22164ac41bf8c0940722dbcb600f1a3ace1a8cb5" - name = "github.com/json-iterator/go" - packages = ["."] - pruneopts = "" - revision = "1624edc4454b8682399def8740d46db5e4362ba4" - version = "v1.1.5" - -[[projects]] - digest = "1:0f51cee70b0d254dbc93c22666ea2abf211af81c1701a96d04e2284b408621db" - name = "github.com/konsorten/go-windows-terminal-sequences" - packages = ["."] - pruneopts = "" - revision = "f55edac94c9bbba5d6182a4be46d86a2c9b5b50e" - version = "v1.0.2" - -[[projects]] - digest = "1:0c0ff2a89c1bb0d01887e1dac043ad7efbf3ec77482ef058ac423d13497e16fd" - name = "github.com/modern-go/concurrent" - packages = ["."] - pruneopts = "" - revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" - version = "1.0.3" - -[[projects]] - digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855" - name = "github.com/modern-go/reflect2" - packages = ["."] - pruneopts = "" - revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" - version = "1.0.1" - -[[projects]] - branch = "master" - digest = "1:c24598ffeadd2762552269271b3b1510df2d83ee6696c1e543a0ff653af494bc" - name = "github.com/petar/GoLLRB" - packages = ["llrb"] - pruneopts = "" - revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" - -[[projects]] - digest = "1:b46305723171710475f2dd37547edd57b67b9de9f2a6267cafdd98331fd6897f" - name = "github.com/peterbourgon/diskv" - packages = ["."] - pruneopts = "" - revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" - version = "v2.0.1" - -[[projects]] - digest = "1:9a3c631555e0351fdc4e696577bb63afd90c399d782a8462dba9d100d7021db3" - name = "github.com/sirupsen/logrus" - packages = ["."] - pruneopts = "" - revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5" - version = "v1.3.0" - -[[projects]] - digest = "1:cbaf13cdbfef0e4734ed8a7504f57fe893d471d62a35b982bf6fb3f036449a66" - name = "github.com/spf13/pflag" - packages = ["."] - pruneopts = "" - revision = "298182f68c66c05229eb03ac171abe6e309ee79a" - version = "v1.0.3" - -[[projects]] - branch = "master" - digest = "1:7a77b79efe106f3304dcf50dc86836151758f246169b527722552a5eb2ae14fc" - name = "golang.org/x/crypto" - packages = ["ssh/terminal"] - pruneopts = "" - revision = "8dd112bcdc25174059e45e07517d9fc663123347" - -[[projects]] - branch = "master" - digest = "1:7489cf41e267d966cbc16d9b98622e7124818af9339d5466aaec4fc736c404c0" - name = "golang.org/x/net" - packages = [ - "context", - "context/ctxhttp", - "http/httpguts", - "http2", - "http2/hpack", - "idna", - ] - pruneopts = "" - revision = "16b79f2e4e95ea23b2bf9903c9809ff7b013ce85" - -[[projects]] - branch = "master" - digest = "1:ffae4a89b63a2c845533a393b3340f8696898b11b71da1b187f82f08135c23a0" - name = "golang.org/x/oauth2" - packages = [ - ".", - "internal", - ] - pruneopts = "" - revision = "e64efc72b421e893cbf63f17ba2221e7d6d0b0f3" - -[[projects]] - branch = "master" - digest = "1:acd61a173af5a8fc666328598f3aed921b0947ff2da2eeb548f7ba77e9a0cbd0" - name = "golang.org/x/sys" - packages = [ - "unix", - "windows", - ] - pruneopts = "" - revision = "b294cbcfc56d2a65a30c02c78722b5df061e99b8" - -[[projects]] - digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "internal/colltab", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "language", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable", - ] - pruneopts = "" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - branch = "master" - digest = "1:14cb1d4240bcbbf1386ae763957e04e2765ec4e4ce7bb2769d05fa6faccd774e" - name = "golang.org/x/time" - packages = ["rate"] - pruneopts = "" - revision = "85acf8d2951cb2a3bde7632f9ff273ef0379bcbd" - -[[projects]] - digest = "1:bc09e719c4e2a15d17163f5272d9a3131c45d77542b7fdc53ff518815bc19ab3" - name = "google.golang.org/appengine" - packages = [ - "internal", - "internal/base", - "internal/datastore", - "internal/log", - "internal/remote_api", - "internal/urlfetch", - "urlfetch", - ] - pruneopts = "" - revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1" - version = "v1.4.0" - -[[projects]] - digest = "1:75fb3fcfc73a8c723efde7777b40e8e8ff9babf30d8c56160d01beffea8a95a6" - name = "gopkg.in/inf.v0" - packages = ["."] - pruneopts = "" - revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" - version = "v0.9.1" - -[[projects]] - digest = "1:cedccf16b71e86db87a24f8d4c70b0a855872eb967cb906a66b95de56aefbd0d" - name = "gopkg.in/yaml.v2" - packages = ["."] - pruneopts = "" - revision = "51d6538a90f86fe93ac480b35f37b2be17fef232" - version = "v2.2.2" - -[[projects]] - digest = "1:be67264067c68b1f601bfc4a6c102b1380ed0743147381de81ed11da88d2e246" - name = "k8s.io/api" - packages = [ - "admissionregistration/v1alpha1", - "admissionregistration/v1beta1", - "apps/v1", - "apps/v1beta1", - "apps/v1beta2", - "auditregistration/v1alpha1", - "authentication/v1", - "authentication/v1beta1", - "authorization/v1", - "authorization/v1beta1", - "autoscaling/v1", - "autoscaling/v2beta1", - "autoscaling/v2beta2", - "batch/v1", - "batch/v1beta1", - "batch/v2alpha1", - "certificates/v1beta1", - "coordination/v1beta1", - "core/v1", - "events/v1beta1", - "extensions/v1beta1", - "networking/v1", - "policy/v1beta1", - "rbac/v1", - "rbac/v1alpha1", - "rbac/v1beta1", - "scheduling/v1alpha1", - "scheduling/v1beta1", - "settings/v1alpha1", - "storage/v1", - "storage/v1alpha1", - "storage/v1beta1", - ] - pruneopts = "" - revision = "89a74a8d264df0e993299876a8cde88379b940ee" - version = "kubernetes-1.13.0" - -[[projects]] - digest = "1:002f84e9f3a08359c968075f8effc76b898dd901459a63817f9d9c568e3a5a57" - name = "k8s.io/apimachinery" - packages = [ - "pkg/api/errors", - "pkg/api/meta", - "pkg/api/resource", - "pkg/apis/meta/v1", - "pkg/apis/meta/v1/unstructured", - "pkg/apis/meta/v1beta1", - "pkg/conversion", - "pkg/conversion/queryparams", - "pkg/fields", - "pkg/labels", - "pkg/runtime", - "pkg/runtime/schema", - "pkg/runtime/serializer", - "pkg/runtime/serializer/json", - "pkg/runtime/serializer/protobuf", - "pkg/runtime/serializer/recognizer", - "pkg/runtime/serializer/streaming", - "pkg/runtime/serializer/versioning", - "pkg/selection", - "pkg/types", - "pkg/util/clock", - "pkg/util/errors", - "pkg/util/framer", - "pkg/util/intstr", - "pkg/util/json", - "pkg/util/naming", - "pkg/util/net", - "pkg/util/runtime", - "pkg/util/sets", - "pkg/util/validation", - "pkg/util/validation/field", - "pkg/util/wait", - "pkg/util/yaml", - "pkg/version", - "pkg/watch", - "third_party/forked/golang/reflect", - ] - pruneopts = "" - revision = "d7deff9243b165ee192f5551710ea4285dcfd615" - version = "kubernetes-1.14.0-rc.1" - -[[projects]] - digest = "1:96ab89894f66b77a0137bba12e607c6a9be992acadfb075b5602939e8519a157" - name = "k8s.io/client-go" - packages = [ - "discovery", - "kubernetes", - "kubernetes/scheme", - "kubernetes/typed/admissionregistration/v1alpha1", - "kubernetes/typed/admissionregistration/v1beta1", - "kubernetes/typed/apps/v1", - "kubernetes/typed/apps/v1beta1", - "kubernetes/typed/apps/v1beta2", - "kubernetes/typed/auditregistration/v1alpha1", - "kubernetes/typed/authentication/v1", - "kubernetes/typed/authentication/v1beta1", - "kubernetes/typed/authorization/v1", - "kubernetes/typed/authorization/v1beta1", - "kubernetes/typed/autoscaling/v1", - "kubernetes/typed/autoscaling/v2beta1", - "kubernetes/typed/autoscaling/v2beta2", - "kubernetes/typed/batch/v1", - "kubernetes/typed/batch/v1beta1", - "kubernetes/typed/batch/v2alpha1", - "kubernetes/typed/certificates/v1beta1", - "kubernetes/typed/coordination/v1beta1", - "kubernetes/typed/core/v1", - "kubernetes/typed/events/v1beta1", - "kubernetes/typed/extensions/v1beta1", - "kubernetes/typed/networking/v1", - "kubernetes/typed/policy/v1beta1", - "kubernetes/typed/rbac/v1", - "kubernetes/typed/rbac/v1alpha1", - "kubernetes/typed/rbac/v1beta1", - "kubernetes/typed/scheduling/v1alpha1", - "kubernetes/typed/scheduling/v1beta1", - "kubernetes/typed/settings/v1alpha1", - "kubernetes/typed/storage/v1", - "kubernetes/typed/storage/v1alpha1", - "kubernetes/typed/storage/v1beta1", - "pkg/apis/clientauthentication", - "pkg/apis/clientauthentication/v1alpha1", - "pkg/apis/clientauthentication/v1beta1", - "pkg/version", - "plugin/pkg/client/auth/exec", - "rest", - "rest/watch", - "tools/auth", - "tools/clientcmd", - "tools/clientcmd/api", - "tools/clientcmd/api/latest", - "tools/clientcmd/api/v1", - "tools/metrics", - "tools/reference", - "transport", - "util/cert", - "util/connrotation", - "util/flowcontrol", - "util/homedir", - "util/integer", - ] - pruneopts = "" - revision = "e64494209f554a6723674bd494d69445fb76a1d4" - version = "v10.0.0" - -[[projects]] - digest = "1:5afb58506f8972419a6e93f051513854291127189f04607aac1388eb378c0608" - name = "k8s.io/klog" - packages = ["."] - pruneopts = "" - revision = "71442cd4037d612096940ceb0f3fec3f7fff66e0" - version = "v0.2.0" - -[[projects]] - digest = "1:321081b4a44256715f2b68411d8eda9a17f17ebfe6f0cc61d2cc52d11c08acfa" - name = "sigs.k8s.io/yaml" - packages = ["."] - pruneopts = "" - revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" - version = "v1.1.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/docopt/docopt-go", - "github.com/sirupsen/logrus", - "gopkg.in/yaml.v2", - "k8s.io/api/core/v1", - "k8s.io/apimachinery/pkg/api/resource", - "k8s.io/apimachinery/pkg/apis/meta/v1", - "k8s.io/apimachinery/pkg/util/wait", - "k8s.io/apimachinery/pkg/util/yaml", - "k8s.io/apimachinery/pkg/watch", - "k8s.io/client-go/kubernetes", - "k8s.io/client-go/tools/clientcmd", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index e0b9008..197ee7f 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -27,10 +27,10 @@ name = "github.com/sirupsen/logrus" version = "1.0.4" -[[constraint]] - version = "kubernetes-1.14.0-rc.1" - name = "k8s.io/apimachinery" +# [[constraint]] +# version = "kubernetes-1.14.0-rc.1" +# name = "k8s.io/apimachinery" -[[constraint]] - version = "kubernetes-1.13.0" - name = "k8s.io/api" +# [[constraint]] +# version = "kubernetes-1.13.0" +# name = "k8s.io/api" diff --git a/cmd/npsim/main.go b/cmd/npsim/main.go index e8925c3..bd9ce06 100644 --- a/cmd/npsim/main.go +++ b/cmd/npsim/main.go @@ -9,7 +9,6 @@ import ( "github.com/docopt/docopt-go" log "github.com/sirupsen/logrus" "k8s.io/client-go/kubernetes" - "github.com/IntelAI/nodus/pkg/client" "github.com/IntelAI/nodus/pkg/config" "github.com/IntelAI/nodus/pkg/node" @@ -49,7 +48,13 @@ Options: // Construct apiserver client master, _ := args.String("--master") kubeconfigPath, _ := args.String("--kubeconfig") - client, err := client.NewK8sClient(master, kubeconfigPath) + cl, err := client.NewK8sClient(master, kubeconfigPath) + if err != nil { + log.WithFields(log.Fields{"error": err.Error()}).Error("failed to construct kubernetes client") + os.Exit(1) + } + + heartbeat, err := client.NewK8sHeartbeatClient(master, kubeconfigPath) if err != nil { log.WithFields(log.Fields{"error": err.Error()}).Error("failed to construct kubernetes client") os.Exit(1) @@ -62,7 +67,7 @@ Options: log.Info("Creating nodes...") nodes := makeNodes(nodeConfig) - err = start(nodes, client) + err = start(nodes, cl, heartbeat) if err != nil { log.WithFields(log.Fields{"error": err.Error()}).Error("failed to start nodes") os.Exit(1) @@ -91,9 +96,9 @@ func makeNodes(nodeConfig *config.NodeConfig) []node.FakeNode { return nodes } -func start(nodes []node.FakeNode, client *kubernetes.Clientset) (err error) { +func start(nodes []node.FakeNode, kubeClient *kubernetes.Clientset, heartbeatClient *kubernetes.Clientset) (err error) { for _, n := range nodes { - if err = n.Start(client); err != nil { + if err = n.Start(kubeClient, heartbeatClient); err != nil { log.WithFields(log.Fields{ "node": n.Name(), "error": err.Error(), diff --git a/cmd/nptest/main.go b/cmd/nptest/main.go index 292b1d8..1404de4 100644 --- a/cmd/nptest/main.go +++ b/cmd/nptest/main.go @@ -76,6 +76,12 @@ Options: os.Exit(1) } + heartbeat, err := client.NewK8sHeartbeatClient(master, kubeconfigPath) + if err != nil { + log.WithFields(log.Fields{"error": err.Error()}).Error("failed to construct heartbeat client") + os.Exit(1) + } + dynamicClientSet, err := client.NewDynamicClient(master, kubeconfigPath) if err != nil { log.WithFields(log.Fields{"error": err.Error()}).Error("failed to construct dynamic client") @@ -86,7 +92,7 @@ Options: namespace, _ := args.String("--namespace") dynamicClient := dynamic.NewDynamicClient(dynamicClientSet, k8sclient, namespace) - runner := exec.NewScenarioRunner(k8sclient, namespace, nodeConfig, podConfig, dynamicClient) + runner := exec.NewScenarioRunner(k8sclient, heartbeat, namespace, nodeConfig, podConfig, dynamicClient) err = runner.RunScenario(scenario) if err != nil { log.WithFields(log.Fields{"error": err.Error()}).Error("failed to complete scenario") diff --git a/pkg/client/k8s.go b/pkg/client/k8s.go index d6a96d6..949e89b 100644 --- a/pkg/client/k8s.go +++ b/pkg/client/k8s.go @@ -1,6 +1,7 @@ package client import ( + "time" log "github.com/sirupsen/logrus" dynamic "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -29,6 +30,16 @@ func NewK8sClient(master string, kubeconfigPath string) (*kubernetes.Clientset, return kubernetes.NewForConfig(kconfig) } +func NewK8sHeartbeatClient(master string, kubeconfigPath string) (*kubernetes.Clientset, error) { + kconfig, err := NewClientConfig(master, kubeconfigPath) + kconfig.Timeout = 30 * time.Second + kconfig.QPS = float32(-1) + if err != nil { + return nil, err + } + return kubernetes.NewForConfig(kconfig) +} + func NewDynamicClient(master string, kubeconfigPath string) (dynamic.Interface, error) { kconfig, err := NewClientConfig(master, kubeconfigPath) if err != nil { diff --git a/pkg/exec/runner.go b/pkg/exec/runner.go index 44fdf52..3104f0d 100644 --- a/pkg/exec/runner.go +++ b/pkg/exec/runner.go @@ -9,7 +9,6 @@ import ( log "github.com/sirupsen/logrus" "k8s.io/client-go/kubernetes" - "github.com/IntelAI/nodus/pkg/config" "github.com/IntelAI/nodus/pkg/dynamic" "github.com/IntelAI/nodus/pkg/node" @@ -28,9 +27,10 @@ type ScenarioRunner interface { Shutdown() } -func NewScenarioRunner(client *kubernetes.Clientset, namespace string, nodeConfig *config.NodeConfig, podConfig *config.PodConfig, dynamicClient *dynamic.DynamicClient) ScenarioRunner { +func NewScenarioRunner(client *kubernetes.Clientset, heartbeat *kubernetes.Clientset, namespace string, nodeConfig *config.NodeConfig, podConfig *config.PodConfig, dynamicClient *dynamic.DynamicClient) ScenarioRunner { return &runner{ client: client, + heartbeat: heartbeat, namespace: namespace, nodeConfig: nodeConfig, podConfig: podConfig, @@ -43,6 +43,7 @@ func NewScenarioRunner(client *kubernetes.Clientset, namespace string, nodeConfi type runner struct { client *kubernetes.Clientset + heartbeat *kubernetes.Clientset dynamicClient *dynamic.DynamicClient namespace string podConfig *config.PodConfig @@ -226,7 +227,7 @@ func (r *runner) createNode(create *config.CreateStep) error { for i := uint64(0); i < create.Count; i++ { nodeName := fmt.Sprintf("%s-%d", class.Name, i) n := node.NewFakeNode(nodeName, class.Name, class.Labels, class.Resources) - err := n.Start(r.client) + err := n.Start(r.client, r.heartbeat) if err != nil { return fmt.Errorf("could not create node of class: %s, err: %s", create.Class, err.Error()) } diff --git a/pkg/node/fakenode.go b/pkg/node/fakenode.go index dee9d89..83c022b 100644 --- a/pkg/node/fakenode.go +++ b/pkg/node/fakenode.go @@ -7,11 +7,14 @@ import ( log "github.com/sirupsen/logrus" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes" - + nodeutil "k8s.io/kubernetes/pkg/util/node" "github.com/IntelAI/nodus/pkg/config" + // "encoding/json" ) const NodeClassLabel = "np.class" @@ -33,15 +36,17 @@ func NewFakeNode(name string, class string, labels map[string]string, resources type FakeNode interface { Name() string Class() string - Start(client *kubernetes.Clientset) error + Start(kubeClient *kubernetes.Clientset, heartbeatClient *kubernetes.Clientset) error Stop() error } type fakeNode struct { name string class string - client *kubernetes.Clientset + kubeClient *kubernetes.Clientset + heartbeatClient *kubernetes.Clientset node *v1.Node + nodeRef *v1.ObjectReference labels map[string]string resources config.NodeResources pods PodSet @@ -57,14 +62,25 @@ func (n *fakeNode) Class() string { return n.class } -func (n *fakeNode) Start(client *kubernetes.Clientset) error { - n.client = client +func (n *fakeNode) Start(kubeClient *kubernetes.Clientset, heartbeatClient *kubernetes.Clientset) error { + n.kubeClient = kubeClient + n.heartbeatClient = heartbeatClient + + n.nodeRef = &v1.ObjectReference{ + Kind: "Node", + Name: string(n.name), + UID: types.UID(n.name), + Namespace: "", + } + err := n.startWatchingPods() if err != nil { return err } n.startUpdatingPods() - return n.register() + n.register() + + return n.startNodeStatusUpdates() } func (n *fakeNode) Stop() error { @@ -79,14 +95,32 @@ func (n *fakeNode) register() error { return err } n.node = node - node, err = n.client.CoreV1().Nodes().Create(node) + node, err = n.kubeClient.CoreV1().Nodes().Create(node) if err != nil { return err } n.node = node + return nil } +func (n *fakeNode) startNodeStatusUpdates() error { + go wait.Until(n.setNodeStatus, 30 * time.Second, wait.NeverStop) + return nil +} + +func (n *fakeNode) setNodeStatus() { + // Patch the current status on the API server + + + for i := range n.node.Status.Conditions { + err := nodeutil.SetNodeCondition(n.heartbeatClient, types.NodeName(n.name), n.node.Status.Conditions[i]) + if err != nil { + log.Error("Unable to update node condition: %v", err) + } + } +} + func (n *fakeNode) startWatchingPods() error { // Only list/watch pods bound to this node lOpts := metav1.ListOptions{ @@ -94,7 +128,7 @@ func (n *fakeNode) startWatchingPods() error { FieldSelector: fmt.Sprintf("spec.nodeName=%s", n.name), } namespace := "" - podWatch, err := n.client.CoreV1().Pods(namespace).Watch(lOpts) + podWatch, err := n.kubeClient.CoreV1().Pods(namespace).Watch(lOpts) if err != nil { return err } @@ -170,7 +204,7 @@ func (n *fakeNode) finalizeDeletedPod(pod *v1.Pod) { log.WithFields(log.Fields{"node": n.name, "pod": pod.Name}).Debug("finalizing pod") gracePeriod := int64(0) opts := &metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod} - n.client.CoreV1().Pods(pod.Namespace).Delete(pod.Name, opts) + n.kubeClient.CoreV1().Pods(pod.Namespace).Delete(pod.Name, opts) } func (n *fakeNode) unregister() error { @@ -181,7 +215,7 @@ func (n *fakeNode) unregister() error { // Delete this node immediately gracePeriod := int64(0) opts := &metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod} - return n.client.CoreV1().Nodes().Delete(n.name, opts) + return n.kubeClient.CoreV1().Nodes().Delete(n.name, opts) } // Updates the list of pods to the desired phase, on a best-effort basis. @@ -192,7 +226,7 @@ func (n *fakeNode) tryUpdatePodPhase(phase v1.PodPhase, pods ...*v1.Pod) { for _, pod := range pods { originalPhase := pod.Status.Phase - podClient := n.client.CoreV1().Pods(pod.Namespace) + podClient := n.kubeClient.CoreV1().Pods(pod.Namespace) var copy v1.Pod copy = *pod @@ -296,10 +330,34 @@ func (n *fakeNode) k8sNode() (*v1.Node, error) { v1.NodeCondition{ Type: v1.NodeReady, Status: v1.ConditionTrue, + Reason: "KubeletReady", + Message: "kubelet is posting ready status", + LastTransitionTime: metav1.Now(), + }, + v1.NodeCondition{ + Type: v1.NodeMemoryPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasInsufficientMemory", + Message: "kubelet has insufficient memory available", + LastTransitionTime: metav1.Now(), }, + v1.NodeCondition{ + Type: v1.NodePIDPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasSufficientPID", + Message: "kubelet has sufficient PID available", + LastTransitionTime: metav1.Now(), + }, + v1.NodeCondition{ + Type: v1.NodeDiskPressure, + Status: v1.ConditionFalse, + Reason: "KubeletHasNoDiskPressure", + Message: "kubelet has no disk pressure", + LastTransitionTime: metav1.Now(), + }, }, }, - } - + } + return &node, nil } diff --git a/pkg/nptest/api.go b/pkg/nptest/api.go index 809a683..704603c 100644 --- a/pkg/nptest/api.go +++ b/pkg/nptest/api.go @@ -21,6 +21,12 @@ func New(namespace string, kubeInfo config.KubeInfo, nodeConfig *config.NodeConf os.Exit(1) } + heartbeat, err := client.NewK8sHeartbeatClient(kubeInfo.Master, kubeInfo.KconfigPath) + if err != nil { + log.WithFields(log.Fields{"error": err.Error()}).Error("failed to construct heartbeat client") + os.Exit(1) + } + dynamicClientSet, err := client.NewDynamicClient(kubeInfo.Master, kubeInfo.KconfigPath) if err != nil { log.WithFields(log.Fields{"error": err.Error()}).Error("failed to construct dynamic client") @@ -28,7 +34,7 @@ func New(namespace string, kubeInfo config.KubeInfo, nodeConfig *config.NodeConf } dynamicClient := dynamic.NewDynamicClient(dynamicClientSet, k8sclient, namespace) - runner := exec.NewScenarioRunner(k8sclient, namespace, nodeConfig, podConfig, dynamicClient) + runner := exec.NewScenarioRunner(k8sclient, heartbeat, namespace, nodeConfig, podConfig, dynamicClient) return &nptest{ client: k8sclient,