diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 00000000..9b9b5ce2 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,744 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "default" + name = "bitbucket.org/ww/goautoneg" + packages = ["."] + revision = "75cd24fc2f2c2a2088577d12123ddee5f54e0675" + +[[projects]] + name = "github.com/NYTimes/gziphandler" + packages = ["."] + revision = "56545f4a5d46df9a6648819d1664c3a03a13ffdb" + +[[projects]] + name = "github.com/PuerkitoBio/purell" + packages = ["."] + revision = "8a290539e2e8629dbc4e6bad948158f790ec31f4" + version = "v1.0.0" + +[[projects]] + name = "github.com/PuerkitoBio/urlesc" + packages = ["."] + revision = "5bd2802263f21d8788851d5305584c82a5c75d7e" + +[[projects]] + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "3ac7bf7a47d159a033b107610db8a1b6575507a4" + +[[projects]] + name = "github.com/coreos/etcd" + packages = [ + "auth/authpb", + "client", + "clientv3", + "etcdserver/api/v3rpc/rpctypes", + "etcdserver/etcdserverpb", + "mvcc/mvccpb", + "pkg/fileutil", + "pkg/pathutil", + "pkg/tlsutil", + "pkg/transport", + "pkg/types" + ] + revision = "0520cb9304cb2385f7e72b8bc02d6e4d3257158a" + version = "v3.1.10" + +[[projects]] + name = "github.com/coreos/go-systemd" + packages = [ + "daemon", + "journal" + ] + revision = "48702e0da86bd25e76cfef347e2adeb434a0d0a6" + version = "v14" + +[[projects]] + name = "github.com/coreos/pkg" + packages = ["capnslog"] + revision = "fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/directxman12/k8s-prometheus-adapter" + packages = [ + "cmd/adapter/app", + "pkg/client", + "pkg/client/metrics", + "pkg/custom-provider" + ] + revision = "8dd527d821f46b9e3961f3f7e5fdf5131d95681c" + version = "v0.2.0" + +[[projects]] + name = "github.com/elazarl/go-bindata-assetfs" + packages = ["."] + revision = "3dcc96556217539f50599357fb481ac0dc7439b9" + +[[projects]] + name = "github.com/emicklei/go-restful" + packages = [ + ".", + "log" + ] + revision = "ff4f55a206334ef123e4f79bbf348980da81ca46" + +[[projects]] + name = "github.com/emicklei/go-restful-swagger12" + packages = ["."] + revision = "dcef7f55730566d41eae5db10e7d6981829720f6" + version = "1.0.1" + +[[projects]] + name = "github.com/evanphx/json-patch" + packages = ["."] + revision = "944e07253867aacae43c04b2e6a239005443f33a" + +[[projects]] + name = "github.com/ghodss/yaml" + packages = ["."] + revision = "73d445a93680fa1a78ae23a5839bad48f32ba1ee" + +[[projects]] + name = "github.com/go-openapi/jsonpointer" + packages = ["."] + revision = "46af16f9f7b149af66e5d1bd010e3574dc06de98" + +[[projects]] + name = "github.com/go-openapi/jsonreference" + packages = ["."] + revision = "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" + +[[projects]] + name = "github.com/go-openapi/spec" + packages = ["."] + revision = "6aced65f8501fe1217321abf0749d354824ba2ff" + +[[projects]] + name = "github.com/go-openapi/swag" + packages = ["."] + revision = "1d0bd113de87027671077d3c71eb3ac5d7dbba72" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "proto", + "sortkeys" + ] + revision = "c0656edd0d9eab7c66d1eb0c568f9039345796f7" + +[[projects]] + name = "github.com/golang/glog" + packages = ["."] + revision = "44145f04b68cf362d9c4df2182967c2275eaefed" + +[[projects]] + name = "github.com/golang/protobuf" + packages = [ + "jsonpb", + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp" + ] + revision = "4bd1920723d7b7c925de087aa32e2187708897f7" + +[[projects]] + name = "github.com/google/btree" + packages = ["."] + revision = "7d79101e329e5a3adf994758c578dab82b90c017" + +[[projects]] + name = "github.com/google/gofuzz" + packages = ["."] + revision = "44d81051d367757e1c7c6a5a86423ece9afcf63c" + +[[projects]] + name = "github.com/googleapis/gnostic" + packages = [ + "OpenAPIv2", + "compiler", + "extensions" + ] + revision = "0c5108395e2debce0d731cf0287ddf7242066aba" + +[[projects]] + name = "github.com/gregjones/httpcache" + packages = [ + ".", + "diskcache" + ] + revision = "787624de3eb7bd915c329cba748687a3b22666a6" + +[[projects]] + name = "github.com/grpc-ecosystem/go-grpc-prometheus" + packages = ["."] + revision = "2500245aa6110c562d17020fb31a2c133d737799" + +[[projects]] + name = "github.com/grpc-ecosystem/grpc-gateway" + packages = [ + "runtime", + "runtime/internal", + "utilities" + ] + revision = "84398b94e188ee336f307779b57b3aa91af7063c" + +[[projects]] + name = "github.com/hashicorp/golang-lru" + packages = [ + ".", + "simplelru" + ] + revision = "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" + +[[projects]] + branch = "master" + name = "github.com/howeyc/gopass" + packages = ["."] + revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8" + +[[projects]] + name = "github.com/imdario/mergo" + packages = ["."] + revision = "6633656539c1639d9d78127b7d47c622b5d7b6dc" + +[[projects]] + name = "github.com/inconshreveable/mousetrap" + packages = ["."] + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + +[[projects]] + name = "github.com/json-iterator/go" + packages = ["."] + revision = "36b14963da70d11297d313183d7e6388c8510e1e" + version = "1.0.0" + +[[projects]] + name = "github.com/juju/ratelimit" + packages = ["."] + revision = "5b9ff866471762aa2ab2dced63c9fb6f53921342" + version = "1.0" + +[[projects]] + name = "github.com/kubernetes-incubator/custom-metrics-apiserver" + packages = [ + "pkg/apiserver", + "pkg/apiserver/installer", + "pkg/cmd/server", + "pkg/dynamicmapper", + "pkg/provider", + "pkg/registry/custom_metrics", + "pkg/registry/external_metrics" + ] + revision = "e61f72fec56ab519d74ebd396cd3fcf31b084558" + +[[projects]] + name = "github.com/mailru/easyjson" + packages = [ + "buffer", + "jlexer", + "jwriter" + ] + revision = "d5b7844b561a7bc640052f1b935f7b800330d7e0" + +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a" + +[[projects]] + branch = "master" + name = "github.com/mxk/go-flowrate" + packages = ["flowrate"] + revision = "cca7078d478f8520f85629ad7c68962d31ed7682" + +[[projects]] + name = "github.com/pborman/uuid" + packages = ["."] + revision = "ca53cad383cad2479bbba7f7a1a05797ec1386e4" + +[[projects]] + branch = "master" + name = "github.com/petar/GoLLRB" + packages = ["llrb"] + revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" + +[[projects]] + name = "github.com/peterbourgon/diskv" + packages = ["."] + revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" + version = "v2.0.1" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "a22138067af1c4942683050411a841ade67fe1eb" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/prometheus/client_golang" + packages = ["prometheus"] + revision = "e7e903064f5e9eb5da98208bae10b475d4db0f8c" + +[[projects]] + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "fa8ad6fec33561be4280a8f0514318c79d7f6cb6" + +[[projects]] + name = "github.com/prometheus/common" + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model" + ] + revision = "13ba4ddd0caa9c28ca7b7bffe1dfa9ed8d5ef207" + +[[projects]] + name = "github.com/prometheus/procfs" + packages = [ + ".", + "xfs" + ] + revision = "65c1f6f8f0fc1e2185eb9863a3bc751496404259" + +[[projects]] + name = "github.com/spf13/cobra" + packages = ["."] + revision = "f62e98d28ab7ad31d707ba837a966378465c7b57" + +[[projects]] + name = "github.com/spf13/pflag" + packages = ["."] + revision = "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + +[[projects]] + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require" + ] + revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" + version = "v1.2.2" + +[[projects]] + name = "github.com/ugorji/go" + packages = ["codec"] + revision = "ded73eae5db7e7a0ef6f55aace87a2873c5d2b74" + +[[projects]] + name = "golang.org/x/crypto" + packages = ["ssh/terminal"] + revision = "81e90905daefcd6fd217b62423c0908922eadb30" + +[[projects]] + name = "golang.org/x/net" + packages = [ + "context", + "html", + "html/atom", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "lex/httplex", + "trace", + "websocket" + ] + revision = "1c05540f6879653db88113bc4a2b70aec4bd491f" + +[[projects]] + name = "golang.org/x/sys" + packages = [ + "unix", + "windows" + ] + revision = "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "cases", + "internal", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "runes", + "secure/bidirule", + "secure/precis", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + "width" + ] + revision = "b19bf474d317b857955b12035d2c5acb57ce8b01" + +[[projects]] + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + revision = "09f6ed296fc66555a25fe4ce95173148778dfa85" + +[[projects]] + name = "google.golang.org/grpc" + packages = [ + ".", + "codes", + "credentials", + "grpclb/grpc_lb_v1", + "grpclog", + "internal", + "keepalive", + "metadata", + "naming", + "peer", + "stats", + "status", + "tap", + "transport" + ] + revision = "d2e1b51f33ff8c5e4a15560ff049d200e83726c5" + version = "v1.3.0" + +[[projects]] + name = "gopkg.in/inf.v0" + packages = ["."] + revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" + version = "v0.9.0" + +[[projects]] + name = "gopkg.in/natefinch/lumberjack.v2" + packages = ["."] + revision = "20b71e5b60d756d3d2f80def009790325acc2b23" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "53feefa2559fb8dfa8d81baad31be332c97d6c77" + +[[projects]] + name = "k8s.io/api" + packages = [ + "admissionregistration/v1alpha1", + "apps/v1beta1", + "apps/v1beta2", + "authentication/v1", + "authentication/v1beta1", + "authorization/v1", + "authorization/v1beta1", + "autoscaling/v1", + "autoscaling/v2beta1", + "batch/v1", + "batch/v1beta1", + "batch/v2alpha1", + "certificates/v1beta1", + "core/v1", + "extensions/v1beta1", + "networking/v1", + "policy/v1beta1", + "rbac/v1", + "rbac/v1alpha1", + "rbac/v1beta1", + "scheduling/v1alpha1", + "settings/v1alpha1", + "storage/v1", + "storage/v1beta1" + ] + revision = "cadaf100c0a3dd6b254f320d6d651df079ec8e0a" + +[[projects]] + name = "k8s.io/apimachinery" + packages = [ + "pkg/api/equality", + "pkg/api/errors", + "pkg/api/meta", + "pkg/api/resource", + "pkg/api/validation", + "pkg/api/validation/path", + "pkg/apimachinery", + "pkg/apimachinery/announced", + "pkg/apimachinery/registered", + "pkg/apis/meta/internalversion", + "pkg/apis/meta/v1", + "pkg/apis/meta/v1/unstructured", + "pkg/apis/meta/v1/validation", + "pkg/apis/meta/v1alpha1", + "pkg/conversion", + "pkg/conversion/queryparams", + "pkg/conversion/unstructured", + "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/cache", + "pkg/util/clock", + "pkg/util/diff", + "pkg/util/errors", + "pkg/util/framer", + "pkg/util/httpstream", + "pkg/util/intstr", + "pkg/util/json", + "pkg/util/mergepatch", + "pkg/util/net", + "pkg/util/proxy", + "pkg/util/rand", + "pkg/util/runtime", + "pkg/util/sets", + "pkg/util/strategicpatch", + "pkg/util/uuid", + "pkg/util/validation", + "pkg/util/validation/field", + "pkg/util/wait", + "pkg/util/yaml", + "pkg/version", + "pkg/watch", + "third_party/forked/golang/json", + "third_party/forked/golang/netutil", + "third_party/forked/golang/reflect" + ] + revision = "3b05bbfa0a45413bfa184edbf9af617e277962fb" + version = "kubernetes-1.9.0-alpha.1" + +[[projects]] + name = "k8s.io/apiserver" + packages = [ + "pkg/admission", + "pkg/admission/initializer", + "pkg/admission/plugin/namespace/lifecycle", + "pkg/apis/apiserver", + "pkg/apis/apiserver/install", + "pkg/apis/apiserver/v1alpha1", + "pkg/apis/audit", + "pkg/apis/audit/install", + "pkg/apis/audit/v1alpha1", + "pkg/apis/audit/v1beta1", + "pkg/apis/audit/validation", + "pkg/audit", + "pkg/audit/policy", + "pkg/authentication/authenticator", + "pkg/authentication/authenticatorfactory", + "pkg/authentication/group", + "pkg/authentication/request/anonymous", + "pkg/authentication/request/bearertoken", + "pkg/authentication/request/headerrequest", + "pkg/authentication/request/union", + "pkg/authentication/request/websocket", + "pkg/authentication/request/x509", + "pkg/authentication/serviceaccount", + "pkg/authentication/token/tokenfile", + "pkg/authentication/user", + "pkg/authorization/authorizer", + "pkg/authorization/authorizerfactory", + "pkg/authorization/union", + "pkg/endpoints", + "pkg/endpoints/discovery", + "pkg/endpoints/filters", + "pkg/endpoints/handlers", + "pkg/endpoints/handlers/negotiation", + "pkg/endpoints/handlers/responsewriters", + "pkg/endpoints/metrics", + "pkg/endpoints/openapi", + "pkg/endpoints/request", + "pkg/features", + "pkg/registry/generic", + "pkg/registry/generic/registry", + "pkg/registry/rest", + "pkg/server", + "pkg/server/filters", + "pkg/server/healthz", + "pkg/server/httplog", + "pkg/server/mux", + "pkg/server/options", + "pkg/server/routes", + "pkg/server/routes/data/swagger", + "pkg/server/storage", + "pkg/storage", + "pkg/storage/errors", + "pkg/storage/etcd", + "pkg/storage/etcd/metrics", + "pkg/storage/etcd/util", + "pkg/storage/etcd3", + "pkg/storage/etcd3/preflight", + "pkg/storage/names", + "pkg/storage/storagebackend", + "pkg/storage/storagebackend/factory", + "pkg/storage/value", + "pkg/util/feature", + "pkg/util/flag", + "pkg/util/flushwriter", + "pkg/util/logs", + "pkg/util/trace", + "pkg/util/webhook", + "pkg/util/wsstream", + "plugin/pkg/audit/log", + "plugin/pkg/audit/webhook", + "plugin/pkg/authenticator/token/webhook", + "plugin/pkg/authorizer/webhook" + ] + revision = "c1e53d745d0fe45bf7d5d44697e6eface25fceca" + version = "kubernetes-1.9.0-alpha.1" + +[[projects]] + name = "k8s.io/client-go" + packages = [ + "discovery", + "dynamic", + "dynamic/fake", + "informers", + "informers/admissionregistration", + "informers/admissionregistration/v1alpha1", + "informers/apps", + "informers/apps/v1beta1", + "informers/apps/v1beta2", + "informers/autoscaling", + "informers/autoscaling/v1", + "informers/autoscaling/v2beta1", + "informers/batch", + "informers/batch/v1", + "informers/batch/v1beta1", + "informers/batch/v2alpha1", + "informers/certificates", + "informers/certificates/v1beta1", + "informers/core", + "informers/core/v1", + "informers/extensions", + "informers/extensions/v1beta1", + "informers/internalinterfaces", + "informers/networking", + "informers/networking/v1", + "informers/policy", + "informers/policy/v1beta1", + "informers/rbac", + "informers/rbac/v1", + "informers/rbac/v1alpha1", + "informers/rbac/v1beta1", + "informers/scheduling", + "informers/scheduling/v1alpha1", + "informers/settings", + "informers/settings/v1alpha1", + "informers/storage", + "informers/storage/v1", + "informers/storage/v1beta1", + "kubernetes", + "kubernetes/scheme", + "kubernetes/typed/admissionregistration/v1alpha1", + "kubernetes/typed/apps/v1beta1", + "kubernetes/typed/apps/v1beta2", + "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/batch/v1", + "kubernetes/typed/batch/v1beta1", + "kubernetes/typed/batch/v2alpha1", + "kubernetes/typed/certificates/v1beta1", + "kubernetes/typed/core/v1", + "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/settings/v1alpha1", + "kubernetes/typed/storage/v1", + "kubernetes/typed/storage/v1beta1", + "listers/admissionregistration/v1alpha1", + "listers/apps/v1beta1", + "listers/apps/v1beta2", + "listers/autoscaling/v1", + "listers/autoscaling/v2beta1", + "listers/batch/v1", + "listers/batch/v1beta1", + "listers/batch/v2alpha1", + "listers/certificates/v1beta1", + "listers/core/v1", + "listers/extensions/v1beta1", + "listers/networking/v1", + "listers/policy/v1beta1", + "listers/rbac/v1", + "listers/rbac/v1alpha1", + "listers/rbac/v1beta1", + "listers/scheduling/v1alpha1", + "listers/settings/v1alpha1", + "listers/storage/v1", + "listers/storage/v1beta1", + "pkg/version", + "rest", + "rest/watch", + "testing", + "tools/auth", + "tools/cache", + "tools/clientcmd", + "tools/clientcmd/api", + "tools/clientcmd/api/latest", + "tools/clientcmd/api/v1", + "tools/metrics", + "tools/pager", + "tools/reference", + "transport", + "util/cert", + "util/flowcontrol", + "util/homedir", + "util/integer" + ] + revision = "82aa063804cf055e16e8911250f888bc216e8b61" + version = "kubernetes-1.9.0-alpha.1" + +[[projects]] + name = "k8s.io/kube-openapi" + packages = [ + "pkg/builder", + "pkg/common", + "pkg/handler", + "pkg/util" + ] + revision = "868f2f29720b192240e18284659231b440f9cda5" + +[[projects]] + branch = "master" + name = "k8s.io/metrics" + packages = [ + "pkg/apis/custom_metrics", + "pkg/apis/custom_metrics/install", + "pkg/apis/custom_metrics/v1beta1", + "pkg/apis/external_metrics", + "pkg/apis/external_metrics/install", + "pkg/apis/external_metrics/v1beta1" + ] + revision = "baa04983db4e01d02a16d9c9fe32dd5b478b3248" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ffa0ef091b3683f02efac4dc0a1a071ab5a0ff9741346b1532be064fb6c176c4" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 00000000..e93d8b2c --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,33 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + +[prune] + go-tests = true + unused-packages = true + +[[constraint]] + name = "github.com/kubernetes-incubator/custom-metrics-apiserver" + revision = "e61f72fec56ab519d74ebd396cd3fcf31b084558" diff --git a/cmd/adapter/app/start.go b/cmd/adapter/app/start.go index 7c7a8b60..2c68e482 100644 --- a/cmd/adapter/app/start.go +++ b/cmd/adapter/app/start.go @@ -176,7 +176,7 @@ func (o PrometheusAdapterServerOptions) RunCustomMetricsAdapterServer(stopCh <-c instrumentedGenericPromClient := mprom.InstrumentGenericAPIClient(genericPromClient, baseURL.String()) promClient := prom.NewClientForAPI(instrumentedGenericPromClient) - cmProvider := cmprov.NewPrometheusProvider(dynamicMapper, clientPool, promClient, o.LabelPrefix, o.MetricsRelistInterval, o.RateInterval, stopCh) + cmProvider := cmprov.NewCustomPrometheusProvider(dynamicMapper, clientPool, promClient, o.LabelPrefix, o.MetricsRelistInterval, o.RateInterval, stopCh) server, err := config.Complete().New("prometheus-custom-metrics-adapter", cmProvider) if err != nil { diff --git a/pkg/custom-provider/provider.go b/pkg/custom-provider/custom_provider.go similarity index 71% rename from pkg/custom-provider/provider.go rename to pkg/custom-provider/custom_provider.go index 9a529104..74d4723c 100644 --- a/pkg/custom-provider/provider.go +++ b/pkg/custom-provider/custom_provider.go @@ -19,28 +19,27 @@ package provider import ( "context" "fmt" - "github.com/golang/glog" "time" + "github.com/golang/glog" + "github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/provider" pmodel "github.com/prometheus/common/model" apierr "k8s.io/apimachinery/pkg/api/errors" apimeta "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/dynamic" "k8s.io/metrics/pkg/apis/custom_metrics" prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client" ) -type prometheusProvider struct { +type customPrometheusProvider struct { mapper apimeta.RESTMapper kubeClient dynamic.ClientPool promClient prom.Client @@ -50,7 +49,7 @@ type prometheusProvider struct { rateInterval time.Duration } -func NewPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.ClientPool, promClient prom.Client, labelPrefix string, updateInterval time.Duration, rateInterval time.Duration, stopChan <-chan struct{}) provider.CustomMetricsProvider { +func NewCustomPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.ClientPool, promClient prom.Client, labelPrefix string, updateInterval time.Duration, rateInterval time.Duration, stopChan <-chan struct{}) provider.CustomMetricsProvider { lister := &cachingMetricsLister{ updateInterval: updateInterval, promClient: promClient, @@ -67,7 +66,7 @@ func NewPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.ClientP lister.RunUntil(stopChan) - return &prometheusProvider{ + return &customPrometheusProvider{ mapper: mapper, kubeClient: kubeClient, promClient: promClient, @@ -78,7 +77,7 @@ func NewPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.ClientP } } -func (p *prometheusProvider) metricFor(value pmodel.SampleValue, groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) { +func (p *customPrometheusProvider) metricFor(value pmodel.SampleValue, groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) { kind, err := p.mapper.KindFor(groupResource.WithVersion("")) if err != nil { return nil, err @@ -92,12 +91,12 @@ func (p *prometheusProvider) metricFor(value pmodel.SampleValue, groupResource s Namespace: namespace, }, MetricName: metricName, - Timestamp: metav1.Time{time.Now()}, - Value: *resource.NewMilliQuantity(int64(value*1000.0), resource.DecimalSI), + Timestamp: metaV1.Time{time.Now()}, + Value: *resource.NewMilliQuantity(int64(value*1000.0), resource.DecimalSI).ToDec(), }, nil } -func (p *prometheusProvider) metricsFor(valueSet pmodel.Vector, info provider.MetricInfo, list runtime.Object) (*custom_metrics.MetricValueList, error) { +func (p *customPrometheusProvider) metricsFor(valueSet pmodel.Vector, info provider.CustomMetricInfo, list runtime.Object) (*custom_metrics.MetricValueList, error) { if !apimeta.IsListType(list) { return nil, apierr.NewInternalError(fmt.Errorf("result of label selector list operation was not a list")) } @@ -131,7 +130,7 @@ func (p *prometheusProvider) metricsFor(valueSet pmodel.Vector, info provider.Me }, nil } -func (p *prometheusProvider) buildQuery(info provider.MetricInfo, namespace string, names ...string) (pmodel.Vector, error) { +func (p *customPrometheusProvider) buildQuery(info provider.CustomMetricInfo, namespace string, names ...string) (pmodel.Vector, error) { kind, baseQuery, groupBy, found := p.QueryForMetric(info, namespace, names...) if !found { return nil, provider.NewMetricNotFoundError(info.GroupResource, info.Metric) @@ -169,7 +168,7 @@ func (p *prometheusProvider) buildQuery(info provider.MetricInfo, namespace stri return *queryResults.Vector, nil } -func (p *prometheusProvider) getSingle(info provider.MetricInfo, namespace, name string) (*custom_metrics.MetricValue, error) { +func (p *customPrometheusProvider) getSingle(info provider.CustomMetricInfo, namespace, name string) (*custom_metrics.MetricValue, error) { queryResults, err := p.buildQuery(info, namespace, name) if err != nil { return nil, err @@ -197,7 +196,7 @@ func (p *prometheusProvider) getSingle(info provider.MetricInfo, namespace, name return p.metricFor(resultValue, info.GroupResource, "", name, info.Metric) } -func (p *prometheusProvider) getMultiple(info provider.MetricInfo, namespace string, selector labels.Selector) (*custom_metrics.MetricValueList, error) { +func (p *customPrometheusProvider) getMultiple(info provider.CustomMetricInfo, namespace string, selector labels.Selector) (*custom_metrics.MetricValueList, error) { // construct a client to list the names of objects matching the label selector client, err := p.kubeClient.ClientForGroupVersionResource(info.GroupResource.WithVersion("")) if err != nil { @@ -207,14 +206,14 @@ func (p *prometheusProvider) getMultiple(info provider.MetricInfo, namespace str } // we can construct a this APIResource ourself, since the dynamic client only uses Name and Namespaced - apiRes := &metav1.APIResource{ + apiRes := &metaV1.APIResource{ Name: info.GroupResource.Resource, Namespaced: info.Namespaced, } // actually list the objects matching the label selector matchingObjectsRaw, err := client.Resource(apiRes, namespace). - List(metav1.ListOptions{LabelSelector: selector.String()}) + List(metaV1.ListOptions{LabelSelector: selector.String()}) if err != nil { glog.Errorf("unable to list matching resource names: %v", err) // don't leak implementation details to the user @@ -242,8 +241,8 @@ func (p *prometheusProvider) getMultiple(info provider.MetricInfo, namespace str return p.metricsFor(queryResults, info, matchingObjectsRaw) } -func (p *prometheusProvider) GetRootScopedMetricByName(groupResource schema.GroupResource, name string, metricName string) (*custom_metrics.MetricValue, error) { - info := provider.MetricInfo{ +func (p *customPrometheusProvider) GetRootScopedMetricByName(groupResource schema.GroupResource, name string, metricName string) (*custom_metrics.MetricValue, error) { + info := provider.CustomMetricInfo{ GroupResource: groupResource, Metric: metricName, Namespaced: false, @@ -252,8 +251,8 @@ func (p *prometheusProvider) GetRootScopedMetricByName(groupResource schema.Grou return p.getSingle(info, "", name) } -func (p *prometheusProvider) GetRootScopedMetricBySelector(groupResource schema.GroupResource, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) { - info := provider.MetricInfo{ +func (p *customPrometheusProvider) GetRootScopedMetricBySelector(groupResource schema.GroupResource, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) { + info := provider.CustomMetricInfo{ GroupResource: groupResource, Metric: metricName, Namespaced: false, @@ -261,8 +260,8 @@ func (p *prometheusProvider) GetRootScopedMetricBySelector(groupResource schema. return p.getMultiple(info, "", selector) } -func (p *prometheusProvider) GetNamespacedMetricByName(groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) { - info := provider.MetricInfo{ +func (p *customPrometheusProvider) GetNamespacedMetricByName(groupResource schema.GroupResource, namespace string, name string, metricName string) (*custom_metrics.MetricValue, error) { + info := provider.CustomMetricInfo{ GroupResource: groupResource, Metric: metricName, Namespaced: true, @@ -271,48 +270,11 @@ func (p *prometheusProvider) GetNamespacedMetricByName(groupResource schema.Grou return p.getSingle(info, namespace, name) } -func (p *prometheusProvider) GetNamespacedMetricBySelector(groupResource schema.GroupResource, namespace string, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) { - info := provider.MetricInfo{ +func (p *customPrometheusProvider) GetNamespacedMetricBySelector(groupResource schema.GroupResource, namespace string, selector labels.Selector, metricName string) (*custom_metrics.MetricValueList, error) { + info := provider.CustomMetricInfo{ GroupResource: groupResource, Metric: metricName, Namespaced: true, } return p.getMultiple(info, namespace, selector) } - -type cachingMetricsLister struct { - SeriesRegistry - - promClient prom.Client - updateInterval time.Duration -} - -func (l *cachingMetricsLister) Run() { - l.RunUntil(wait.NeverStop) -} - -func (l *cachingMetricsLister) RunUntil(stopChan <-chan struct{}) { - go wait.Until(func() { - if err := l.updateMetrics(); err != nil { - utilruntime.HandleError(err) - } - }, l.updateInterval, stopChan) -} - -func (l *cachingMetricsLister) updateMetrics() error { - startTime := pmodel.Now().Add(-1 * l.updateInterval) - - sels := l.Selectors() - - // TODO: use an actual context here - series, err := l.promClient.Series(context.Background(), pmodel.Interval{startTime, 0}, sels...) - if err != nil { - return fmt.Errorf("unable to update list of all available metrics: %v", err) - } - - glog.V(10).Infof("Set available metric list from Prometheus to: %v", series) - - l.SetSeries(series) - - return nil -} diff --git a/pkg/custom-provider/provider_test.go b/pkg/custom-provider/custom_provider_test.go similarity index 100% rename from pkg/custom-provider/provider_test.go rename to pkg/custom-provider/custom_provider_test.go diff --git a/pkg/custom-provider/external_provider.go b/pkg/custom-provider/external_provider.go new file mode 100644 index 00000000..743829a8 --- /dev/null +++ b/pkg/custom-provider/external_provider.go @@ -0,0 +1,162 @@ +/* +Copyright 2017 The Kubernetes 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 provider + +import ( + "fmt" + s "strings" + "time" + + "github.com/kubernetes-incubator/custom-metrics-apiserver/pkg/provider" + apimeta "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" + "k8s.io/client-go/dynamic" + "k8s.io/metrics/pkg/apis/external_metrics" + + prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client" +) + +type externalPrometheusProvider struct { + mapper apimeta.RESTMapper + kubeClient dynamic.ClientPool + promClient prom.Client + + SeriesRegistry + + rateInterval time.Duration +} + +func NewExternalPrometheusProvider(mapper apimeta.RESTMapper, kubeClient dynamic.ClientPool, promClient prom.Client, labelPrefix string, updateInterval time.Duration, rateInterval time.Duration, stopChan <-chan struct{}) provider.ExternalMetricsProvider { + lister := &cachingMetricsLister{ + updateInterval: updateInterval, + promClient: promClient, + + SeriesRegistry: &basicSeriesRegistry{ + namer: metricNamer{ + // TODO: populate the overrides list + overrides: nil, + mapper: mapper, + labelPrefix: labelPrefix, + }, + }, + } + + lister.RunUntil(stopChan) + + return &externalPrometheusProvider{ + mapper: mapper, + kubeClient: kubeClient, + promClient: promClient, + + SeriesRegistry: lister, + + rateInterval: rateInterval, + } +} + +func (p *externalPrometheusProvider) GetExternalMetric(namespace string, metricName string, metricSelector labels.Selector) (*external_metrics.ExternalMetricValueList, error) { + //TODO: Steps + //1. Generate a Prometheus Query. + // Something like my_metric{namespace="namespace" some_label="some_value"} + //2. Send that query to Prometheus. + //3. Adapt the results. + //The query generation for external metrics is much more straightforward + //than for custom metrics because no renaming is applied. + //So we'll just start with some simple string operations and see how far that gets us. + //Then I'll circle back and figure out how much code reuse I can get out of the original implementation. + namespaceSelector := p.makeLabelFilter("namespace", "=", namespace) + otherSelectors := p.convertSelectors(metricSelector) + + finalTargets := append([]string{namespaceSelector}, otherSelectors...) + + //TODO: Only here to stop compiler issues in this incomplete code. + fmt.Printf("len=%d", len(finalTargets)) + + //TODO: Construct a real result. + return nil, nil +} + +func (p *externalPrometheusProvider) makeLabelFilter(labelName string, operator string, targetValue string) string { + return fmt.Sprintf("%s%s\"%s\"", labelName, operator, targetValue) +} + +func (p *externalPrometheusProvider) convertSelectors(metricSelector labels.Selector) []string { + requirements, _ := metricSelector.Requirements() + + selectors := []string{} + for i := 0; i < len(requirements); i++ { + selector := p.convertRequirement(requirements[i]) + + selectors = append(selectors, selector) + } + + return selectors +} + +func (p *externalPrometheusProvider) convertRequirement(requirement labels.Requirement) string { + labelName := requirement.Key() + values := requirement.Values().List() + + stringValues := values[0] + + valueCount := len(values) + if valueCount > 1 { + stringValues = s.Join(values, "|") + } + + operator := p.selectOperator(requirement.Operator(), valueCount) + + return p.makeLabelFilter(labelName, operator, stringValues) +} + +func (p *externalPrometheusProvider) selectOperator(operator selection.Operator, valueCount int) string { + if valueCount > 1 { + return p.selectRegexOperator(operator) + } + + return p.selectSingleValueOperator(operator) +} + +func (p *externalPrometheusProvider) selectRegexOperator(operator selection.Operator) string { + switch operator { + case selection.Equals: + return "=~" + case selection.NotEquals: + return "!~" + } + + //TODO: Cover more cases, supply appropriate errors for any unhandled cases. + return "=" +} + +func (p *externalPrometheusProvider) selectSingleValueOperator(operator selection.Operator) string { + switch operator { + case selection.Equals: + return "=" + case selection.NotEquals: + return "!=" + } + + //TODO: Cover more cases, supply appropriate errors for any unhandled cases. + return "=" +} + +func (p *externalPrometheusProvider) ListAllExternalMetrics() []provider.ExternalMetricInfo { + //TODO: Provide a real response. + return nil +} diff --git a/pkg/custom-provider/metric_namer.go b/pkg/custom-provider/metric_namer.go index 90d7cdd5..a46f3218 100644 --- a/pkg/custom-provider/metric_namer.go +++ b/pkg/custom-provider/metric_namer.go @@ -51,12 +51,12 @@ type SeriesRegistry interface { // SetSeries replaces the known series in this registry SetSeries(series []prom.Series) error // ListAllMetrics lists all metrics known to this registry - ListAllMetrics() []provider.MetricInfo + ListAllMetrics() []provider.CustomMetricInfo // SeriesForMetric looks up the minimum required series information to make a query for the given metric // against the given resource (namespace may be empty for non-namespaced resources) - QueryForMetric(info provider.MetricInfo, namespace string, resourceNames ...string) (kind SeriesType, query prom.Selector, groupBy string, found bool) + QueryForMetric(info provider.CustomMetricInfo, namespace string, resourceNames ...string) (kind SeriesType, query prom.Selector, groupBy string, found bool) // MatchValuesToNames matches result values to resource names for the given metric and value set - MatchValuesToNames(metricInfo provider.MetricInfo, values pmodel.Vector) (matchedValues map[string]pmodel.SampleValue, found bool) + MatchValuesToNames(metricInfo provider.CustomMetricInfo, values pmodel.Vector) (matchedValues map[string]pmodel.SampleValue, found bool) } type seriesInfo struct { @@ -73,9 +73,9 @@ type basicSeriesRegistry struct { mu sync.RWMutex // info maps metric info to information about the corresponding series - info map[provider.MetricInfo]seriesInfo + info map[provider.CustomMetricInfo]seriesInfo // metrics is the list of all known metrics - metrics []provider.MetricInfo + metrics []provider.CustomMetricInfo // namer is the metricNamer responsible for converting series to metric names and information namer metricNamer @@ -91,7 +91,7 @@ func (r *basicSeriesRegistry) Selectors() []prom.Selector { } func (r *basicSeriesRegistry) SetSeries(newSeries []prom.Series) error { - newInfo := make(map[provider.MetricInfo]seriesInfo) + newInfo := make(map[provider.CustomMetricInfo]seriesInfo) for _, series := range newSeries { if strings.HasPrefix(series.Name, "container_") { r.namer.processContainerSeries(series, newInfo) @@ -109,7 +109,7 @@ func (r *basicSeriesRegistry) SetSeries(newSeries []prom.Series) error { } } - newMetrics := make([]provider.MetricInfo, 0, len(newInfo)) + newMetrics := make([]provider.CustomMetricInfo, 0, len(newInfo)) for info := range newInfo { newMetrics = append(newMetrics, info) } @@ -123,14 +123,14 @@ func (r *basicSeriesRegistry) SetSeries(newSeries []prom.Series) error { return nil } -func (r *basicSeriesRegistry) ListAllMetrics() []provider.MetricInfo { +func (r *basicSeriesRegistry) ListAllMetrics() []provider.CustomMetricInfo { r.mu.RLock() defer r.mu.RUnlock() return r.metrics } -func (r *basicSeriesRegistry) QueryForMetric(metricInfo provider.MetricInfo, namespace string, resourceNames ...string) (kind SeriesType, query prom.Selector, groupBy string, found bool) { +func (r *basicSeriesRegistry) QueryForMetric(metricInfo provider.CustomMetricInfo, namespace string, resourceNames ...string) (kind SeriesType, query prom.Selector, groupBy string, found bool) { r.mu.RLock() defer r.mu.RUnlock() @@ -180,7 +180,7 @@ func (r *basicSeriesRegistry) QueryForMetric(metricInfo provider.MetricInfo, nam return 0, "", "", false } -func (r *basicSeriesRegistry) MatchValuesToNames(metricInfo provider.MetricInfo, values pmodel.Vector) (matchedValues map[string]pmodel.SampleValue, found bool) { +func (r *basicSeriesRegistry) MatchValuesToNames(metricInfo provider.CustomMetricInfo, values pmodel.Vector) (matchedValues map[string]pmodel.SampleValue, found bool) { r.mu.RLock() defer r.mu.RUnlock() @@ -234,7 +234,7 @@ type seriesSpec struct { // processContainerSeries performs special work to extract metric definitions // from cAdvisor-sourced container metrics, which don't particularly follow any useful conventions consistently. -func (n *metricNamer) processContainerSeries(series prom.Series, infos map[provider.MetricInfo]seriesInfo) { +func (n *metricNamer) processContainerSeries(series prom.Series, infos map[provider.CustomMetricInfo]seriesInfo) { originalName := series.Name @@ -249,7 +249,7 @@ func (n *metricNamer) processContainerSeries(series prom.Series, infos map[provi name, metricKind = n.metricNameFromSeries(series) } - info := provider.MetricInfo{ + info := provider.CustomMetricInfo{ GroupResource: schema.GroupResource{Resource: "pods"}, Namespaced: true, Metric: name, @@ -264,7 +264,7 @@ func (n *metricNamer) processContainerSeries(series prom.Series, infos map[provi // processNamespacedSeries adds the metric info for the given generic namespaced series to // the map of metric info. -func (n *metricNamer) processNamespacedSeries(series prom.Series, infos map[provider.MetricInfo]seriesInfo) error { +func (n *metricNamer) processNamespacedSeries(series prom.Series, infos map[provider.CustomMetricInfo]seriesInfo) error { // NB: all errors must occur *before* we save the series info name, metricKind := n.metricNameFromSeries(series) resources, err := n.groupResourcesFromSeries(series) @@ -274,7 +274,7 @@ func (n *metricNamer) processNamespacedSeries(series prom.Series, infos map[prov // we add one metric for each resource that this could describe for _, resource := range resources { - info := provider.MetricInfo{ + info := provider.CustomMetricInfo{ GroupResource: resource, Namespaced: true, Metric: name, @@ -296,7 +296,7 @@ func (n *metricNamer) processNamespacedSeries(series prom.Series, infos map[prov // processesRootScopedSeries adds the metric info for the given generic namespaced series to // the map of metric info. -func (n *metricNamer) processRootScopedSeries(series prom.Series, infos map[provider.MetricInfo]seriesInfo) error { +func (n *metricNamer) processRootScopedSeries(series prom.Series, infos map[provider.CustomMetricInfo]seriesInfo) error { // NB: all errors must occur *before* we save the series info name, metricKind := n.metricNameFromSeries(series) resources, err := n.groupResourcesFromSeries(series) @@ -306,7 +306,7 @@ func (n *metricNamer) processRootScopedSeries(series prom.Series, infos map[prov // we add one metric for each resource that this could describe for _, resource := range resources { - info := provider.MetricInfo{ + info := provider.CustomMetricInfo{ GroupResource: resource, Namespaced: false, Metric: name, diff --git a/pkg/custom-provider/types.go b/pkg/custom-provider/types.go new file mode 100644 index 00000000..cf53f988 --- /dev/null +++ b/pkg/custom-provider/types.go @@ -0,0 +1,50 @@ +package provider + +import ( + "context" + "fmt" + "time" + + prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client" + "github.com/golang/glog" + pmodel "github.com/prometheus/common/model" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" +) + +type cachingMetricsLister struct { + SeriesRegistry + + promClient prom.Client + updateInterval time.Duration +} + +func (l *cachingMetricsLister) Run() { + l.RunUntil(wait.NeverStop) +} + +func (l *cachingMetricsLister) RunUntil(stopChan <-chan struct{}) { + go wait.Until(func() { + if err := l.updateMetrics(); err != nil { + utilruntime.HandleError(err) + } + }, l.updateInterval, stopChan) +} + +func (l *cachingMetricsLister) updateMetrics() error { + startTime := pmodel.Now().Add(-1 * l.updateInterval) + + sels := l.Selectors() + + // TODO: use an actual context here + series, err := l.promClient.Series(context.Background(), pmodel.Interval{startTime, 0}, sels...) + if err != nil { + return fmt.Errorf("unable to update list of all available metrics: %v", err) + } + + glog.V(10).Infof("Set available metric list from Prometheus to: %v", series) + + l.SetSeries(series) + + return nil +}