diff --git a/Makefile b/Makefile index 3a43e1a36..007fd68ff 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,10 @@ ARANGOSYNCTESTCTRLBINNAME := $(PROJECT)_sync_test_ctrl ARANGOSYNCTESTCTRLBIN := $(BINDIR)/$(ARANGOSYNCTESTCTRLBINNAME) .PHONY: all -all: verify-generated build +all: build + +.PHONY: allall +allall: verify-generated build # # Tip: Run `eval $(minikube docker-env)` before calling make if you're developing on minikube. diff --git a/docs/Manual/Deployment/Kubernetes/DeploymentResource.md b/docs/Manual/Deployment/Kubernetes/DeploymentResource.md index cca1996dd..a3c616d63 100644 --- a/docs/Manual/Deployment/Kubernetes/DeploymentResource.md +++ b/docs/Manual/Deployment/Kubernetes/DeploymentResource.md @@ -354,6 +354,54 @@ There are two magic values for the secret name: - `None` specifies no action. This disables root password randomization. This is the default value. (Thus the root password is empty - not recommended) - `Auto` specifies automatic name generation, which is `-root-password`. +### `spec.metrics.enabled: bool` + +If this is set to `true`, the operator runs a sidecar container for +every DBserver pod and every coordinator pod. The sidecar container runs +the ArangoDB-exporter and exposes metrics of the corresponding `arangod` +instance in Prometheus format on port 9101 under path `/metrics`. You +also have to specify a string for `spec.metrics.image`, which is the +Docker image name of the `arangodb-exporter`. At the time of this +writing you should use `arangodb/arangodb-exporter:0.1.6`. See [this +repository](https://github.com/arangodb-helper/arangodb-exporter) for +the latest version. If the image name is left empty, the same image as +for the main deployment is used. Note however, that current ArangoDB +releases (<= 3.4.5) do not ship the exporter in their image. This is +going to change in the future. + +In addition to the sidecar containers the operator will deploy a service +to access the exporter ports (from within the k8s cluster), and a +resource of type `ServiceMonitor`, provided the corresponding custom +resource definition is deployed in the k8s cluster. If you are running +Prometheus in the same k8s cluster with the Prometheus operator, this +will be the case. The `ServiceMonitor` will have the following labels +set: + + - `app: arangodb` + - `arango_deployment: YOUR_DEPLOYMENT_NAME` + - `context: metrics` + - `metrics: prometheus` + +This makes it possible that you configure your Prometheus deployment to +automatically start monitoring on the available Prometheus feeds. To +this end, you must configure the `serviceMonitorSelector` in the specs +of your Prometheus deployment to match these labels. For example: + +```yaml + serviceMonitorSelector: + matchLabels: + metrics: prometheus +``` + +would automatically select all pods of all ArangoDB cluster deployments +which have metrics enabled. + +### `spec.metrics.image: string` + +See above, this is the name of the Docker image for the ArangoDB +exporter to expose metrics. If empty, the same image as for the main +deployment is used. + ### `spec..count: number` This setting specifies the number of servers to start for the given group. @@ -457,4 +505,4 @@ because servers in these groups do not need persistent storage. Please use VolumeClaimTemplate from now on. This field is not considered if VolumeClaimTemplate is set. Note however, that the information in requests -is completely handed over to the pod in this case. \ No newline at end of file +is completely handed over to the pod in this case. diff --git a/docs/Manual/Deployment/Kubernetes/Metrics.md b/docs/Manual/Deployment/Kubernetes/Metrics.md index aad3b5400..2b1ec822e 100644 --- a/docs/Manual/Deployment/Kubernetes/Metrics.md +++ b/docs/Manual/Deployment/Kubernetes/Metrics.md @@ -8,3 +8,8 @@ The metrics are exposed through HTTPS on port `8528` under path `/metrics`. Look at [examples/metrics](https://github.com/arangodb/kube-arangodb/tree/master/examples/metrics) for examples of `Services` and `ServiceMonitors` you can use to integrate with Prometheus through the [Prometheus-Operator by CoreOS](https://github.com/coreos/prometheus-operator). + +Furthermore, the operator can run sidecar containers for ArangoDB +deployments of type Cluster which expose metrics in Prometheus format. +Use the attribute `spec.metrics` to set this up see the [spec +reference](./DeploymentResource.md) for details. diff --git a/go.mod b/go.mod index 95469a280..4d49f3660 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/coreos/go-semver v0.3.0 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f + github.com/coreos/prometheus-operator v0.30.0 github.com/cpuguy83/go-md2man v1.0.10 github.com/davecgh/go-spew v1.1.1 github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9 @@ -45,7 +46,7 @@ require ( github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 github.com/dustin/go-broadcast v0.0.0-20171205050544-f664265f5a66 github.com/dustin/go-humanize v1.0.0 - github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 + github.com/emicklei/go-restful v2.6.0+incompatible github.com/evanphx/json-patch v4.2.0+incompatible // indirect github.com/ewoutp/go-gitlab-client v0.0.0-20150214183219-6e4464cd3221 github.com/ghodss/yaml v1.0.0 @@ -55,8 +56,8 @@ require ( github.com/go-kit/kit v0.8.0 github.com/go-openapi/analysis v0.19.0 github.com/go-openapi/errors v0.19.0 - github.com/go-openapi/jsonpointer v0.18.0 - github.com/go-openapi/jsonreference v0.18.0 + github.com/go-openapi/jsonpointer v0.19.0 + github.com/go-openapi/jsonreference v0.19.0 github.com/go-openapi/loads v0.19.0 github.com/go-openapi/runtime v0.19.0 github.com/go-openapi/spec v0.18.0 @@ -130,7 +131,7 @@ require ( golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/sys v0.0.0-20190506115046-ca7f33d4116e - golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db + golang.org/x/text v0.3.1 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc google.golang.org/api v0.4.0 // indirect @@ -147,9 +148,8 @@ require ( k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8 k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d k8s.io/client-go v11.0.0+incompatible - k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6 + k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a k8s.io/klog v0.3.0 k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503 // indirect k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 // indirect - sigs.k8s.io/yaml v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index b711c2abb..15d9ea5aa 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,7 @@ github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0 h1:0GoNN3taZV6QI81IXgCbxMyEaJDXMSIjArYBCYzVVvs= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= @@ -39,6 +40,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5Vpd github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/ant31/crd-validation v0.0.0-20180702145049-30f8a35d0ac2/go.mod h1:X0noFIik9YqfhGYBLEHg8LJKEwy7QIitLQuFMpKLcPk= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/arangodb-helper/go-certificates v0.0.0-20180821055445-9fca24fc2680 h1:5YCGq0gkf/sCEkDFIsMBPj59GOm5cMibGqDBH2OWWfQ= github.com/arangodb-helper/go-certificates v0.0.0-20180821055445-9fca24fc2680/go.mod h1:xDyzBwyYzcEhsaDXtmxCNM4p5BrtuoVYYsRTuJqmCeg= @@ -54,12 +56,16 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/brancz/gojsontoyaml v0.0.0-20190425155809-e8bd32d46b3d/go.mod h1:IyUJYN1gvWjtLF5ZuygmxbnsAyP3aJS6cHzIuZY50B0= github.com/bugagazavr/go-gitlab-client v0.0.0-20150830002541-e5999f934dc4 h1:khrxuHeHUqaH4DFwhr68pf3VuTpuAex15stAhVhoQI4= github.com/bugagazavr/go-gitlab-client v0.0.0-20150830002541-e5999f934dc4/go.mod h1:1Zuosrhy9+Yk4gBednaZSIzlgYH0V6vDxcQwhwV7ys0= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292 h1:dzj1/xcivGjNPwwifh/dWTczkwcuqsXXFHY1X/TZMtw= github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292/go.mod h1:qRiX68mZX1lGBkTWyp3CLcenw9I94W2dLeRvMzcn9N4= @@ -81,6 +87,8 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/prometheus-operator v0.30.0 h1:nL8WuyoXXuamSMXF5PU9o86/ro7+uiWNZvK6FkMEuvQ= +github.com/coreos/prometheus-operator v0.30.0/go.mod h1:nG9QpZ0yNU8gihsEC70fKmaOq1ezDBrvoGooAwzZdBQ= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -109,11 +117,16 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.6.0+incompatible h1:luAX89wpjId5gV+GJV11MFD56GpAJTG2eUqCeDDgB98= +github.com/emicklei/go-restful v2.6.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/ewoutp/go-gitlab-client v0.0.0-20150214183219-6e4464cd3221 h1:buDu9bgh45rr9QLBPgqUP4vrEmicLebHjxiotDNpKic= github.com/ewoutp/go-gitlab-client v0.0.0-20150214183219-6e4464cd3221/go.mod h1:WUzoBqR60IiOmO1pYtxKPkOkv+kMkofAJfnI3q7LQkQ= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -150,12 +163,14 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+ github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.18.0 h1:KVRzjXpMzgdM4GEMDmDTnGcY5yBwGWreJwmmk4k35yU= github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.0 h1:FTUMcX77w5rQkClIzDtTxvn6Bsa894CcrzNj2MMfeg8= github.com/go-openapi/jsonpointer v0.19.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9 h1:tF+augKRWlWx0J0B7ZyyKSiTyV6E1zZe+7b3qQlcEf8= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0 h1:oP2OUNdG1l2r5kYhrfVMXO54gWmzcfAwP/GFuHpNTkE= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.0 h1:BqWKpV1dFd+AuiKlgtddwVIFQsuMpxfBDBHGfM2yNpk= github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -195,6 +210,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekf github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20180924190550-6f2cf27854a4/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -208,6 +224,7 @@ github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/gofuzz v0.0.0-20150304233714-bbcb9da2d746/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -220,6 +237,7 @@ github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= @@ -242,6 +260,7 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/go-version v0.0.0-20171129150820-4fe82ae3040f/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= @@ -250,6 +269,7 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/improbable-eng/thanos v0.3.2/go.mod h1:GZewVGILKuJVPNRn7L4Zw+7X96qzFOwj63b22xYGXBE= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15 h1:cW/amwGEJK5MSKntPXRjX4dxs/nGxGT8gXKIsKFmHGc= github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15/go.mod h1:Fdm/oWRW+CH8PRbLntksCNtmcCBximKPkVQYvmMl80k= @@ -266,6 +286,7 @@ github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBv github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jsonnet-bundler/jsonnet-bundler v0.1.0/go.mod h1:YKsSFc9VFhhLITkJS3X2PrRqWG9u2Jq99udTdDjQLfM= github.com/juju/errgo v0.0.0-20140925100237-08cceb5d0b53 h1:tGpfbOOO0SV3qtMUx8O9RbJeei6VDBwnpQQ0JYIFaVg= github.com/juju/errgo v0.0.0-20140925100237-08cceb5d0b53/go.mod h1:ZtgUe3RyZisw/AlQjgU9DeO3hqUH9E/bkreI2FLg/QY= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= @@ -279,6 +300,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a h1:TpvdAwDAt1K4ANVOfcihouRdvP+MgAfDWwBuct4l6ZY= @@ -288,10 +310,12 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe h1:W/GaMY0y69G4cFl github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227 h1:KIaAZ/V+/0/6BOULrmBQ9T1ed8BkKqGIjIKW923nJuo= github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227/go.mod h1:ruMr5t05gVho4tuDv0PbI0Bb8nOxc/5Y6JzRHe/yfA0= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -300,11 +324,13 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1f github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= @@ -312,11 +338,14 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= @@ -347,6 +376,7 @@ github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJ github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181218105931-67670fe90761/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -354,6 +384,7 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nL github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/tsdb v0.2.0/go.mod h1:lFf/o1J2a31WmWQbxYXfY1azJK5Xp5D8hwKMnVMBTGU= github.com/pulcy/pulsar v0.0.0-20180915062927-71ea24b0ec2f h1:+dJQtfHvWgnTNoGsakK8pDu6kwC878j5lVxf2ASSDF8= github.com/pulcy/pulsar v0.0.0-20180915062927-71ea24b0ec2f/go.mod h1:dHXm2PpZz13Ieu/Sk+Qw5mJ07qPEUHJy08HxKW57z78= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -375,6 +406,7 @@ github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/go-vcsurl v0.0.0-20161114165620-2305ecca26ab h1:Fow2FGdj7yriDAK2yZeHJsm/5SZqL2AD1iEybfWJytQ= github.com/sourcegraph/go-vcsurl v0.0.0-20161114165620-2305ecca26ab/go.mod h1:Dl+4tLnKopzymgEhEZCi6/KSIZPFBe1rvoKMxCGh0Ms= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -441,6 +473,7 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190424203555-c05e17bb3b2d/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -469,6 +502,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJV golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -493,9 +527,11 @@ golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190506115046-ca7f33d4116e h1:bq5BY1tGuaK8HxuwN6pT6kWgTVLeJ5KwuyBpsl1CZL4= golang.org/x/sys v0.0.0-20190506115046-ca7f33d4116e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -503,7 +539,10 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.1 h1:nsUiJHvm6yOoRozW9Tz0siNk9sHieLzR+w814Ihse3A= +golang.org/x/text v0.3.1/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -517,6 +556,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc h1:N3zlSgxkefUH/ecsl37RWTkESTB026kmXzNly8TuZCI= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= @@ -562,6 +602,7 @@ gopkg.in/square/go-jose.v2 v2.0.0-20180411045311-89060dee6a84/go.mod h1:M9dMgbHi gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.1.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= @@ -612,6 +653,7 @@ k8s.io/component-base v0.0.0-20190424053038-9fe063da3132/go.mod h1:pi2NQz+AaW5UM k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6 h1:4s3/R4+OYYYUKptXPhZKjQ04WJ6EhQQVFdjOFvCazDk= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE= @@ -622,6 +664,7 @@ k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503 h1:IrnrEIp9du1SngrzGC1fdY k8s.io/kube-openapi v0.0.0-20190502190224-411b2483e503/go.mod h1:iU+ZGYsNlvU9XKUSso6SQfKTCCw7lFduMZy26Mgr2Fw= k8s.io/utils v0.0.0-20190221042446-c2654d5206da h1:ElyM7RPonbKnQqOcw7dG2IK5uvQQn3b/WPHqD5mBvP4= k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= diff --git a/manifests/templates/deployment/rbac.yaml b/manifests/templates/deployment/rbac.yaml index 085f742fe..04f4b1d6a 100644 --- a/manifests/templates/deployment/rbac.yaml +++ b/manifests/templates/deployment/rbac.yaml @@ -24,7 +24,7 @@ rules: verbs: ["*"] - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] - verbs: ["get"] + verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["pods", "services", "endpoints", "persistentvolumeclaims", "events", "secrets"] verbs: ["*"] @@ -40,6 +40,10 @@ rules: - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list"] +- apiGroups: ["monitoring.coreos.com"] + resources: ["servicemonitors"] + verbs: ["get", "create", "delete"] + --- diff --git a/pkg/apis/deployment/v1alpha/deployment_status.go b/pkg/apis/deployment/v1alpha/deployment_status.go index 5ef925d34..d7835f08b 100644 --- a/pkg/apis/deployment/v1alpha/deployment_status.go +++ b/pkg/apis/deployment/v1alpha/deployment_status.go @@ -40,6 +40,8 @@ type DeploymentStatus struct { ExporterServiceName string `json:"exporterServiceName,omitempty"` + ExporterServiceMonitorName string `json:"exporterServiceMonitorName,omitempty"` + // Images holds a list of ArangoDB images with their ID and ArangoDB version. Images ImageInfoList `json:"arangodb-images,omitempty"` // Image that is currently being used when new pods are created @@ -72,6 +74,7 @@ func (ds *DeploymentStatus) Equal(other DeploymentStatus) bool { ds.ServiceName == other.ServiceName && ds.SyncServiceName == other.SyncServiceName && ds.ExporterServiceName == other.ExporterServiceName && + ds.ExporterServiceMonitorName == other.ExporterServiceMonitorName && ds.Images.Equal(other.Images) && ds.CurrentImage.Equal(other.CurrentImage) && ds.Members.Equal(other.Members) && diff --git a/pkg/deployment/deployment.go b/pkg/deployment/deployment.go index 35d7cad69..caacffb66 100644 --- a/pkg/deployment/deployment.go +++ b/pkg/deployment/deployment.go @@ -31,6 +31,7 @@ import ( "github.com/arangodb/arangosync/client" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" @@ -59,6 +60,7 @@ type Config struct { type Dependencies struct { Log zerolog.Logger KubeCli kubernetes.Interface + KubeExtCli apiextensionsclient.Interface DatabaseCRCli versioned.Interface EventRecorder record.EventRecorder } @@ -98,6 +100,7 @@ type Deployment struct { stopped int32 inspectTrigger trigger.Trigger + inspectCRDTrigger trigger.Trigger updateDeploymentTrigger trigger.Trigger clientCache *clientCache recentInspectionErrors int @@ -107,6 +110,7 @@ type Deployment struct { resources *resources.Resources chaosMonkey *chaos.Monkey syncClientCache client.ClientCache + haveServiceMonitorCRD bool } // New creates a new Deployment from the given API object. @@ -136,6 +140,7 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De go d.listenForPVCEvents(d.stopCh) go d.listenForSecretEvents(d.stopCh) go d.listenForServiceEvents(d.stopCh) + go d.listenForCRDEvents(d.stopCh) if apiObject.Spec.GetMode() == api.DeploymentModeCluster { ci := newClusterScalingIntegration(d) d.clusterScalingIntegration = ci @@ -201,6 +206,13 @@ func (d *Deployment) run() { d.CreateEvent(k8sutil.NewErrorEvent("Failed to create services", err, d.GetAPIObject())) } + // Create service monitor + if d.haveServiceMonitorCRD { + if err := d.resources.EnsureServiceMonitor(); err != nil { + d.CreateEvent(k8sutil.NewErrorEvent("Failed to create service monitor", err, d.GetAPIObject())) + } + } + // Create members if err := d.createInitialMembers(d.apiObject); err != nil { d.CreateEvent(k8sutil.NewErrorEvent("Failed to create initial members", err, d.GetAPIObject())) @@ -229,6 +241,8 @@ func (d *Deployment) run() { log.Info().Msg("start running...") } + d.lookForServiceMonitorCRD() + inspectionInterval := maxInspectionInterval for { select { @@ -258,6 +272,8 @@ func (d *Deployment) run() { inspectionInterval = d.inspectDeployment(inspectionInterval) log.Debug().Str("interval", inspectionInterval.String()).Msg("...inspected deployment") + case <-d.inspectCRDTrigger.Done(): + d.lookForServiceMonitorCRD() case <-d.updateDeploymentTrigger.Done(): inspectionInterval = minInspectionInterval if err := d.handleArangoDeploymentUpdatedEvent(); err != nil { @@ -492,3 +508,29 @@ func (d *Deployment) isOwnerOf(obj metav1.Object) bool { } return ownerRefs[0].UID == d.apiObject.UID } + +// lookForServiceMonitorCRD checks if there is a CRD for the ServiceMonitor +// CR and sets the flag haveServiceMonitorCRD accordingly. This is called +// once at creation time of the deployment and then always if the CRD +// informer is triggered. +func (d *Deployment) lookForServiceMonitorCRD() { + _, err := d.deps.KubeExtCli.ApiextensionsV1beta1().CustomResourceDefinitions().Get("servicemonitors.monitoring.coreos.com", metav1.GetOptions{}) + log := d.deps.Log + log.Debug().Msgf("Looking for ServiceMonitor CRD...") + if err == nil { + if !d.haveServiceMonitorCRD { + log.Info().Msgf("...have discovered ServiceMonitor CRD") + } + d.haveServiceMonitorCRD = true + d.triggerInspection() + return + } else if k8sutil.IsNotFound(err) { + if d.haveServiceMonitorCRD { + log.Info().Msgf("...ServiceMonitor CRD no longer there") + } + d.haveServiceMonitorCRD = false + return + } + log.Warn().Err(err).Msgf("Error when looking for ServiceMonitor CRD") + return +} diff --git a/pkg/deployment/deployment_inspector.go b/pkg/deployment/deployment_inspector.go index 9af2f6bb6..0f7458983 100644 --- a/pkg/deployment/deployment_inspector.go +++ b/pkg/deployment/deployment_inspector.go @@ -152,6 +152,13 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval hasError = true d.CreateEvent(k8sutil.NewErrorEvent("Service creation failed", err, d.apiObject)) } + if d.haveServiceMonitorCRD { + if err := d.resources.EnsureServiceMonitor(); err != nil { + hasError = true + d.CreateEvent(k8sutil.NewErrorEvent("Service monitor creation failed", err, d.apiObject)) + } + } + if err := d.resources.EnsurePVCs(); err != nil { hasError = true d.CreateEvent(k8sutil.NewErrorEvent("PVC creation failed", err, d.apiObject)) @@ -208,3 +215,8 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval func (d *Deployment) triggerInspection() { d.inspectTrigger.Trigger() } + +// triggerCRDInspection ensures that an inspection is run soon. +func (d *Deployment) triggerCRDInspection() { + d.inspectCRDTrigger.Trigger() +} diff --git a/pkg/deployment/informers.go b/pkg/deployment/informers.go index da4ddcc6d..0a7fc172e 100644 --- a/pkg/deployment/informers.go +++ b/pkg/deployment/informers.go @@ -24,6 +24,7 @@ package deployment import ( "k8s.io/api/core/v1" + v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/client-go/tools/cache" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" @@ -197,3 +198,23 @@ func (d *Deployment) listenForServiceEvents(stopCh <-chan struct{}) { rw.Run(stopCh) } + +// listenForCRDEvents keep listening for changes in CRDs until the given channel is closed. +func (d *Deployment) listenForCRDEvents(stopCh <-chan struct{}) { + rw := k8sutil.NewResourceWatcher( + d.deps.Log, + d.deps.KubeExtCli.ApiextensionsV1beta1().RESTClient(), + "customresourcedefinitions", + "", + &v1beta1.CustomResourceDefinition{}, + cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + d.triggerCRDInspection() + }, + DeleteFunc: func(obj interface{}) { + d.triggerCRDInspection() + }, + }) + + rw.Run(stopCh) +} diff --git a/pkg/deployment/resources/resources.go b/pkg/deployment/resources/resources.go index ab5f281ff..d036a0816 100644 --- a/pkg/deployment/resources/resources.go +++ b/pkg/deployment/resources/resources.go @@ -28,6 +28,7 @@ import ( driver "github.com/arangodb/go-driver" "github.com/arangodb/kube-arangodb/pkg/util/trigger" + clientv1 "github.com/coreos/prometheus-operator/pkg/client/versioned/typed/monitoring/v1" "github.com/rs/zerolog" ) @@ -47,6 +48,7 @@ type Resources struct { mutex sync.Mutex triggerSyncInspection trigger.Trigger } + monitoringClient *clientv1.MonitoringV1Client } // NewResources creates a new Resources service, used to diff --git a/pkg/deployment/resources/servicemonitor.go b/pkg/deployment/resources/servicemonitor.go new file mode 100644 index 000000000..9dd75b199 --- /dev/null +++ b/pkg/deployment/resources/servicemonitor.go @@ -0,0 +1,172 @@ +// +// DISCLAIMER +// +// Copyright 2019 ArangoDB Inc, Cologne, Germany +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 holder is ArangoDB GmbH, Cologne, Germany +// +// Author Max Neunhoeffer +// + +package resources + +import ( + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" + + "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha" + coreosv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" + clientv1 "github.com/coreos/prometheus-operator/pkg/client/versioned/typed/monitoring/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" +) + +func LabelsForExporterServiceMonitor(deploymentName string) map[string]string { + return map[string]string{ + k8sutil.LabelKeyArangoDeployment: deploymentName, + k8sutil.LabelKeyApp: k8sutil.AppName, + "context": "metrics", + "metrics": "prometheus", + } +} + +func LabelsForExporterServiceMonitorSelector(deploymentName string) map[string]string { + return map[string]string{ + k8sutil.LabelKeyArangoDeployment: deploymentName, + k8sutil.LabelKeyApp: k8sutil.AppName, + } +} + +// EnsureMonitoringClient returns a client for looking at ServiceMonitors +// and keeps it in the Resources. +func (r *Resources) EnsureMonitoringClient() (*clientv1.MonitoringV1Client, error) { + if r.monitoringClient != nil { + return r.monitoringClient, nil + } + + // Make a client: + var restConfig *rest.Config + restConfig, err := k8sutil.InClusterConfig() + if err != nil { + return nil, maskAny(err) + } + mClient, err := clientv1.NewForConfig(restConfig) + if err != nil { + return nil, maskAny(err) + } + r.monitoringClient = mClient + return mClient, nil +} + +func (r *Resources) makeEndpoint(isSecure bool) coreosv1.Endpoint { + if isSecure { + return coreosv1.Endpoint{ + Port: "exporter", + Interval: "10s", + Scheme: "https", + TLSConfig: &coreosv1.TLSConfig{ + InsecureSkipVerify: true, + }, + } + } else { + return coreosv1.Endpoint{ + Port: "exporter", + Interval: "10s", + Scheme: "http", + } + } +} + +// EnsureServiceMonitor creates or updates a ServiceMonitor. +func (r *Resources) EnsureServiceMonitor() error { + // Some preparations: + log := r.log + apiObject := r.context.GetAPIObject() + deploymentName := apiObject.GetName() + ns := apiObject.GetNamespace() + owner := apiObject.AsOwner() + spec := r.context.GetSpec() + wantMetrics := spec.Metrics.IsEnabled() + serviceMonitorName := k8sutil.CreateExporterClientServiceName(deploymentName) + + mClient, err := r.EnsureMonitoringClient() + if err != nil { + log.Error().Err(err).Msgf("Cannot get a monitoring client.") + return maskAny(err) + } + + // Check if ServiceMonitor already exists + serviceMonitors := mClient.ServiceMonitors(ns) + servMon, err := serviceMonitors.Get(serviceMonitorName, metav1.GetOptions{}) + if err != nil { + if k8sutil.IsNotFound(err) { + if !wantMetrics { + return nil + } + // Need to create one: + smon := &coreosv1.ServiceMonitor{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceMonitorName, + Labels: LabelsForExporterServiceMonitor(deploymentName), + OwnerReferences: []metav1.OwnerReference{owner}, + }, + Spec: coreosv1.ServiceMonitorSpec{ + JobLabel: "k8s-app", + Endpoints: []coreosv1.Endpoint{ + r.makeEndpoint(spec.IsSecure()), + }, + Selector: metav1.LabelSelector{ + MatchLabels: LabelsForExporterServiceMonitorSelector(deploymentName), + }, + }, + } + smon, err = serviceMonitors.Create(smon) + if err != nil { + log.Error().Err(err).Msgf("Failed to create ServiceMonitor %s", serviceMonitorName) + return maskAny(err) + } + log.Debug().Msgf("ServiceMonitor %s successfully created.", serviceMonitorName) + return nil + } else { + log.Error().Err(err).Msgf("Failed to get ServiceMonitor %s", serviceMonitorName) + return maskAny(err) + } + } + if wantMetrics { + log.Debug().Msgf("ServiceMonitor %s already found, no need to create.", + serviceMonitorName) + return nil + } + // Check if the service monitor is ours, otherwise we do not touch it: + found := false + for _, owner := range servMon.ObjectMeta.OwnerReferences { + if owner.Kind == v1alpha.ArangoDeploymentResourceKind && + owner.Name == deploymentName { + found = true + break + } + } + if !found { + log.Debug().Msgf("Found unneeded ServiceMonitor %s, but not owned by us, will not touch it", serviceMonitorName) + return nil + } + // Need to get rid of the ServiceMonitor: + err = serviceMonitors.Delete(serviceMonitorName, &metav1.DeleteOptions{}) + if err == nil { + log.Debug().Msgf("Deleted ServiceMonitor %s", serviceMonitorName) + return nil + } + log.Error().Err(err).Msgf("Could not delete ServiceMonitor %s.", serviceMonitorName) + return maskAny(err) +} diff --git a/pkg/logging/logger.go b/pkg/logging/logger.go index 87cc277b6..08741525b 100644 --- a/pkg/logging/logger.go +++ b/pkg/logging/logger.go @@ -27,6 +27,7 @@ import ( "os" "strings" "sync" + "time" "github.com/rs/zerolog" ) @@ -62,8 +63,9 @@ type loggingService struct { // NewRootLogger creates a new zerolog logger with default settings. func NewRootLogger() zerolog.Logger { return zerolog.New(zerolog.ConsoleWriter{ - Out: os.Stdout, - NoColor: true, + Out: os.Stdout, + TimeFormat: time.RFC3339Nano, + NoColor: true, }).With().Timestamp().Logger() } diff --git a/pkg/operator/operator_deployment.go b/pkg/operator/operator_deployment.go index c6a7349a5..c8e3d5320 100644 --- a/pkg/operator/operator_deployment.go +++ b/pkg/operator/operator_deployment.go @@ -212,6 +212,7 @@ func (o *Operator) makeDeploymentConfigAndDeps(apiObject *api.ArangoDeployment) Str("deployment", apiObject.GetName()). Logger(), KubeCli: o.Dependencies.KubeCli, + KubeExtCli: o.Dependencies.KubeExtCli, DatabaseCRCli: o.Dependencies.CRCli, EventRecorder: o.Dependencies.EventRecorder, } diff --git a/tests/metrics_test.go b/tests/metrics_test.go new file mode 100644 index 000000000..b45fb5d5c --- /dev/null +++ b/tests/metrics_test.go @@ -0,0 +1,121 @@ +// +// DISCLAIMER +// +// Copyright 2019 ArangoDB GmbH, Cologne, Germany +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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 holder is ArangoDB GmbH, Cologne, Germany +// +// Author Max Neunhoeffer +// +package tests + +import ( + "context" + "fmt" + "testing" + "time" + + api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha" + kubeArangoClient "github.com/arangodb/kube-arangodb/pkg/client" + "github.com/arangodb/kube-arangodb/pkg/util" + "github.com/dchest/uniuri" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" +) + +func TestAddingMetrics(t *testing.T) { + longOrSkip(t) + + ns := getNamespace(t) + kubecli := mustNewKubeClient(t) + c := kubeArangoClient.MustNewInCluster() + + depl := newDeployment(fmt.Sprintf("%s-%s", "arangodb-metrics-test", uniuri.NewLen(4))) + depl.Spec.Mode = api.NewMode(api.DeploymentModeCluster) + depl.Spec.StorageEngine = api.NewStorageEngine(api.StorageEngineRocksDB) + depl.Spec.TLS = api.TLSSpec{} // should auto-generate cert + depl.Spec.SetDefaults(depl.GetName()) // this must be last + + // Create deployment + deployment, err := c.DatabaseV1alpha().ArangoDeployments(ns).Create(depl) + if err != nil { + t.Fatalf("Create deployment failed: %v", err) + } + defer deferedCleanupDeployment(c, depl.GetName(), ns) + + // Wait for deployment to be ready + deployment, err = waitUntilDeployment(c, depl.GetName(), ns, deploymentIsReady()) + if err != nil { + t.Fatalf("Deployment not running in time: %v", err) + } + + // Create a database client + ctx := context.Background() + DBClient := mustNewArangodDatabaseClient(ctx, kubecli, deployment, t, nil) + if err := waitUntilArangoDeploymentHealthy(deployment, DBClient, kubecli, ""); err != nil { + t.Fatalf("Deployment not healthy in time: %v", err) + } + + // Try to switch on metrics: + deployment, err = updateDeployment(c, depl.GetName(), ns, + func(depl *api.DeploymentSpec) { + depl.Metrics = api.MetricsSpec{ + Enabled: util.NewBool(true), + Image: util.NewString("arangodb/arangodb-exporter:0.1.6"), + } + }) + if err != nil { + t.Fatalf("Failed to add metrics") + } else { + t.Log("Updated deployment by adding metrics") + } + + if err := waitUntilArangoDeploymentHealthy(deployment, DBClient, kubecli, ""); err != nil { + t.Errorf("Deployment not healthy in time: %v", err) + } else { + t.Log("Deployment healthy") + } + + _, err = waitUntilService(kubecli, depl.GetName()+"-exporter", ns, + func(service *corev1.Service) error { + return nil + }, time.Second*30) + if err != nil { + t.Errorf("Exporter service did not show up in time") + } else { + t.Log("Found exporter service") + } + + _, err = waitUntilEndpoints(kubecli, depl.GetName()+"-exporter", ns, + func(endpoints *corev1.Endpoints) error { + count := 0 + for _, subset := range endpoints.Subsets { + count += len(subset.Addresses) + } + t.Logf("Found %d endpoints in the Endpoints resource", count) + if count < 6 { + return errors.New("did not find enough endpoints in Endpoints resource") + } + return nil + }, time.Second*360) // needs a full rotation with extra containers + if err != nil { + t.Errorf("Exporter endpoints did not show up in time") + } else { + t.Log("Found exporter endpoints") + } + + // Cleanup + removeDeployment(c, depl.GetName(), ns) +} diff --git a/tests/test_util.go b/tests/test_util.go index 0b8120754..24031c5d9 100644 --- a/tests/test_util.go +++ b/tests/test_util.go @@ -341,6 +341,56 @@ func waitUntilSecret(cli kubernetes.Interface, secretName, ns string, predicate return result, nil } +// waitUntilService waits until a service with given name in given +// namespace exists and has reached a state where the given predicate +// returns nil. +func waitUntilService(cli kubernetes.Interface, serviceName, ns string, predicate func(*v1.Service) error, timeout time.Duration) (*v1.Service, error) { + var result *v1.Service + op := func() error { + obj, err := cli.CoreV1().Services(ns).Get(serviceName, metav1.GetOptions{}) + if err != nil { + result = nil + return maskAny(err) + } + result = obj + if predicate != nil { + if err := predicate(obj); err != nil { + return maskAny(err) + } + } + return nil + } + if err := retry.Retry(op, timeout); err != nil { + return nil, maskAny(err) + } + return result, nil +} + +// waitUntilEndpoints waits until an endpoints resource with given name +// in given namespace exists and has reached a state where the given +// predicate returns nil. +func waitUntilEndpoints(cli kubernetes.Interface, serviceName, ns string, predicate func(*v1.Endpoints) error, timeout time.Duration) (*v1.Endpoints, error) { + var result *v1.Endpoints + op := func() error { + obj, err := cli.CoreV1().Endpoints(ns).Get(serviceName, metav1.GetOptions{}) + if err != nil { + result = nil + return maskAny(err) + } + result = obj + if predicate != nil { + if err := predicate(obj); err != nil { + return maskAny(err) + } + } + return nil + } + if err := retry.Retry(op, timeout); err != nil { + return nil, maskAny(err) + } + return result, nil +} + // waitUntilSecretNotFound waits until a secret with given name in given namespace // is no longer found. func waitUntilSecretNotFound(cli kubernetes.Interface, secretName, ns string, timeout time.Duration) error {