From 7255f51ae74bb0eb5ce34f3461c808b20e467620 Mon Sep 17 00:00:00 2001 From: Mathieu Tortuyaux Date: Mon, 10 Jun 2024 15:05:06 +0200 Subject: [PATCH 1/6] mod: add hetzner Go SDK Signed-off-by: Mathieu Tortuyaux --- go.mod | 23 +++++++++--------- go.sum | 74 +++++++++++++++++++--------------------------------------- 2 files changed, 36 insertions(+), 61 deletions(-) diff --git a/go.mod b/go.mod index e11affa56..7d7e84e67 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 github.com/anatol/tang.go v0.0.0-20230725175645-dcc6e9494f14 + github.com/apricote/hcloud-upload-image/hcloudimages v0.3.0 github.com/aws/aws-sdk-go v1.44.46 github.com/brightbox/gobrightbox/v2 v2.2.0 github.com/coreos/butane v0.14.1-0.20220401164106-6b5239299226 @@ -31,6 +32,7 @@ require ( github.com/golang/protobuf v1.5.4 github.com/gophercloud/gophercloud v0.25.0 github.com/gophercloud/utils v0.0.0-20220704184730-55bdbbaec4ba + github.com/hetznercloud/hcloud-go/v2 v2.9.0 github.com/kballard/go-shellquote v0.0.0-20150810074751-d8ec1a69a250 github.com/kylelemons/godebug v1.1.0 github.com/packethost/packngo v0.21.0 @@ -50,8 +52,8 @@ require ( go.uber.org/zap v1.17.0 golang.org/x/crypto v0.24.0 golang.org/x/net v0.26.0 - golang.org/x/oauth2 v0.14.0 - golang.org/x/sys v0.21.0 + golang.org/x/oauth2 v0.16.0 + golang.org/x/sys v0.22.0 google.golang.org/api v0.126.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -64,7 +66,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 // indirect - github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 // indirect + github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/clarketm/json v1.17.1 // indirect @@ -91,23 +93,22 @@ require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/json-iterator/go v1.1.11 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/jwx v1.2.29 // indirect github.com/lestrrat-go/option v1.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.11.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect go.etcd.io/bbolt v1.3.9 // indirect go.etcd.io/etcd/api/v3 v3.5.13 // indirect @@ -124,7 +125,7 @@ require ( go.uber.org/multierr v1.6.0 // indirect go4.org v0.0.0-20201209231011-d4a079459e60 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/term v0.21.0 // indirect + golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/go.sum b/go.sum index 05b2fe510..6a4cc38ae 100644 --- a/go.sum +++ b/go.sum @@ -74,17 +74,17 @@ github.com/ajeddeloh/go-json v0.0.0-20160803184958-73d058cf8437/go.mod h1:otnto4 github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 h1:4SPQljF/GJ8Q+QlCWMWxRBepub4DresnOm4eI2ebFGc= github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559/go.mod h1:otnto4/Icqn88WCcM4bhIJNSgsh9VLBuspyyCfvof9c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4= github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/anatol/clevis.go v0.0.0-20230629234939-684702e18e07 h1:fy40nbjTIObq7SMts2H7InVLl4uQC2xcRxZ/pHRpdoU= github.com/anatol/clevis.go v0.0.0-20230629234939-684702e18e07/go.mod h1:nEwwKRAb80BFvdT8KoDE6C7ct/Gu9222nBnnpVWQ3gM= github.com/anatol/tang.go v0.0.0-20230725175645-dcc6e9494f14 h1:/ar8G0JGXDb/O/rG3Z/Q7v1M6KzJFshqYqjN+dMGRY8= github.com/anatol/tang.go v0.0.0-20230725175645-dcc6e9494f14/go.mod h1:6aDwt+p3xVpKfTsK1ZR5/nFyxe6Jy4T3CJyH4WxfDyc= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apricote/hcloud-upload-image/hcloudimages v0.3.0 h1:POoU0nKeTq3fw7Ok/BTwJ/I3CTKhcChtn8L+Ecpba5U= +github.com/apricote/hcloud-upload-image/hcloudimages v0.3.0/go.mod h1:9W0XQVhzb9x69UBXXR0nxF0taC6s6fl0/nemDGUVrfI= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -196,11 +196,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -264,7 +261,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -332,6 +328,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hetznercloud/hcloud-go/v2 v2.9.0 h1:s0N6R7Zoi2DPfMtUF5o9VeUBzTtHVY6MIkHOQnfu/AY= +github.com/hetznercloud/hcloud-go/v2 v2.9.0/go.mod h1:qtW/TuU7Bs16ibXl/ktJarWqU2LwHr7eGlwoilHxtgg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -344,24 +342,20 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kballard/go-shellquote v0.0.0-20150810074751-d8ec1a69a250 h1:QyPDU73WRl/8CnuK3JltZLLuNhL3E4o3BROt4g8nFf0= github.com/kballard/go-shellquote v0.0.0-20150810074751-d8ec1a69a250/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -388,7 +382,6 @@ github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmt github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -402,11 +395,10 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 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-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/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/packethost/packngo v0.21.0 h1:Q9j3+/1kijXDwIg71523U6FaT/1CG90CgtVwz+15HDk= github.com/packethost/packngo v0.21.0/go.mod h1:/UHguFdPs6Lf6FOkkSEPnRY5tgS0fsVM+Zv/bvBrmt0= @@ -428,27 +420,21 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -465,8 +451,6 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sigma/bdoor v0.0.0-20160202064022-babf2a4017b0/go.mod h1:WBu7REWbxC/s/J06jsk//d+9DOz9BbsmcIrimuGRFbs= github.com/sigma/vmw-guestinfo v0.0.0-20160204083807-95dd4126d6e8/go.mod h1:JrRFFC0veyh0cibh0DAhriSY7/gV3kDdNaVUOmfx01U= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= @@ -630,7 +614,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -645,7 +628,6 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -663,8 +645,8 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= -golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -673,7 +655,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= @@ -687,7 +668,6 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -697,7 +677,6 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -712,14 +691,10 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -729,8 +704,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -738,8 +713,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -913,7 +888,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= From 1578fc9d6ed2d8364e58ad8d2a5cb9ec8b1bc8ce Mon Sep 17 00:00:00 2001 From: Mathieu Tortuyaux Date: Mon, 10 Jun 2024 15:08:00 +0200 Subject: [PATCH 2/6] vendor: go mod vendor Signed-off-by: Mathieu Tortuyaux --- vendor/github.com/alecthomas/units/README.md | 2 + vendor/github.com/alecthomas/units/bytes.go | 124 +- .../hcloudimages/CHANGELOG.md | 14 + .../hcloud-upload-image/hcloudimages/LICENSE | 7 + .../hcloudimages/backoff/backoff.go | 29 + .../hcloudimages/client.go | 483 ++ .../hcloudimages/contextlogger/context.go | 27 + .../hcloudimages/contextlogger/discard.go | 15 + .../hcloud-upload-image/hcloudimages/doc.go | 42 + .../internal/actionutil/action.go | 25 + .../hcloudimages/internal/control/retry.go | 40 + .../hcloudimages/internal/labelutil/labels.go | 30 + .../internal/randomid/randomid.go | 20 + .../hcloudimages/internal/sshkey/ssh_key.go | 49 + .../internal/sshsession/session.go | 21 + .../testdata/client_intermediate_cert.der | Bin 998 -> 0 bytes .../testdata/client_leaf_cert.der | Bin 1147 -> 0 bytes .../testdata/client_root_cert.der | Bin 1013 -> 0 bytes .../testdata/server_intermediate_cert.der | Bin 998 -> 0 bytes .../testdata/server_leaf_cert.der | Bin 1147 -> 0 bytes .../testdata/server_root_cert.der | Bin 1013 -> 0 bytes .../v2/remotesigner/testdata/client_cert.der | Bin 1013 -> 0 bytes .../v2/remotesigner/testdata/client_cert.pem | 24 - .../v2/remotesigner/testdata/client_key.pem | 27 - .../v2/remotesigner/testdata/server_cert.der | Bin 1013 -> 0 bytes .../v2/remotesigner/testdata/server_cert.pem | 24 - .../v2/remotesigner/testdata/server_key.pem | 27 - .../internal/v2/testdata/client_cert.pem | 24 - .../internal/v2/testdata/client_key.pem | 27 - .../internal/v2/testdata/server_cert.pem | 24 - .../internal/v2/testdata/server_key.pem | 27 - .../tlsconfigstore/testdata/client_cert.pem | 24 - .../v2/tlsconfigstore/testdata/client_key.pem | 27 - .../tlsconfigstore/testdata/server_cert.pem | 24 - .../v2/tlsconfigstore/testdata/server_key.pem | 27 - .../google/s2a-go/testdata/client_cert.pem | 24 - .../google/s2a-go/testdata/client_key.pem | 27 - .../google/s2a-go/testdata/server_cert.pem | 24 - .../google/s2a-go/testdata/server_key.pem | 27 - .../hetznercloud/hcloud-go/v2/LICENSE | 21 + .../hcloud-go/v2/hcloud/action.go | 200 + .../hcloud-go/v2/hcloud/action_waiter.go | 116 + .../hcloud-go/v2/hcloud/action_watch.go | 131 + .../hcloud-go/v2/hcloud/architecture.go | 12 + .../hcloud-go/v2/hcloud/certificate.go | 370 + .../hcloud-go/v2/hcloud/client.go | 468 ++ .../hcloud-go/v2/hcloud/datacenter.go | 136 + .../hcloud-go/v2/hcloud/deprecation.go | 59 + .../hetznercloud/hcloud-go/v2/hcloud/error.go | 150 + .../hcloud-go/v2/hcloud/firewall.go | 372 + .../hcloud-go/v2/hcloud/floating_ip.go | 405 + .../hcloud-go/v2/hcloud/hcloud.go | 5 + .../hcloud-go/v2/hcloud/helper.go | 28 + .../hetznercloud/hcloud-go/v2/hcloud/image.go | 313 + .../hcloud-go/v2/hcloud/interface_gen.go | 22 + .../internal/instrumentation/metrics.go | 117 + .../hetznercloud/hcloud-go/v2/hcloud/iso.go | 159 + .../hcloud-go/v2/hcloud/labels.go | 23 + .../hcloud-go/v2/hcloud/load_balancer.go | 1062 +++ .../hcloud-go/v2/hcloud/load_balancer_type.go | 133 + .../hcloud-go/v2/hcloud/location.go | 132 + .../hcloud-go/v2/hcloud/network.go | 484 ++ .../hcloud-go/v2/hcloud/placement_group.go | 247 + .../hcloud-go/v2/hcloud/pricing.go | 139 + .../hcloud-go/v2/hcloud/primary_ip.go | 422 ++ .../hetznercloud/hcloud-go/v2/hcloud/rdns.go | 52 + .../hcloud-go/v2/hcloud/resource.go | 7 + .../hcloud-go/v2/hcloud/schema.go | 370 + .../hcloud-go/v2/hcloud/schema/action.go | 39 + .../hcloud-go/v2/hcloud/schema/certificate.go | 76 + .../hcloud-go/v2/hcloud/schema/datacenter.go | 27 + .../hcloud-go/v2/hcloud/schema/deprecation.go | 12 + .../hcloud-go/v2/hcloud/schema/error.go | 42 + .../hcloud-go/v2/hcloud/schema/firewall.go | 115 + .../hcloud-go/v2/hcloud/schema/floating_ip.go | 118 + .../hcloud-go/v2/hcloud/schema/image.go | 70 + .../hcloud-go/v2/hcloud/schema/iso.go | 21 + .../v2/hcloud/schema/load_balancer.go | 418 ++ .../v2/hcloud/schema/load_balancer_type.go | 26 + .../hcloud-go/v2/hcloud/schema/location.go | 23 + .../hcloud-go/v2/hcloud/schema/meta.go | 23 + .../hcloud-go/v2/hcloud/schema/network.go | 155 + .../v2/hcloud/schema/placement_group.go | 40 + .../hcloud-go/v2/hcloud/schema/pricing.go | 110 + .../hcloud-go/v2/hcloud/schema/primary_ip.go | 62 + .../hcloud-go/v2/hcloud/schema/server.go | 436 ++ .../hcloud-go/v2/hcloud/schema/server_type.go | 30 + .../hcloud-go/v2/hcloud/schema/ssh_key.go | 50 + .../hcloud-go/v2/hcloud/schema/volume.go | 111 + .../hcloud-go/v2/hcloud/schema_assign.go | 15 + .../hcloud-go/v2/hcloud/schema_gen.go | 957 +++ .../hcloud-go/v2/hcloud/server.go | 1224 +++ .../hcloud-go/v2/hcloud/server_type.go | 159 + .../hcloud-go/v2/hcloud/ssh_key.go | 237 + .../hcloud-go/v2/hcloud/testing.go | 16 + .../hcloud-go/v2/hcloud/volume.go | 410 ++ .../v2/hcloud/zz_action_client_iface.go | 79 + .../v2/hcloud/zz_certificate_client_iface.go | 40 + .../v2/hcloud/zz_datacenter_client_iface.go | 27 + .../v2/hcloud/zz_firewall_client_iface.go | 37 + .../v2/hcloud/zz_floating_ip_client_iface.go | 43 + .../v2/hcloud/zz_image_client_iface.go | 48 + .../v2/hcloud/zz_iso_client_iface.go | 26 + .../hcloud/zz_load_balancer_client_iface.go | 71 + .../zz_load_balancer_type_client_iface.go | 27 + .../v2/hcloud/zz_location_client_iface.go | 27 + .../v2/hcloud/zz_network_client_iface.go | 45 + .../hcloud/zz_placement_group_client_iface.go | 33 + .../v2/hcloud/zz_pricing_client_iface.go | 13 + .../v2/hcloud/zz_primary_ip_client_iface.go | 43 + .../v2/hcloud/zz_rdns_client_iface.go | 15 + .../hcloud/zz_resource_action_client_iface.go | 20 + .../hcloud-go/v2/hcloud/zz_schema.go | 2491 +++++++ .../v2/hcloud/zz_server_client_iface.go | 90 + .../v2/hcloud/zz_server_type_client_iface.go | 27 + .../v2/hcloud/zz_ssh_key_client_iface.go | 35 + .../v2/hcloud/zz_volume_client_iface.go | 43 + vendor/github.com/json-iterator/go/README.md | 2 - .../golang_protobuf_extensions/LICENSE | 201 - .../golang_protobuf_extensions/NOTICE | 1 - .../pbutil/.gitignore | 1 - .../pbutil/Makefile | 7 - .../pbutil/decode.go | 75 - .../pbutil/encode.go | 46 - .../github.com/modern-go/reflect2/.travis.yml | 2 +- .../github.com/modern-go/reflect2/Gopkg.lock | 8 +- .../github.com/modern-go/reflect2/Gopkg.toml | 4 - .../modern-go/reflect2/go_above_118.go | 23 + .../modern-go/reflect2/go_above_17.go | 8 - .../modern-go/reflect2/go_above_19.go | 3 + .../modern-go/reflect2/go_below_118.go | 21 + .../modern-go/reflect2/go_below_17.go | 9 - .../modern-go/reflect2/go_below_19.go | 14 - .../github.com/modern-go/reflect2/reflect2.go | 20 +- vendor/github.com/modern-go/reflect2/test.sh | 12 - .../github.com/modern-go/reflect2/type_map.go | 51 +- .../modern-go/reflect2/unsafe_link.go | 26 +- .../modern-go/reflect2/unsafe_map.go | 8 - .../client_golang/prometheus/README.md | 2 +- .../prometheus/build_info_collector.go | 38 + .../client_golang/prometheus/collector.go | 14 +- .../client_golang/prometheus/counter.go | 65 +- .../client_golang/prometheus/desc.go | 57 +- .../client_golang/prometheus/doc.go | 107 +- .../prometheus/expvar_collector.go | 2 +- .../client_golang/prometheus/gauge.go | 36 +- .../client_golang/prometheus/get_pid.go | 26 + .../prometheus/get_pid_gopherjs.go | 23 + .../client_golang/prometheus/go_collector.go | 496 +- .../prometheus/go_collector_go116.go | 122 + .../prometheus/go_collector_latest.go | 567 ++ .../client_golang/prometheus/histogram.go | 1123 ++- .../prometheus/internal/almost_equal.go | 60 + .../prometheus/internal/difflib.go | 654 ++ .../internal/go_collector_options.go | 32 + .../prometheus/internal/go_runtime_metrics.go | 142 + .../prometheus/internal/metric.go | 28 +- .../client_golang/prometheus/labels.go | 109 +- .../client_golang/prometheus/metric.go | 121 +- .../client_golang/prometheus/num_threads.go | 25 + .../prometheus/num_threads_gopherjs.go | 22 + .../client_golang/prometheus/observer.go | 2 +- .../prometheus/process_collector.go | 10 +- .../prometheus/process_collector_js.go | 26 + .../prometheus/process_collector_other.go | 3 +- .../prometheus/process_collector_wasip1.go | 26 + .../prometheus/promhttp/delegator.go | 18 +- .../client_golang/prometheus/promhttp/http.go | 39 +- .../prometheus/promhttp/instrument_client.go | 46 +- .../prometheus/promhttp/instrument_server.go | 149 +- .../prometheus/promhttp/option.go | 65 +- .../client_golang/prometheus/registry.go | 171 +- .../client_golang/prometheus/summary.go | 81 +- .../client_golang/prometheus/timer.go | 39 +- .../client_golang/prometheus/value.go | 108 +- .../client_golang/prometheus/vec.go | 181 +- .../client_golang/prometheus/vnext.go | 23 + .../client_golang/prometheus/wrap.go | 8 +- .../prometheus/client_model/go/metrics.pb.go | 1579 ++-- .../prometheus/common/expfmt/decode.go | 66 +- .../prometheus/common/expfmt/encode.go | 79 +- .../prometheus/common/expfmt/expfmt.go | 156 +- .../prometheus/common/expfmt/fuzz.go | 5 +- .../common/expfmt/openmetrics_create.go | 111 +- .../prometheus/common/expfmt/text_create.go | 121 +- .../prometheus/common/expfmt/text_parse.go | 16 +- .../bitbucket.org/ww/goautoneg/autoneg.go | 22 +- .../prometheus/common/model/alert.go | 4 +- .../prometheus/common/model/labels.go | 22 +- .../prometheus/common/model/metadata.go | 28 + .../prometheus/common/model/metric.go | 368 +- .../prometheus/common/model/signature.go | 6 +- .../prometheus/common/model/silence.go | 2 +- .../prometheus/common/model/time.go | 91 +- .../prometheus/common/model/value.go | 262 +- .../prometheus/common/model/value_float.go | 98 + .../common/model/value_histogram.go | 178 + .../prometheus/common/model/value_type.go | 83 + .../github.com/prometheus/procfs/.gitignore | 3 +- .../prometheus/procfs/.golangci.yml | 13 +- .../prometheus/procfs/CODE_OF_CONDUCT.md | 4 +- .../prometheus/procfs/CONTRIBUTING.md | 4 +- vendor/github.com/prometheus/procfs/Makefile | 10 +- .../prometheus/procfs/Makefile.common | 117 +- vendor/github.com/prometheus/procfs/README.md | 8 +- .../github.com/prometheus/procfs/SECURITY.md | 2 +- vendor/github.com/prometheus/procfs/arp.go | 51 +- .../github.com/prometheus/procfs/buddyinfo.go | 6 +- .../github.com/prometheus/procfs/cmdline.go | 30 + .../github.com/prometheus/procfs/cpuinfo.go | 58 +- .../prometheus/procfs/cpuinfo_armx.go | 1 + .../procfs/cpuinfo_loong64.go} | 13 +- .../prometheus/procfs/cpuinfo_mipsx.go | 1 + .../prometheus/procfs/cpuinfo_others.go | 4 +- .../prometheus/procfs/cpuinfo_ppcx.go | 1 + .../prometheus/procfs/cpuinfo_riscvx.go | 1 + .../prometheus/procfs/cpuinfo_s390x.go | 1 + .../prometheus/procfs/cpuinfo_x86.go | 1 + vendor/github.com/prometheus/procfs/crypto.go | 7 +- vendor/github.com/prometheus/procfs/doc.go | 51 +- .../prometheus/procfs/fixtures.ttar | 6553 ----------------- vendor/github.com/prometheus/procfs/fs.go | 11 +- .../prometheus/procfs/fs_statfs_notype.go | 23 + .../prometheus/procfs/fs_statfs_type.go | 33 + .../github.com/prometheus/procfs/fscache.go | 6 +- .../prometheus/procfs/internal/fs/fs.go | 2 +- .../prometheus/procfs/internal/util/parse.go | 21 +- .../procfs/internal/util/readfile.go | 11 +- .../procfs/internal/util/sysreadfile.go | 8 +- .../internal/util/sysreadfile_compat.go | 3 +- vendor/github.com/prometheus/procfs/ipvs.go | 10 +- .../prometheus/procfs/kernel_random.go | 1 + .../github.com/prometheus/procfs/loadavg.go | 6 +- vendor/github.com/prometheus/procfs/mdstat.go | 125 +- .../github.com/prometheus/procfs/meminfo.go | 4 +- .../github.com/prometheus/procfs/mountinfo.go | 10 +- .../prometheus/procfs/mountstats.go | 120 +- .../prometheus/procfs/net_conntrackstat.go | 101 +- .../github.com/prometheus/procfs/net_dev.go | 8 +- .../prometheus/procfs/net_ip_socket.go | 40 +- .../prometheus/procfs/net_protocols.go | 8 +- .../github.com/prometheus/procfs/net_route.go | 143 + .../prometheus/procfs/net_sockstat.go | 9 +- .../prometheus/procfs/net_softnet.go | 87 +- .../github.com/prometheus/procfs/net_unix.go | 16 +- .../prometheus/procfs/net_wireless.go | 182 + .../procfs/{xfrm.go => net_xfrm.go} | 11 +- .../github.com/prometheus/procfs/netstat.go | 82 + vendor/github.com/prometheus/procfs/proc.go | 47 +- .../prometheus/procfs/proc_cgroup.go | 14 +- .../prometheus/procfs/proc_cgroups.go | 98 + .../prometheus/procfs/proc_environ.go | 2 +- .../prometheus/procfs/proc_fdinfo.go | 13 +- .../prometheus/procfs/proc_interrupts.go | 98 + .../prometheus/procfs/proc_limits.go | 6 +- .../github.com/prometheus/procfs/proc_maps.go | 36 +- .../prometheus/procfs/proc_netstat.go | 443 ++ .../github.com/prometheus/procfs/proc_ns.go | 6 +- .../github.com/prometheus/procfs/proc_psi.go | 20 +- .../prometheus/procfs/proc_smaps.go | 27 +- .../github.com/prometheus/procfs/proc_snmp.go | 353 + .../prometheus/procfs/proc_snmp6.go | 381 + .../github.com/prometheus/procfs/proc_stat.go | 55 +- .../prometheus/procfs/proc_status.go | 91 +- .../github.com/prometheus/procfs/proc_sys.go | 51 + .../github.com/prometheus/procfs/schedstat.go | 6 +- vendor/github.com/prometheus/procfs/slab.go | 4 +- .../github.com/prometheus/procfs/softirqs.go | 160 + vendor/github.com/prometheus/procfs/stat.go | 60 +- vendor/github.com/prometheus/procfs/swaps.go | 8 +- vendor/github.com/prometheus/procfs/thread.go | 80 + vendor/github.com/prometheus/procfs/vm.go | 12 +- .../github.com/prometheus/procfs/zoneinfo.go | 10 +- vendor/golang.org/x/oauth2/google/default.go | 72 +- vendor/golang.org/x/sys/unix/mremap.go | 5 + .../golang.org/x/sys/unix/syscall_darwin.go | 12 + vendor/golang.org/x/sys/unix/syscall_unix.go | 9 + .../x/sys/unix/zsyscall_darwin_amd64.go | 33 + .../x/sys/unix/zsyscall_darwin_amd64.s | 10 + .../x/sys/unix/zsyscall_darwin_arm64.go | 33 + .../x/sys/unix/zsyscall_darwin_arm64.s | 10 + .../x/sys/windows/security_windows.go | 24 +- .../x/sys/windows/zsyscall_windows.go | 9 + .../encoding/protodelim/protodelim.go | 160 + vendor/modules.txt | 50 +- 285 files changed, 25544 insertions(+), 9483 deletions(-) create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/CHANGELOG.md create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/LICENSE create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/backoff/backoff.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/client.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/context.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/discard.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/doc.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/actionutil/action.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/control/retry.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/labelutil/labels.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/randomid/randomid.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshkey/ssh_key.go create mode 100644 vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshsession/session.go delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_intermediate_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_leaf_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_root_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_intermediate_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_leaf_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_root_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_key.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/server_cert.der delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/server_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/server_key.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/testdata/client_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/testdata/client_key.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/testdata/server_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/testdata/server_key.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/tlsconfigstore/testdata/client_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/tlsconfigstore/testdata/client_key.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/tlsconfigstore/testdata/server_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/internal/v2/tlsconfigstore/testdata/server_key.pem delete mode 100644 vendor/github.com/google/s2a-go/testdata/client_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/testdata/client_key.pem delete mode 100644 vendor/github.com/google/s2a-go/testdata/server_cert.pem delete mode 100644 vendor/github.com/google/s2a-go/testdata/server_key.pem create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/LICENSE create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/action.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/action_waiter.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/action_watch.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/architecture.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/certificate.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/client.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/datacenter.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/error.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/helper.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/interface_gen.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/internal/instrumentation/metrics.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/iso.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/labels.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer_type.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/location.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/placement_group.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/pricing.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/rdns.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/resource.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/action.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/certificate.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/datacenter.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/deprecation.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/error.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/firewall.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/floating_ip.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/image.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/iso.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer_type.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/location.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/meta.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/network.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/placement_group.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/pricing.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/primary_ip.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server_type.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/ssh_key.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/volume.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_assign.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_gen.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server_type.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/ssh_key.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/testing.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_certificate_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_datacenter_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_firewall_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_floating_ip_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_image_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_iso_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_type_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_location_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_network_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_placement_group_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_pricing_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_primary_ip_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_rdns_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_type_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_ssh_key_client_iface.go create mode 100644 vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_volume_client_iface.go delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go delete mode 100644 vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go create mode 100644 vendor/github.com/modern-go/reflect2/go_above_118.go delete mode 100644 vendor/github.com/modern-go/reflect2/go_above_17.go create mode 100644 vendor/github.com/modern-go/reflect2/go_below_118.go delete mode 100644 vendor/github.com/modern-go/reflect2/go_below_17.go delete mode 100644 vendor/github.com/modern-go/reflect2/go_below_19.go delete mode 100644 vendor/github.com/modern-go/reflect2/test.sh create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/build_info_collector.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/get_pid.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/num_threads.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/vnext.go create mode 100644 vendor/github.com/prometheus/common/model/metadata.go create mode 100644 vendor/github.com/prometheus/common/model/value_float.go create mode 100644 vendor/github.com/prometheus/common/model/value_histogram.go create mode 100644 vendor/github.com/prometheus/common/model/value_type.go create mode 100644 vendor/github.com/prometheus/procfs/cmdline.go rename vendor/github.com/{matttproud/golang_protobuf_extensions/pbutil/doc.go => prometheus/procfs/cpuinfo_loong64.go} (73%) delete mode 100644 vendor/github.com/prometheus/procfs/fixtures.ttar create mode 100644 vendor/github.com/prometheus/procfs/fs_statfs_notype.go create mode 100644 vendor/github.com/prometheus/procfs/fs_statfs_type.go create mode 100644 vendor/github.com/prometheus/procfs/net_route.go create mode 100644 vendor/github.com/prometheus/procfs/net_wireless.go rename vendor/github.com/prometheus/procfs/{xfrm.go => net_xfrm.go} (94%) create mode 100644 vendor/github.com/prometheus/procfs/netstat.go create mode 100644 vendor/github.com/prometheus/procfs/proc_cgroups.go create mode 100644 vendor/github.com/prometheus/procfs/proc_interrupts.go create mode 100644 vendor/github.com/prometheus/procfs/proc_netstat.go create mode 100644 vendor/github.com/prometheus/procfs/proc_snmp.go create mode 100644 vendor/github.com/prometheus/procfs/proc_snmp6.go create mode 100644 vendor/github.com/prometheus/procfs/proc_sys.go create mode 100644 vendor/github.com/prometheus/procfs/softirqs.go create mode 100644 vendor/github.com/prometheus/procfs/thread.go create mode 100644 vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go diff --git a/vendor/github.com/alecthomas/units/README.md b/vendor/github.com/alecthomas/units/README.md index bee884e3c..57b458aef 100644 --- a/vendor/github.com/alecthomas/units/README.md +++ b/vendor/github.com/alecthomas/units/README.md @@ -1,3 +1,5 @@ +[![Go Reference](https://pkg.go.dev/badge/github.com/alecthomas/units.svg)](https://pkg.go.dev/github.com/alecthomas/units) + # Units - Helpful unit multipliers and functions for Go The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package. diff --git a/vendor/github.com/alecthomas/units/bytes.go b/vendor/github.com/alecthomas/units/bytes.go index cd439f51c..f13a842e4 100644 --- a/vendor/github.com/alecthomas/units/bytes.go +++ b/vendor/github.com/alecthomas/units/bytes.go @@ -40,15 +40,76 @@ func (b Base2Bytes) String() string { return ToString(int64(b), 1024, "iB", "B") } +// MarshalText implement encoding.TextMarshaler to process json/yaml. +func (b Base2Bytes) MarshalText() ([]byte, error) { + return []byte(b.String()), nil +} + +// UnmarshalText implement encoding.TextUnmarshaler to process json/yaml. func (b *Base2Bytes) UnmarshalText(text []byte) error { n, err := ParseBase2Bytes(string(text)) *b = n return err } -var ( - metricBytesUnitMap = MakeUnitMap("B", "B", 1000) -) +// Floor returns Base2Bytes with all but the largest unit zeroed out. So that e.g. 1GiB1MiB1KiB → 1GiB. +func (b Base2Bytes) Floor() Base2Bytes { + switch { + case b > Exbibyte: + return (b / Exbibyte) * Exbibyte + case b > Pebibyte: + return (b / Pebibyte) * Pebibyte + case b > Tebibyte: + return (b / Tebibyte) * Tebibyte + case b > Gibibyte: + return (b / Gibibyte) * Gibibyte + case b > Mebibyte: + return (b / Mebibyte) * Mebibyte + case b > Kibibyte: + return (b / Kibibyte) * Kibibyte + default: + return b + } +} + +// Round returns Base2Bytes with all but the first n units zeroed out. So that e.g. 1GiB1MiB1KiB → 1GiB1MiB, if n is 2. +func (b Base2Bytes) Round(n int) Base2Bytes { + idx := 0 + + switch { + case b > Exbibyte: + idx = n + case b > Pebibyte: + idx = n + 1 + case b > Tebibyte: + idx = n + 2 + case b > Gibibyte: + idx = n + 3 + case b > Mebibyte: + idx = n + 4 + case b > Kibibyte: + idx = n + 5 + } + + switch idx { + case 1: + return b - b%Exbibyte + case 2: + return b - b%Pebibyte + case 3: + return b - b%Tebibyte + case 4: + return b - b%Gibibyte + case 5: + return b - b%Mebibyte + case 6: + return b - b%Kibibyte + default: + return b + } +} + +var metricBytesUnitMap = MakeUnitMap("B", "B", 1000) // MetricBytes are SI byte units (1000 bytes in a kilobyte). type MetricBytes SI @@ -80,6 +141,63 @@ func (m MetricBytes) String() string { return ToString(int64(m), 1000, "B", "B") } +// Floor returns MetricBytes with all but the largest unit zeroed out. So that e.g. 1GB1MB1KB → 1GB. +func (b MetricBytes) Floor() MetricBytes { + switch { + case b > Exabyte: + return (b / Exabyte) * Exabyte + case b > Petabyte: + return (b / Petabyte) * Petabyte + case b > Terabyte: + return (b / Terabyte) * Terabyte + case b > Gigabyte: + return (b / Gigabyte) * Gigabyte + case b > Megabyte: + return (b / Megabyte) * Megabyte + case b > Kilobyte: + return (b / Kilobyte) * Kilobyte + default: + return b + } +} + +// Round returns MetricBytes with all but the first n units zeroed out. So that e.g. 1GB1MB1KB → 1GB1MB, if n is 2. +func (b MetricBytes) Round(n int) MetricBytes { + idx := 0 + + switch { + case b > Exabyte: + idx = n + case b > Petabyte: + idx = n + 1 + case b > Terabyte: + idx = n + 2 + case b > Gigabyte: + idx = n + 3 + case b > Megabyte: + idx = n + 4 + case b > Kilobyte: + idx = n + 5 + } + + switch idx { + case 1: + return b - b%Exabyte + case 2: + return b - b%Petabyte + case 3: + return b - b%Terabyte + case 4: + return b - b%Gigabyte + case 5: + return b - b%Megabyte + case 6: + return b - b%Kilobyte + default: + return b + } +} + // ParseStrictBytes supports both iB and B suffixes for base 2 and metric, // respectively. That is, KiB represents 1024 and kB, KB represent 1000. func ParseStrictBytes(s string) (int64, error) { diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/CHANGELOG.md b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/CHANGELOG.md new file mode 100644 index 000000000..e7811785c --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/CHANGELOG.md @@ -0,0 +1,14 @@ +# Changelog + +## [0.3.0](https://github.com/apricote/hcloud-upload-image/compare/hcloudimages/v0.2.0...hcloudimages/v0.3.0) (2024-06-23) + + +### Features + +* set server type explicitly ([#36](https://github.com/apricote/hcloud-upload-image/issues/36)) ([42eeb00](https://github.com/apricote/hcloud-upload-image/commit/42eeb00a0784e13a00a52cf15a8659b497d78d72)), closes [#30](https://github.com/apricote/hcloud-upload-image/issues/30) +* update default x86 server type to cx22 ([#38](https://github.com/apricote/hcloud-upload-image/issues/38)) ([ebe08b3](https://github.com/apricote/hcloud-upload-image/commit/ebe08b345c8f31df73087b091fa39f5fdc195156)) + + +### Bug Fixes + +* error early when the image write fails ([#34](https://github.com/apricote/hcloud-upload-image/issues/34)) ([256989f](https://github.com/apricote/hcloud-upload-image/commit/256989f4a37e7b124c0684aab0f34cf5e09559be)), closes [#33](https://github.com/apricote/hcloud-upload-image/issues/33) diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/LICENSE b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/LICENSE new file mode 100644 index 000000000..84692cf60 --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2024 Julian Tölle + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/backoff/backoff.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/backoff/backoff.go new file mode 100644 index 000000000..310312a33 --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/backoff/backoff.go @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MPL-2.0 +// From https://github.com/hetznercloud/terraform-provider-hcloud/blob/v1.46.1/internal/control/retry.go +// Copyright (c) Hetzner Cloud GmbH + +package backoff + +import ( + "math" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +// ExponentialBackoffWithLimit returns a [hcloud.BackoffFunc] which implements an exponential +// backoff. +// It uses the formula: +// +// min(b^retries * d, limit) +func ExponentialBackoffWithLimit(b float64, d time.Duration, limit time.Duration) hcloud.BackoffFunc { + return func(retries int) time.Duration { + current := time.Duration(math.Pow(b, float64(retries))) * d + + if current > limit { + return limit + } else { + return current + } + } +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/client.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/client.go new file mode 100644 index 000000000..7240ef74a --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/client.go @@ -0,0 +1,483 @@ +package hcloudimages + +import ( + "context" + "errors" + "fmt" + "io" + "log/slog" + "net/url" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" + "golang.org/x/crypto/ssh" + + "github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger" + "github.com/apricote/hcloud-upload-image/hcloudimages/internal/actionutil" + "github.com/apricote/hcloud-upload-image/hcloudimages/internal/control" + "github.com/apricote/hcloud-upload-image/hcloudimages/internal/labelutil" + "github.com/apricote/hcloud-upload-image/hcloudimages/internal/randomid" + "github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshkey" + "github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshsession" +) + +const ( + CreatedByLabel = "apricote.de/created-by" + CreatedByValue = "hcloud-upload-image" + + resourcePrefix = "hcloud-upload-image-" +) + +var ( + DefaultLabels = map[string]string{ + CreatedByLabel: CreatedByValue, + } + + serverTypePerArchitecture = map[hcloud.Architecture]*hcloud.ServerType{ + hcloud.ArchitectureX86: {Name: "cx22"}, + hcloud.ArchitectureARM: {Name: "cax11"}, + } + + defaultImage = &hcloud.Image{Name: "ubuntu-24.04"} + defaultLocation = &hcloud.Location{Name: "fsn1"} + defaultRescueType = hcloud.ServerRescueTypeLinux64 + + defaultSSHDialTimeout = 1 * time.Minute +) + +type UploadOptions struct { + // ImageURL must be publicly available. The instance will download the image from this endpoint. + ImageURL *url.URL + + // ImageReader + ImageReader io.Reader + + // ImageCompression describes the compression of the referenced image file. It defaults to [CompressionNone]. If + // set to anything else, the file will be decompressed before written to the disk. + ImageCompression Compression + + // Possible future additions: + // ImageSignatureVerification + // ImageLocalPath + // ImageType (RawDiskImage, ISO, qcow2, ...) + + // Architecture should match the architecture of the Image. This decides if the Snapshot can later be + // used with [hcloud.ArchitectureX86] or [hcloud.ArchitectureARM] servers. + // + // Internally this decides what server type is used for the temporary server. + // + // Optional if [UploadOptions.ServerType] is set. + Architecture hcloud.Architecture + + // ServerType can be optionally set to override the default server type for the architecture. + // Situations where this makes sense: + // + // - Your image is larger than the root disk of the default server types. + // - The default server type is no longer available, or not temporarily out of stock. + ServerType *hcloud.ServerType + + // Description is an optional description that the resulting image (snapshot) will have. There is no way to + // select images by its description, you should use Labels if you need to identify your image later. + Description *string + + // Labels will be added to the resulting image (snapshot). Use these to filter the image list if you + // need to identify the image later on. + // + // We also always add a label `apricote.de/created-by=hcloud-image-upload` ([CreatedByLabel], [CreatedByValue]). + Labels map[string]string + + // DebugSkipResourceCleanup will skip the cleanup of the temporary SSH Key and Server. + DebugSkipResourceCleanup bool +} + +type Compression string + +const ( + CompressionNone Compression = "" + CompressionBZ2 Compression = "bz2" + CompressionXZ Compression = "xz" + + // Possible future additions: + // zip,zstd +) + +// NewClient instantiates a new client. It requires a working [*hcloud.Client] to interact with the Hetzner Cloud API. +func NewClient(c *hcloud.Client) *Client { + return &Client{ + c: c, + } +} + +type Client struct { + c *hcloud.Client +} + +// Upload the specified image into a snapshot on Hetzner Cloud. +// +// As the Hetzner Cloud API has no direct way to upload images, we create a temporary server, +// overwrite the root disk and take a snapshot of that disk instead. +// +// The temporary server costs money. If the upload fails, we might be unable to delete the server. Check out +// CleanupTempResources for a helper in this case. +func (s *Client) Upload(ctx context.Context, options UploadOptions) (*hcloud.Image, error) { + logger := contextlogger.From(ctx).With( + "library", "hcloudimages", + "method", "upload", + ) + + id, err := randomid.Generate() + if err != nil { + return nil, err + } + logger = logger.With("run-id", id) + // For simplicity, we use the name random name for SSH Key + Server + resourceName := resourcePrefix + id + labels := labelutil.Merge(DefaultLabels, options.Labels) + + // 1. Create SSH Key + logger.InfoContext(ctx, "# Step 1: Generating SSH Key") + publicKey, privateKey, err := sshkey.GenerateKeyPair() + if err != nil { + return nil, fmt.Errorf("failed to generate temporary ssh key pair: %w", err) + } + + key, _, err := s.c.SSHKey.Create(ctx, hcloud.SSHKeyCreateOpts{ + Name: resourceName, + PublicKey: string(publicKey), + Labels: labels, + }) + if err != nil { + return nil, fmt.Errorf("failed to submit temporary ssh key to API: %w", err) + } + logger.DebugContext(ctx, "Uploaded ssh key", "ssh-key-id", key.ID) + defer func() { + // Cleanup SSH Key + if options.DebugSkipResourceCleanup { + logger.InfoContext(ctx, "Cleanup: Skipping cleanup of temporary ssh key") + return + } + + logger.InfoContext(ctx, "Cleanup: Deleting temporary ssh key") + + _, err := s.c.SSHKey.Delete(ctx, key) + if err != nil { + logger.WarnContext(ctx, "Cleanup: ssh key could not be deleted", "error", err) + // TODO + } + }() + + // 2. Create Server + logger.InfoContext(ctx, "# Step 2: Creating Server") + var serverType *hcloud.ServerType + if options.ServerType != nil { + serverType = options.ServerType + } else { + var ok bool + serverType, ok = serverTypePerArchitecture[options.Architecture] + if !ok { + return nil, fmt.Errorf("unknown architecture %q, valid options: %q, %q", options.Architecture, hcloud.ArchitectureX86, hcloud.ArchitectureARM) + } + } + + logger.DebugContext(ctx, "creating server with config", + "image", defaultImage.Name, + "location", defaultLocation.Name, + "serverType", serverType.Name, + ) + serverCreateResult, _, err := s.c.Server.Create(ctx, hcloud.ServerCreateOpts{ + Name: resourceName, + ServerType: serverType, + + // Not used, but without this the user receives an email with a password for every created server + SSHKeys: []*hcloud.SSHKey{key}, + + // We need to enable rescue system first + StartAfterCreate: hcloud.Ptr(false), + // Image will never be booted, we only boot into rescue system + Image: defaultImage, + Location: defaultLocation, + Labels: labels, + }) + if err != nil { + return nil, fmt.Errorf("creating the temporary server failed: %w", err) + } + logger = logger.With("server", serverCreateResult.Server.ID) + logger.DebugContext(ctx, "Created Server") + + logger.DebugContext(ctx, "waiting on actions") + err = s.c.Action.WaitFor(ctx, append(serverCreateResult.NextActions, serverCreateResult.Action)...) + if err != nil { + return nil, fmt.Errorf("creating the temporary server failed: %w", err) + } + logger.DebugContext(ctx, "actions finished") + + server := serverCreateResult.Server + defer func() { + // Cleanup Server + if options.DebugSkipResourceCleanup { + logger.InfoContext(ctx, "Cleanup: Skipping cleanup of temporary server") + return + } + + logger.InfoContext(ctx, "Cleanup: Deleting temporary server") + + _, _, err := s.c.Server.DeleteWithResult(ctx, server) + if err != nil { + logger.WarnContext(ctx, "Cleanup: server could not be deleted", "error", err) + } + }() + + // 3. Activate Rescue System + logger.InfoContext(ctx, "# Step 3: Activating Rescue System") + enableRescueResult, _, err := s.c.Server.EnableRescue(ctx, server, hcloud.ServerEnableRescueOpts{ + Type: defaultRescueType, + SSHKeys: []*hcloud.SSHKey{key}, + }) + if err != nil { + return nil, fmt.Errorf("enabling the rescue system on the temporary server failed: %w", err) + } + + logger.DebugContext(ctx, "rescue system requested, waiting on action") + + err = s.c.Action.WaitFor(ctx, enableRescueResult.Action) + if err != nil { + return nil, fmt.Errorf("enabling the rescue system on the temporary server failed: %w", err) + } + logger.DebugContext(ctx, "action finished, rescue system enabled") + + // 4. Boot Server + logger.InfoContext(ctx, "# Step 4: Booting Server") + powerOnAction, _, err := s.c.Server.Poweron(ctx, server) + if err != nil { + return nil, fmt.Errorf("starting the temporary server failed: %w", err) + } + + logger.DebugContext(ctx, "boot requested, waiting on action") + + err = s.c.Action.WaitFor(ctx, powerOnAction) + if err != nil { + return nil, fmt.Errorf("starting the temporary server failed: %w", err) + } + logger.DebugContext(ctx, "action finished, server is booting") + + // 5. Open SSH Session + logger.InfoContext(ctx, "# Step 5: Opening SSH Connection") + signer, err := ssh.ParsePrivateKey(privateKey) + if err != nil { + return nil, fmt.Errorf("parsing the automatically generated temporary private key failed: %w", err) + } + + sshClientConfig := &ssh.ClientConfig{ + User: "root", + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), + }, + // There is no way to get the host key of the rescue system beforehand + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + Timeout: defaultSSHDialTimeout, + } + + // the server needs some time until its properly started and ssh is available + var sshClient *ssh.Client + + err = control.Retry( + contextlogger.New(ctx, logger.With("operation", "ssh")), + 10, + func() error { + var err error + logger.DebugContext(ctx, "trying to connect to server", "ip", server.PublicNet.IPv4.IP) + sshClient, err = ssh.Dial("tcp", server.PublicNet.IPv4.IP.String()+":ssh", sshClientConfig) + return err + }, + ) + if err != nil { + return nil, fmt.Errorf("failed to ssh into temporary server: %w", err) + } + defer sshClient.Close() + + // 6. SSH On Server: Download Image, Decompress, Write to Root Disk + logger.InfoContext(ctx, "# Step 6: Downloading image and writing to disk") + cmd := "" + if options.ImageURL != nil { + cmd += fmt.Sprintf("wget --no-verbose -O - %q | ", options.ImageURL.String()) + } + + if options.ImageCompression != CompressionNone { + switch options.ImageCompression { + case CompressionBZ2: + cmd += "bzip2 -cd | " + case CompressionXZ: + cmd += "xz -cd | " + default: + return nil, fmt.Errorf("unknown compression: %q", options.ImageCompression) + } + } + + cmd += "dd of=/dev/sda bs=4M && sync" + + // Make sure that we fail early, ie. if the image url does not work. + // the pipefail does not work correctly without wrapping in bash. + cmd = fmt.Sprintf("bash -c 'set -euo pipefail && %s'", cmd) + logger.DebugContext(ctx, "running download, decompress and write to disk command", "cmd", cmd) + + output, err := sshsession.Run(sshClient, cmd, options.ImageReader) + logger.InfoContext(ctx, "# Step 6: Finished writing image to disk") + logger.DebugContext(ctx, string(output)) + if err != nil { + return nil, fmt.Errorf("failed to download and write the image: %w", err) + } + + // 7. SSH On Server: Shutdown + logger.InfoContext(ctx, "# Step 7: Shutting down server") + _, err = sshsession.Run(sshClient, "shutdown now", nil) + if err != nil { + // TODO Verify if shutdown error, otherwise return + logger.WarnContext(ctx, "shutdown returned error", "err", err) + } + + // 8. Create Image from Server + logger.InfoContext(ctx, "# Step 8: Creating Image") + createImageResult, _, err := s.c.Server.CreateImage(ctx, server, &hcloud.ServerCreateImageOpts{ + Type: hcloud.ImageTypeSnapshot, + Description: options.Description, + Labels: labels, + }) + if err != nil { + return nil, fmt.Errorf("failed to create snapshot: %w", err) + } + logger.DebugContext(ctx, "image creation requested, waiting on action") + + err = s.c.Action.WaitFor(ctx, createImageResult.Action) + if err != nil { + return nil, fmt.Errorf("failed to create snapshot: %w", err) + } + logger.DebugContext(ctx, "action finished, image was created") + + image := createImageResult.Image + logger.InfoContext(ctx, "# Image was created", "image", image.ID) + + // Resource cleanup is happening in `defer` + return image, nil +} + +// CleanupTempResources tries to delete any resources that were left over from previous calls to [Client.Upload]. +// Upload tries to clean up any temporary resources it created at runtime, but might fail at any point. +// You can then use this command to make sure that all temporary resources are removed from your project. +// +// This method tries to delete any server or ssh keys that match the [DefaultLabels] +func (s *Client) CleanupTempResources(ctx context.Context) error { + logger := contextlogger.From(ctx).With( + "library", "hcloudimages", + "method", "cleanup", + ) + + selector := labelutil.Selector(DefaultLabels) + logger = logger.With("selector", selector) + + logger.InfoContext(ctx, "# Cleaning up Servers") + err := s.cleanupTempServers(ctx, logger, selector) + if err != nil { + return fmt.Errorf("failed to clean up all servers: %w", err) + } + logger.DebugContext(ctx, "cleaned up all servers") + + logger.InfoContext(ctx, "# Cleaning up SSH Keys") + err = s.cleanupTempSSHKeys(ctx, logger, selector) + if err != nil { + return fmt.Errorf("failed to clean up all ssh keys: %w", err) + } + logger.DebugContext(ctx, "cleaned up all ssh keys") + + return nil +} + +func (s *Client) cleanupTempServers(ctx context.Context, logger *slog.Logger, selector string) error { + servers, err := s.c.Server.AllWithOpts(ctx, hcloud.ServerListOpts{ListOpts: hcloud.ListOpts{ + LabelSelector: selector, + }}) + if err != nil { + return fmt.Errorf("failed to list servers: %w", err) + } + + if len(servers) == 0 { + logger.InfoContext(ctx, "No servers found") + return nil + } + logger.InfoContext(ctx, "removing servers", "count", len(servers)) + + errs := []error{} + actions := make([]*hcloud.Action, 0, len(servers)) + + for _, server := range servers { + result, _, err := s.c.Server.DeleteWithResult(ctx, server) + if err != nil { + errs = append(errs, err) + logger.WarnContext(ctx, "failed to delete server", "server", server.ID, "error", err) + continue + } + + actions = append(actions, result.Action) + } + + successActions, errorActions, err := actionutil.Settle(ctx, &s.c.Action, actions...) + if err != nil { + return fmt.Errorf("failed to wait for server delete: %w", err) + } + + if len(successActions) > 0 { + ids := make([]int64, 0, len(successActions)) + for _, action := range successActions { + for _, resource := range action.Resources { + if resource.Type == hcloud.ActionResourceTypeServer { + ids = append(ids, resource.ID) + } + } + } + + logger.InfoContext(ctx, "successfully deleted servers", "servers", ids) + } + + if len(errorActions) > 0 { + for _, action := range errorActions { + errs = append(errs, action.Error()) + } + } + + if len(errs) > 0 { + // The returned message contains no info about the server IDs which failed + return fmt.Errorf("failed to delete some of the servers: %w", errors.Join(errs...)) + } + + return nil +} + +func (s *Client) cleanupTempSSHKeys(ctx context.Context, logger *slog.Logger, selector string) error { + keys, _, err := s.c.SSHKey.List(ctx, hcloud.SSHKeyListOpts{ListOpts: hcloud.ListOpts{ + LabelSelector: selector, + }}) + if err != nil { + return fmt.Errorf("failed to list keys: %w", err) + } + + if len(keys) == 0 { + logger.InfoContext(ctx, "No ssh keys found") + return nil + } + + errs := []error{} + for _, key := range keys { + _, err := s.c.SSHKey.Delete(ctx, key) + if err != nil { + errs = append(errs, err) + logger.WarnContext(ctx, "failed to delete ssh key", "ssh-key", key.ID, "error", err) + continue + } + } + + if len(errs) > 0 { + // The returned message contains no info about the server IDs which failed + return fmt.Errorf("failed to delete some of the ssh keys: %w", errors.Join(errs...)) + } + + return nil +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/context.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/context.go new file mode 100644 index 000000000..708478ae8 --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/context.go @@ -0,0 +1,27 @@ +package contextlogger + +import ( + "context" + "log/slog" +) + +type key int + +var loggerKey key + +// New saves the logger as a value to the context. This can then be retrieved through [From]. +func New(ctx context.Context, logger *slog.Logger) context.Context { + return context.WithValue(ctx, loggerKey, logger) +} + +// From returns the [*slog.Logger] set on the context by [New]. If there is none, +// it returns a no-op logger that discards any output it receives. +func From(ctx context.Context) *slog.Logger { + if ctxLogger := ctx.Value(loggerKey); ctxLogger != nil { + if logger, ok := ctxLogger.(*slog.Logger); ok { + return logger + } + } + + return slog.New(discardHandler{}) +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/discard.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/discard.go new file mode 100644 index 000000000..545f6ac6f --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger/discard.go @@ -0,0 +1,15 @@ +package contextlogger + +import ( + "context" + "log/slog" +) + +// discardHandler is a [slog.Handler] that just discards any input. It is a safe default if any library +// method does not get passed a logger through the context. +type discardHandler struct{} + +func (discardHandler) Enabled(_ context.Context, _ slog.Level) bool { return false } +func (discardHandler) Handle(_ context.Context, _ slog.Record) error { return nil } +func (d discardHandler) WithAttrs(_ []slog.Attr) slog.Handler { return d } +func (d discardHandler) WithGroup(_ string) slog.Handler { return d } diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/doc.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/doc.go new file mode 100644 index 000000000..786ba7463 --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/doc.go @@ -0,0 +1,42 @@ +// Package hcloudimages is a library to upload Disk Images into your Hetzner Cloud project. +// +// # Overview +// +// The Hetzner Cloud API does not support uploading disk images directly, and it only provides a limited set of default +// images. The only option for custom disk images that users have is by taking a "snapshot" of an existing servers root +// disk. These can then be used to create new servers. +// +// To create a completely custom disk image, users have to follow these steps: +// +// 1. Create server with the correct server type +// 2. Enable rescue system for the server +// 3. Boot the server +// 4. Download the disk image from within the rescue system +// 5. Write disk image to servers root disk +// 6. Shut down the server +// 7. Take a snapshot of the servers root disk +// 8. Delete the server +// +// This is an annoyingly long process. Many users have automated this with Packer before, but Packer offers a lot of +// additional complexity to understand. +// +// This library is a single call to do the above: [Client.Upload] +// +// # Costs +// +// The temporary server and the snapshot itself cost money. See the [Hetzner Cloud website] for up-to-date pricing +// information. +// +// Usually the upload takes no more than a few minutes of server time, so you will only be billed for the first hour +// (<1ct for most cases). If this process fails, the server might stay around until you manually delete it. In that case +// it continues to cost its hourly price. There is a utility [Client.CleanupTemporaryResources] that removes any +// leftover resources. +// +// # Logging +// +// By default, nothing is logged. As the update process takes a bit of time you might want to gain some insight into +// the process. For this we provide optional logs through [log/slog]. You can set a [log/slog.Logger] in the +// [context.Context] through [github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger.New]. +// +// [Hetzner Cloud website]: https://www.hetzner.com/cloud/ +package hcloudimages diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/actionutil/action.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/actionutil/action.go new file mode 100644 index 000000000..855c3ec3d --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/actionutil/action.go @@ -0,0 +1,25 @@ +package actionutil + +import ( + "context" + + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +func Settle(ctx context.Context, client hcloud.IActionClient, actions ...*hcloud.Action) (successActions []*hcloud.Action, errorActions []*hcloud.Action, err error) { + err = client.WaitForFunc(ctx, func(update *hcloud.Action) error { + switch update.Status { + case hcloud.ActionStatusSuccess: + successActions = append(successActions, update) + case hcloud.ActionStatusError: + errorActions = append(errorActions, update) + } + + return nil + }, actions...) + if err != nil { + return nil, nil, err + } + + return successActions, errorActions, nil +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/control/retry.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/control/retry.go new file mode 100644 index 000000000..d053aeec6 --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/control/retry.go @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MPL-2.0 +// From https://github.com/hetznercloud/terraform-provider-hcloud/blob/v1.46.1/internal/control/retry.go +// Copyright (c) Hetzner Cloud GmbH + +package control + +import ( + "context" + "time" + + "github.com/apricote/hcloud-upload-image/hcloudimages/backoff" + "github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger" +) + +// Retry executes f at most maxTries times. +func Retry(ctx context.Context, maxTries int, f func() error) error { + logger := contextlogger.From(ctx) + + var err error + + backoffFunc := backoff.ExponentialBackoffWithLimit(2, 1*time.Second, 30*time.Second) + + for try := 0; try < maxTries; try++ { + if ctx.Err() != nil { + return ctx.Err() + } + + err = f() + if err != nil { + sleep := backoffFunc(try) + logger.DebugContext(ctx, "operation failed, waiting before trying again", "try", try, "backoff", sleep) + time.Sleep(sleep) + continue + } + + return nil + } + + return err +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/labelutil/labels.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/labelutil/labels.go new file mode 100644 index 000000000..28e0eb94c --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/labelutil/labels.go @@ -0,0 +1,30 @@ +package labelutil + +import "fmt" + +func Merge(a, b map[string]string) map[string]string { + result := make(map[string]string, len(a)+len(b)) + + for k, v := range a { + result[k] = v + } + for k, v := range b { + result[k] = v + } + + return result +} + +func Selector(labels map[string]string) string { + selector := make([]byte, 0, 64) + separator := "" + + for k, v := range labels { + selector = fmt.Appendf(selector, "%s%s=%s", separator, k, v) + + // Do not print separator on first element + separator = "," + } + + return string(selector) +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/randomid/randomid.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/randomid/randomid.go new file mode 100644 index 000000000..9d0ab1442 --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/randomid/randomid.go @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// From https://gitlab.com/hetznercloud/fleeting-plugin-hetzner/-/blob/0f60204582289c243599f8ca0f5be4822789131d/internal/utils/random.go +// Copyright (c) 2024 Hetzner Cloud GmbH + +package randomid + +import ( + "crypto/rand" + "encoding/hex" + "fmt" +) + +func Generate() (string, error) { + b := make([]byte, 4) + _, err := rand.Read(b) + if err != nil { + return "", fmt.Errorf("failed to generate random string: %w", err) + } + return hex.EncodeToString(b), nil +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshkey/ssh_key.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshkey/ssh_key.go new file mode 100644 index 000000000..e5c497fd7 --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshkey/ssh_key.go @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +// From https://gitlab.com/hetznercloud/fleeting-plugin-hetzner/-/blob/0f60204582289c243599f8ca0f5be4822789131d/internal/utils/ssh_key.go +// Copyright (c) 2024 Hetzner Cloud GmbH + +package sshkey + +import ( + "crypto/ed25519" + "encoding/pem" + + "golang.org/x/crypto/ssh" +) + +func GenerateKeyPair() ([]byte, []byte, error) { + pub, priv, err := ed25519.GenerateKey(nil) + if err != nil { + return nil, nil, err + } + + pubBytes, err := encodePublicKey(pub) + if err != nil { + return nil, nil, err + } + + privBytes, err := encodePrivateKey(priv) + if err != nil { + return nil, nil, err + } + + return pubBytes, privBytes, nil +} + +func encodePublicKey(pub ed25519.PublicKey) ([]byte, error) { + sshPub, err := ssh.NewPublicKey(pub) + if err != nil { + return nil, err + } + + return ssh.MarshalAuthorizedKey(sshPub), nil +} + +func encodePrivateKey(priv ed25519.PrivateKey) ([]byte, error) { + privPem, err := ssh.MarshalPrivateKey(priv, "") + if err != nil { + return nil, err + } + + return pem.EncodeToMemory(privPem), nil +} diff --git a/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshsession/session.go b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshsession/session.go new file mode 100644 index 000000000..4306ce1ad --- /dev/null +++ b/vendor/github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshsession/session.go @@ -0,0 +1,21 @@ +package sshsession + +import ( + "io" + + "golang.org/x/crypto/ssh" +) + +func Run(client *ssh.Client, cmd string, stdin io.Reader) ([]byte, error) { + sess, err := client.NewSession() + + if err != nil { + return nil, err + } + defer sess.Close() + + if stdin != nil { + sess.Stdin = stdin + } + return sess.CombinedOutput(cmd) +} diff --git a/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_intermediate_cert.der b/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_intermediate_cert.der deleted file mode 100644 index 958f3cfaddf3645fa6c0578b5b6955d65ac4c172..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 998 zcmXqLVt!=M#B^!_GZP~dlZfxTkgMw#Mx5CteAhsdS=K*t&xAY!UN%mxHjlRNyo`+8 ztPBQ??S|Y2oNUaYENsF|p}{Z?2M?38qoI(207!`V#>K<# zoS$2em{(~iXuuB=;pX9R$t=q(&dkp<6f+P32{H5V78@nTm!uY##3!c~l^9AHNWiV< zWEA7BsH}1TV!h=2Tmw0AULzv|Gec7&Lt`^z^C)p%6J+ina%mHz5^^vyvNA9?G4eAQ zG%<29H8CnfQWlH+MyjTjz z2Bjk+Ub9TzT(Z$!`+w1f9a{SYn?h^$U$mDJKK^KOurlxGlhf8coXvjW^}bgt-rFjD znHJ|Xo9Wew;}%JlW_Kjsthc+chb^XXpU3LOdy_KCS4OTntgUFd?YsGkV{8gPCrIUU z7xZ1<|6Oe5g44&3J$ODp>G5YKW=00a#V!U;2J*mEAgjzGVIbBZvce&_^W7!+r|T*d zavIkkZ(n>dQ`LY6q(GR3)qt6i@xOr}h$qOxWx&zImXe>Fn2DZTf#J-^uui3sYst!# z{ImS~I{#0uS#WDz%!i-3yIxOGkACKhN$DyM2L{LbrkL@xJCpY3crHP)J~LHEx;nsZlX$z1Na++S~*x&F8L zSHsIX`Pf;-7fz4f$yxWfRV}c$Te2$X#22gkrUlwjtNp9{IiD}~zjo}z)1J=iJoj~z zPFk$n)~eK8B%5+0@w1g$N8H(l+-H4!LOMmyS_+%b`$^TD`}g=z?!9=Gts-l=GE2@y HTP6bly#{pd diff --git a/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_leaf_cert.der b/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_leaf_cert.der deleted file mode 100644 index d2817641bafb022339926786ab85b545f40ac665..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1147 zcmXqLVktLhVvb+H%*4pVB*OPMYW498DSV5WgVNVW|Jr8oCgimNFB_*;n@8JsUPeZ4 zRtAH{c0+ChPB!LH7B*p~&|nycgNMo4(NM@h03^fC!x>zfmseSqn3HNKV890w6yxnyM_06xZQcZ?W@M4y!->Y40>Qzg1y0 z&gNQpqF{|c>D+ZZ(rFIKEL_n{%!~|-iyLnkG+s4m+z3nvvdS!tD-9Z#Eo|&v(%3b4 zVzNoZ_g%=<^$R1;>=M3fAjvH2AGv2jo&gWY$-*qG2F#3%{|y8|JV6#N1CA!Pl>FSp z%sk}C2j(GQ()!XwH^ngbB~t_{rh@w&h5|n>_#Tt3odjy zuPCdY_u)fF^#8=jc^^+Q{aqN5`$@Gm({I-q6VU_LtQOD6naL>j(`V|D&;QI6%^$Dc z@$uH$=blqSKTV1FFaEpmVP=>@vvi*Y`l|mqO|ORNA0oIS8nOI z?NiA8%5=ljL@D29-OKpueEYz|zv5rHb554&taa#n7142tpUKWU?R-O_r^0)6j>G3Y aOB;Xxy<$H9NT-Uzt(mu6i*GEf3IzZ)c%0q< diff --git a/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_root_cert.der b/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/client_root_cert.der deleted file mode 100644 index d8c3710c85f9ff41ddfc709924c866350a727a4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1013 zcmXqLV*Y5*#B_53GZP~dlZa+?pWMd9xVH0Kw4Tf@Xyh=ks1AdSQHxGwPW?5!&W`3Tbn1KjLh?$4C*eEf+B(=CCJ~_3h#8ApW0&YDg zqZoHZWt9UE>m}#s8pw(B8W|aw8XFoJ7#JIxMv3#90J%nHQ0^ddX%nLoaxgNoGB7tW z@-rATF>*0AF)}hdZr#y6M}F(|x(>G^%gcAlKWcTb*S((Se#vIyuMojqJ6T@W9G$-N zZ|C3aC}V-ru$PA$a>||`V5!;WvLO9;#Z4xLTYkS~Q%%)mH+DGbsA<2rr@8F$Psyk! zC02_czBy5RY)XCG=Yl1DX=(>VSrdJ-C#|hK7^zn?b35awX)f$Ntvf$$ zcUg9sL1fPSDbXqWt6$VVZu~MYZrj`2y}fI?80UuXsujC8ao09pzReSEFH3&Hjk;!&j?yPw^7|NHlfMLseyY=TyHB}&&4U!T;kt&%Ic z-@@f=`1w!pGyVU%zJI$PWGYXZ;?Bg($iTQb*dWkA7MKcT`B=nQL{>NicfPwM|8!l2 zLQdoQtUFt($qvv(cdI=i6tz3tUW`|a0C z&5N-8^H(H$?psgMz!}^;s& z=?+d?)Hkg%emvc~QLj+DwRvTMu)Tl4_m}{_7kTC1{xNsF-p9krsM-B)Ge_#Kiu#~{ zd67^5U(N6lVcaug+5}Tw2V+f_-BCNQyG;7WAZ_<^`6QjCrOhu7&ztq4tdo7t^%&>) zTR0VF*I2Sr HHQW{e5x{wf diff --git a/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_intermediate_cert.der b/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_intermediate_cert.der deleted file mode 100644 index dae619c097512f20d09d2054c63fc0f715d7be24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 998 zcmXqLVt!=M#B^!_GZP~dlZZk6mxvepr#-!NVoqOL*`yn*LOZ7#@Un4gwRyCC=VfH% zW@RvFY&YaK;ACSCWnmL$3Jr#FICz+x9SwyH1VA$EJeHTH8JZfJT11KSnjmurkxQExm5_sxk(GhDiIJbd zpox)-sfm%1VO{t`EzVyWX$3+}`kJnrGQY>^=jnZyz4d%;|IQeuB_Gcfo1a{_>B5Fg zXYbI=4K*7QZdjc*51-)~EjRzyir2SPA5Z@zcTLeXV*g^*2f0P(7p>c z?c<>#uh>H(ryKBq6bQ4h8Za|5{x=W=@dR183^XGxLzc8JJvw;mpWjp+5Pu z!*lq#5Sb^i@`a>klJNjzx%iu)2*?h3yy-gEL(;p^g~mZo#n!wzh9Qua5C+wfRd ztarh_l9E{Oro7&WNVTl@3-~vy&EDU;)-f|r-8<&mQ>C=;``&D2+5V0(pW(g3o1}Sj z^gY793Mi&+ntK1`1tm%ENt=U{rb%k1PtbRHEhYTylqR?8HqOeuvA1fBY>pc~NUFTR KZE!sDzAgX``fm0B diff --git a/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_leaf_cert.der b/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_leaf_cert.der deleted file mode 100644 index ce7f8d31d6802c7e68c188af8797c3a063894857..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1147 zcmXqLVktLhVvb+H%*4pVB%&$)xidhT`$ARBi)~L`p2_`@+!*`b5acj4ER7|Ts-W~ z`MCv&d6kBO2K*oqZXOPo%(Bel%=|nTUzhK>3dC_Z(le%bCn$9moio9jI@8{ zd;5%c{XT!(ig$;5K+$bpwI6ChVmse+UV1r`!RY5*U#A%ppFJxS>PX#w$sz7*X_R~A zg!|$g&z66XI$)aW-TrxDio@fp!U^sS#+*GdHMB|H?BTf!^g~J_=D$Y-Ot{~xpTg~G+{k6 Zdr{DieczoQDL-a%Ib3(Tsv+bGCjf+Ap-TV& diff --git a/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_root_cert.der b/vendor/github.com/google/s2a-go/internal/v2/certverifier/testdata/server_root_cert.der deleted file mode 100644 index 04b0d73600b72f80a03943d41973b279db9e8b32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1013 zcmXqLV*Y5*#B_53GZP~dlZb{E^N!s~snriRh?%)HJiGKl>CAisUN%mxHjlRNyo`+8 ztPBQ??S|Y2oNUaYENsF|p}{Z?2M?38qoI(207!`V#>K<# zoS$2em{(~iXuuB=;pX9R$t=q(&dkp<6f+P32{H5V78@nTm!uY##3!c~l^9AHNWiV< zWEA7BsH}1TV!h=2Tmw0AULzv|Q)5FT0|N^q(aL-(RkWjuO*nCZC(^b4{cp%V+e53*PfoZW)2DU5BJN^Jypf0+ z%dyqB7eAAEDfH_&Z*6C3aP8^9M)sYbgC^`~v;4F5#oepTLYl5+2bdY(i!-?My>4G) z&8u+L`?_9LxQB1$HP?fpd*5i(-|SJJ!`sZHa8UZu(QeP3Dc(Yr8?G#iY20z>);Fh$ zMQ>DZHkC%KUBdEb&cYv;1sHCx@Vv~#%*epFIM^W2Ko*z^WcgUcSVVXxICA%7?w=9J zwOIRjXviz}kjUu<@*rtt76}8f2J8wz2}@R(k?}tZs{u2RLJoFd>IDWnBZI}4y?mP{ zW+WALO{`uTY0T-O8uy=9`&z_;*e^$wYu3!Wz-Re-&a7vV%g_8h++q8CMf&zxTFdl~ zp5i+{-R9L&+mdUFEBoKr@u=5M->UQ>MNWJ7BRi)4^M4~B*uKhe`J%yAbG&-Thr?bk zCap+`USuL4V}qf=6kBV_EFAN zmIn*31Qb`P{oxd|=2o5l$|&AdTJ_-*k&5oDQvTTOiN8OjczyHyta?pWMd9xVH0Kw4Tf@Xyh=ks1AdSQHxGwPW?5!&W`3Tbn1KjLh?$4C*eEf+B(=CCJ~_3h#8ApW0&YDg zqZoHZWt9UE>m}#s8pw(B8W|aw8XFoJ7#JIxMv3#90J%nHQ0^ddX%nLoaxgNoGB7tW z@-rATF>*0AF)}hdZr#y6M}F(|x(>G^%gcAlKWcTb*S((Se#vIyuMojqJ6T@W9G$-N zZ|C3aC}V-ru$PA$a>||`V5!;WvLO9;#Z4xLTYkS~Q%%)mH+DGbsA<2rr@8F$Psyk! zC02_czBy5RY)XCG=Yl1DX=(>VSrdJ-C#|hK7^zn?b35awX)f$Ntvf$$ zcUg9sL1fPSDbXqWt6$VVZu~MYZrj`2y}fI?80UuXsujC8ao09pzReSEFH3&Hjk;!&j?yPw^7|NHlfMLseyY=TyHB}&&4U!T;kt&%Ic z-@@f=`1w!pGyVU%zJI$PWGYXZ;?Bg($iTQb*dWkA7MKcT`B=nQL{>NicfPwM|8!l2 zLQdoQtUFt($qvv(cdI=i6tz3tUW`|a0C z&5N-8^H(H$?psgMz!}^;s& z=?+d?)Hkg%emvc~QLj+DwRvTMu)Tl4_m}{_7kTC1{xNsF-p9krsM-B)Ge_#Kiu#~{ zd67^5U(N6lVcaug+5}Tw2V+f_-BCNQyG;7WAZ_<^`6QjCrOhu7&ztq4tdo7t^%&>) zTR0VF*I2Sr HHQW{e5x{wf diff --git a/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_cert.pem b/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_cert.pem deleted file mode 100644 index 493a5a264..000000000 --- a/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_cert.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIUKXNlBRVe6UepjQUijIFPZBd/4qYwDQYJKoZIhvcNAQEL -BQAwgYcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU3Vubnl2 -YWxlMRAwDgYDVQQKDAdDb21wYW55MREwDwYDVQQLDAhEaXZpc2lvbjEWMBQGA1UE -AwwNczJhX3Rlc3RfY2VydDEaMBgGCSqGSIb3DQEJARYLeHl6QHh5ei5jb20wHhcN -MjIwNTMxMjAwMzE1WhcNNDIwNTI2MjAwMzE1WjCBhzELMAkGA1UEBhMCVVMxCzAJ -BgNVBAgMAkNBMRIwEAYDVQQHDAlTdW5ueXZhbGUxEDAOBgNVBAoMB0NvbXBhbnkx -ETAPBgNVBAsMCERpdmlzaW9uMRYwFAYDVQQDDA1zMmFfdGVzdF9jZXJ0MRowGAYJ -KoZIhvcNAQkBFgt4eXpAeHl6LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAOOFuIucH7XXfohGxKd3uR/ihUA/LdduR9I8kfpUEbq5BOt8xZe5/Yn9 -a1ozEHVW6cOAbHbnwAR8tkSgZ/t42QIA2k77HWU1Jh2xiEIsJivo3imm4/kZWuR0 -OqPh7MhzxpR/hvNwpI5mJsAVBWFMa5KtecFZLnyZtwHylrRN1QXzuLrOxuKFufK3 -RKbTABScn5RbZL976H/jgfSeXrbt242NrIoBnVe6fRbekbq2DQ6zFArbQMUgHjHK -P0UqBgdr1QmHfi9KytFyx9BTP3gXWnWIu+bY7/v7qKJMHFwGETo+dCLWYevJL316 -HnLfhApDMfP8U+Yv/y1N/YvgaSOSlEcCAwEAAaNTMFEwHQYDVR0OBBYEFKhAU4nu -0h/lrnggbIGvx4ej0WklMB8GA1UdIwQYMBaAFKhAU4nu0h/lrnggbIGvx4ej0Wkl -MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAE/6NghzQ5fu6yR6 -EHKbj/YMrFdT7aGn5n2sAf7wJ33LIhiFHkpWBsVlm7rDtZtwhe891ZK/P60anlg9 -/P0Ua53tSRVRmCvTnEbXWOVMN4is6MsR7BlmzUxl4AtIn7jbeifEwRL7B4xDYmdA -QrQnsqoz45dLgS5xK4WDqXATP09Q91xQDuhud/b+A4jrvgwFASmL7rMIZbp4f1JQ -nlnl/9VoTBQBvJiWkDUtQDMpRLtauddEkv4AGz75p5IspXWD6cOemuh2iQec11xD -X20rs2WZbAcAiUa3nmy8OKYw435vmpj8gp39WYbX/Yx9TymrFFbVY92wYn+quTco -pKklVz0= ------END CERTIFICATE----- diff --git a/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_key.pem b/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_key.pem deleted file mode 100644 index 55a7f10c7..000000000 --- a/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/client_key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEA44W4i5wftdd+iEbEp3e5H+KFQD8t125H0jyR+lQRurkE63zF -l7n9if1rWjMQdVbpw4BsdufABHy2RKBn+3jZAgDaTvsdZTUmHbGIQiwmK+jeKabj -+Rla5HQ6o+HsyHPGlH+G83CkjmYmwBUFYUxrkq15wVkufJm3AfKWtE3VBfO4us7G -4oW58rdEptMAFJyflFtkv3vof+OB9J5etu3bjY2sigGdV7p9Ft6RurYNDrMUCttA -xSAeMco/RSoGB2vVCYd+L0rK0XLH0FM/eBdadYi75tjv+/uookwcXAYROj50ItZh -68kvfXoect+ECkMx8/xT5i//LU39i+BpI5KURwIDAQABAoIBABgyjo/6iLzUMFbZ -/+w3pW6orrdIgN2akvTfED9pVYFgUA+jc3hRhY95bkNnjuaL2cy7Cc4Tk65mfRQL -Y0OxdJLr+EvSFSxAXM9npDA1ddHRsF8JqtFBSxNk8R+g1Yf0GDiO35Fgd3/ViWWA -VtQkRoSRApP3oiQKTRZd8H04keFR+PvmDk/Lq11l3Kc24A1PevKIPX1oI990ggw9 -9i4uSV+cnuMxmcI9xxJtgwdDFdjr39l2arLOHr4s6LGoV2IOdXHNlv5xRqWUZ0FH -MDHowkLgwDrdSTnNeaVNkce14Gqx+bd4hNaLCdKXMpedBTEmrut3f3hdV1kKjaKt -aqRYr8ECgYEA/YDGZY2jvFoHHBywlqmEMFrrCvQGH51m5R1Ntpkzr+Rh3YCmrpvq -xgwJXING0PUw3dz+xrH5lJICrfNE5Kt3fPu1rAEy+13mYsNowghtUq2Rtu0Hsjjx -2E3Bf8vEB6RNBMmGkUpTTIAroGF5tpJoRvfnWax+k4pFdrKYFtyZdNcCgYEA5cNv -EPltvOobjTXlUmtVP3n27KZN2aXexTcagLzRxE9CV4cYySENl3KuOMmccaZpIl6z -aHk6BT4X+M0LqElNUczrInfVqI+SGAFLGy7W6CJaqSr6cpyFUP/fosKpm6wKGgLq -udHfpvz5rckhKd8kJxFLvhGOK9yN5qpzih0gfhECgYAJfwRvk3G5wYmYpP58dlcs -VIuPenqsPoI3PPTHTU/hW+XKnWIhElgmGRdUrto9Q6IT/Y5RtSMLTLjq+Tzwb/fm -56rziYv2XJsfwgAvnI8z1Kqrto9ePsHYf3krJ1/thVsZPc9bq/QY3ohD1sLvcuaT -GgBBnLOVJU3a12/ZE2RwOwKBgF0csWMAoj8/5IB6if+3ral2xOGsl7oPZVMo/J2V -Z7EVqb4M6rd/pKFugTpUQgkwtkSOekhpcGD1hAN5HTNK2YG/+L5UMAsKe9sskwJm -HgOfAHy0BSDzW3ey6i9skg2bT9Cww+0gJ3Hl7U1HSCBO5LjMYpSZSrNtwzfqdb5Q -BX3xAoGARZdR28Ej3+/+0+fz47Yu2h4z0EI/EbrudLOWY936jIeAVwHckI3+BuqH -qR4poj1gfbnMxNuI9UzIXzjEmGewx9kDZ7IYnvloZKqoVQODO5GlKF2ja6IcMNlh -GCNdD6PSAS6HcmalmWo9sj+1YMkrl+GJikKZqVBHrHNwMGAG67w= ------END RSA PRIVATE KEY----- diff --git a/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/server_cert.der b/vendor/github.com/google/s2a-go/internal/v2/remotesigner/testdata/server_cert.der deleted file mode 100644 index 04b0d73600b72f80a03943d41973b279db9e8b32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1013 zcmXqLV*Y5*#B_53GZP~dlZb{E^N!s~snriRh?%)HJiGKl>CAisUN%mxHjlRNyo`+8 ztPBQ??S|Y2oNUaYENsF|p}{Z?2M?38qoI(207!`V#>K<# zoS$2em{(~iXuuB=;pX9R$t=q(&dkp<6f+P32{H5V78@nTm!uY##3!c~l^9AHNWiV< zWEA7BsH}1TV!h=2Tmw0AULzv|Q)5FT0|N^q(aL-(RkWjuO*nCZC(^b4{cp%V+e53*PfoZW)2DU5BJN^Jypf0+ z%dyqB7eAAEDfH_&Z*6C3aP8^9M)sYbgC^`~v;4F5#oepTLYl5+2bdY(i!-?My>4G) z&8u+L`?_9LxQB1$HP?fpd*5i(-|SJJ!`sZHa8UZu(QeP3Dc(Yr8?G#iY20z>);Fh$ zMQ>DZHkC%KUBdEb&cYv;1sHCx@Vv~#%*epFIM^W2Ko*z^WcgUcSVVXxICA%7?w=9J zwOIRjXviz}kjUu<@*rtt76}8f2J8wz2}@R(k?}tZs{u2RLJoFd>IDWnBZI}4y?mP{ zW+WALO{`uTY0T-O8uy=9`&z_;*e^$wYu3!Wz-Re-&a7vV%g_8h++q8CMf&zxTFdl~ zp5i+{-R9L&+mdUFEBoKr@u=5M->UQ>MNWJ7BRi)4^M4~B*uKhe`J%yAbG&-Thr?bk zCap+`USuL4V}qf=6kBV_EFAN zmIn*31Qb`P{oxd|=2o5l$|&AdTJ_-*k&5oDQvTTOiN8OjczyHyta 0 { + body, err = io.ReadAll(r.Body) + if err != nil { + r.Body.Close() + return nil, err + } + r.Body.Close() + } + for { + if r.ContentLength > 0 { + r.Body = io.NopCloser(bytes.NewReader(body)) + } + + if c.debugWriter != nil { + dumpReq, err := dumpRequest(r) + if err != nil { + return nil, err + } + fmt.Fprintf(c.debugWriter, "--- Request:\n%s\n\n", dumpReq) + } + + resp, err := c.httpClient.Do(r) + if err != nil { + return nil, err + } + response := &Response{Response: resp} + body, err := io.ReadAll(resp.Body) + if err != nil { + resp.Body.Close() + return response, err + } + resp.Body.Close() + resp.Body = io.NopCloser(bytes.NewReader(body)) + + if c.debugWriter != nil { + dumpResp, err := httputil.DumpResponse(resp, true) + if err != nil { + return nil, err + } + fmt.Fprintf(c.debugWriter, "--- Response:\n%s\n\n", dumpResp) + } + + if err = response.readMeta(body); err != nil { + return response, fmt.Errorf("hcloud: error reading response meta data: %s", err) + } + + if response.StatusCode >= 400 && response.StatusCode <= 599 { + err = errorFromResponse(response, body) + if err == nil { + err = fmt.Errorf("hcloud: server responded with status code %d", resp.StatusCode) + } else if IsError(err, ErrorCodeConflict) { + c.backoff(retries) + retries++ + continue + } + return response, err + } + if v != nil { + if w, ok := v.(io.Writer); ok { + _, err = io.Copy(w, bytes.NewReader(body)) + } else { + err = json.Unmarshal(body, v) + } + } + + return response, err + } +} + +func (c *Client) backoff(retries int) { + time.Sleep(c.backoffFunc(retries)) +} + +func (c *Client) all(f func(int) (*Response, error)) error { + var ( + page = 1 + ) + for { + resp, err := f(page) + if err != nil { + return err + } + if resp.Meta.Pagination == nil || resp.Meta.Pagination.NextPage == 0 { + return nil + } + page = resp.Meta.Pagination.NextPage + } +} + +func (c *Client) buildUserAgent() { + switch { + case c.applicationName != "" && c.applicationVersion != "": + c.userAgent = c.applicationName + "/" + c.applicationVersion + " " + UserAgent + case c.applicationName != "" && c.applicationVersion == "": + c.userAgent = c.applicationName + " " + UserAgent + default: + c.userAgent = UserAgent + } +} + +func dumpRequest(r *http.Request) ([]byte, error) { + // Duplicate the request, so we can redact the auth header + rDuplicate := r.Clone(context.Background()) + rDuplicate.Header.Set("Authorization", "REDACTED") + + // To get the request body we need to read it before the request was actually sent. + // See https://github.com/golang/go/issues/29792 + dumpReq, err := httputil.DumpRequestOut(rDuplicate, true) + if err != nil { + return nil, err + } + + // Set original request body to the duplicate created by DumpRequestOut. The request body is not duplicated + // by .Clone() and instead just referenced, so it would be completely read otherwise. + r.Body = rDuplicate.Body + + return dumpReq, nil +} + +func errorFromResponse(resp *Response, body []byte) error { + if !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") { + return nil + } + + var respBody schema.ErrorResponse + if err := json.Unmarshal(body, &respBody); err != nil { + return nil + } + if respBody.Error.Code == "" && respBody.Error.Message == "" { + return nil + } + + hcErr := ErrorFromSchema(respBody.Error) + hcErr.response = resp + return hcErr +} + +const ( + headerCorrelationID = "X-Correlation-Id" +) + +// Response represents a response from the API. It embeds http.Response. +type Response struct { + *http.Response + Meta Meta +} + +func (r *Response) readMeta(body []byte) error { + if h := r.Header.Get("RateLimit-Limit"); h != "" { + r.Meta.Ratelimit.Limit, _ = strconv.Atoi(h) + } + if h := r.Header.Get("RateLimit-Remaining"); h != "" { + r.Meta.Ratelimit.Remaining, _ = strconv.Atoi(h) + } + if h := r.Header.Get("RateLimit-Reset"); h != "" { + if ts, err := strconv.ParseInt(h, 10, 64); err == nil { + r.Meta.Ratelimit.Reset = time.Unix(ts, 0) + } + } + + if strings.HasPrefix(r.Header.Get("Content-Type"), "application/json") { + var s schema.MetaResponse + if err := json.Unmarshal(body, &s); err != nil { + return err + } + if s.Meta.Pagination != nil { + p := PaginationFromSchema(*s.Meta.Pagination) + r.Meta.Pagination = &p + } + } + + return nil +} + +// internalCorrelationID returns the unique ID of the request as set by the API. This ID can help with support requests, +// as it allows the people working on identify this request in particular. +func (r *Response) internalCorrelationID() string { + return r.Header.Get(headerCorrelationID) +} + +// Meta represents meta information included in an API response. +type Meta struct { + Pagination *Pagination + Ratelimit Ratelimit +} + +// Pagination represents pagination meta information. +type Pagination struct { + Page int + PerPage int + PreviousPage int + NextPage int + LastPage int + TotalEntries int +} + +// Ratelimit represents ratelimit information. +type Ratelimit struct { + Limit int + Remaining int + Reset time.Time +} + +// ListOpts specifies options for listing resources. +type ListOpts struct { + Page int // Page (starting at 1) + PerPage int // Items per page (0 means default) + LabelSelector string // Label selector for filtering by labels +} + +// Values returns the ListOpts as URL values. +func (l ListOpts) Values() url.Values { + vals := url.Values{} + if l.Page > 0 { + vals.Add("page", strconv.Itoa(l.Page)) + } + if l.PerPage > 0 { + vals.Add("per_page", strconv.Itoa(l.PerPage)) + } + if len(l.LabelSelector) > 0 { + vals.Add("label_selector", l.LabelSelector) + } + return vals +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/datacenter.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/datacenter.go new file mode 100644 index 000000000..42c443da3 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/datacenter.go @@ -0,0 +1,136 @@ +package hcloud + +import ( + "context" + "fmt" + "net/url" + "strconv" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// Datacenter represents a datacenter in the Hetzner Cloud. +type Datacenter struct { + ID int64 + Name string + Description string + Location *Location + ServerTypes DatacenterServerTypes +} + +// DatacenterServerTypes represents the server types available and supported in a datacenter. +type DatacenterServerTypes struct { + Supported []*ServerType + AvailableForMigration []*ServerType + Available []*ServerType +} + +// DatacenterClient is a client for the datacenter API. +type DatacenterClient struct { + client *Client +} + +// GetByID retrieves a datacenter by its ID. If the datacenter does not exist, nil is returned. +func (c *DatacenterClient) GetByID(ctx context.Context, id int64) (*Datacenter, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/datacenters/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.DatacenterGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, resp, err + } + return DatacenterFromSchema(body.Datacenter), resp, nil +} + +// GetByName retrieves a datacenter by its name. If the datacenter does not exist, nil is returned. +func (c *DatacenterClient) GetByName(ctx context.Context, name string) (*Datacenter, *Response, error) { + if name == "" { + return nil, nil, nil + } + datacenters, response, err := c.List(ctx, DatacenterListOpts{Name: name}) + if len(datacenters) == 0 { + return nil, response, err + } + return datacenters[0], response, err +} + +// Get retrieves a datacenter by its ID if the input can be parsed as an integer, otherwise it +// retrieves a datacenter by its name. If the datacenter does not exist, nil is returned. +func (c *DatacenterClient) Get(ctx context.Context, idOrName string) (*Datacenter, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// DatacenterListOpts specifies options for listing datacenters. +type DatacenterListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l DatacenterListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of datacenters for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *DatacenterClient) List(ctx context.Context, opts DatacenterListOpts) ([]*Datacenter, *Response, error) { + path := "/datacenters?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.DatacenterListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + datacenters := make([]*Datacenter, 0, len(body.Datacenters)) + for _, i := range body.Datacenters { + datacenters = append(datacenters, DatacenterFromSchema(i)) + } + return datacenters, resp, nil +} + +// All returns all datacenters. +func (c *DatacenterClient) All(ctx context.Context) ([]*Datacenter, error) { + return c.AllWithOpts(ctx, DatacenterListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all datacenters for the given options. +func (c *DatacenterClient) AllWithOpts(ctx context.Context, opts DatacenterListOpts) ([]*Datacenter, error) { + allDatacenters := []*Datacenter{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + datacenters, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allDatacenters = append(allDatacenters, datacenters...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allDatacenters, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go new file mode 100644 index 000000000..17c6949cb --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/deprecation.go @@ -0,0 +1,59 @@ +package hcloud + +import "time" + +// Deprecatable is a shared interface implemented by all Resources that have a defined deprecation workflow. +type Deprecatable interface { + // IsDeprecated returns true if the resource is marked as deprecated. + IsDeprecated() bool + + // UnavailableAfter returns the time that the deprecated resource will be removed from the API. + // This only returns a valid value if [Deprecatable.IsDeprecated] returned true. + UnavailableAfter() time.Time + + // DeprecationAnnounced returns the time that the deprecation of this resource was announced. + // This only returns a valid value if [Deprecatable.IsDeprecated] returned true. + DeprecationAnnounced() time.Time +} + +// DeprecationInfo contains the information published when a resource is actually deprecated. +type DeprecationInfo struct { + Announced time.Time + UnavailableAfter time.Time +} + +// DeprecatableResource implements the [Deprecatable] interface and can be embedded in structs for Resources that can be +// deprecated. +type DeprecatableResource struct { + Deprecation *DeprecationInfo +} + +// IsDeprecated returns true if the resource is marked as deprecated. +func (d DeprecatableResource) IsDeprecated() bool { + return d.Deprecation != nil +} + +// UnavailableAfter returns the time that the deprecated resource will be removed from the API. +// This only returns a valid value if [Deprecatable.IsDeprecated] returned true. +func (d DeprecatableResource) UnavailableAfter() time.Time { + if !d.IsDeprecated() { + // Return "null" time if resource is not deprecated + return time.Unix(0, 0) + } + + return d.Deprecation.UnavailableAfter +} + +// DeprecationAnnounced returns the time that the deprecation of this resource was announced. +// This only returns a valid value if [Deprecatable.IsDeprecated] returned true. +func (d DeprecatableResource) DeprecationAnnounced() time.Time { + if !d.IsDeprecated() { + // Return "null" time if resource is not deprecated + return time.Unix(0, 0) + } + + return d.Deprecation.Announced +} + +// Make sure that all expected Resources actually implement the interface. +var _ Deprecatable = ServerType{} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/error.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/error.go new file mode 100644 index 000000000..371a92e31 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/error.go @@ -0,0 +1,150 @@ +package hcloud + +import ( + "errors" + "fmt" + "net" +) + +// ErrorCode represents an error code returned from the API. +type ErrorCode string + +// Error codes returned from the API. +const ( + ErrorCodeServiceError ErrorCode = "service_error" // Generic service error + ErrorCodeRateLimitExceeded ErrorCode = "rate_limit_exceeded" // Rate limit exceeded + ErrorCodeUnknownError ErrorCode = "unknown_error" // Unknown error + ErrorCodeNotFound ErrorCode = "not_found" // Resource not found + ErrorCodeInvalidInput ErrorCode = "invalid_input" // Validation error + ErrorCodeForbidden ErrorCode = "forbidden" // Insufficient permissions + ErrorCodeUnauthorized ErrorCode = "unauthorized" // Request was made with an invalid or unknown token + ErrorCodeJSONError ErrorCode = "json_error" // Invalid JSON in request + ErrorCodeLocked ErrorCode = "locked" // Item is locked (Another action is running) + ErrorCodeResourceLimitExceeded ErrorCode = "resource_limit_exceeded" // Resource limit exceeded + ErrorCodeResourceUnavailable ErrorCode = "resource_unavailable" // Resource currently unavailable + ErrorCodeUniquenessError ErrorCode = "uniqueness_error" // One or more fields must be unique + ErrorCodeProtected ErrorCode = "protected" // The actions you are trying is protected + ErrorCodeMaintenance ErrorCode = "maintenance" // Cannot perform operation due to maintenance + ErrorCodeConflict ErrorCode = "conflict" // The resource has changed during the request, please retry + ErrorCodeRobotUnavailable ErrorCode = "robot_unavailable" // Robot was not available. The caller may retry the operation after a short delay + ErrorCodeResourceLocked ErrorCode = "resource_locked" // The resource is locked. The caller should contact support + ErrorUnsupportedError ErrorCode = "unsupported_error" // The given resource does not support this + + // Server related error codes. + + ErrorCodeInvalidServerType ErrorCode = "invalid_server_type" // The server type does not fit for the given server or is deprecated + ErrorCodeServerNotStopped ErrorCode = "server_not_stopped" // The action requires a stopped server + ErrorCodeNetworksOverlap ErrorCode = "networks_overlap" // The network IP range overlaps with one of the server networks + ErrorCodePlacementError ErrorCode = "placement_error" // An error during the placement occurred + ErrorCodeServerAlreadyAttached ErrorCode = "server_already_attached" // The server is already attached to the resource + + // Load Balancer related error codes. + + ErrorCodeIPNotOwned ErrorCode = "ip_not_owned" // The IP you are trying to add as a target is not owned by the Project owner + ErrorCodeSourcePortAlreadyUsed ErrorCode = "source_port_already_used" // The source port you are trying to add is already in use + ErrorCodeCloudResourceIPNotAllowed ErrorCode = "cloud_resource_ip_not_allowed" // The IP you are trying to add as a target belongs to a Hetzner Cloud resource + ErrorCodeServerNotAttachedToNetwork ErrorCode = "server_not_attached_to_network" // The server you are trying to add as a target is not attached to the same network as the Load Balancer + ErrorCodeTargetAlreadyDefined ErrorCode = "target_already_defined" // The Load Balancer target you are trying to define is already defined + ErrorCodeInvalidLoadBalancerType ErrorCode = "invalid_load_balancer_type" // The Load Balancer type does not fit for the given Load Balancer + ErrorCodeLoadBalancerAlreadyAttached ErrorCode = "load_balancer_already_attached" // The Load Balancer is already attached to a network + ErrorCodeTargetsWithoutUsePrivateIP ErrorCode = "targets_without_use_private_ip" // The Load Balancer has targets that use the public IP instead of the private IP + ErrorCodeLoadBalancerNotAttachedToNetwork ErrorCode = "load_balancer_not_attached_to_network" // The Load Balancer is not attached to a network + + // Network related error codes. + + ErrorCodeIPNotAvailable ErrorCode = "ip_not_available" // The provided Network IP is not available + ErrorCodeNoSubnetAvailable ErrorCode = "no_subnet_available" // No Subnet or IP is available for the Load Balancer/Server within the network + ErrorCodeVSwitchAlreadyUsed ErrorCode = "vswitch_id_already_used" // The given Robot vSwitch ID is already registered in another network + + // Volume related error codes. + + ErrorCodeNoSpaceLeftInLocation ErrorCode = "no_space_left_in_location" // There is no volume space left in the given location + ErrorCodeVolumeAlreadyAttached ErrorCode = "volume_already_attached" // Volume is already attached to a server, detach first + + // Firewall related error codes. + + ErrorCodeFirewallAlreadyApplied ErrorCode = "firewall_already_applied" // Firewall was already applied on resource + ErrorCodeFirewallAlreadyRemoved ErrorCode = "firewall_already_removed" // Firewall was already removed from the resource + ErrorCodeIncompatibleNetworkType ErrorCode = "incompatible_network_type" // The Network type is incompatible for the given resource + ErrorCodeResourceInUse ErrorCode = "resource_in_use" // Firewall must not be in use to be deleted + ErrorCodeServerAlreadyAdded ErrorCode = "server_already_added" // Server added more than one time to resource + ErrorCodeFirewallResourceNotFound ErrorCode = "firewall_resource_not_found" // Resource a firewall should be attached to / detached from not found + + // Certificate related error codes. + + ErrorCodeCAARecordDoesNotAllowCA ErrorCode = "caa_record_does_not_allow_ca" // CAA record does not allow certificate authority + ErrorCodeCADNSValidationFailed ErrorCode = "ca_dns_validation_failed" // Certificate Authority: DNS validation failed + ErrorCodeCATooManyAuthorizationsFailedRecently ErrorCode = "ca_too_many_authorizations_failed_recently" // Certificate Authority: Too many authorizations failed recently + ErrorCodeCATooManyCertificatedIssuedForRegisteredDomain ErrorCode = "ca_too_many_certificates_issued_for_registered_domain" // Certificate Authority: Too many certificates issued for registered domain + ErrorCodeCATooManyDuplicateCertificates ErrorCode = "ca_too_many_duplicate_certificates" // Certificate Authority: Too many duplicate certificates + ErrorCodeCloudNotVerifyDomainDelegatedToZone ErrorCode = "could_not_verify_domain_delegated_to_zone" // Could not verify domain delegated to zone + ErrorCodeDNSZoneNotFound ErrorCode = "dns_zone_not_found" // DNS zone not found + + // Deprecated error codes. + + // Deprecated: The actual value of this error code is limit_reached. The + // new error code rate_limit_exceeded for rate limiting was introduced + // before Hetzner Cloud launched into the public. To make clients using the + // old error code still work as expected, we set the value of the old error + // code to that of the new error code. + ErrorCodeLimitReached = ErrorCodeRateLimitExceeded +) + +// Error is an error returned from the API. +type Error struct { + Code ErrorCode + Message string + Details interface{} + + response *Response +} + +func (e Error) Error() string { + if resp := e.Response(); resp != nil { + correlationID := resp.internalCorrelationID() + if correlationID != "" { + // For easier debugging, the error string contains the Correlation ID of the response. + return fmt.Sprintf("%s (%s, %s)", e.Message, e.Code, correlationID) + } + } + return fmt.Sprintf("%s (%s)", e.Message, e.Code) +} + +// Response returns the [Response] that contained the error if available. +func (e Error) Response() *Response { + return e.response +} + +// ErrorDetailsInvalidInput contains the details of an 'invalid_input' error. +type ErrorDetailsInvalidInput struct { + Fields []ErrorDetailsInvalidInputField +} + +// ErrorDetailsInvalidInputField contains the validation errors reported on a field. +type ErrorDetailsInvalidInputField struct { + Name string + Messages []string +} + +// IsError returns whether err is an API error with the given error code. +func IsError(err error, code ErrorCode) bool { + var apiErr Error + ok := errors.As(err, &apiErr) + return ok && apiErr.Code == code +} + +type InvalidIPError struct { + IP string +} + +func (e InvalidIPError) Error() string { + return fmt.Sprintf("could not parse ip address %s", e.IP) +} + +type DNSNotFoundError struct { + IP net.IP +} + +func (e DNSNotFoundError) Error() string { + return fmt.Sprintf("dns for ip %s not found", e.IP.String()) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go new file mode 100644 index 000000000..a22191353 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/firewall.go @@ -0,0 +1,372 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// Firewall represents a Firewall in the Hetzner Cloud. +type Firewall struct { + ID int64 + Name string + Labels map[string]string + Created time.Time + Rules []FirewallRule + AppliedTo []FirewallResource +} + +// FirewallRule represents a Firewall's rules. +type FirewallRule struct { + Direction FirewallRuleDirection + SourceIPs []net.IPNet + DestinationIPs []net.IPNet + Protocol FirewallRuleProtocol + Port *string + Description *string +} + +// FirewallRuleDirection specifies the direction of a Firewall rule. +type FirewallRuleDirection string + +const ( + // FirewallRuleDirectionIn specifies a rule for inbound traffic. + FirewallRuleDirectionIn FirewallRuleDirection = "in" + + // FirewallRuleDirectionOut specifies a rule for outbound traffic. + FirewallRuleDirectionOut FirewallRuleDirection = "out" +) + +// FirewallRuleProtocol specifies the protocol of a Firewall rule. +type FirewallRuleProtocol string + +const ( + // FirewallRuleProtocolTCP specifies a TCP rule. + FirewallRuleProtocolTCP FirewallRuleProtocol = "tcp" + // FirewallRuleProtocolUDP specifies a UDP rule. + FirewallRuleProtocolUDP FirewallRuleProtocol = "udp" + // FirewallRuleProtocolICMP specifies an ICMP rule. + FirewallRuleProtocolICMP FirewallRuleProtocol = "icmp" + // FirewallRuleProtocolESP specifies an esp rule. + FirewallRuleProtocolESP FirewallRuleProtocol = "esp" + // FirewallRuleProtocolGRE specifies an gre rule. + FirewallRuleProtocolGRE FirewallRuleProtocol = "gre" +) + +// FirewallResourceType specifies the resource to apply a Firewall on. +type FirewallResourceType string + +const ( + // FirewallResourceTypeServer specifies a Server. + FirewallResourceTypeServer FirewallResourceType = "server" + // FirewallResourceTypeLabelSelector specifies a LabelSelector. + FirewallResourceTypeLabelSelector FirewallResourceType = "label_selector" +) + +// FirewallResource represents a resource to apply the new Firewall on. +type FirewallResource struct { + Type FirewallResourceType + Server *FirewallResourceServer + LabelSelector *FirewallResourceLabelSelector +} + +// FirewallResourceServer represents a Server to apply a Firewall on. +type FirewallResourceServer struct { + ID int64 +} + +// FirewallResourceLabelSelector represents a LabelSelector to apply a Firewall on. +type FirewallResourceLabelSelector struct { + Selector string +} + +// FirewallClient is a client for the Firewalls API. +type FirewallClient struct { + client *Client + Action *ResourceActionClient +} + +// GetByID retrieves a Firewall by its ID. If the Firewall does not exist, nil is returned. +func (c *FirewallClient) GetByID(ctx context.Context, id int64) (*Firewall, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/firewalls/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.FirewallGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return FirewallFromSchema(body.Firewall), resp, nil +} + +// GetByName retrieves a Firewall by its name. If the Firewall does not exist, nil is returned. +func (c *FirewallClient) GetByName(ctx context.Context, name string) (*Firewall, *Response, error) { + if name == "" { + return nil, nil, nil + } + firewalls, response, err := c.List(ctx, FirewallListOpts{Name: name}) + if len(firewalls) == 0 { + return nil, response, err + } + return firewalls[0], response, err +} + +// Get retrieves a Firewall by its ID if the input can be parsed as an integer, otherwise it +// retrieves a Firewall by its name. If the Firewall does not exist, nil is returned. +func (c *FirewallClient) Get(ctx context.Context, idOrName string) (*Firewall, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// FirewallListOpts specifies options for listing Firewalls. +type FirewallListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l FirewallListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of Firewalls for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *FirewallClient) List(ctx context.Context, opts FirewallListOpts) ([]*Firewall, *Response, error) { + path := "/firewalls?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.FirewallListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + firewalls := make([]*Firewall, 0, len(body.Firewalls)) + for _, s := range body.Firewalls { + firewalls = append(firewalls, FirewallFromSchema(s)) + } + return firewalls, resp, nil +} + +// All returns all Firewalls. +func (c *FirewallClient) All(ctx context.Context) ([]*Firewall, error) { + return c.AllWithOpts(ctx, FirewallListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all Firewalls for the given options. +func (c *FirewallClient) AllWithOpts(ctx context.Context, opts FirewallListOpts) ([]*Firewall, error) { + allFirewalls := []*Firewall{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + firewalls, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allFirewalls = append(allFirewalls, firewalls...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allFirewalls, nil +} + +// FirewallCreateOpts specifies options for creating a new Firewall. +type FirewallCreateOpts struct { + Name string + Labels map[string]string + Rules []FirewallRule + ApplyTo []FirewallResource +} + +// Validate checks if options are valid. +func (o FirewallCreateOpts) Validate() error { + if o.Name == "" { + return errors.New("missing name") + } + return nil +} + +// FirewallCreateResult is the result of a create Firewall call. +type FirewallCreateResult struct { + Firewall *Firewall + Actions []*Action +} + +// Create creates a new Firewall. +func (c *FirewallClient) Create(ctx context.Context, opts FirewallCreateOpts) (FirewallCreateResult, *Response, error) { + if err := opts.Validate(); err != nil { + return FirewallCreateResult{}, nil, err + } + reqBody := firewallCreateOptsToSchema(opts) + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return FirewallCreateResult{}, nil, err + } + req, err := c.client.NewRequest(ctx, "POST", "/firewalls", bytes.NewReader(reqBodyData)) + if err != nil { + return FirewallCreateResult{}, nil, err + } + + respBody := schema.FirewallCreateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return FirewallCreateResult{}, resp, err + } + result := FirewallCreateResult{ + Firewall: FirewallFromSchema(respBody.Firewall), + Actions: ActionsFromSchema(respBody.Actions), + } + return result, resp, nil +} + +// FirewallUpdateOpts specifies options for updating a Firewall. +type FirewallUpdateOpts struct { + Name string + Labels map[string]string +} + +// Update updates a Firewall. +func (c *FirewallClient) Update(ctx context.Context, firewall *Firewall, opts FirewallUpdateOpts) (*Firewall, *Response, error) { + reqBody := schema.FirewallUpdateRequest{} + if opts.Name != "" { + reqBody.Name = &opts.Name + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/firewalls/%d", firewall.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.FirewallUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return FirewallFromSchema(respBody.Firewall), resp, nil +} + +// Delete deletes a Firewall. +func (c *FirewallClient) Delete(ctx context.Context, firewall *Firewall) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/firewalls/%d", firewall.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +// FirewallSetRulesOpts specifies options for setting rules of a Firewall. +type FirewallSetRulesOpts struct { + Rules []FirewallRule +} + +// SetRules sets the rules of a Firewall. +func (c *FirewallClient) SetRules(ctx context.Context, firewall *Firewall, opts FirewallSetRulesOpts) ([]*Action, *Response, error) { + reqBody := firewallSetRulesOptsToSchema(opts) + + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/firewalls/%d/actions/set_rules", firewall.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.FirewallActionSetRulesResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionsFromSchema(respBody.Actions), resp, nil +} + +func (c *FirewallClient) ApplyResources(ctx context.Context, firewall *Firewall, resources []FirewallResource) ([]*Action, *Response, error) { + applyTo := make([]schema.FirewallResource, len(resources)) + for i, r := range resources { + applyTo[i] = firewallResourceToSchema(r) + } + + reqBody := schema.FirewallActionApplyToResourcesRequest{ApplyTo: applyTo} + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/firewalls/%d/actions/apply_to_resources", firewall.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.FirewallActionApplyToResourcesResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionsFromSchema(respBody.Actions), resp, nil +} + +func (c *FirewallClient) RemoveResources(ctx context.Context, firewall *Firewall, resources []FirewallResource) ([]*Action, *Response, error) { + removeFrom := make([]schema.FirewallResource, len(resources)) + for i, r := range resources { + removeFrom[i] = firewallResourceToSchema(r) + } + + reqBody := schema.FirewallActionRemoveFromResourcesRequest{RemoveFrom: removeFrom} + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/firewalls/%d/actions/remove_from_resources", firewall.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.FirewallActionRemoveFromResourcesResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionsFromSchema(respBody.Actions), resp, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go new file mode 100644 index 000000000..0e6962ab9 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/floating_ip.go @@ -0,0 +1,405 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// FloatingIP represents a Floating IP in the Hetzner Cloud. +type FloatingIP struct { + ID int64 + Description string + Created time.Time + IP net.IP + Network *net.IPNet + Type FloatingIPType + Server *Server + DNSPtr map[string]string + HomeLocation *Location + Blocked bool + Protection FloatingIPProtection + Labels map[string]string + Name string +} + +// DNSPtrForIP returns the reverse DNS pointer of the IP address. +// Deprecated: Use GetDNSPtrForIP instead. +func (f *FloatingIP) DNSPtrForIP(ip net.IP) string { + return f.DNSPtr[ip.String()] +} + +// FloatingIPProtection represents the protection level of a Floating IP. +type FloatingIPProtection struct { + Delete bool +} + +// FloatingIPType represents the type of Floating IP. +type FloatingIPType string + +// Floating IP types. +const ( + FloatingIPTypeIPv4 FloatingIPType = "ipv4" + FloatingIPTypeIPv6 FloatingIPType = "ipv6" +) + +// changeDNSPtr changes or resets the reverse DNS pointer for an IP address. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (f *FloatingIP) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { + reqBody := schema.FloatingIPActionChangeDNSPtrRequest{ + IP: ip.String(), + DNSPtr: ptr, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/floating_ips/%d/actions/change_dns_ptr", f.ID) + req, err := client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.FloatingIPActionChangeDNSPtrResponse{} + resp, err := client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// GetDNSPtrForIP searches for the dns assigned to the given IP address. +// It returns an error if there is no dns set for the given IP address. +func (f *FloatingIP) GetDNSPtrForIP(ip net.IP) (string, error) { + dns, ok := f.DNSPtr[ip.String()] + if !ok { + return "", DNSNotFoundError{ip} + } + + return dns, nil +} + +// FloatingIPClient is a client for the Floating IP API. +type FloatingIPClient struct { + client *Client + Action *ResourceActionClient +} + +// GetByID retrieves a Floating IP by its ID. If the Floating IP does not exist, +// nil is returned. +func (c *FloatingIPClient) GetByID(ctx context.Context, id int64) (*FloatingIP, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/floating_ips/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.FloatingIPGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, resp, err + } + return FloatingIPFromSchema(body.FloatingIP), resp, nil +} + +// GetByName retrieves a Floating IP by its name. If the Floating IP does not exist, nil is returned. +func (c *FloatingIPClient) GetByName(ctx context.Context, name string) (*FloatingIP, *Response, error) { + if name == "" { + return nil, nil, nil + } + floatingIPs, response, err := c.List(ctx, FloatingIPListOpts{Name: name}) + if len(floatingIPs) == 0 { + return nil, response, err + } + return floatingIPs[0], response, err +} + +// Get retrieves a Floating IP by its ID if the input can be parsed as an integer, otherwise it +// retrieves a Floating IP by its name. If the Floating IP does not exist, nil is returned. +func (c *FloatingIPClient) Get(ctx context.Context, idOrName string) (*FloatingIP, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// FloatingIPListOpts specifies options for listing Floating IPs. +type FloatingIPListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l FloatingIPListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of Floating IPs for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *FloatingIPClient) List(ctx context.Context, opts FloatingIPListOpts) ([]*FloatingIP, *Response, error) { + path := "/floating_ips?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.FloatingIPListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + floatingIPs := make([]*FloatingIP, 0, len(body.FloatingIPs)) + for _, s := range body.FloatingIPs { + floatingIPs = append(floatingIPs, FloatingIPFromSchema(s)) + } + return floatingIPs, resp, nil +} + +// All returns all Floating IPs. +func (c *FloatingIPClient) All(ctx context.Context) ([]*FloatingIP, error) { + return c.AllWithOpts(ctx, FloatingIPListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all Floating IPs for the given options. +func (c *FloatingIPClient) AllWithOpts(ctx context.Context, opts FloatingIPListOpts) ([]*FloatingIP, error) { + allFloatingIPs := []*FloatingIP{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + floatingIPs, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allFloatingIPs = append(allFloatingIPs, floatingIPs...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allFloatingIPs, nil +} + +// FloatingIPCreateOpts specifies options for creating a Floating IP. +type FloatingIPCreateOpts struct { + Type FloatingIPType + HomeLocation *Location + Server *Server + Description *string + Name *string + Labels map[string]string +} + +// Validate checks if options are valid. +func (o FloatingIPCreateOpts) Validate() error { + switch o.Type { + case FloatingIPTypeIPv4, FloatingIPTypeIPv6: + break + default: + return errors.New("missing or invalid type") + } + if o.HomeLocation == nil && o.Server == nil { + return errors.New("one of home location or server is required") + } + return nil +} + +// FloatingIPCreateResult is the result of creating a Floating IP. +type FloatingIPCreateResult struct { + FloatingIP *FloatingIP + Action *Action +} + +// Create creates a Floating IP. +func (c *FloatingIPClient) Create(ctx context.Context, opts FloatingIPCreateOpts) (FloatingIPCreateResult, *Response, error) { + if err := opts.Validate(); err != nil { + return FloatingIPCreateResult{}, nil, err + } + + reqBody := schema.FloatingIPCreateRequest{ + Type: string(opts.Type), + Description: opts.Description, + Name: opts.Name, + } + if opts.HomeLocation != nil { + reqBody.HomeLocation = Ptr(opts.HomeLocation.Name) + } + if opts.Server != nil { + reqBody.Server = Ptr(opts.Server.ID) + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return FloatingIPCreateResult{}, nil, err + } + + req, err := c.client.NewRequest(ctx, "POST", "/floating_ips", bytes.NewReader(reqBodyData)) + if err != nil { + return FloatingIPCreateResult{}, nil, err + } + + var respBody schema.FloatingIPCreateResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return FloatingIPCreateResult{}, resp, err + } + var action *Action + if respBody.Action != nil { + action = ActionFromSchema(*respBody.Action) + } + return FloatingIPCreateResult{ + FloatingIP: FloatingIPFromSchema(respBody.FloatingIP), + Action: action, + }, resp, nil +} + +// Delete deletes a Floating IP. +func (c *FloatingIPClient) Delete(ctx context.Context, floatingIP *FloatingIP) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/floating_ips/%d", floatingIP.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +// FloatingIPUpdateOpts specifies options for updating a Floating IP. +type FloatingIPUpdateOpts struct { + Description string + Labels map[string]string + Name string +} + +// Update updates a Floating IP. +func (c *FloatingIPClient) Update(ctx context.Context, floatingIP *FloatingIP, opts FloatingIPUpdateOpts) (*FloatingIP, *Response, error) { + reqBody := schema.FloatingIPUpdateRequest{ + Description: opts.Description, + Name: opts.Name, + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/floating_ips/%d", floatingIP.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.FloatingIPUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return FloatingIPFromSchema(respBody.FloatingIP), resp, nil +} + +// Assign assigns a Floating IP to a server. +func (c *FloatingIPClient) Assign(ctx context.Context, floatingIP *FloatingIP, server *Server) (*Action, *Response, error) { + reqBody := schema.FloatingIPActionAssignRequest{ + Server: server.ID, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/floating_ips/%d/actions/assign", floatingIP.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.FloatingIPActionAssignResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// Unassign unassigns a Floating IP from the currently assigned server. +func (c *FloatingIPClient) Unassign(ctx context.Context, floatingIP *FloatingIP) (*Action, *Response, error) { + var reqBody schema.FloatingIPActionUnassignRequest + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/floating_ips/%d/actions/unassign", floatingIP.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.FloatingIPActionUnassignResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// ChangeDNSPtr changes or resets the reverse DNS pointer for a Floating IP address. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (c *FloatingIPClient) ChangeDNSPtr(ctx context.Context, floatingIP *FloatingIP, ip string, ptr *string) (*Action, *Response, error) { + netIP := net.ParseIP(ip) + if netIP == nil { + return nil, nil, InvalidIPError{ip} + } + return floatingIP.changeDNSPtr(ctx, c.client, net.ParseIP(ip), ptr) +} + +// FloatingIPChangeProtectionOpts specifies options for changing the resource protection level of a Floating IP. +type FloatingIPChangeProtectionOpts struct { + Delete *bool +} + +// ChangeProtection changes the resource protection level of a Floating IP. +func (c *FloatingIPClient) ChangeProtection(ctx context.Context, floatingIP *FloatingIP, opts FloatingIPChangeProtectionOpts) (*Action, *Response, error) { + reqBody := schema.FloatingIPActionChangeProtectionRequest{ + Delete: opts.Delete, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/floating_ips/%d/actions/change_protection", floatingIP.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.FloatingIPActionChangeProtectionResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go new file mode 100644 index 000000000..4f10fdd06 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/hcloud.go @@ -0,0 +1,5 @@ +// Package hcloud is a library for the Hetzner Cloud API. +package hcloud + +// Version is the library's version following Semantic Versioning. +const Version = "2.9.0" // x-release-please-version diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/helper.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/helper.go new file mode 100644 index 000000000..1965609ad --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/helper.go @@ -0,0 +1,28 @@ +package hcloud + +import "time" + +// Ptr returns a pointer to p. +func Ptr[T any](p T) *T { + return &p +} + +// String returns a pointer to the passed string s. +// +// Deprecated: Use [Ptr] instead. +func String(s string) *string { return Ptr(s) } + +// Int returns a pointer to the passed integer i. +// +// Deprecated: Use [Ptr] instead. +func Int(i int) *int { return Ptr(i) } + +// Bool returns a pointer to the passed bool b. +// +// Deprecated: Use [Ptr] instead. +func Bool(b bool) *bool { return Ptr(b) } + +// Duration returns a pointer to the passed time.Duration d. +// +// Deprecated: Use [Ptr] instead. +func Duration(d time.Duration) *time.Duration { return Ptr(d) } diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go new file mode 100644 index 000000000..185c38d4d --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/image.go @@ -0,0 +1,313 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// Image represents an Image in the Hetzner Cloud. +type Image struct { + ID int64 + Name string + Type ImageType + Status ImageStatus + Description string + ImageSize float32 + DiskSize float32 + Created time.Time + CreatedFrom *Server + BoundTo *Server + RapidDeploy bool + + OSFlavor string + OSVersion string + Architecture Architecture + + Protection ImageProtection + Deprecated time.Time // The zero value denotes the image is not deprecated. + Labels map[string]string + Deleted time.Time +} + +// IsDeprecated returns whether the image is deprecated. +func (image *Image) IsDeprecated() bool { + return !image.Deprecated.IsZero() +} + +// IsDeleted returns whether the image is deleted. +func (image *Image) IsDeleted() bool { + return !image.Deleted.IsZero() +} + +// ImageProtection represents the protection level of an image. +type ImageProtection struct { + Delete bool +} + +// ImageType specifies the type of an image. +type ImageType string + +const ( + // ImageTypeSnapshot represents a snapshot image. + ImageTypeSnapshot ImageType = "snapshot" + // ImageTypeBackup represents a backup image. + ImageTypeBackup ImageType = "backup" + // ImageTypeSystem represents a system image. + ImageTypeSystem ImageType = "system" + // ImageTypeApp represents a one click app image. + ImageTypeApp ImageType = "app" +) + +// ImageStatus specifies the status of an image. +type ImageStatus string + +const ( + // ImageStatusCreating is the status when an image is being created. + ImageStatusCreating ImageStatus = "creating" + // ImageStatusAvailable is the status when an image is available. + ImageStatusAvailable ImageStatus = "available" +) + +// ImageClient is a client for the image API. +type ImageClient struct { + client *Client + Action *ResourceActionClient +} + +// GetByID retrieves an image by its ID. If the image does not exist, nil is returned. +func (c *ImageClient) GetByID(ctx context.Context, id int64) (*Image, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/images/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.ImageGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return ImageFromSchema(body.Image), resp, nil +} + +// GetByName retrieves an image by its name. If the image does not exist, nil is returned. +// +// Deprecated: Use [ImageClient.GetByNameAndArchitecture] instead. +func (c *ImageClient) GetByName(ctx context.Context, name string) (*Image, *Response, error) { + if name == "" { + return nil, nil, nil + } + images, response, err := c.List(ctx, ImageListOpts{Name: name}) + if len(images) == 0 { + return nil, response, err + } + return images[0], response, err +} + +// GetByNameAndArchitecture retrieves an image by its name and architecture. If the image does not exist, +// nil is returned. +// In contrast to [ImageClient.Get], this method also returns deprecated images. Depending on your needs you should +// check for this in your calling method. +func (c *ImageClient) GetByNameAndArchitecture(ctx context.Context, name string, architecture Architecture) (*Image, *Response, error) { + if name == "" { + return nil, nil, nil + } + images, response, err := c.List(ctx, ImageListOpts{Name: name, Architecture: []Architecture{architecture}, IncludeDeprecated: true}) + if len(images) == 0 { + return nil, response, err + } + return images[0], response, err +} + +// Get retrieves an image by its ID if the input can be parsed as an integer, otherwise it +// retrieves an image by its name. If the image does not exist, nil is returned. +// +// Deprecated: Use [ImageClient.GetForArchitecture] instead. +func (c *ImageClient) Get(ctx context.Context, idOrName string) (*Image, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// GetForArchitecture retrieves an image by its ID if the input can be parsed as an integer, otherwise it +// retrieves an image by its name and architecture. If the image does not exist, nil is returned. +// +// In contrast to [ImageClient.Get], this method also returns deprecated images. Depending on your needs you should +// check for this in your calling method. +func (c *ImageClient) GetForArchitecture(ctx context.Context, idOrName string, architecture Architecture) (*Image, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByNameAndArchitecture(ctx, idOrName, architecture) +} + +// ImageListOpts specifies options for listing images. +type ImageListOpts struct { + ListOpts + Type []ImageType + BoundTo *Server + Name string + Sort []string + Status []ImageStatus + IncludeDeprecated bool + Architecture []Architecture +} + +func (l ImageListOpts) values() url.Values { + vals := l.ListOpts.Values() + for _, typ := range l.Type { + vals.Add("type", string(typ)) + } + if l.BoundTo != nil { + vals.Add("bound_to", strconv.FormatInt(l.BoundTo.ID, 10)) + } + if l.Name != "" { + vals.Add("name", l.Name) + } + if l.IncludeDeprecated { + vals.Add("include_deprecated", strconv.FormatBool(l.IncludeDeprecated)) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + for _, status := range l.Status { + vals.Add("status", string(status)) + } + for _, arch := range l.Architecture { + vals.Add("architecture", string(arch)) + } + return vals +} + +// List returns a list of images for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *ImageClient) List(ctx context.Context, opts ImageListOpts) ([]*Image, *Response, error) { + path := "/images?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.ImageListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + images := make([]*Image, 0, len(body.Images)) + for _, i := range body.Images { + images = append(images, ImageFromSchema(i)) + } + return images, resp, nil +} + +// All returns all images. +func (c *ImageClient) All(ctx context.Context) ([]*Image, error) { + return c.AllWithOpts(ctx, ImageListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all images for the given options. +func (c *ImageClient) AllWithOpts(ctx context.Context, opts ImageListOpts) ([]*Image, error) { + allImages := []*Image{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + images, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allImages = append(allImages, images...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allImages, nil +} + +// Delete deletes an image. +func (c *ImageClient) Delete(ctx context.Context, image *Image) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/images/%d", image.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +// ImageUpdateOpts specifies options for updating an image. +type ImageUpdateOpts struct { + Description *string + Type ImageType + Labels map[string]string +} + +// Update updates an image. +func (c *ImageClient) Update(ctx context.Context, image *Image, opts ImageUpdateOpts) (*Image, *Response, error) { + reqBody := schema.ImageUpdateRequest{ + Description: opts.Description, + } + if opts.Type != "" { + reqBody.Type = Ptr(string(opts.Type)) + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/images/%d", image.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ImageUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ImageFromSchema(respBody.Image), resp, nil +} + +// ImageChangeProtectionOpts specifies options for changing the resource protection level of an image. +type ImageChangeProtectionOpts struct { + Delete *bool +} + +// ChangeProtection changes the resource protection level of an image. +func (c *ImageClient) ChangeProtection(ctx context.Context, image *Image, opts ImageChangeProtectionOpts) (*Action, *Response, error) { + reqBody := schema.ImageActionChangeProtectionRequest{ + Delete: opts.Delete, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/images/%d/actions/change_protection", image.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ImageActionChangeProtectionResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/interface_gen.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/interface_gen.go new file mode 100644 index 000000000..2ae8cecb4 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/interface_gen.go @@ -0,0 +1,22 @@ +package hcloud + +//go:generate go run github.com/vburenin/ifacemaker -f action.go -f action_watch.go -f action_waiter.go -s ActionClient -i IActionClient -p hcloud -o zz_action_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f action.go -s ResourceActionClient -i IResourceActionClient -p hcloud -o zz_resource_action_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f datacenter.go -s DatacenterClient -i IDatacenterClient -p hcloud -o zz_datacenter_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f floating_ip.go -s FloatingIPClient -i IFloatingIPClient -p hcloud -o zz_floating_ip_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f image.go -s ImageClient -i IImageClient -p hcloud -o zz_image_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f iso.go -s ISOClient -i IISOClient -p hcloud -o zz_iso_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f location.go -s LocationClient -i ILocationClient -p hcloud -o zz_location_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f network.go -s NetworkClient -i INetworkClient -p hcloud -o zz_network_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f pricing.go -s PricingClient -i IPricingClient -p hcloud -o zz_pricing_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f server.go -s ServerClient -i IServerClient -p hcloud -o zz_server_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f server_type.go -s ServerTypeClient -i IServerTypeClient -p hcloud -o zz_server_type_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f ssh_key.go -s SSHKeyClient -i ISSHKeyClient -p hcloud -o zz_ssh_key_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f volume.go -s VolumeClient -i IVolumeClient -p hcloud -o zz_volume_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f load_balancer.go -s LoadBalancerClient -i ILoadBalancerClient -p hcloud -o zz_load_balancer_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f load_balancer_type.go -s LoadBalancerTypeClient -i ILoadBalancerTypeClient -p hcloud -o zz_load_balancer_type_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f certificate.go -s CertificateClient -i ICertificateClient -p hcloud -o zz_certificate_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f firewall.go -s FirewallClient -i IFirewallClient -p hcloud -o zz_firewall_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f placement_group.go -s PlacementGroupClient -i IPlacementGroupClient -p hcloud -o zz_placement_group_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f rdns.go -s RDNSClient -i IRDNSClient -p hcloud -o zz_rdns_client_iface.go +//go:generate go run github.com/vburenin/ifacemaker -f primary_ip.go -s PrimaryIPClient -i IPrimaryIPClient -p hcloud -o zz_primary_ip_client_iface.go diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/internal/instrumentation/metrics.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/internal/instrumentation/metrics.go new file mode 100644 index 000000000..e52bd606a --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/internal/instrumentation/metrics.go @@ -0,0 +1,117 @@ +package instrumentation + +import ( + "fmt" + "net/http" + "regexp" + "strconv" + "strings" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +type Instrumenter struct { + subsystemIdentifier string // will be used as part of the metric name (hcloud__requests_total) + instrumentationRegistry prometheus.Registerer +} + +// New creates a new Instrumenter. The subsystemIdentifier will be used as part of the metric names (e.g. hcloud__requests_total). +func New(subsystemIdentifier string, instrumentationRegistry prometheus.Registerer) *Instrumenter { + return &Instrumenter{subsystemIdentifier: subsystemIdentifier, instrumentationRegistry: instrumentationRegistry} +} + +// InstrumentedRoundTripper returns an instrumented round tripper. +func (i *Instrumenter) InstrumentedRoundTripper() http.RoundTripper { + inFlightRequestsGauge := registerOrReuse( + i.instrumentationRegistry, + prometheus.NewGauge(prometheus.GaugeOpts{ + Name: fmt.Sprintf("hcloud_%s_in_flight_requests", i.subsystemIdentifier), + Help: fmt.Sprintf("A gauge of in-flight requests to the hcloud %s.", i.subsystemIdentifier), + }), + ) + + requestsPerEndpointCounter := registerOrReuse( + i.instrumentationRegistry, + prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: fmt.Sprintf("hcloud_%s_requests_total", i.subsystemIdentifier), + Help: fmt.Sprintf("A counter for requests to the hcloud %s per endpoint.", i.subsystemIdentifier), + }, + []string{"code", "method", "api_endpoint"}, + ), + ) + + requestLatencyHistogram := registerOrReuse( + i.instrumentationRegistry, + prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: fmt.Sprintf("hcloud_%s_request_duration_seconds", i.subsystemIdentifier), + Help: fmt.Sprintf("A histogram of request latencies to the hcloud %s .", i.subsystemIdentifier), + Buckets: prometheus.DefBuckets, + }, + []string{"method"}, + ), + ) + + return promhttp.InstrumentRoundTripperInFlight(inFlightRequestsGauge, + promhttp.InstrumentRoundTripperDuration(requestLatencyHistogram, + i.instrumentRoundTripperEndpoint(requestsPerEndpointCounter, + http.DefaultTransport, + ), + ), + ) +} + +// instrumentRoundTripperEndpoint implements a hcloud specific round tripper to count requests per API endpoint +// numeric IDs are removed from the URI Path. +// +// Sample: +// +// /volumes/1234/actions/attach --> /volumes/actions/attach +func (i *Instrumenter) instrumentRoundTripperEndpoint(counter *prometheus.CounterVec, next http.RoundTripper) promhttp.RoundTripperFunc { + return func(r *http.Request) (*http.Response, error) { + resp, err := next.RoundTrip(r) + if err == nil { + statusCode := strconv.Itoa(resp.StatusCode) + counter.WithLabelValues(statusCode, strings.ToLower(resp.Request.Method), preparePathForLabel(resp.Request.URL.Path)).Inc() + } + + return resp, err + } +} + +// registerOrReuse will try to register the passed Collector, but in case a conflicting collector was already registered, +// it will instead return that collector. Make sure to always use the collector return by this method. +// Similar to [Registry.MustRegister] it will panic if any other error occurs. +func registerOrReuse[C prometheus.Collector](registry prometheus.Registerer, collector C) C { + err := registry.Register(collector) + if err != nil { + // If we get a AlreadyRegisteredError we can return the existing collector + if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + if existingCollector, ok := are.ExistingCollector.(C); ok { + collector = existingCollector + } else { + panic("received incompatible existing collector") + } + } else { + panic(err) + } + } + + return collector +} + +func preparePathForLabel(path string) string { + path = strings.ToLower(path) + + // replace all numbers and chars that are not a-z, / or _ + reg := regexp.MustCompile("[^a-z/_]+") + path = reg.ReplaceAllString(path, "") + + // replace all artifacts of number replacement (//) + path = strings.ReplaceAll(path, "//", "/") + + // replace the /v/ that indicated the API version + return strings.Replace(path, "/v/", "/", 1) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/iso.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/iso.go new file mode 100644 index 000000000..08f7072ce --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/iso.go @@ -0,0 +1,159 @@ +package hcloud + +import ( + "context" + "fmt" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// ISO represents an ISO image in the Hetzner Cloud. +type ISO struct { + ID int64 + Name string + Description string + Type ISOType + Architecture *Architecture + // Deprecated: Use [ISO.Deprecation] instead. + Deprecated time.Time + DeprecatableResource +} + +// ISOType specifies the type of an ISO image. +type ISOType string + +const ( + // ISOTypePublic is the type of a public ISO image. + ISOTypePublic ISOType = "public" + + // ISOTypePrivate is the type of a private ISO image. + ISOTypePrivate ISOType = "private" +) + +// ISOClient is a client for the ISO API. +type ISOClient struct { + client *Client +} + +// GetByID retrieves an ISO by its ID. +func (c *ISOClient) GetByID(ctx context.Context, id int64) (*ISO, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/isos/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.ISOGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, resp, err + } + return ISOFromSchema(body.ISO), resp, nil +} + +// GetByName retrieves an ISO by its name. +func (c *ISOClient) GetByName(ctx context.Context, name string) (*ISO, *Response, error) { + if name == "" { + return nil, nil, nil + } + isos, response, err := c.List(ctx, ISOListOpts{Name: name}) + if len(isos) == 0 { + return nil, response, err + } + return isos[0], response, err +} + +// Get retrieves an ISO by its ID if the input can be parsed as an integer, otherwise it retrieves an ISO by its name. +func (c *ISOClient) Get(ctx context.Context, idOrName string) (*ISO, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// ISOListOpts specifies options for listing isos. +type ISOListOpts struct { + ListOpts + Name string + Sort []string + // Architecture filters the ISOs by Architecture. Note that custom ISOs do not have any architecture set, and you + // must use IncludeWildcardArchitecture to include them. + Architecture []Architecture + // IncludeWildcardArchitecture must be set to also return custom ISOs that have no architecture set, if you are + // also setting the Architecture field. + // Deprecated: Use [ISOListOpts.IncludeArchitectureWildcard] instead. + IncludeWildcardArchitecture bool + // IncludeWildcardArchitecture must be set to also return custom ISOs that have no architecture set, if you are + // also setting the Architecture field. + IncludeArchitectureWildcard bool +} + +func (l ISOListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + for _, arch := range l.Architecture { + vals.Add("architecture", string(arch)) + } + if l.IncludeArchitectureWildcard || l.IncludeWildcardArchitecture { + vals.Add("include_architecture_wildcard", "true") + } + return vals +} + +// List returns a list of ISOs for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *ISOClient) List(ctx context.Context, opts ISOListOpts) ([]*ISO, *Response, error) { + path := "/isos?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.ISOListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + isos := make([]*ISO, 0, len(body.ISOs)) + for _, i := range body.ISOs { + isos = append(isos, ISOFromSchema(i)) + } + return isos, resp, nil +} + +// All returns all ISOs. +func (c *ISOClient) All(ctx context.Context) ([]*ISO, error) { + return c.AllWithOpts(ctx, ISOListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all ISOs for the given options. +func (c *ISOClient) AllWithOpts(ctx context.Context, opts ISOListOpts) ([]*ISO, error) { + allISOs := []*ISO{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + isos, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allISOs = append(allISOs, isos...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allISOs, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/labels.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/labels.go new file mode 100644 index 000000000..3dc7d781f --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/labels.go @@ -0,0 +1,23 @@ +package hcloud + +import ( + "fmt" + "regexp" +) + +var keyRegexp = regexp.MustCompile( + `^([a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]){0,253}[a-z0-9A-Z])?/)?[a-z0-9A-Z]((?:[\-_.]|[a-z0-9A-Z]|){0,61}[a-z0-9A-Z])?$`) +var valueRegexp = regexp.MustCompile(`^(([a-z0-9A-Z](?:[\-_.]|[a-z0-9A-Z]){0,61})?[a-z0-9A-Z]$|$)`) + +func ValidateResourceLabels(labels map[string]interface{}) (bool, error) { + for k, v := range labels { + if match := keyRegexp.MatchString(k); !match { + return false, fmt.Errorf("label key '%s' is not correctly formatted", k) + } + + if match := valueRegexp.MatchString(v.(string)); !match { + return false, fmt.Errorf("label value '%s' (key: %s) is not correctly formatted", v, k) + } + } + return true, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go new file mode 100644 index 000000000..fb40057b7 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer.go @@ -0,0 +1,1062 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net" + "net/http" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// LoadBalancer represents a Load Balancer in the Hetzner Cloud. +type LoadBalancer struct { + ID int64 + Name string + PublicNet LoadBalancerPublicNet + PrivateNet []LoadBalancerPrivateNet + Location *Location + LoadBalancerType *LoadBalancerType + Algorithm LoadBalancerAlgorithm + Services []LoadBalancerService + Targets []LoadBalancerTarget + Protection LoadBalancerProtection + Labels map[string]string + Created time.Time + IncludedTraffic uint64 + OutgoingTraffic uint64 + IngoingTraffic uint64 +} + +// LoadBalancerPublicNet represents a Load Balancer's public network. +type LoadBalancerPublicNet struct { + Enabled bool + IPv4 LoadBalancerPublicNetIPv4 + IPv6 LoadBalancerPublicNetIPv6 +} + +// LoadBalancerPublicNetIPv4 represents a Load Balancer's public IPv4 address. +type LoadBalancerPublicNetIPv4 struct { + IP net.IP + DNSPtr string +} + +// LoadBalancerPublicNetIPv6 represents a Load Balancer's public IPv6 address. +type LoadBalancerPublicNetIPv6 struct { + IP net.IP + DNSPtr string +} + +// LoadBalancerPrivateNet represents a Load Balancer's private network. +type LoadBalancerPrivateNet struct { + Network *Network + IP net.IP +} + +// LoadBalancerService represents a Load Balancer service. +type LoadBalancerService struct { + Protocol LoadBalancerServiceProtocol + ListenPort int + DestinationPort int + Proxyprotocol bool + HTTP LoadBalancerServiceHTTP + HealthCheck LoadBalancerServiceHealthCheck +} + +// LoadBalancerServiceHTTP stores configuration for a service using the HTTP protocol. +type LoadBalancerServiceHTTP struct { + CookieName string + CookieLifetime time.Duration + Certificates []*Certificate + RedirectHTTP bool + StickySessions bool +} + +// LoadBalancerServiceHealthCheck stores configuration for a service health check. +type LoadBalancerServiceHealthCheck struct { + Protocol LoadBalancerServiceProtocol + Port int + Interval time.Duration + Timeout time.Duration + Retries int + HTTP *LoadBalancerServiceHealthCheckHTTP +} + +// LoadBalancerServiceHealthCheckHTTP stores configuration for a service health check +// using the HTTP protocol. +type LoadBalancerServiceHealthCheckHTTP struct { + Domain string + Path string + Response string + StatusCodes []string + TLS bool +} + +// LoadBalancerAlgorithmType specifies the algorithm type a Load Balancer +// uses for distributing requests. +type LoadBalancerAlgorithmType string + +const ( + // LoadBalancerAlgorithmTypeRoundRobin is an algorithm which distributes + // requests to targets in a round-robin fashion. + LoadBalancerAlgorithmTypeRoundRobin LoadBalancerAlgorithmType = "round_robin" + // LoadBalancerAlgorithmTypeLeastConnections is an algorithm which distributes + // requests to targets with the least number of connections. + LoadBalancerAlgorithmTypeLeastConnections LoadBalancerAlgorithmType = "least_connections" +) + +// LoadBalancerAlgorithm configures the algorithm a Load Balancer uses +// for distributing requests. +type LoadBalancerAlgorithm struct { + Type LoadBalancerAlgorithmType +} + +// LoadBalancerTargetType specifies the type of Load Balancer target. +type LoadBalancerTargetType string + +const ( + // LoadBalancerTargetTypeServer is a target type which points to a specific + // server. + LoadBalancerTargetTypeServer LoadBalancerTargetType = "server" + + // LoadBalancerTargetTypeLabelSelector is a target type which selects the + // servers a Load Balancer points to using labels assigned to the servers. + LoadBalancerTargetTypeLabelSelector LoadBalancerTargetType = "label_selector" + + // LoadBalancerTargetTypeIP is a target type which points to an IP. + LoadBalancerTargetTypeIP LoadBalancerTargetType = "ip" +) + +// LoadBalancerServiceProtocol specifies the protocol of a Load Balancer service. +type LoadBalancerServiceProtocol string + +const ( + // LoadBalancerServiceProtocolTCP specifies a TCP service. + LoadBalancerServiceProtocolTCP LoadBalancerServiceProtocol = "tcp" + // LoadBalancerServiceProtocolHTTP specifies an HTTP service. + LoadBalancerServiceProtocolHTTP LoadBalancerServiceProtocol = "http" + // LoadBalancerServiceProtocolHTTPS specifies an HTTPS service. + LoadBalancerServiceProtocolHTTPS LoadBalancerServiceProtocol = "https" +) + +// LoadBalancerTarget represents a Load Balancer target. +type LoadBalancerTarget struct { + Type LoadBalancerTargetType + Server *LoadBalancerTargetServer + LabelSelector *LoadBalancerTargetLabelSelector + IP *LoadBalancerTargetIP + HealthStatus []LoadBalancerTargetHealthStatus + Targets []LoadBalancerTarget + UsePrivateIP bool +} + +// LoadBalancerTargetServer configures a Load Balancer target +// pointing at a specific server. +type LoadBalancerTargetServer struct { + Server *Server +} + +// LoadBalancerTargetLabelSelector configures a Load Balancer target pointing +// at the servers matching the selector. This includes the target pointing at +// nothing, if no servers match the Selector. +type LoadBalancerTargetLabelSelector struct { + Selector string +} + +// LoadBalancerTargetIP configures a Load Balancer target pointing to a Hetzner +// Online IP address. +type LoadBalancerTargetIP struct { + IP string +} + +// LoadBalancerTargetHealthStatusStatus describes a target's health status. +type LoadBalancerTargetHealthStatusStatus string + +const ( + // LoadBalancerTargetHealthStatusStatusUnknown denotes that the health status is unknown. + LoadBalancerTargetHealthStatusStatusUnknown LoadBalancerTargetHealthStatusStatus = "unknown" + // LoadBalancerTargetHealthStatusStatusHealthy denotes a healthy target. + LoadBalancerTargetHealthStatusStatusHealthy LoadBalancerTargetHealthStatusStatus = "healthy" + // LoadBalancerTargetHealthStatusStatusUnhealthy denotes an unhealthy target. + LoadBalancerTargetHealthStatusStatusUnhealthy LoadBalancerTargetHealthStatusStatus = "unhealthy" +) + +// LoadBalancerTargetHealthStatus describes a target's health for a specific service. +type LoadBalancerTargetHealthStatus struct { + ListenPort int + Status LoadBalancerTargetHealthStatusStatus +} + +// LoadBalancerProtection represents the protection level of a Load Balancer. +type LoadBalancerProtection struct { + Delete bool +} + +// changeDNSPtr changes or resets the reverse DNS pointer for an IP address. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (lb *LoadBalancer) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionChangeDNSPtrRequest{ + IP: ip.String(), + DNSPtr: ptr, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/change_dns_ptr", lb.ID) + req, err := client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.LoadBalancerActionChangeDNSPtrResponse{} + resp, err := client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// GetDNSPtrForIP searches for the dns assigned to the given IP address. +// It returns an error if there is no dns set for the given IP address. +func (lb *LoadBalancer) GetDNSPtrForIP(ip net.IP) (string, error) { + if net.IP.Equal(lb.PublicNet.IPv4.IP, ip) { + return lb.PublicNet.IPv4.DNSPtr, nil + } else if net.IP.Equal(lb.PublicNet.IPv6.IP, ip) { + return lb.PublicNet.IPv6.DNSPtr, nil + } + + return "", DNSNotFoundError{ip} +} + +// LoadBalancerClient is a client for the Load Balancers API. +type LoadBalancerClient struct { + client *Client + Action *ResourceActionClient +} + +// GetByID retrieves a Load Balancer by its ID. If the Load Balancer does not exist, nil is returned. +func (c *LoadBalancerClient) GetByID(ctx context.Context, id int64) (*LoadBalancer, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/load_balancers/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.LoadBalancerGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return LoadBalancerFromSchema(body.LoadBalancer), resp, nil +} + +// GetByName retrieves a Load Balancer by its name. If the Load Balancer does not exist, nil is returned. +func (c *LoadBalancerClient) GetByName(ctx context.Context, name string) (*LoadBalancer, *Response, error) { + if name == "" { + return nil, nil, nil + } + LoadBalancer, response, err := c.List(ctx, LoadBalancerListOpts{Name: name}) + if len(LoadBalancer) == 0 { + return nil, response, err + } + return LoadBalancer[0], response, err +} + +// Get retrieves a Load Balancer by its ID if the input can be parsed as an integer, otherwise it +// retrieves a Load Balancer by its name. If the Load Balancer does not exist, nil is returned. +func (c *LoadBalancerClient) Get(ctx context.Context, idOrName string) (*LoadBalancer, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// LoadBalancerListOpts specifies options for listing Load Balancers. +type LoadBalancerListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l LoadBalancerListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of Load Balancers for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *LoadBalancerClient) List(ctx context.Context, opts LoadBalancerListOpts) ([]*LoadBalancer, *Response, error) { + path := "/load_balancers?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.LoadBalancerListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + LoadBalancers := make([]*LoadBalancer, 0, len(body.LoadBalancers)) + for _, s := range body.LoadBalancers { + LoadBalancers = append(LoadBalancers, LoadBalancerFromSchema(s)) + } + return LoadBalancers, resp, nil +} + +// All returns all Load Balancers. +func (c *LoadBalancerClient) All(ctx context.Context) ([]*LoadBalancer, error) { + return c.AllWithOpts(ctx, LoadBalancerListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all Load Balancers for the given options. +func (c *LoadBalancerClient) AllWithOpts(ctx context.Context, opts LoadBalancerListOpts) ([]*LoadBalancer, error) { + allLoadBalancers := []*LoadBalancer{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + LoadBalancers, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allLoadBalancers = append(allLoadBalancers, LoadBalancers...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allLoadBalancers, nil +} + +// LoadBalancerUpdateOpts specifies options for updating a Load Balancer. +type LoadBalancerUpdateOpts struct { + Name string + Labels map[string]string +} + +// Update updates a Load Balancer. +func (c *LoadBalancerClient) Update(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerUpdateOpts) (*LoadBalancer, *Response, error) { + reqBody := schema.LoadBalancerUpdateRequest{} + if opts.Name != "" { + reqBody.Name = &opts.Name + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.LoadBalancerUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return LoadBalancerFromSchema(respBody.LoadBalancer), resp, nil +} + +// LoadBalancerCreateOpts specifies options for creating a new Load Balancer. +type LoadBalancerCreateOpts struct { + Name string + LoadBalancerType *LoadBalancerType + Algorithm *LoadBalancerAlgorithm + Location *Location + NetworkZone NetworkZone + Labels map[string]string + Targets []LoadBalancerCreateOptsTarget + Services []LoadBalancerCreateOptsService + PublicInterface *bool + Network *Network +} + +// LoadBalancerCreateOptsTarget holds options for specifying a target +// when creating a new Load Balancer. +type LoadBalancerCreateOptsTarget struct { + Type LoadBalancerTargetType + Server LoadBalancerCreateOptsTargetServer + LabelSelector LoadBalancerCreateOptsTargetLabelSelector + IP LoadBalancerCreateOptsTargetIP + UsePrivateIP *bool +} + +// LoadBalancerCreateOptsTargetServer holds options for specifying a server target +// when creating a new Load Balancer. +type LoadBalancerCreateOptsTargetServer struct { + Server *Server +} + +// LoadBalancerCreateOptsTargetLabelSelector holds options for specifying a label selector target +// when creating a new Load Balancer. +type LoadBalancerCreateOptsTargetLabelSelector struct { + Selector string +} + +// LoadBalancerCreateOptsTargetIP holds options for specifying an IP target +// when creating a new Load Balancer. +type LoadBalancerCreateOptsTargetIP struct { + IP string +} + +// LoadBalancerCreateOptsService holds options for specifying a service +// when creating a new Load Balancer. +type LoadBalancerCreateOptsService struct { + Protocol LoadBalancerServiceProtocol + ListenPort *int + DestinationPort *int + Proxyprotocol *bool + HTTP *LoadBalancerCreateOptsServiceHTTP + HealthCheck *LoadBalancerCreateOptsServiceHealthCheck +} + +// LoadBalancerCreateOptsServiceHTTP holds options for specifying an HTTP service +// when creating a new Load Balancer. +type LoadBalancerCreateOptsServiceHTTP struct { + CookieName *string + CookieLifetime *time.Duration + Certificates []*Certificate + RedirectHTTP *bool + StickySessions *bool +} + +// LoadBalancerCreateOptsServiceHealthCheck holds options for specifying a service +// health check when creating a new Load Balancer. +type LoadBalancerCreateOptsServiceHealthCheck struct { + Protocol LoadBalancerServiceProtocol + Port *int + Interval *time.Duration + Timeout *time.Duration + Retries *int + HTTP *LoadBalancerCreateOptsServiceHealthCheckHTTP +} + +// LoadBalancerCreateOptsServiceHealthCheckHTTP holds options for specifying a service +// HTTP health check when creating a new Load Balancer. +type LoadBalancerCreateOptsServiceHealthCheckHTTP struct { + Domain *string + Path *string + Response *string + StatusCodes []string + TLS *bool +} + +// LoadBalancerCreateResult is the result of a create Load Balancer call. +type LoadBalancerCreateResult struct { + LoadBalancer *LoadBalancer + Action *Action +} + +// Create creates a new Load Balancer. +func (c *LoadBalancerClient) Create(ctx context.Context, opts LoadBalancerCreateOpts) (LoadBalancerCreateResult, *Response, error) { + reqBody := loadBalancerCreateOptsToSchema(opts) + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return LoadBalancerCreateResult{}, nil, err + } + req, err := c.client.NewRequest(ctx, "POST", "/load_balancers", bytes.NewReader(reqBodyData)) + if err != nil { + return LoadBalancerCreateResult{}, nil, err + } + + respBody := schema.LoadBalancerCreateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return LoadBalancerCreateResult{}, resp, err + } + return LoadBalancerCreateResult{ + LoadBalancer: LoadBalancerFromSchema(respBody.LoadBalancer), + Action: ActionFromSchema(respBody.Action), + }, resp, nil +} + +// Delete deletes a Load Balancer. +func (c *LoadBalancerClient) Delete(ctx context.Context, loadBalancer *LoadBalancer) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/load_balancers/%d", loadBalancer.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +func (c *LoadBalancerClient) addTarget(ctx context.Context, loadBalancer *LoadBalancer, reqBody schema.LoadBalancerActionAddTargetRequest) (*Action, *Response, error) { + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/add_target", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.LoadBalancerActionAddTargetResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +func (c *LoadBalancerClient) removeTarget(ctx context.Context, loadBalancer *LoadBalancer, reqBody schema.LoadBalancerActionRemoveTargetRequest) (*Action, *Response, error) { + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/remove_target", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.LoadBalancerActionRemoveTargetResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// LoadBalancerAddServerTargetOpts specifies options for adding a server target +// to a Load Balancer. +type LoadBalancerAddServerTargetOpts struct { + Server *Server + UsePrivateIP *bool +} + +// AddServerTarget adds a server target to a Load Balancer. +func (c *LoadBalancerClient) AddServerTarget(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddServerTargetOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionAddTargetRequest{ + Type: string(LoadBalancerTargetTypeServer), + Server: &schema.LoadBalancerActionAddTargetRequestServer{ + ID: opts.Server.ID, + }, + UsePrivateIP: opts.UsePrivateIP, + } + return c.addTarget(ctx, loadBalancer, reqBody) +} + +// RemoveServerTarget removes a server target from a Load Balancer. +func (c *LoadBalancerClient) RemoveServerTarget(ctx context.Context, loadBalancer *LoadBalancer, server *Server) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionRemoveTargetRequest{ + Type: string(LoadBalancerTargetTypeServer), + Server: &schema.LoadBalancerActionRemoveTargetRequestServer{ + ID: server.ID, + }, + } + return c.removeTarget(ctx, loadBalancer, reqBody) +} + +// LoadBalancerAddLabelSelectorTargetOpts specifies options for adding a label selector target +// to a Load Balancer. +type LoadBalancerAddLabelSelectorTargetOpts struct { + Selector string + UsePrivateIP *bool +} + +// AddLabelSelectorTarget adds a label selector target to a Load Balancer. +func (c *LoadBalancerClient) AddLabelSelectorTarget(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddLabelSelectorTargetOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionAddTargetRequest{ + Type: string(LoadBalancerTargetTypeLabelSelector), + LabelSelector: &schema.LoadBalancerActionAddTargetRequestLabelSelector{ + Selector: opts.Selector, + }, + UsePrivateIP: opts.UsePrivateIP, + } + return c.addTarget(ctx, loadBalancer, reqBody) +} + +// RemoveLabelSelectorTarget removes a label selector target from a Load Balancer. +func (c *LoadBalancerClient) RemoveLabelSelectorTarget(ctx context.Context, loadBalancer *LoadBalancer, labelSelector string) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionRemoveTargetRequest{ + Type: string(LoadBalancerTargetTypeLabelSelector), + LabelSelector: &schema.LoadBalancerActionRemoveTargetRequestLabelSelector{ + Selector: labelSelector, + }, + } + return c.removeTarget(ctx, loadBalancer, reqBody) +} + +// LoadBalancerAddIPTargetOpts specifies options for adding an IP target to a +// Load Balancer. +type LoadBalancerAddIPTargetOpts struct { + IP net.IP +} + +// AddIPTarget adds an IP target to a Load Balancer. +func (c *LoadBalancerClient) AddIPTarget(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddIPTargetOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionAddTargetRequest{ + Type: string(LoadBalancerTargetTypeIP), + IP: &schema.LoadBalancerActionAddTargetRequestIP{IP: opts.IP.String()}, + } + return c.addTarget(ctx, loadBalancer, reqBody) +} + +// RemoveIPTarget removes an IP target from a Load Balancer. +func (c *LoadBalancerClient) RemoveIPTarget(ctx context.Context, loadBalancer *LoadBalancer, ip net.IP) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionRemoveTargetRequest{ + Type: string(LoadBalancerTargetTypeIP), + IP: &schema.LoadBalancerActionRemoveTargetRequestIP{ + IP: ip.String(), + }, + } + return c.removeTarget(ctx, loadBalancer, reqBody) +} + +// LoadBalancerAddServiceOpts specifies options for adding a service to a Load Balancer. +type LoadBalancerAddServiceOpts struct { + Protocol LoadBalancerServiceProtocol + ListenPort *int + DestinationPort *int + Proxyprotocol *bool + HTTP *LoadBalancerAddServiceOptsHTTP + HealthCheck *LoadBalancerAddServiceOptsHealthCheck +} + +// LoadBalancerAddServiceOptsHTTP holds options for specifying an HTTP service +// when adding a service to a Load Balancer. +type LoadBalancerAddServiceOptsHTTP struct { + CookieName *string + CookieLifetime *time.Duration + Certificates []*Certificate + RedirectHTTP *bool + StickySessions *bool +} + +// LoadBalancerAddServiceOptsHealthCheck holds options for specifying a health check +// when adding a service to a Load Balancer. +type LoadBalancerAddServiceOptsHealthCheck struct { + Protocol LoadBalancerServiceProtocol + Port *int + Interval *time.Duration + Timeout *time.Duration + Retries *int + HTTP *LoadBalancerAddServiceOptsHealthCheckHTTP +} + +// LoadBalancerAddServiceOptsHealthCheckHTTP holds options for specifying an +// HTTP health check when adding a service to a Load Balancer. +type LoadBalancerAddServiceOptsHealthCheckHTTP struct { + Domain *string + Path *string + Response *string + StatusCodes []string + TLS *bool +} + +// AddService adds a service to a Load Balancer. +func (c *LoadBalancerClient) AddService(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddServiceOpts) (*Action, *Response, error) { + reqBody := loadBalancerAddServiceOptsToSchema(opts) + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/add_service", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.LoadBalancerActionAddServiceResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// LoadBalancerUpdateServiceOpts specifies options for updating a service. +type LoadBalancerUpdateServiceOpts struct { + Protocol LoadBalancerServiceProtocol + DestinationPort *int + Proxyprotocol *bool + HTTP *LoadBalancerUpdateServiceOptsHTTP + HealthCheck *LoadBalancerUpdateServiceOptsHealthCheck +} + +// LoadBalancerUpdateServiceOptsHTTP specifies options for updating an HTTP(S) service. +type LoadBalancerUpdateServiceOptsHTTP struct { + CookieName *string + CookieLifetime *time.Duration + Certificates []*Certificate + RedirectHTTP *bool + StickySessions *bool +} + +// LoadBalancerUpdateServiceOptsHealthCheck specifies options for updating +// a service's health check. +type LoadBalancerUpdateServiceOptsHealthCheck struct { + Protocol LoadBalancerServiceProtocol + Port *int + Interval *time.Duration + Timeout *time.Duration + Retries *int + HTTP *LoadBalancerUpdateServiceOptsHealthCheckHTTP +} + +// LoadBalancerUpdateServiceOptsHealthCheckHTTP specifies options for updating +// the HTTP-specific settings of a service's health check. +type LoadBalancerUpdateServiceOptsHealthCheckHTTP struct { + Domain *string + Path *string + Response *string + StatusCodes []string + TLS *bool +} + +// UpdateService updates a Load Balancer service. +func (c *LoadBalancerClient) UpdateService(ctx context.Context, loadBalancer *LoadBalancer, listenPort int, opts LoadBalancerUpdateServiceOpts) (*Action, *Response, error) { + reqBody := loadBalancerUpdateServiceOptsToSchema(opts) + reqBody.ListenPort = listenPort + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/update_service", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.LoadBalancerActionUpdateServiceResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// DeleteService deletes a Load Balancer service. +func (c *LoadBalancerClient) DeleteService(ctx context.Context, loadBalancer *LoadBalancer, listenPort int) (*Action, *Response, error) { + reqBody := schema.LoadBalancerDeleteServiceRequest{ + ListenPort: listenPort, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/delete_service", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.LoadBalancerDeleteServiceResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// LoadBalancerChangeProtectionOpts specifies options for changing the resource protection level of a Load Balancer. +type LoadBalancerChangeProtectionOpts struct { + Delete *bool +} + +// ChangeProtection changes the resource protection level of a Load Balancer. +func (c *LoadBalancerClient) ChangeProtection(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerChangeProtectionOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionChangeProtectionRequest{ + Delete: opts.Delete, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/change_protection", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.LoadBalancerActionChangeProtectionResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// LoadBalancerChangeAlgorithmOpts specifies options for changing the algorithm of a Load Balancer. +type LoadBalancerChangeAlgorithmOpts struct { + Type LoadBalancerAlgorithmType +} + +// ChangeAlgorithm changes the algorithm of a Load Balancer. +func (c *LoadBalancerClient) ChangeAlgorithm(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerChangeAlgorithmOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionChangeAlgorithmRequest{ + Type: string(opts.Type), + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/change_algorithm", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.LoadBalancerActionChangeAlgorithmResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// LoadBalancerAttachToNetworkOpts specifies options for attaching a Load Balancer to a network. +type LoadBalancerAttachToNetworkOpts struct { + Network *Network + IP net.IP +} + +// AttachToNetwork attaches a Load Balancer to a network. +func (c *LoadBalancerClient) AttachToNetwork(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAttachToNetworkOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionAttachToNetworkRequest{ + Network: opts.Network.ID, + } + if opts.IP != nil { + reqBody.IP = Ptr(opts.IP.String()) + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/attach_to_network", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.LoadBalancerActionAttachToNetworkResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// LoadBalancerDetachFromNetworkOpts specifies options for detaching a Load Balancer from a network. +type LoadBalancerDetachFromNetworkOpts struct { + Network *Network +} + +// DetachFromNetwork detaches a Load Balancer from a network. +func (c *LoadBalancerClient) DetachFromNetwork(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerDetachFromNetworkOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionDetachFromNetworkRequest{ + Network: opts.Network.ID, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/detach_from_network", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.LoadBalancerActionDetachFromNetworkResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// EnablePublicInterface enables the Load Balancer's public network interface. +func (c *LoadBalancerClient) EnablePublicInterface(ctx context.Context, loadBalancer *LoadBalancer) (*Action, *Response, error) { + path := fmt.Sprintf("/load_balancers/%d/actions/enable_public_interface", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + respBody := schema.LoadBalancerActionEnablePublicInterfaceResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// DisablePublicInterface disables the Load Balancer's public network interface. +func (c *LoadBalancerClient) DisablePublicInterface(ctx context.Context, loadBalancer *LoadBalancer) (*Action, *Response, error) { + path := fmt.Sprintf("/load_balancers/%d/actions/disable_public_interface", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + respBody := schema.LoadBalancerActionDisablePublicInterfaceResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// LoadBalancerChangeTypeOpts specifies options for changing a Load Balancer's type. +type LoadBalancerChangeTypeOpts struct { + LoadBalancerType *LoadBalancerType // new Load Balancer type +} + +// ChangeType changes a Load Balancer's type. +func (c *LoadBalancerClient) ChangeType(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerChangeTypeOpts) (*Action, *Response, error) { + reqBody := schema.LoadBalancerActionChangeTypeRequest{} + if opts.LoadBalancerType.ID != 0 { + reqBody.LoadBalancerType = opts.LoadBalancerType.ID + } else { + reqBody.LoadBalancerType = opts.LoadBalancerType.Name + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/load_balancers/%d/actions/change_type", loadBalancer.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.LoadBalancerActionChangeTypeResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// LoadBalancerMetricType is the type of available metrics for Load Balancers. +type LoadBalancerMetricType string + +// Available types of Load Balancer metrics. See Hetzner Cloud API +// documentation for details. +const ( + LoadBalancerMetricOpenConnections LoadBalancerMetricType = "open_connections" + LoadBalancerMetricConnectionsPerSecond LoadBalancerMetricType = "connections_per_second" + LoadBalancerMetricRequestsPerSecond LoadBalancerMetricType = "requests_per_second" + LoadBalancerMetricBandwidth LoadBalancerMetricType = "bandwidth" +) + +// LoadBalancerGetMetricsOpts configures the call to get metrics for a Load +// Balancer. +type LoadBalancerGetMetricsOpts struct { + Types []LoadBalancerMetricType + Start time.Time + End time.Time + Step int +} + +func (o *LoadBalancerGetMetricsOpts) addQueryParams(req *http.Request) error { + query := req.URL.Query() + + if len(o.Types) == 0 { + return fmt.Errorf("no metric types specified") + } + for _, typ := range o.Types { + query.Add("type", string(typ)) + } + + if o.Start.IsZero() { + return fmt.Errorf("no start time specified") + } + query.Add("start", o.Start.Format(time.RFC3339)) + + if o.End.IsZero() { + return fmt.Errorf("no end time specified") + } + query.Add("end", o.End.Format(time.RFC3339)) + + if o.Step > 0 { + query.Add("step", strconv.Itoa(o.Step)) + } + req.URL.RawQuery = query.Encode() + + return nil +} + +// LoadBalancerMetrics contains the metrics requested for a Load Balancer. +type LoadBalancerMetrics struct { + Start time.Time + End time.Time + Step float64 + TimeSeries map[string][]LoadBalancerMetricsValue +} + +// LoadBalancerMetricsValue represents a single value in a time series of metrics. +type LoadBalancerMetricsValue struct { + Timestamp float64 + Value string +} + +// GetMetrics obtains metrics for a Load Balancer. +func (c *LoadBalancerClient) GetMetrics( + ctx context.Context, lb *LoadBalancer, opts LoadBalancerGetMetricsOpts, +) (*LoadBalancerMetrics, *Response, error) { + var respBody schema.LoadBalancerGetMetricsResponse + + if lb == nil { + return nil, nil, fmt.Errorf("illegal argument: load balancer is nil") + } + + path := fmt.Sprintf("/load_balancers/%d/metrics", lb.ID) + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, fmt.Errorf("new request: %v", err) + } + if err := opts.addQueryParams(req); err != nil { + return nil, nil, fmt.Errorf("add query params: %v", err) + } + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, nil, fmt.Errorf("get metrics: %v", err) + } + ms, err := loadBalancerMetricsFromSchema(&respBody) + if err != nil { + return nil, nil, fmt.Errorf("convert response body: %v", err) + } + return ms, resp, nil +} + +// ChangeDNSPtr changes or resets the reverse DNS pointer for a Load Balancer. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (c *LoadBalancerClient) ChangeDNSPtr(ctx context.Context, lb *LoadBalancer, ip string, ptr *string) (*Action, *Response, error) { + netIP := net.ParseIP(ip) + if netIP == nil { + return nil, nil, InvalidIPError{ip} + } + return lb.changeDNSPtr(ctx, c.client, net.ParseIP(ip), ptr) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer_type.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer_type.go new file mode 100644 index 000000000..605021276 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/load_balancer_type.go @@ -0,0 +1,133 @@ +package hcloud + +import ( + "context" + "fmt" + "net/url" + "strconv" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// LoadBalancerType represents a LoadBalancer type in the Hetzner Cloud. +type LoadBalancerType struct { + ID int64 + Name string + Description string + MaxConnections int + MaxServices int + MaxTargets int + MaxAssignedCertificates int + Pricings []LoadBalancerTypeLocationPricing + Deprecated *string +} + +// LoadBalancerTypeClient is a client for the Load Balancer types API. +type LoadBalancerTypeClient struct { + client *Client +} + +// GetByID retrieves a Load Balancer type by its ID. If the Load Balancer type does not exist, nil is returned. +func (c *LoadBalancerTypeClient) GetByID(ctx context.Context, id int64) (*LoadBalancerType, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/load_balancer_types/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.LoadBalancerTypeGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return LoadBalancerTypeFromSchema(body.LoadBalancerType), resp, nil +} + +// GetByName retrieves a Load Balancer type by its name. If the Load Balancer type does not exist, nil is returned. +func (c *LoadBalancerTypeClient) GetByName(ctx context.Context, name string) (*LoadBalancerType, *Response, error) { + if name == "" { + return nil, nil, nil + } + LoadBalancerTypes, response, err := c.List(ctx, LoadBalancerTypeListOpts{Name: name}) + if len(LoadBalancerTypes) == 0 { + return nil, response, err + } + return LoadBalancerTypes[0], response, err +} + +// Get retrieves a Load Balancer type by its ID if the input can be parsed as an integer, otherwise it +// retrieves a Load Balancer type by its name. If the Load Balancer type does not exist, nil is returned. +func (c *LoadBalancerTypeClient) Get(ctx context.Context, idOrName string) (*LoadBalancerType, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// LoadBalancerTypeListOpts specifies options for listing Load Balancer types. +type LoadBalancerTypeListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l LoadBalancerTypeListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of Load Balancer types for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *LoadBalancerTypeClient) List(ctx context.Context, opts LoadBalancerTypeListOpts) ([]*LoadBalancerType, *Response, error) { + path := "/load_balancer_types?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.LoadBalancerTypeListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + LoadBalancerTypes := make([]*LoadBalancerType, 0, len(body.LoadBalancerTypes)) + for _, s := range body.LoadBalancerTypes { + LoadBalancerTypes = append(LoadBalancerTypes, LoadBalancerTypeFromSchema(s)) + } + return LoadBalancerTypes, resp, nil +} + +// All returns all Load Balancer types. +func (c *LoadBalancerTypeClient) All(ctx context.Context) ([]*LoadBalancerType, error) { + return c.AllWithOpts(ctx, LoadBalancerTypeListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all Load Balancer types for the given options. +func (c *LoadBalancerTypeClient) AllWithOpts(ctx context.Context, opts LoadBalancerTypeListOpts) ([]*LoadBalancerType, error) { + allLoadBalancerTypes := []*LoadBalancerType{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + LoadBalancerTypes, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allLoadBalancerTypes = append(allLoadBalancerTypes, LoadBalancerTypes...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allLoadBalancerTypes, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/location.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/location.go new file mode 100644 index 000000000..bd5eb7981 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/location.go @@ -0,0 +1,132 @@ +package hcloud + +import ( + "context" + "fmt" + "net/url" + "strconv" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// Location represents a location in the Hetzner Cloud. +type Location struct { + ID int64 + Name string + Description string + Country string + City string + Latitude float64 + Longitude float64 + NetworkZone NetworkZone +} + +// LocationClient is a client for the location API. +type LocationClient struct { + client *Client +} + +// GetByID retrieves a location by its ID. If the location does not exist, nil is returned. +func (c *LocationClient) GetByID(ctx context.Context, id int64) (*Location, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/locations/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.LocationGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, resp, err + } + return LocationFromSchema(body.Location), resp, nil +} + +// GetByName retrieves an location by its name. If the location does not exist, nil is returned. +func (c *LocationClient) GetByName(ctx context.Context, name string) (*Location, *Response, error) { + if name == "" { + return nil, nil, nil + } + locations, response, err := c.List(ctx, LocationListOpts{Name: name}) + if len(locations) == 0 { + return nil, response, err + } + return locations[0], response, err +} + +// Get retrieves a location by its ID if the input can be parsed as an integer, otherwise it +// retrieves a location by its name. If the location does not exist, nil is returned. +func (c *LocationClient) Get(ctx context.Context, idOrName string) (*Location, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// LocationListOpts specifies options for listing location. +type LocationListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l LocationListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of locations for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *LocationClient) List(ctx context.Context, opts LocationListOpts) ([]*Location, *Response, error) { + path := "/locations?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.LocationListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + locations := make([]*Location, 0, len(body.Locations)) + for _, i := range body.Locations { + locations = append(locations, LocationFromSchema(i)) + } + return locations, resp, nil +} + +// All returns all locations. +func (c *LocationClient) All(ctx context.Context) ([]*Location, error) { + return c.AllWithOpts(ctx, LocationListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all locations for the given options. +func (c *LocationClient) AllWithOpts(ctx context.Context, opts LocationListOpts) ([]*Location, error) { + allLocations := []*Location{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + locations, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allLocations = append(allLocations, locations...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allLocations, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go new file mode 100644 index 000000000..2688c93c4 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/network.go @@ -0,0 +1,484 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// NetworkZone specifies a network zone. +type NetworkZone string + +// List of available Network Zones. +const ( + NetworkZoneEUCentral NetworkZone = "eu-central" + NetworkZoneUSEast NetworkZone = "us-east" + NetworkZoneUSWest NetworkZone = "us-west" +) + +// NetworkSubnetType specifies a type of a subnet. +type NetworkSubnetType string + +// List of available network subnet types. +const ( + NetworkSubnetTypeCloud NetworkSubnetType = "cloud" + NetworkSubnetTypeServer NetworkSubnetType = "server" + NetworkSubnetTypeVSwitch NetworkSubnetType = "vswitch" +) + +// Network represents a network in the Hetzner Cloud. +type Network struct { + ID int64 + Name string + Created time.Time + IPRange *net.IPNet + Subnets []NetworkSubnet + Routes []NetworkRoute + Servers []*Server + Protection NetworkProtection + Labels map[string]string + + // ExposeRoutesToVSwitch indicates if the routes from this network should be exposed to the vSwitch connection. + ExposeRoutesToVSwitch bool +} + +// NetworkSubnet represents a subnet of a network in the Hetzner Cloud. +type NetworkSubnet struct { + Type NetworkSubnetType + IPRange *net.IPNet + NetworkZone NetworkZone + Gateway net.IP + VSwitchID int64 +} + +// NetworkRoute represents a route of a network. +type NetworkRoute struct { + Destination *net.IPNet + Gateway net.IP +} + +// NetworkProtection represents the protection level of a network. +type NetworkProtection struct { + Delete bool +} + +// NetworkClient is a client for the network API. +type NetworkClient struct { + client *Client + Action *ResourceActionClient +} + +// GetByID retrieves a network by its ID. If the network does not exist, nil is returned. +func (c *NetworkClient) GetByID(ctx context.Context, id int64) (*Network, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/networks/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.NetworkGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return NetworkFromSchema(body.Network), resp, nil +} + +// GetByName retrieves a network by its name. If the network does not exist, nil is returned. +func (c *NetworkClient) GetByName(ctx context.Context, name string) (*Network, *Response, error) { + if name == "" { + return nil, nil, nil + } + Networks, response, err := c.List(ctx, NetworkListOpts{Name: name}) + if len(Networks) == 0 { + return nil, response, err + } + return Networks[0], response, err +} + +// Get retrieves a network by its ID if the input can be parsed as an integer, otherwise it +// retrieves a network by its name. If the network does not exist, nil is returned. +func (c *NetworkClient) Get(ctx context.Context, idOrName string) (*Network, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// NetworkListOpts specifies options for listing networks. +type NetworkListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l NetworkListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of networks for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *NetworkClient) List(ctx context.Context, opts NetworkListOpts) ([]*Network, *Response, error) { + path := "/networks?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.NetworkListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + Networks := make([]*Network, 0, len(body.Networks)) + for _, s := range body.Networks { + Networks = append(Networks, NetworkFromSchema(s)) + } + return Networks, resp, nil +} + +// All returns all networks. +func (c *NetworkClient) All(ctx context.Context) ([]*Network, error) { + return c.AllWithOpts(ctx, NetworkListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all networks for the given options. +func (c *NetworkClient) AllWithOpts(ctx context.Context, opts NetworkListOpts) ([]*Network, error) { + allNetworks := []*Network{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + Networks, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allNetworks = append(allNetworks, Networks...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allNetworks, nil +} + +// Delete deletes a network. +func (c *NetworkClient) Delete(ctx context.Context, network *Network) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/networks/%d", network.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +// NetworkUpdateOpts specifies options for updating a network. +type NetworkUpdateOpts struct { + Name string + Labels map[string]string + // ExposeRoutesToVSwitch indicates if the routes from this network should be exposed to the vSwitch connection. + // The exposing only takes effect if a vSwitch connection is active. + ExposeRoutesToVSwitch *bool +} + +// Update updates a network. +func (c *NetworkClient) Update(ctx context.Context, network *Network, opts NetworkUpdateOpts) (*Network, *Response, error) { + reqBody := schema.NetworkUpdateRequest{ + Name: opts.Name, + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + if opts.ExposeRoutesToVSwitch != nil { + reqBody.ExposeRoutesToVSwitch = opts.ExposeRoutesToVSwitch + } + + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/networks/%d", network.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return NetworkFromSchema(respBody.Network), resp, nil +} + +// NetworkCreateOpts specifies options for creating a new network. +type NetworkCreateOpts struct { + Name string + IPRange *net.IPNet + Subnets []NetworkSubnet + Routes []NetworkRoute + Labels map[string]string + // ExposeRoutesToVSwitch indicates if the routes from this network should be exposed to the vSwitch connection. + // The exposing only takes effect if a vSwitch connection is active. + ExposeRoutesToVSwitch bool +} + +// Validate checks if options are valid. +func (o NetworkCreateOpts) Validate() error { + if o.Name == "" { + return errors.New("missing name") + } + if o.IPRange == nil || o.IPRange.String() == "" { + return errors.New("missing IP range") + } + return nil +} + +// Create creates a new network. +func (c *NetworkClient) Create(ctx context.Context, opts NetworkCreateOpts) (*Network, *Response, error) { + if err := opts.Validate(); err != nil { + return nil, nil, err + } + reqBody := schema.NetworkCreateRequest{ + Name: opts.Name, + IPRange: opts.IPRange.String(), + ExposeRoutesToVSwitch: opts.ExposeRoutesToVSwitch, + } + for _, subnet := range opts.Subnets { + s := schema.NetworkSubnet{ + Type: string(subnet.Type), + IPRange: subnet.IPRange.String(), + NetworkZone: string(subnet.NetworkZone), + } + if subnet.VSwitchID != 0 { + s.VSwitchID = subnet.VSwitchID + } + reqBody.Subnets = append(reqBody.Subnets, s) + } + for _, route := range opts.Routes { + reqBody.Routes = append(reqBody.Routes, schema.NetworkRoute{ + Destination: route.Destination.String(), + Gateway: route.Gateway.String(), + }) + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + req, err := c.client.NewRequest(ctx, "POST", "/networks", bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkCreateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return NetworkFromSchema(respBody.Network), resp, nil +} + +// NetworkChangeIPRangeOpts specifies options for changing the IP range of a network. +type NetworkChangeIPRangeOpts struct { + IPRange *net.IPNet +} + +// ChangeIPRange changes the IP range of a network. +func (c *NetworkClient) ChangeIPRange(ctx context.Context, network *Network, opts NetworkChangeIPRangeOpts) (*Action, *Response, error) { + reqBody := schema.NetworkActionChangeIPRangeRequest{ + IPRange: opts.IPRange.String(), + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/networks/%d/actions/change_ip_range", network.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkActionChangeIPRangeResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// NetworkAddSubnetOpts specifies options for adding a subnet to a network. +type NetworkAddSubnetOpts struct { + Subnet NetworkSubnet +} + +// AddSubnet adds a subnet to a network. +func (c *NetworkClient) AddSubnet(ctx context.Context, network *Network, opts NetworkAddSubnetOpts) (*Action, *Response, error) { + reqBody := schema.NetworkActionAddSubnetRequest{ + Type: string(opts.Subnet.Type), + NetworkZone: string(opts.Subnet.NetworkZone), + } + if opts.Subnet.IPRange != nil { + reqBody.IPRange = opts.Subnet.IPRange.String() + } + if opts.Subnet.VSwitchID != 0 { + reqBody.VSwitchID = opts.Subnet.VSwitchID + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/networks/%d/actions/add_subnet", network.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkActionAddSubnetResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// NetworkDeleteSubnetOpts specifies options for deleting a subnet from a network. +type NetworkDeleteSubnetOpts struct { + Subnet NetworkSubnet +} + +// DeleteSubnet deletes a subnet from a network. +func (c *NetworkClient) DeleteSubnet(ctx context.Context, network *Network, opts NetworkDeleteSubnetOpts) (*Action, *Response, error) { + reqBody := schema.NetworkActionDeleteSubnetRequest{ + IPRange: opts.Subnet.IPRange.String(), + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/networks/%d/actions/delete_subnet", network.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkActionDeleteSubnetResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// NetworkAddRouteOpts specifies options for adding a route to a network. +type NetworkAddRouteOpts struct { + Route NetworkRoute +} + +// AddRoute adds a route to a network. +func (c *NetworkClient) AddRoute(ctx context.Context, network *Network, opts NetworkAddRouteOpts) (*Action, *Response, error) { + reqBody := schema.NetworkActionAddRouteRequest{ + Destination: opts.Route.Destination.String(), + Gateway: opts.Route.Gateway.String(), + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/networks/%d/actions/add_route", network.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkActionAddSubnetResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// NetworkDeleteRouteOpts specifies options for deleting a route from a network. +type NetworkDeleteRouteOpts struct { + Route NetworkRoute +} + +// DeleteRoute deletes a route from a network. +func (c *NetworkClient) DeleteRoute(ctx context.Context, network *Network, opts NetworkDeleteRouteOpts) (*Action, *Response, error) { + reqBody := schema.NetworkActionDeleteRouteRequest{ + Destination: opts.Route.Destination.String(), + Gateway: opts.Route.Gateway.String(), + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/networks/%d/actions/delete_route", network.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkActionDeleteSubnetResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// NetworkChangeProtectionOpts specifies options for changing the resource protection level of a network. +type NetworkChangeProtectionOpts struct { + Delete *bool +} + +// ChangeProtection changes the resource protection level of a network. +func (c *NetworkClient) ChangeProtection(ctx context.Context, network *Network, opts NetworkChangeProtectionOpts) (*Action, *Response, error) { + reqBody := schema.NetworkActionChangeProtectionRequest{ + Delete: opts.Delete, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/networks/%d/actions/change_protection", network.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.NetworkActionChangeProtectionResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/placement_group.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/placement_group.go new file mode 100644 index 000000000..5ad3515e0 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/placement_group.go @@ -0,0 +1,247 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// PlacementGroup represents a Placement Group in the Hetzner Cloud. +type PlacementGroup struct { + ID int64 + Name string + Labels map[string]string + Created time.Time + Servers []int64 + Type PlacementGroupType +} + +// PlacementGroupType specifies the type of a Placement Group. +type PlacementGroupType string + +const ( + // PlacementGroupTypeSpread spreads all servers in the group on different vhosts. + PlacementGroupTypeSpread PlacementGroupType = "spread" +) + +// PlacementGroupClient is a client for the Placement Groups API. +type PlacementGroupClient struct { + client *Client +} + +// GetByID retrieves a PlacementGroup by its ID. If the PlacementGroup does not exist, nil is returned. +func (c *PlacementGroupClient) GetByID(ctx context.Context, id int64) (*PlacementGroup, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/placement_groups/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.PlacementGroupGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return PlacementGroupFromSchema(body.PlacementGroup), resp, nil +} + +// GetByName retrieves a PlacementGroup by its name. If the PlacementGroup does not exist, nil is returned. +func (c *PlacementGroupClient) GetByName(ctx context.Context, name string) (*PlacementGroup, *Response, error) { + if name == "" { + return nil, nil, nil + } + placementGroups, response, err := c.List(ctx, PlacementGroupListOpts{Name: name}) + if len(placementGroups) == 0 { + return nil, response, err + } + return placementGroups[0], response, err +} + +// Get retrieves a PlacementGroup by its ID if the input can be parsed as an integer, otherwise it +// retrieves a PlacementGroup by its name. If the PlacementGroup does not exist, nil is returned. +func (c *PlacementGroupClient) Get(ctx context.Context, idOrName string) (*PlacementGroup, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// PlacementGroupListOpts specifies options for listing PlacementGroup. +type PlacementGroupListOpts struct { + ListOpts + Name string + Type PlacementGroupType + Sort []string +} + +func (l PlacementGroupListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + if l.Type != "" { + vals.Add("type", string(l.Type)) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of PlacementGroups for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *PlacementGroupClient) List(ctx context.Context, opts PlacementGroupListOpts) ([]*PlacementGroup, *Response, error) { + path := "/placement_groups?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.PlacementGroupListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + placementGroups := make([]*PlacementGroup, 0, len(body.PlacementGroups)) + for _, g := range body.PlacementGroups { + placementGroups = append(placementGroups, PlacementGroupFromSchema(g)) + } + return placementGroups, resp, nil +} + +// All returns all PlacementGroups. +func (c *PlacementGroupClient) All(ctx context.Context) ([]*PlacementGroup, error) { + opts := PlacementGroupListOpts{ + ListOpts: ListOpts{ + PerPage: 50, + }, + } + + return c.AllWithOpts(ctx, opts) +} + +// AllWithOpts returns all PlacementGroups for the given options. +func (c *PlacementGroupClient) AllWithOpts(ctx context.Context, opts PlacementGroupListOpts) ([]*PlacementGroup, error) { + allPlacementGroups := []*PlacementGroup{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + placementGroups, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allPlacementGroups = append(allPlacementGroups, placementGroups...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allPlacementGroups, nil +} + +// PlacementGroupCreateOpts specifies options for creating a new PlacementGroup. +type PlacementGroupCreateOpts struct { + Name string + Labels map[string]string + Type PlacementGroupType +} + +// Validate checks if options are valid. +func (o PlacementGroupCreateOpts) Validate() error { + if o.Name == "" { + return errors.New("missing name") + } + return nil +} + +// PlacementGroupCreateResult is the result of a create PlacementGroup call. +type PlacementGroupCreateResult struct { + PlacementGroup *PlacementGroup + Action *Action +} + +// Create creates a new PlacementGroup. +func (c *PlacementGroupClient) Create(ctx context.Context, opts PlacementGroupCreateOpts) (PlacementGroupCreateResult, *Response, error) { + if err := opts.Validate(); err != nil { + return PlacementGroupCreateResult{}, nil, err + } + reqBody := placementGroupCreateOptsToSchema(opts) + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return PlacementGroupCreateResult{}, nil, err + } + req, err := c.client.NewRequest(ctx, "POST", "/placement_groups", bytes.NewReader(reqBodyData)) + if err != nil { + return PlacementGroupCreateResult{}, nil, err + } + + respBody := schema.PlacementGroupCreateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return PlacementGroupCreateResult{}, nil, err + } + result := PlacementGroupCreateResult{ + PlacementGroup: PlacementGroupFromSchema(respBody.PlacementGroup), + } + if respBody.Action != nil { + result.Action = ActionFromSchema(*respBody.Action) + } + + return result, resp, nil +} + +// PlacementGroupUpdateOpts specifies options for updating a PlacementGroup. +type PlacementGroupUpdateOpts struct { + Name string + Labels map[string]string +} + +// Update updates a PlacementGroup. +func (c *PlacementGroupClient) Update(ctx context.Context, placementGroup *PlacementGroup, opts PlacementGroupUpdateOpts) (*PlacementGroup, *Response, error) { + reqBody := schema.PlacementGroupUpdateRequest{} + if opts.Name != "" { + reqBody.Name = &opts.Name + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/placement_groups/%d", placementGroup.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.PlacementGroupUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + + return PlacementGroupFromSchema(respBody.PlacementGroup), resp, nil +} + +// Delete deletes a PlacementGroup. +func (c *PlacementGroupClient) Delete(ctx context.Context, placementGroup *PlacementGroup) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/placement_groups/%d", placementGroup.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/pricing.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/pricing.go new file mode 100644 index 000000000..2a1b96b76 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/pricing.go @@ -0,0 +1,139 @@ +package hcloud + +import ( + "context" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// Pricing specifies pricing information for various resources. +type Pricing struct { + Image ImagePricing + FloatingIP FloatingIPPricing + FloatingIPs []FloatingIPTypePricing + PrimaryIPs []PrimaryIPPricing + Traffic TrafficPricing + ServerBackup ServerBackupPricing + ServerTypes []ServerTypePricing + LoadBalancerTypes []LoadBalancerTypePricing + Volume VolumePricing +} + +// Price represents a price. Net amount, gross amount, as well as VAT rate are +// specified as strings and it is the user's responsibility to convert them to +// appropriate types for calculations. +type Price struct { + Currency string + VATRate string + Net string + Gross string +} + +// PrimaryIPPrice represents a price. Net amount and gross amount are +// specified as strings and it is the user's responsibility to convert them to +// appropriate types for calculations. +type PrimaryIPPrice struct { + Net string + Gross string +} + +// ImagePricing provides pricing information for imaegs. +type ImagePricing struct { + PerGBMonth Price +} + +// FloatingIPPricing provides pricing information for Floating IPs. +type FloatingIPPricing struct { + Monthly Price +} + +// FloatingIPTypePricing provides pricing information for Floating IPs per Type. +type FloatingIPTypePricing struct { + Type FloatingIPType + Pricings []FloatingIPTypeLocationPricing +} + +// PrimaryIPTypePricing defines the schema of pricing information for a primary IP +// type at a datacenter. +type PrimaryIPTypePricing struct { + Datacenter string // Deprecated: the API does not return pricing for the individual DCs anymore + Location string + Hourly PrimaryIPPrice + Monthly PrimaryIPPrice +} + +// PrimaryIPTypePricing provides pricing information for PrimaryIPs. +type PrimaryIPPricing struct { + Type string + Pricings []PrimaryIPTypePricing +} + +// FloatingIPTypeLocationPricing provides pricing information for a Floating IP type +// at a location. +type FloatingIPTypeLocationPricing struct { + Location *Location + Monthly Price +} + +// TrafficPricing provides pricing information for traffic. +type TrafficPricing struct { + PerTB Price +} + +// VolumePricing provides pricing information for a Volume. +type VolumePricing struct { + PerGBMonthly Price +} + +// ServerBackupPricing provides pricing information for server backups. +type ServerBackupPricing struct { + Percentage string +} + +// ServerTypePricing provides pricing information for a server type. +type ServerTypePricing struct { + ServerType *ServerType + Pricings []ServerTypeLocationPricing +} + +// ServerTypeLocationPricing provides pricing information for a server type +// at a location. +type ServerTypeLocationPricing struct { + Location *Location + Hourly Price + Monthly Price +} + +// LoadBalancerTypePricing provides pricing information for a Load Balancer type. +type LoadBalancerTypePricing struct { + LoadBalancerType *LoadBalancerType + Pricings []LoadBalancerTypeLocationPricing +} + +// LoadBalancerTypeLocationPricing provides pricing information for a Load Balancer type +// at a location. +type LoadBalancerTypeLocationPricing struct { + Location *Location + Hourly Price + Monthly Price +} + +// PricingClient is a client for the pricing API. +type PricingClient struct { + client *Client +} + +// Get retrieves pricing information. +func (c *PricingClient) Get(ctx context.Context) (Pricing, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", "/pricing", nil) + if err != nil { + return Pricing{}, nil, err + } + + var body schema.PricingGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return Pricing{}, nil, err + } + return PricingFromSchema(body.Pricing), resp, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go new file mode 100644 index 000000000..5d241e6d4 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/primary_ip.go @@ -0,0 +1,422 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// PrimaryIP defines a Primary IP. +type PrimaryIP struct { + ID int64 + IP net.IP + Network *net.IPNet + Labels map[string]string + Name string + Type PrimaryIPType + Protection PrimaryIPProtection + DNSPtr map[string]string + AssigneeID int64 + AssigneeType string + AutoDelete bool + Blocked bool + Created time.Time + Datacenter *Datacenter +} + +// PrimaryIPProtection represents the protection level of a Primary IP. +type PrimaryIPProtection struct { + Delete bool +} + +// PrimaryIPDNSPTR contains reverse DNS information for a +// IPv4 or IPv6 Primary IP. +type PrimaryIPDNSPTR struct { + DNSPtr string + IP string +} + +// changeDNSPtr changes or resets the reverse DNS pointer for a IP address. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (p *PrimaryIP) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { + reqBody := schema.PrimaryIPActionChangeDNSPtrRequest{ + IP: ip.String(), + DNSPtr: ptr, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/primary_ips/%d/actions/change_dns_ptr", p.ID) + req, err := client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody PrimaryIPChangeDNSPtrResult + resp, err := client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// GetDNSPtrForIP searches for the dns assigned to the given IP address. +// It returns an error if there is no dns set for the given IP address. +func (p *PrimaryIP) GetDNSPtrForIP(ip net.IP) (string, error) { + dns, ok := p.DNSPtr[ip.String()] + if !ok { + return "", DNSNotFoundError{ip} + } + + return dns, nil +} + +// PrimaryIPType represents the type of Primary IP. +type PrimaryIPType string + +// PrimaryIPType Primary IP types. +const ( + PrimaryIPTypeIPv4 PrimaryIPType = "ipv4" + PrimaryIPTypeIPv6 PrimaryIPType = "ipv6" +) + +// PrimaryIPCreateOpts defines the request to +// create a Primary IP. +type PrimaryIPCreateOpts struct { + AssigneeID *int64 `json:"assignee_id,omitempty"` + AssigneeType string `json:"assignee_type"` + AutoDelete *bool `json:"auto_delete,omitempty"` + Datacenter string `json:"datacenter,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Name string `json:"name"` + Type PrimaryIPType `json:"type"` +} + +// PrimaryIPCreateResult defines the response +// when creating a Primary IP. +type PrimaryIPCreateResult struct { + PrimaryIP *PrimaryIP + Action *Action +} + +// PrimaryIPUpdateOpts defines the request to +// update a Primary IP. +type PrimaryIPUpdateOpts struct { + AutoDelete *bool `json:"auto_delete,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` + Name string `json:"name,omitempty"` +} + +// PrimaryIPAssignOpts defines the request to +// assign a Primary IP to an assignee (usually a server). +type PrimaryIPAssignOpts struct { + ID int64 + AssigneeID int64 `json:"assignee_id"` + AssigneeType string `json:"assignee_type"` +} + +// PrimaryIPAssignResult defines the response +// when assigning a Primary IP to a assignee. +type PrimaryIPAssignResult struct { + Action schema.Action `json:"action"` +} + +// PrimaryIPChangeDNSPtrOpts defines the request to +// change a DNS PTR entry from a Primary IP. +type PrimaryIPChangeDNSPtrOpts struct { + ID int64 + DNSPtr string `json:"dns_ptr"` + IP string `json:"ip"` +} + +// PrimaryIPChangeDNSPtrResult defines the response +// when assigning a Primary IP to a assignee. +type PrimaryIPChangeDNSPtrResult struct { + Action schema.Action `json:"action"` +} + +// PrimaryIPChangeProtectionOpts defines the request to +// change protection configuration of a Primary IP. +type PrimaryIPChangeProtectionOpts struct { + ID int64 + Delete bool `json:"delete"` +} + +// PrimaryIPChangeProtectionResult defines the response +// when changing a protection of a PrimaryIP. +type PrimaryIPChangeProtectionResult struct { + Action schema.Action `json:"action"` +} + +// PrimaryIPClient is a client for the Primary IP API. +type PrimaryIPClient struct { + client *Client + Action *ResourceActionClient +} + +// GetByID retrieves a Primary IP by its ID. If the Primary IP does not exist, nil is returned. +func (c *PrimaryIPClient) GetByID(ctx context.Context, id int64) (*PrimaryIP, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/primary_ips/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.PrimaryIPGetResult + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return PrimaryIPFromSchema(body.PrimaryIP), resp, nil +} + +// GetByIP retrieves a Primary IP by its IP Address. If the Primary IP does not exist, nil is returned. +func (c *PrimaryIPClient) GetByIP(ctx context.Context, ip string) (*PrimaryIP, *Response, error) { + if ip == "" { + return nil, nil, nil + } + primaryIPs, response, err := c.List(ctx, PrimaryIPListOpts{IP: ip}) + if len(primaryIPs) == 0 { + return nil, response, err + } + return primaryIPs[0], response, err +} + +// GetByName retrieves a Primary IP by its name. If the Primary IP does not exist, nil is returned. +func (c *PrimaryIPClient) GetByName(ctx context.Context, name string) (*PrimaryIP, *Response, error) { + if name == "" { + return nil, nil, nil + } + primaryIPs, response, err := c.List(ctx, PrimaryIPListOpts{Name: name}) + if len(primaryIPs) == 0 { + return nil, response, err + } + return primaryIPs[0], response, err +} + +// Get retrieves a Primary IP by its ID if the input can be parsed as an integer, otherwise it +// retrieves a Primary IP by its name. If the Primary IP does not exist, nil is returned. +func (c *PrimaryIPClient) Get(ctx context.Context, idOrName string) (*PrimaryIP, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// PrimaryIPListOpts specifies options for listing Primary IPs. +type PrimaryIPListOpts struct { + ListOpts + Name string + IP string + Sort []string +} + +func (l PrimaryIPListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + if l.IP != "" { + vals.Add("ip", l.IP) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of Primary IPs for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *PrimaryIPClient) List(ctx context.Context, opts PrimaryIPListOpts) ([]*PrimaryIP, *Response, error) { + path := "/primary_ips?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.PrimaryIPListResult + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + primaryIPs := make([]*PrimaryIP, 0, len(body.PrimaryIPs)) + for _, s := range body.PrimaryIPs { + primaryIPs = append(primaryIPs, PrimaryIPFromSchema(s)) + } + return primaryIPs, resp, nil +} + +// All returns all Primary IPs. +func (c *PrimaryIPClient) All(ctx context.Context) ([]*PrimaryIP, error) { + return c.AllWithOpts(ctx, PrimaryIPListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all Primary IPs for the given options. +func (c *PrimaryIPClient) AllWithOpts(ctx context.Context, opts PrimaryIPListOpts) ([]*PrimaryIP, error) { + allPrimaryIPs := []*PrimaryIP{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + primaryIPs, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allPrimaryIPs = append(allPrimaryIPs, primaryIPs...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allPrimaryIPs, nil +} + +// Create creates a Primary IP. +func (c *PrimaryIPClient) Create(ctx context.Context, reqBody PrimaryIPCreateOpts) (*PrimaryIPCreateResult, *Response, error) { + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return &PrimaryIPCreateResult{}, nil, err + } + + req, err := c.client.NewRequest(ctx, "POST", "/primary_ips", bytes.NewReader(reqBodyData)) + if err != nil { + return &PrimaryIPCreateResult{}, nil, err + } + + var respBody schema.PrimaryIPCreateResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return &PrimaryIPCreateResult{}, resp, err + } + var action *Action + if respBody.Action != nil { + action = ActionFromSchema(*respBody.Action) + } + primaryIP := PrimaryIPFromSchema(respBody.PrimaryIP) + return &PrimaryIPCreateResult{ + PrimaryIP: primaryIP, + Action: action, + }, resp, nil +} + +// Delete deletes a Primary IP. +func (c *PrimaryIPClient) Delete(ctx context.Context, primaryIP *PrimaryIP) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/primary_ips/%d", primaryIP.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +// Update updates a Primary IP. +func (c *PrimaryIPClient) Update(ctx context.Context, primaryIP *PrimaryIP, reqBody PrimaryIPUpdateOpts) (*PrimaryIP, *Response, error) { + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/primary_ips/%d", primaryIP.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.PrimaryIPUpdateResult + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return PrimaryIPFromSchema(respBody.PrimaryIP), resp, nil +} + +// Assign a Primary IP to a resource. +func (c *PrimaryIPClient) Assign(ctx context.Context, opts PrimaryIPAssignOpts) (*Action, *Response, error) { + reqBodyData, err := json.Marshal(opts) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/primary_ips/%d/actions/assign", opts.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody PrimaryIPAssignResult + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// Unassign a Primary IP from a resource. +func (c *PrimaryIPClient) Unassign(ctx context.Context, id int64) (*Action, *Response, error) { + path := fmt.Sprintf("/primary_ips/%d/actions/unassign", id) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader([]byte{})) + if err != nil { + return nil, nil, err + } + + var respBody PrimaryIPAssignResult + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// ChangeDNSPtr Change the reverse DNS from a Primary IP. +func (c *PrimaryIPClient) ChangeDNSPtr(ctx context.Context, opts PrimaryIPChangeDNSPtrOpts) (*Action, *Response, error) { + reqBodyData, err := json.Marshal(opts) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/primary_ips/%d/actions/change_dns_ptr", opts.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody PrimaryIPChangeDNSPtrResult + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// ChangeProtection Changes the protection configuration of a Primary IP. +func (c *PrimaryIPClient) ChangeProtection(ctx context.Context, opts PrimaryIPChangeProtectionOpts) (*Action, *Response, error) { + reqBodyData, err := json.Marshal(opts) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/primary_ips/%d/actions/change_protection", opts.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody PrimaryIPChangeProtectionResult + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/rdns.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/rdns.go new file mode 100644 index 000000000..f53c030da --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/rdns.go @@ -0,0 +1,52 @@ +package hcloud + +import ( + "context" + "fmt" + "net" +) + +// RDNSSupporter defines functions to change and lookup reverse dns entries. +// currently implemented by Server, FloatingIP, PrimaryIP and LoadBalancer. +type RDNSSupporter interface { + // changeDNSPtr changes or resets the reverse DNS pointer for a IP address. + // Pass a nil ptr to reset the reverse DNS pointer to its default value. + changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) + // GetDNSPtrForIP searches for the dns assigned to the given IP address. + // It returns an error if there is no dns set for the given IP address. + GetDNSPtrForIP(ip net.IP) (string, error) +} + +// RDNSClient simplifies the handling objects which support reverse dns entries. +type RDNSClient struct { + client *Client +} + +// ChangeDNSPtr changes or resets the reverse DNS pointer for a IP address. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (c *RDNSClient) ChangeDNSPtr(ctx context.Context, rdns RDNSSupporter, ip net.IP, ptr *string) (*Action, *Response, error) { + return rdns.changeDNSPtr(ctx, c.client, ip, ptr) +} + +// SupportsRDNS checks if the object supports reverse dns functions. +func SupportsRDNS(i interface{}) bool { + _, ok := i.(RDNSSupporter) + return ok +} + +// RDNSLookup searches for the dns assigned to the given IP address. +// It returns an error if the object does not support reverse dns or if there is no dns set for the given IP address. +func RDNSLookup(i interface{}, ip net.IP) (string, error) { + rdns, ok := i.(RDNSSupporter) + if !ok { + return "", fmt.Errorf("%+v does not support RDNS", i) + } + + return rdns.GetDNSPtrForIP(ip) +} + +// Make sure that all expected Resources actually implement the interface. +var _ RDNSSupporter = &FloatingIP{} +var _ RDNSSupporter = &PrimaryIP{} +var _ RDNSSupporter = &Server{} +var _ RDNSSupporter = &LoadBalancer{} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/resource.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/resource.go new file mode 100644 index 000000000..a74b2cf7a --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/resource.go @@ -0,0 +1,7 @@ +package hcloud + +// Resource defines the schema of a resource. +type Resource struct { + ID int64 + Type string +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema.go new file mode 100644 index 000000000..097b282ce --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema.go @@ -0,0 +1,370 @@ +package hcloud + +import ( + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// This file provides converter functions to convert models in the +// schema package to models in the hcloud package and vice versa. + +var c converter + +// ActionFromSchema converts a schema.Action to an Action. +func ActionFromSchema(s schema.Action) *Action { + return c.ActionFromSchema(s) +} + +// SchemaFromAction converts an Action to a schema.Action. +func SchemaFromAction(a *Action) schema.Action { + return c.SchemaFromAction(a) +} + +// ActionsFromSchema converts a slice of schema.Action to a slice of Action. +func ActionsFromSchema(s []schema.Action) []*Action { + return c.ActionsFromSchema(s) +} + +// SchemaFromActions converts a slice of Action to a slice of schema.Action. +func SchemaFromActions(a []*Action) []schema.Action { + return c.SchemaFromActions(a) +} + +// FloatingIPFromSchema converts a schema.FloatingIP to a FloatingIP. +func FloatingIPFromSchema(s schema.FloatingIP) *FloatingIP { + return c.FloatingIPFromSchema(s) +} + +// SchemaFromFloatingIP converts a FloatingIP to a schema.FloatingIP. +func SchemaFromFloatingIP(f *FloatingIP) schema.FloatingIP { + return c.SchemaFromFloatingIP(f) +} + +// PrimaryIPFromSchema converts a schema.PrimaryIP to a PrimaryIP. +func PrimaryIPFromSchema(s schema.PrimaryIP) *PrimaryIP { + return c.PrimaryIPFromSchema(s) +} + +// SchemaFromPrimaryIP converts a PrimaryIP to a schema.PrimaryIP. +func SchemaFromPrimaryIP(p *PrimaryIP) schema.PrimaryIP { + return c.SchemaFromPrimaryIP(p) +} + +// ISOFromSchema converts a schema.ISO to an ISO. +func ISOFromSchema(s schema.ISO) *ISO { + return c.ISOFromSchema(s) +} + +// SchemaFromISO converts an ISO to a schema.ISO. +func SchemaFromISO(i *ISO) schema.ISO { + return c.SchemaFromISO(i) +} + +// LocationFromSchema converts a schema.Location to a Location. +func LocationFromSchema(s schema.Location) *Location { + return c.LocationFromSchema(s) +} + +// SchemaFromLocation converts a Location to a schema.Location. +func SchemaFromLocation(l *Location) schema.Location { + return c.SchemaFromLocation(l) +} + +// DatacenterFromSchema converts a schema.Datacenter to a Datacenter. +func DatacenterFromSchema(s schema.Datacenter) *Datacenter { + return c.DatacenterFromSchema(s) +} + +// SchemaFromDatacenter converts a Datacenter to a schema.Datacenter. +func SchemaFromDatacenter(d *Datacenter) schema.Datacenter { + return c.SchemaFromDatacenter(d) +} + +// ServerFromSchema converts a schema.Server to a Server. +func ServerFromSchema(s schema.Server) *Server { + return c.ServerFromSchema(s) +} + +// SchemaFromServer converts a Server to a schema.Server. +func SchemaFromServer(s *Server) schema.Server { + return c.SchemaFromServer(s) +} + +// ServerPublicNetFromSchema converts a schema.ServerPublicNet to a ServerPublicNet. +func ServerPublicNetFromSchema(s schema.ServerPublicNet) ServerPublicNet { + return c.ServerPublicNetFromSchema(s) +} + +// SchemaFromServerPublicNet converts a ServerPublicNet to a schema.ServerPublicNet. +func SchemaFromServerPublicNet(s ServerPublicNet) schema.ServerPublicNet { + return c.SchemaFromServerPublicNet(s) +} + +// ServerPublicNetIPv4FromSchema converts a schema.ServerPublicNetIPv4 to +// a ServerPublicNetIPv4. +func ServerPublicNetIPv4FromSchema(s schema.ServerPublicNetIPv4) ServerPublicNetIPv4 { + return c.ServerPublicNetIPv4FromSchema(s) +} + +// SchemaFromServerPublicNetIPv4 converts a ServerPublicNetIPv4 to +// a schema.ServerPublicNetIPv4. +func SchemaFromServerPublicNetIPv4(s ServerPublicNetIPv4) schema.ServerPublicNetIPv4 { + return c.SchemaFromServerPublicNetIPv4(s) +} + +// ServerPublicNetIPv6FromSchema converts a schema.ServerPublicNetIPv6 to +// a ServerPublicNetIPv6. +func ServerPublicNetIPv6FromSchema(s schema.ServerPublicNetIPv6) ServerPublicNetIPv6 { + return c.ServerPublicNetIPv6FromSchema(s) +} + +// SchemaFromServerPublicNetIPv6 converts a ServerPublicNetIPv6 to +// a schema.ServerPublicNetIPv6. +func SchemaFromServerPublicNetIPv6(s ServerPublicNetIPv6) schema.ServerPublicNetIPv6 { + return c.SchemaFromServerPublicNetIPv6(s) +} + +// ServerPrivateNetFromSchema converts a schema.ServerPrivateNet to a ServerPrivateNet. +func ServerPrivateNetFromSchema(s schema.ServerPrivateNet) ServerPrivateNet { + return c.ServerPrivateNetFromSchema(s) +} + +// SchemaFromServerPrivateNet converts a ServerPrivateNet to a schema.ServerPrivateNet. +func SchemaFromServerPrivateNet(s ServerPrivateNet) schema.ServerPrivateNet { + return c.SchemaFromServerPrivateNet(s) +} + +// ServerTypeFromSchema converts a schema.ServerType to a ServerType. +func ServerTypeFromSchema(s schema.ServerType) *ServerType { + return c.ServerTypeFromSchema(s) +} + +// SchemaFromServerType converts a ServerType to a schema.ServerType. +func SchemaFromServerType(s *ServerType) schema.ServerType { + return c.SchemaFromServerType(s) +} + +// SSHKeyFromSchema converts a schema.SSHKey to a SSHKey. +func SSHKeyFromSchema(s schema.SSHKey) *SSHKey { + return c.SSHKeyFromSchema(s) +} + +// SchemaFromSSHKey converts a SSHKey to a schema.SSHKey. +func SchemaFromSSHKey(s *SSHKey) schema.SSHKey { + return c.SchemaFromSSHKey(s) +} + +// ImageFromSchema converts a schema.Image to an Image. +func ImageFromSchema(s schema.Image) *Image { + return c.ImageFromSchema(s) +} + +// SchemaFromImage converts an Image to a schema.Image. +func SchemaFromImage(i *Image) schema.Image { + return c.SchemaFromImage(i) +} + +// VolumeFromSchema converts a schema.Volume to a Volume. +func VolumeFromSchema(s schema.Volume) *Volume { + return c.VolumeFromSchema(s) +} + +// SchemaFromVolume converts a Volume to a schema.Volume. +func SchemaFromVolume(v *Volume) schema.Volume { + return c.SchemaFromVolume(v) +} + +// NetworkFromSchema converts a schema.Network to a Network. +func NetworkFromSchema(s schema.Network) *Network { + return c.NetworkFromSchema(s) +} + +// SchemaFromNetwork converts a Network to a schema.Network. +func SchemaFromNetwork(n *Network) schema.Network { + return c.SchemaFromNetwork(n) +} + +// NetworkSubnetFromSchema converts a schema.NetworkSubnet to a NetworkSubnet. +func NetworkSubnetFromSchema(s schema.NetworkSubnet) NetworkSubnet { + return c.NetworkSubnetFromSchema(s) +} + +// SchemaFromNetworkSubnet converts a NetworkSubnet to a schema.NetworkSubnet. +func SchemaFromNetworkSubnet(n NetworkSubnet) schema.NetworkSubnet { + return c.SchemaFromNetworkSubnet(n) +} + +// NetworkRouteFromSchema converts a schema.NetworkRoute to a NetworkRoute. +func NetworkRouteFromSchema(s schema.NetworkRoute) NetworkRoute { + return c.NetworkRouteFromSchema(s) +} + +// SchemaFromNetworkRoute converts a NetworkRoute to a schema.NetworkRoute. +func SchemaFromNetworkRoute(n NetworkRoute) schema.NetworkRoute { + return c.SchemaFromNetworkRoute(n) +} + +// LoadBalancerTypeFromSchema converts a schema.LoadBalancerType to a LoadBalancerType. +func LoadBalancerTypeFromSchema(s schema.LoadBalancerType) *LoadBalancerType { + return c.LoadBalancerTypeFromSchema(s) +} + +// SchemaFromLoadBalancerType converts a LoadBalancerType to a schema.LoadBalancerType. +func SchemaFromLoadBalancerType(l *LoadBalancerType) schema.LoadBalancerType { + return c.SchemaFromLoadBalancerType(l) +} + +// LoadBalancerFromSchema converts a schema.LoadBalancer to a LoadBalancer. +func LoadBalancerFromSchema(s schema.LoadBalancer) *LoadBalancer { + return c.LoadBalancerFromSchema(s) +} + +// SchemaFromLoadBalancer converts a LoadBalancer to a schema.LoadBalancer. +func SchemaFromLoadBalancer(l *LoadBalancer) schema.LoadBalancer { + return c.SchemaFromLoadBalancer(l) +} + +// LoadBalancerServiceFromSchema converts a schema.LoadBalancerService to a LoadBalancerService. +func LoadBalancerServiceFromSchema(s schema.LoadBalancerService) LoadBalancerService { + return c.LoadBalancerServiceFromSchema(s) +} + +// SchemaFromLoadBalancerService converts a LoadBalancerService to a schema.LoadBalancerService. +func SchemaFromLoadBalancerService(l LoadBalancerService) schema.LoadBalancerService { + return c.SchemaFromLoadBalancerService(l) +} + +// LoadBalancerServiceHealthCheckFromSchema converts a schema.LoadBalancerServiceHealthCheck to a LoadBalancerServiceHealthCheck. +func LoadBalancerServiceHealthCheckFromSchema(s *schema.LoadBalancerServiceHealthCheck) LoadBalancerServiceHealthCheck { + return c.LoadBalancerServiceHealthCheckFromSchema(s) +} + +// SchemaFromLoadBalancerServiceHealthCheck converts a LoadBalancerServiceHealthCheck to a schema.LoadBalancerServiceHealthCheck. +func SchemaFromLoadBalancerServiceHealthCheck(l LoadBalancerServiceHealthCheck) *schema.LoadBalancerServiceHealthCheck { + return c.SchemaFromLoadBalancerServiceHealthCheck(l) +} + +// LoadBalancerTargetFromSchema converts a schema.LoadBalancerTarget to a LoadBalancerTarget. +func LoadBalancerTargetFromSchema(s schema.LoadBalancerTarget) LoadBalancerTarget { + return c.LoadBalancerTargetFromSchema(s) +} + +// SchemaFromLoadBalancerTarget converts a LoadBalancerTarget to a schema.LoadBalancerTarget. +func SchemaFromLoadBalancerTarget(l LoadBalancerTarget) schema.LoadBalancerTarget { + return c.SchemaFromLoadBalancerTarget(l) +} + +// LoadBalancerTargetHealthStatusFromSchema converts a schema.LoadBalancerTarget to a LoadBalancerTarget. +func LoadBalancerTargetHealthStatusFromSchema(s schema.LoadBalancerTargetHealthStatus) LoadBalancerTargetHealthStatus { + return c.LoadBalancerTargetHealthStatusFromSchema(s) +} + +// SchemaFromLoadBalancerTargetHealthStatus converts a LoadBalancerTarget to a schema.LoadBalancerTarget. +func SchemaFromLoadBalancerTargetHealthStatus(l LoadBalancerTargetHealthStatus) schema.LoadBalancerTargetHealthStatus { + return c.SchemaFromLoadBalancerTargetHealthStatus(l) +} + +// CertificateFromSchema converts a schema.Certificate to a Certificate. +func CertificateFromSchema(s schema.Certificate) *Certificate { + return c.CertificateFromSchema(s) +} + +// SchemaFromCertificate converts a Certificate to a schema.Certificate. +func SchemaFromCertificate(ct *Certificate) schema.Certificate { + return c.SchemaFromCertificate(ct) +} + +// PaginationFromSchema converts a schema.MetaPagination to a Pagination. +func PaginationFromSchema(s schema.MetaPagination) Pagination { + return c.PaginationFromSchema(s) +} + +// SchemaFromPagination converts a Pagination to a schema.MetaPagination. +func SchemaFromPagination(p Pagination) schema.MetaPagination { + return c.SchemaFromPagination(p) +} + +// ErrorFromSchema converts a schema.Error to an Error. +func ErrorFromSchema(s schema.Error) Error { + return c.ErrorFromSchema(s) +} + +// SchemaFromError converts an Error to a schema.Error. +func SchemaFromError(e Error) schema.Error { + return c.SchemaFromError(e) +} + +// PricingFromSchema converts a schema.Pricing to a Pricing. +func PricingFromSchema(s schema.Pricing) Pricing { + return c.PricingFromSchema(s) +} + +// SchemaFromPricing converts a Pricing to a schema.Pricing. +func SchemaFromPricing(p Pricing) schema.Pricing { + return c.SchemaFromPricing(p) +} + +// FirewallFromSchema converts a schema.Firewall to a Firewall. +func FirewallFromSchema(s schema.Firewall) *Firewall { + return c.FirewallFromSchema(s) +} + +// SchemaFromFirewall converts a Firewall to a schema.Firewall. +func SchemaFromFirewall(f *Firewall) schema.Firewall { + return c.SchemaFromFirewall(f) +} + +// PlacementGroupFromSchema converts a schema.PlacementGroup to a PlacementGroup. +func PlacementGroupFromSchema(s schema.PlacementGroup) *PlacementGroup { + return c.PlacementGroupFromSchema(s) +} + +// SchemaFromPlacementGroup converts a PlacementGroup to a schema.PlacementGroup. +func SchemaFromPlacementGroup(p *PlacementGroup) schema.PlacementGroup { + return c.SchemaFromPlacementGroup(p) +} + +// DeprecationFromSchema converts a [schema.DeprecationInfo] to a [DeprecationInfo]. +func DeprecationFromSchema(s *schema.DeprecationInfo) *DeprecationInfo { + return c.DeprecationFromSchema(s) +} + +// SchemaFromDeprecation converts a [DeprecationInfo] to a [schema.DeprecationInfo]. +func SchemaFromDeprecation(d *DeprecationInfo) *schema.DeprecationInfo { + return c.SchemaFromDeprecation(d) +} + +func placementGroupCreateOptsToSchema(opts PlacementGroupCreateOpts) schema.PlacementGroupCreateRequest { + return c.SchemaFromPlacementGroupCreateOpts(opts) +} + +func loadBalancerCreateOptsToSchema(opts LoadBalancerCreateOpts) schema.LoadBalancerCreateRequest { + return c.SchemaFromLoadBalancerCreateOpts(opts) +} + +func loadBalancerAddServiceOptsToSchema(opts LoadBalancerAddServiceOpts) schema.LoadBalancerActionAddServiceRequest { + return c.SchemaFromLoadBalancerAddServiceOpts(opts) +} + +func loadBalancerUpdateServiceOptsToSchema(opts LoadBalancerUpdateServiceOpts) schema.LoadBalancerActionUpdateServiceRequest { + return c.SchemaFromLoadBalancerUpdateServiceOpts(opts) +} + +func firewallCreateOptsToSchema(opts FirewallCreateOpts) schema.FirewallCreateRequest { + return c.SchemaFromFirewallCreateOpts(opts) +} + +func firewallSetRulesOptsToSchema(opts FirewallSetRulesOpts) schema.FirewallActionSetRulesRequest { + return c.SchemaFromFirewallSetRulesOpts(opts) +} + +func firewallResourceToSchema(resource FirewallResource) schema.FirewallResource { + return c.SchemaFromFirewallResource(resource) +} + +func serverMetricsFromSchema(s *schema.ServerGetMetricsResponse) (*ServerMetrics, error) { + return c.ServerMetricsFromSchema(s) +} + +func loadBalancerMetricsFromSchema(s *schema.LoadBalancerGetMetricsResponse) (*LoadBalancerMetrics, error) { + return c.LoadBalancerMetricsFromSchema(s) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/action.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/action.go new file mode 100644 index 000000000..49ac96a22 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/action.go @@ -0,0 +1,39 @@ +package schema + +import "time" + +// Action defines the schema of an action. +type Action struct { + ID int64 `json:"id"` + Status string `json:"status"` + Command string `json:"command"` + Progress int `json:"progress"` + Started time.Time `json:"started"` + Finished *time.Time `json:"finished"` + Error *ActionError `json:"error"` + Resources []ActionResourceReference `json:"resources"` +} + +// ActionResourceReference defines the schema of an action resource reference. +type ActionResourceReference struct { + ID int64 `json:"id"` + Type string `json:"type"` +} + +// ActionError defines the schema of an error embedded +// in an action. +type ActionError struct { + Code string `json:"code"` + Message string `json:"message"` +} + +// ActionGetResponse is the schema of the response when +// retrieving a single action. +type ActionGetResponse struct { + Action Action `json:"action"` +} + +// ActionListResponse defines the schema of the response when listing actions. +type ActionListResponse struct { + Actions []Action `json:"actions"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/certificate.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/certificate.go new file mode 100644 index 000000000..eb7b03ce2 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/certificate.go @@ -0,0 +1,76 @@ +package schema + +import "time" + +// CertificateUsedByRef defines the schema of a resource using a certificate. +type CertificateUsedByRef struct { + ID int64 `json:"id"` + Type string `json:"type"` +} + +type CertificateStatusRef struct { + Issuance string `json:"issuance"` + Renewal string `json:"renewal"` + Error *Error `json:"error,omitempty"` +} + +// Certificate defines the schema of an certificate. +type Certificate struct { + ID int64 `json:"id"` + Name string `json:"name"` + Labels map[string]string `json:"labels"` + Type string `json:"type"` + Certificate string `json:"certificate"` + Created time.Time `json:"created"` + NotValidBefore time.Time `json:"not_valid_before"` + NotValidAfter time.Time `json:"not_valid_after"` + DomainNames []string `json:"domain_names"` + Fingerprint string `json:"fingerprint"` + Status *CertificateStatusRef `json:"status"` + UsedBy []CertificateUsedByRef `json:"used_by"` +} + +// CertificateListResponse defines the schema of the response when +// listing Certificates. +type CertificateListResponse struct { + Certificates []Certificate `json:"certificates"` +} + +// CertificateGetResponse defines the schema of the response when +// retrieving a single Certificate. +type CertificateGetResponse struct { + Certificate Certificate `json:"certificate"` +} + +// CertificateCreateRequest defines the schema of the request to create a certificate. +type CertificateCreateRequest struct { + Name string `json:"name"` + Type string `json:"type"` + DomainNames []string `json:"domain_names,omitempty"` + Certificate string `json:"certificate,omitempty"` + PrivateKey string `json:"private_key,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// CertificateCreateResponse defines the schema of the response when creating a certificate. +type CertificateCreateResponse struct { + Certificate Certificate `json:"certificate"` + Action *Action `json:"action"` +} + +// CertificateUpdateRequest defines the schema of the request to update a certificate. +type CertificateUpdateRequest struct { + Name *string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// CertificateUpdateResponse defines the schema of the response when updating a certificate. +type CertificateUpdateResponse struct { + Certificate Certificate `json:"certificate"` +} + +// CertificateIssuanceRetryResponse defines the schema for the response of the +// retry issuance endpoint. +type CertificateIssuanceRetryResponse struct { + Action Action `json:"action"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/datacenter.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/datacenter.go new file mode 100644 index 000000000..54590d2a2 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/datacenter.go @@ -0,0 +1,27 @@ +package schema + +// Datacenter defines the schema of a datacenter. +type Datacenter struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Location Location `json:"location"` + ServerTypes DatacenterServerTypes `json:"server_types"` +} + +// DatacenterServerTypes defines the schema of the server types available in a datacenter. +type DatacenterServerTypes struct { + Supported []int64 `json:"supported"` + AvailableForMigration []int64 `json:"available_for_migration"` + Available []int64 `json:"available"` +} + +// DatacenterGetResponse defines the schema of the response when retrieving a single datacenter. +type DatacenterGetResponse struct { + Datacenter Datacenter `json:"datacenter"` +} + +// DatacenterListResponse defines the schema of the response when listing datacenters. +type DatacenterListResponse struct { + Datacenters []Datacenter `json:"datacenters"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/deprecation.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/deprecation.go new file mode 100644 index 000000000..87292f78b --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/deprecation.go @@ -0,0 +1,12 @@ +package schema + +import "time" + +type DeprecationInfo struct { + Announced time.Time `json:"announced"` + UnavailableAfter time.Time `json:"unavailable_after"` +} + +type DeprecatableResource struct { + Deprecation *DeprecationInfo `json:"deprecation"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/error.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/error.go new file mode 100644 index 000000000..2d5cf5ddd --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/error.go @@ -0,0 +1,42 @@ +package schema + +import "encoding/json" + +// Error represents the schema of an error response. +type Error struct { + Code string `json:"code"` + Message string `json:"message"` + DetailsRaw json.RawMessage `json:"details"` + Details interface{} +} + +// UnmarshalJSON overrides default json unmarshalling. +func (e *Error) UnmarshalJSON(data []byte) (err error) { + type Alias Error + alias := (*Alias)(e) + if err = json.Unmarshal(data, alias); err != nil { + return + } + if e.Code == "invalid_input" { + details := ErrorDetailsInvalidInput{} + if err = json.Unmarshal(e.DetailsRaw, &details); err != nil { + return + } + alias.Details = details + } + return +} + +// ErrorResponse defines the schema of a response containing an error. +type ErrorResponse struct { + Error Error `json:"error"` +} + +// ErrorDetailsInvalidInput defines the schema of the Details field +// of an error with code 'invalid_input'. +type ErrorDetailsInvalidInput struct { + Fields []struct { + Name string `json:"name"` + Messages []string `json:"messages"` + } `json:"fields"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/firewall.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/firewall.go new file mode 100644 index 000000000..d393f1e0e --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/firewall.go @@ -0,0 +1,115 @@ +package schema + +import "time" + +// Firewall defines the schema of a Firewall. +type Firewall struct { + ID int64 `json:"id"` + Name string `json:"name"` + Labels map[string]string `json:"labels"` + Created time.Time `json:"created"` + Rules []FirewallRule `json:"rules"` + AppliedTo []FirewallResource `json:"applied_to"` +} + +// FirewallRule defines the schema of a Firewall rule in responses. +type FirewallRule struct { + Direction string `json:"direction"` + SourceIPs []string `json:"source_ips"` + DestinationIPs []string `json:"destination_ips"` + Protocol string `json:"protocol"` + Port *string `json:"port"` + Description *string `json:"description"` +} + +// FirewallRuleRequest defines the schema of a Firewall rule in requests. +type FirewallRuleRequest struct { + Direction string `json:"direction"` + SourceIPs []string `json:"source_ips,omitempty"` + DestinationIPs []string `json:"destination_ips,omitempty"` + Protocol string `json:"protocol"` + Port *string `json:"port,omitempty"` + Description *string `json:"description,omitempty"` +} + +// FirewallListResponse defines the schema of the response when listing Firewalls. +type FirewallListResponse struct { + Firewalls []Firewall `json:"firewalls"` +} + +// FirewallGetResponse defines the schema of the response when retrieving a single Firewall. +type FirewallGetResponse struct { + Firewall Firewall `json:"firewall"` +} + +// FirewallCreateRequest defines the schema of the request to create a Firewall. +type FirewallCreateRequest struct { + Name string `json:"name"` + Labels *map[string]string `json:"labels,omitempty"` + Rules []FirewallRuleRequest `json:"rules,omitempty"` + ApplyTo []FirewallResource `json:"apply_to,omitempty"` +} + +// FirewallResource defines the schema of a resource to apply the new Firewall on. +type FirewallResource struct { + Type string `json:"type"` + Server *FirewallResourceServer `json:"server,omitempty"` + LabelSelector *FirewallResourceLabelSelector `json:"label_selector,omitempty"` +} + +// FirewallResourceLabelSelector defines the schema of a LabelSelector to apply a Firewall on. +type FirewallResourceLabelSelector struct { + Selector string `json:"selector"` +} + +// FirewallResourceServer defines the schema of a Server to apply a Firewall on. +type FirewallResourceServer struct { + ID int64 `json:"id"` +} + +// FirewallCreateResponse defines the schema of the response when creating a Firewall. +type FirewallCreateResponse struct { + Firewall Firewall `json:"firewall"` + Actions []Action `json:"actions"` +} + +// FirewallUpdateRequest defines the schema of the request to update a Firewall. +type FirewallUpdateRequest struct { + Name *string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// FirewallUpdateResponse defines the schema of the response when updating a Firewall. +type FirewallUpdateResponse struct { + Firewall Firewall `json:"firewall"` +} + +// FirewallActionSetRulesRequest defines the schema of the request when setting Firewall rules. +type FirewallActionSetRulesRequest struct { + Rules []FirewallRuleRequest `json:"rules"` +} + +// FirewallActionSetRulesResponse defines the schema of the response when setting Firewall rules. +type FirewallActionSetRulesResponse struct { + Actions []Action `json:"actions"` +} + +// FirewallActionApplyToResourcesRequest defines the schema of the request when applying a Firewall on resources. +type FirewallActionApplyToResourcesRequest struct { + ApplyTo []FirewallResource `json:"apply_to"` +} + +// FirewallActionApplyToResourcesResponse defines the schema of the response when applying a Firewall on resources. +type FirewallActionApplyToResourcesResponse struct { + Actions []Action `json:"actions"` +} + +// FirewallActionRemoveFromResourcesRequest defines the schema of the request when removing a Firewall from resources. +type FirewallActionRemoveFromResourcesRequest struct { + RemoveFrom []FirewallResource `json:"remove_from"` +} + +// FirewallActionRemoveFromResourcesResponse defines the schema of the response when removing a Firewall from resources. +type FirewallActionRemoveFromResourcesResponse struct { + Actions []Action `json:"actions"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/floating_ip.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/floating_ip.go new file mode 100644 index 000000000..6256b0d96 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/floating_ip.go @@ -0,0 +1,118 @@ +package schema + +import "time" + +// FloatingIP defines the schema of a Floating IP. +type FloatingIP struct { + ID int64 `json:"id"` + Description *string `json:"description"` + Created time.Time `json:"created"` + IP string `json:"ip"` + Type string `json:"type"` + Server *int64 `json:"server"` + DNSPtr []FloatingIPDNSPtr `json:"dns_ptr"` + HomeLocation Location `json:"home_location"` + Blocked bool `json:"blocked"` + Protection FloatingIPProtection `json:"protection"` + Labels map[string]string `json:"labels"` + Name string `json:"name"` +} + +// FloatingIPProtection represents the protection level of a Floating IP. +type FloatingIPProtection struct { + Delete bool `json:"delete"` +} + +// FloatingIPDNSPtr contains reverse DNS information for a +// IPv4 or IPv6 Floating IP. +type FloatingIPDNSPtr struct { + IP string `json:"ip"` + DNSPtr string `json:"dns_ptr"` +} + +// FloatingIPGetResponse defines the schema of the response when +// retrieving a single Floating IP. +type FloatingIPGetResponse struct { + FloatingIP FloatingIP `json:"floating_ip"` +} + +// FloatingIPUpdateRequest defines the schema of the request to update a Floating IP. +type FloatingIPUpdateRequest struct { + Description string `json:"description,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` + Name string `json:"name,omitempty"` +} + +// FloatingIPUpdateResponse defines the schema of the response when updating a Floating IP. +type FloatingIPUpdateResponse struct { + FloatingIP FloatingIP `json:"floating_ip"` +} + +// FloatingIPListResponse defines the schema of the response when +// listing Floating IPs. +type FloatingIPListResponse struct { + FloatingIPs []FloatingIP `json:"floating_ips"` +} + +// FloatingIPCreateRequest defines the schema of the request to +// create a Floating IP. +type FloatingIPCreateRequest struct { + Type string `json:"type"` + HomeLocation *string `json:"home_location,omitempty"` + Server *int64 `json:"server,omitempty"` + Description *string `json:"description,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` + Name *string `json:"name,omitempty"` +} + +// FloatingIPCreateResponse defines the schema of the response +// when creating a Floating IP. +type FloatingIPCreateResponse struct { + FloatingIP FloatingIP `json:"floating_ip"` + Action *Action `json:"action"` +} + +// FloatingIPActionAssignRequest defines the schema of the request to +// create an assign Floating IP action. +type FloatingIPActionAssignRequest struct { + Server int64 `json:"server"` +} + +// FloatingIPActionAssignResponse defines the schema of the response when +// creating an assign action. +type FloatingIPActionAssignResponse struct { + Action Action `json:"action"` +} + +// FloatingIPActionUnassignRequest defines the schema of the request to +// create an unassign Floating IP action. +type FloatingIPActionUnassignRequest struct{} + +// FloatingIPActionUnassignResponse defines the schema of the response when +// creating an unassign action. +type FloatingIPActionUnassignResponse struct { + Action Action `json:"action"` +} + +// FloatingIPActionChangeDNSPtrRequest defines the schema for the request to +// change a Floating IP's reverse DNS pointer. +type FloatingIPActionChangeDNSPtrRequest struct { + IP string `json:"ip"` + DNSPtr *string `json:"dns_ptr"` +} + +// FloatingIPActionChangeDNSPtrResponse defines the schema of the response when +// creating a change_dns_ptr Floating IP action. +type FloatingIPActionChangeDNSPtrResponse struct { + Action Action `json:"action"` +} + +// FloatingIPActionChangeProtectionRequest defines the schema of the request to change the resource protection of a Floating IP. +type FloatingIPActionChangeProtectionRequest struct { + Delete *bool `json:"delete,omitempty"` +} + +// FloatingIPActionChangeProtectionResponse defines the schema of the response when changing the resource protection of a Floating IP. +type FloatingIPActionChangeProtectionResponse struct { + Action Action `json:"action"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/image.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/image.go new file mode 100644 index 000000000..eacc20f89 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/image.go @@ -0,0 +1,70 @@ +package schema + +import "time" + +// Image defines the schema of an image. +type Image struct { + ID int64 `json:"id"` + Status string `json:"status"` + Type string `json:"type"` + Name *string `json:"name"` + Description string `json:"description"` + ImageSize *float32 `json:"image_size"` + DiskSize float32 `json:"disk_size"` + Created *time.Time `json:"created"` + CreatedFrom *ImageCreatedFrom `json:"created_from"` + BoundTo *int64 `json:"bound_to"` + OSFlavor string `json:"os_flavor"` + OSVersion *string `json:"os_version"` + Architecture string `json:"architecture"` + RapidDeploy bool `json:"rapid_deploy"` + Protection ImageProtection `json:"protection"` + Deprecated *time.Time `json:"deprecated"` + Deleted *time.Time `json:"deleted"` + Labels map[string]string `json:"labels"` +} + +// ImageProtection represents the protection level of a image. +type ImageProtection struct { + Delete bool `json:"delete"` +} + +// ImageCreatedFrom defines the schema of the images created from reference. +type ImageCreatedFrom struct { + ID int64 `json:"id"` + Name string `json:"name"` +} + +// ImageGetResponse defines the schema of the response when +// retrieving a single image. +type ImageGetResponse struct { + Image Image `json:"image"` +} + +// ImageListResponse defines the schema of the response when +// listing images. +type ImageListResponse struct { + Images []Image `json:"images"` +} + +// ImageUpdateRequest defines the schema of the request to update an image. +type ImageUpdateRequest struct { + Description *string `json:"description,omitempty"` + Type *string `json:"type,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// ImageUpdateResponse defines the schema of the response when updating an image. +type ImageUpdateResponse struct { + Image Image `json:"image"` +} + +// ImageActionChangeProtectionRequest defines the schema of the request to change the resource protection of an image. +type ImageActionChangeProtectionRequest struct { + Delete *bool `json:"delete,omitempty"` +} + +// ImageActionChangeProtectionResponse defines the schema of the response when changing the resource protection of an image. +type ImageActionChangeProtectionResponse struct { + Action Action `json:"action"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/iso.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/iso.go new file mode 100644 index 000000000..4cf48cc1a --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/iso.go @@ -0,0 +1,21 @@ +package schema + +// ISO defines the schema of an ISO image. +type ISO struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Type string `json:"type"` + Architecture *string `json:"architecture"` + DeprecatableResource +} + +// ISOGetResponse defines the schema of the response when retrieving a single ISO. +type ISOGetResponse struct { + ISO ISO `json:"iso"` +} + +// ISOListResponse defines the schema of the response when listing ISOs. +type ISOListResponse struct { + ISOs []ISO `json:"isos"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer.go new file mode 100644 index 000000000..7e1c4f5da --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer.go @@ -0,0 +1,418 @@ +package schema + +import "time" + +type LoadBalancer struct { + ID int64 `json:"id"` + Name string `json:"name"` + PublicNet LoadBalancerPublicNet `json:"public_net"` + PrivateNet []LoadBalancerPrivateNet `json:"private_net"` + Location Location `json:"location"` + LoadBalancerType LoadBalancerType `json:"load_balancer_type"` + Protection LoadBalancerProtection `json:"protection"` + Labels map[string]string `json:"labels"` + Created time.Time `json:"created"` + Services []LoadBalancerService `json:"services"` + Targets []LoadBalancerTarget `json:"targets"` + Algorithm LoadBalancerAlgorithm `json:"algorithm"` + IncludedTraffic uint64 `json:"included_traffic"` + OutgoingTraffic *uint64 `json:"outgoing_traffic"` + IngoingTraffic *uint64 `json:"ingoing_traffic"` +} + +type LoadBalancerPublicNet struct { + Enabled bool `json:"enabled"` + IPv4 LoadBalancerPublicNetIPv4 `json:"ipv4"` + IPv6 LoadBalancerPublicNetIPv6 `json:"ipv6"` +} + +type LoadBalancerPublicNetIPv4 struct { + IP string `json:"ip"` + DNSPtr string `json:"dns_ptr"` +} + +type LoadBalancerPublicNetIPv6 struct { + IP string `json:"ip"` + DNSPtr string `json:"dns_ptr"` +} + +type LoadBalancerPrivateNet struct { + Network int64 `json:"network"` + IP string `json:"ip"` +} + +type LoadBalancerAlgorithm struct { + Type string `json:"type"` +} + +type LoadBalancerProtection struct { + Delete bool `json:"delete"` +} + +type LoadBalancerService struct { + Protocol string `json:"protocol"` + ListenPort int `json:"listen_port"` + DestinationPort int `json:"destination_port"` + Proxyprotocol bool `json:"proxyprotocol"` + HTTP *LoadBalancerServiceHTTP `json:"http"` + HealthCheck *LoadBalancerServiceHealthCheck `json:"health_check"` +} + +type LoadBalancerServiceHTTP struct { + CookieName string `json:"cookie_name"` + CookieLifetime int `json:"cookie_lifetime"` + Certificates []int64 `json:"certificates"` + RedirectHTTP bool `json:"redirect_http"` + StickySessions bool `json:"sticky_sessions"` +} + +type LoadBalancerServiceHealthCheck struct { + Protocol string `json:"protocol"` + Port int `json:"port"` + Interval int `json:"interval"` + Timeout int `json:"timeout"` + Retries int `json:"retries"` + HTTP *LoadBalancerServiceHealthCheckHTTP `json:"http"` +} + +type LoadBalancerServiceHealthCheckHTTP struct { + Domain string `json:"domain"` + Path string `json:"path"` + Response string `json:"response"` + StatusCodes []string `json:"status_codes"` + TLS bool `json:"tls"` +} + +type LoadBalancerTarget struct { + Type string `json:"type"` + Server *LoadBalancerTargetServer `json:"server"` + LabelSelector *LoadBalancerTargetLabelSelector `json:"label_selector"` + IP *LoadBalancerTargetIP `json:"ip"` + HealthStatus []LoadBalancerTargetHealthStatus `json:"health_status"` + UsePrivateIP bool `json:"use_private_ip"` + Targets []LoadBalancerTarget `json:"targets,omitempty"` +} + +type LoadBalancerTargetHealthStatus struct { + ListenPort int `json:"listen_port"` + Status string `json:"status"` +} + +type LoadBalancerTargetServer struct { + ID int64 `json:"id"` +} + +type LoadBalancerTargetLabelSelector struct { + Selector string `json:"selector"` +} + +type LoadBalancerTargetIP struct { + IP string `json:"ip"` +} + +type LoadBalancerListResponse struct { + LoadBalancers []LoadBalancer `json:"load_balancers"` +} + +type LoadBalancerGetResponse struct { + LoadBalancer LoadBalancer `json:"load_balancer"` +} + +type LoadBalancerActionAddTargetRequest struct { + Type string `json:"type"` + Server *LoadBalancerActionAddTargetRequestServer `json:"server,omitempty"` + LabelSelector *LoadBalancerActionAddTargetRequestLabelSelector `json:"label_selector,omitempty"` + IP *LoadBalancerActionAddTargetRequestIP `json:"ip,omitempty"` + UsePrivateIP *bool `json:"use_private_ip,omitempty"` +} + +type LoadBalancerActionAddTargetRequestServer struct { + ID int64 `json:"id"` +} + +type LoadBalancerActionAddTargetRequestLabelSelector struct { + Selector string `json:"selector"` +} + +type LoadBalancerActionAddTargetRequestIP struct { + IP string `json:"ip"` +} + +type LoadBalancerActionAddTargetResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionRemoveTargetRequest struct { + Type string `json:"type"` + Server *LoadBalancerActionRemoveTargetRequestServer `json:"server,omitempty"` + LabelSelector *LoadBalancerActionRemoveTargetRequestLabelSelector `json:"label_selector,omitempty"` + IP *LoadBalancerActionRemoveTargetRequestIP `json:"ip,omitempty"` +} + +type LoadBalancerActionRemoveTargetRequestServer struct { + ID int64 `json:"id"` +} + +type LoadBalancerActionRemoveTargetRequestLabelSelector struct { + Selector string `json:"selector"` +} + +type LoadBalancerActionRemoveTargetRequestIP struct { + IP string `json:"ip"` +} + +type LoadBalancerActionRemoveTargetResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionAddServiceRequest struct { + Protocol string `json:"protocol"` + ListenPort *int `json:"listen_port,omitempty"` + DestinationPort *int `json:"destination_port,omitempty"` + Proxyprotocol *bool `json:"proxyprotocol,omitempty"` + HTTP *LoadBalancerActionAddServiceRequestHTTP `json:"http,omitempty"` + HealthCheck *LoadBalancerActionAddServiceRequestHealthCheck `json:"health_check,omitempty"` +} + +type LoadBalancerActionAddServiceRequestHTTP struct { + CookieName *string `json:"cookie_name,omitempty"` + CookieLifetime *int `json:"cookie_lifetime,omitempty"` + Certificates *[]int64 `json:"certificates,omitempty"` + RedirectHTTP *bool `json:"redirect_http,omitempty"` + StickySessions *bool `json:"sticky_sessions,omitempty"` +} + +type LoadBalancerActionAddServiceRequestHealthCheck struct { + Protocol string `json:"protocol"` + Port *int `json:"port,omitempty"` + Interval *int `json:"interval,omitempty"` + Timeout *int `json:"timeout,omitempty"` + Retries *int `json:"retries,omitempty"` + HTTP *LoadBalancerActionAddServiceRequestHealthCheckHTTP `json:"http,omitempty"` +} + +type LoadBalancerActionAddServiceRequestHealthCheckHTTP struct { + Domain *string `json:"domain,omitempty"` + Path *string `json:"path,omitempty"` + Response *string `json:"response,omitempty"` + StatusCodes *[]string `json:"status_codes,omitempty"` + TLS *bool `json:"tls,omitempty"` +} + +type LoadBalancerActionAddServiceResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionUpdateServiceRequest struct { + ListenPort int `json:"listen_port"` + Protocol *string `json:"protocol,omitempty"` + DestinationPort *int `json:"destination_port,omitempty"` + Proxyprotocol *bool `json:"proxyprotocol,omitempty"` + HTTP *LoadBalancerActionUpdateServiceRequestHTTP `json:"http,omitempty"` + HealthCheck *LoadBalancerActionUpdateServiceRequestHealthCheck `json:"health_check,omitempty"` +} + +type LoadBalancerActionUpdateServiceRequestHTTP struct { + CookieName *string `json:"cookie_name,omitempty"` + CookieLifetime *int `json:"cookie_lifetime,omitempty"` + Certificates *[]int64 `json:"certificates,omitempty"` + RedirectHTTP *bool `json:"redirect_http,omitempty"` + StickySessions *bool `json:"sticky_sessions,omitempty"` +} + +type LoadBalancerActionUpdateServiceRequestHealthCheck struct { + Protocol *string `json:"protocol,omitempty"` + Port *int `json:"port,omitempty"` + Interval *int `json:"interval,omitempty"` + Timeout *int `json:"timeout,omitempty"` + Retries *int `json:"retries,omitempty"` + HTTP *LoadBalancerActionUpdateServiceRequestHealthCheckHTTP `json:"http,omitempty"` +} + +type LoadBalancerActionUpdateServiceRequestHealthCheckHTTP struct { + Domain *string `json:"domain,omitempty"` + Path *string `json:"path,omitempty"` + Response *string `json:"response,omitempty"` + StatusCodes *[]string `json:"status_codes,omitempty"` + TLS *bool `json:"tls,omitempty"` +} + +type LoadBalancerActionUpdateServiceResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerDeleteServiceRequest struct { + ListenPort int `json:"listen_port"` +} + +type LoadBalancerDeleteServiceResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerCreateRequest struct { + Name string `json:"name"` + LoadBalancerType interface{} `json:"load_balancer_type"` // int or string + Algorithm *LoadBalancerCreateRequestAlgorithm `json:"algorithm,omitempty"` + Location *string `json:"location,omitempty"` + NetworkZone *string `json:"network_zone,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` + Targets []LoadBalancerCreateRequestTarget `json:"targets,omitempty"` + Services []LoadBalancerCreateRequestService `json:"services,omitempty"` + PublicInterface *bool `json:"public_interface,omitempty"` + Network *int64 `json:"network,omitempty"` +} + +type LoadBalancerCreateRequestAlgorithm struct { + Type string `json:"type"` +} + +type LoadBalancerCreateRequestTarget struct { + Type string `json:"type"` + Server *LoadBalancerCreateRequestTargetServer `json:"server,omitempty"` + LabelSelector *LoadBalancerCreateRequestTargetLabelSelector `json:"label_selector,omitempty"` + IP *LoadBalancerCreateRequestTargetIP `json:"ip,omitempty"` + UsePrivateIP *bool `json:"use_private_ip,omitempty"` +} + +type LoadBalancerCreateRequestTargetServer struct { + ID int64 `json:"id"` +} + +type LoadBalancerCreateRequestTargetLabelSelector struct { + Selector string `json:"selector"` +} + +type LoadBalancerCreateRequestTargetIP struct { + IP string `json:"ip"` +} + +type LoadBalancerCreateRequestService struct { + Protocol string `json:"protocol"` + ListenPort *int `json:"listen_port,omitempty"` + DestinationPort *int `json:"destination_port,omitempty"` + Proxyprotocol *bool `json:"proxyprotocol,omitempty"` + HTTP *LoadBalancerCreateRequestServiceHTTP `json:"http,omitempty"` + HealthCheck *LoadBalancerCreateRequestServiceHealthCheck `json:"health_check,omitempty"` +} + +type LoadBalancerCreateRequestServiceHTTP struct { + CookieName *string `json:"cookie_name,omitempty"` + CookieLifetime *int `json:"cookie_lifetime,omitempty"` + Certificates *[]int64 `json:"certificates,omitempty"` + RedirectHTTP *bool `json:"redirect_http,omitempty"` + StickySessions *bool `json:"sticky_sessions,omitempty"` +} + +type LoadBalancerCreateRequestServiceHealthCheck struct { + Protocol string `json:"protocol"` + Port *int `json:"port,omitempty"` + Interval *int `json:"interval,omitempty"` + Timeout *int `json:"timeout,omitempty"` + Retries *int `json:"retries,omitempty"` + HTTP *LoadBalancerCreateRequestServiceHealthCheckHTTP `json:"http,omitempty"` +} + +type LoadBalancerCreateRequestServiceHealthCheckHTTP struct { + Domain *string `json:"domain,omitempty"` + Path *string `json:"path,omitempty"` + Response *string `json:"response,omitempty"` + StatusCodes *[]string `json:"status_codes,omitempty"` + TLS *bool `json:"tls,omitempty"` +} + +type LoadBalancerCreateResponse struct { + LoadBalancer LoadBalancer `json:"load_balancer"` + Action Action `json:"action"` +} + +type LoadBalancerActionChangeProtectionRequest struct { + Delete *bool `json:"delete,omitempty"` +} + +type LoadBalancerActionChangeProtectionResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerUpdateRequest struct { + Name *string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +type LoadBalancerUpdateResponse struct { + LoadBalancer LoadBalancer `json:"load_balancer"` +} + +type LoadBalancerActionChangeAlgorithmRequest struct { + Type string `json:"type"` +} + +type LoadBalancerActionChangeAlgorithmResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionAttachToNetworkRequest struct { + Network int64 `json:"network"` + IP *string `json:"ip,omitempty"` +} + +type LoadBalancerActionAttachToNetworkResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionDetachFromNetworkRequest struct { + Network int64 `json:"network"` +} + +type LoadBalancerActionDetachFromNetworkResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionEnablePublicInterfaceRequest struct{} + +type LoadBalancerActionEnablePublicInterfaceResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionDisablePublicInterfaceRequest struct{} + +type LoadBalancerActionDisablePublicInterfaceResponse struct { + Action Action `json:"action"` +} + +type LoadBalancerActionChangeTypeRequest struct { + LoadBalancerType interface{} `json:"load_balancer_type"` // int or string +} + +type LoadBalancerActionChangeTypeResponse struct { + Action Action `json:"action"` +} + +// LoadBalancerGetMetricsResponse defines the schema of the response when +// requesting metrics for a Load Balancer. +type LoadBalancerGetMetricsResponse struct { + Metrics struct { + Start time.Time `json:"start"` + End time.Time `json:"end"` + Step float64 `json:"step"` + TimeSeries map[string]LoadBalancerTimeSeriesVals `json:"time_series"` + } `json:"metrics"` +} + +// LoadBalancerTimeSeriesVals contains the values for a Load Balancer time +// series. +type LoadBalancerTimeSeriesVals struct { + Values []interface{} `json:"values"` +} + +// LoadBalancerActionChangeDNSPtrRequest defines the schema for the request to +// change a Load Balancer reverse DNS pointer. +type LoadBalancerActionChangeDNSPtrRequest struct { + IP string `json:"ip"` + DNSPtr *string `json:"dns_ptr"` +} + +// LoadBalancerActionChangeDNSPtrResponse defines the schema of the response when +// creating a change_dns_ptr Floating IP action. +type LoadBalancerActionChangeDNSPtrResponse struct { + Action Action `json:"action"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer_type.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer_type.go new file mode 100644 index 000000000..b0193d3a8 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/load_balancer_type.go @@ -0,0 +1,26 @@ +package schema + +// LoadBalancerType defines the schema of a LoadBalancer type. +type LoadBalancerType struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MaxConnections int `json:"max_connections"` + MaxServices int `json:"max_services"` + MaxTargets int `json:"max_targets"` + MaxAssignedCertificates int `json:"max_assigned_certificates"` + Prices []PricingLoadBalancerTypePrice `json:"prices"` + Deprecated *string `json:"deprecated"` +} + +// LoadBalancerTypeListResponse defines the schema of the response when +// listing LoadBalancer types. +type LoadBalancerTypeListResponse struct { + LoadBalancerTypes []LoadBalancerType `json:"load_balancer_types"` +} + +// LoadBalancerTypeGetResponse defines the schema of the response when +// retrieving a single LoadBalancer type. +type LoadBalancerTypeGetResponse struct { + LoadBalancerType LoadBalancerType `json:"load_balancer_type"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/location.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/location.go new file mode 100644 index 000000000..e07306071 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/location.go @@ -0,0 +1,23 @@ +package schema + +// Location defines the schema of a location. +type Location struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Country string `json:"country"` + City string `json:"city"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + NetworkZone string `json:"network_zone"` +} + +// LocationGetResponse defines the schema of the response when retrieving a single location. +type LocationGetResponse struct { + Location Location `json:"location"` +} + +// LocationListResponse defines the schema of the response when listing locations. +type LocationListResponse struct { + Locations []Location `json:"locations"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/meta.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/meta.go new file mode 100644 index 000000000..9b06cda8c --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/meta.go @@ -0,0 +1,23 @@ +package schema + +// Meta defines the schema of meta information which may be included +// in responses. +type Meta struct { + Pagination *MetaPagination `json:"pagination"` +} + +// MetaPagination defines the schema of pagination information. +type MetaPagination struct { + Page int `json:"page"` + PerPage int `json:"per_page"` + PreviousPage int `json:"previous_page"` + NextPage int `json:"next_page"` + LastPage int `json:"last_page"` + TotalEntries int `json:"total_entries"` +} + +// MetaResponse defines the schema of a response containing +// meta information. +type MetaResponse struct { + Meta Meta `json:"meta"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/network.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/network.go new file mode 100644 index 000000000..2344aea45 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/network.go @@ -0,0 +1,155 @@ +package schema + +import "time" + +// Network defines the schema of a network. +type Network struct { + ID int64 `json:"id"` + Name string `json:"name"` + Created time.Time `json:"created"` + IPRange string `json:"ip_range"` + Subnets []NetworkSubnet `json:"subnets"` + Routes []NetworkRoute `json:"routes"` + Servers []int64 `json:"servers"` + Protection NetworkProtection `json:"protection"` + Labels map[string]string `json:"labels"` + ExposeRoutesToVSwitch bool `json:"expose_routes_to_vswitch"` +} + +// NetworkSubnet represents a subnet of a network. +type NetworkSubnet struct { + Type string `json:"type"` + IPRange string `json:"ip_range"` + NetworkZone string `json:"network_zone"` + Gateway string `json:"gateway,omitempty"` + VSwitchID int64 `json:"vswitch_id,omitempty"` +} + +// NetworkRoute represents a route of a network. +type NetworkRoute struct { + Destination string `json:"destination"` + Gateway string `json:"gateway"` +} + +// NetworkProtection represents the protection level of a network. +type NetworkProtection struct { + Delete bool `json:"delete"` +} + +// NetworkUpdateRequest defines the schema of the request to update a network. +type NetworkUpdateRequest struct { + Name string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` + ExposeRoutesToVSwitch *bool `json:"expose_routes_to_vswitch,omitempty"` +} + +// NetworkUpdateResponse defines the schema of the response when updating a network. +type NetworkUpdateResponse struct { + Network Network `json:"network"` +} + +// NetworkListResponse defines the schema of the response when +// listing networks. +type NetworkListResponse struct { + Networks []Network `json:"networks"` +} + +// NetworkGetResponse defines the schema of the response when +// retrieving a single network. +type NetworkGetResponse struct { + Network Network `json:"network"` +} + +// NetworkCreateRequest defines the schema of the request to create a network. +type NetworkCreateRequest struct { + Name string `json:"name"` + IPRange string `json:"ip_range"` + Subnets []NetworkSubnet `json:"subnets,omitempty"` + Routes []NetworkRoute `json:"routes,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` + ExposeRoutesToVSwitch bool `json:"expose_routes_to_vswitch"` +} + +// NetworkCreateResponse defines the schema of the response when +// creating a network. +type NetworkCreateResponse struct { + Network Network `json:"network"` +} + +// NetworkActionChangeIPRangeRequest defines the schema of the request to +// change the IP range of a network. +type NetworkActionChangeIPRangeRequest struct { + IPRange string `json:"ip_range"` +} + +// NetworkActionChangeIPRangeResponse defines the schema of the response when +// changing the IP range of a network. +type NetworkActionChangeIPRangeResponse struct { + Action Action `json:"action"` +} + +// NetworkActionAddSubnetRequest defines the schema of the request to +// add a subnet to a network. +type NetworkActionAddSubnetRequest struct { + Type string `json:"type"` + IPRange string `json:"ip_range,omitempty"` + NetworkZone string `json:"network_zone"` + Gateway string `json:"gateway"` + VSwitchID int64 `json:"vswitch_id,omitempty"` +} + +// NetworkActionAddSubnetResponse defines the schema of the response when +// adding a subnet to a network. +type NetworkActionAddSubnetResponse struct { + Action Action `json:"action"` +} + +// NetworkActionDeleteSubnetRequest defines the schema of the request to +// delete a subnet from a network. +type NetworkActionDeleteSubnetRequest struct { + IPRange string `json:"ip_range"` +} + +// NetworkActionDeleteSubnetResponse defines the schema of the response when +// deleting a subnet from a network. +type NetworkActionDeleteSubnetResponse struct { + Action Action `json:"action"` +} + +// NetworkActionAddRouteRequest defines the schema of the request to +// add a route to a network. +type NetworkActionAddRouteRequest struct { + Destination string `json:"destination"` + Gateway string `json:"gateway"` +} + +// NetworkActionAddRouteResponse defines the schema of the response when +// adding a route to a network. +type NetworkActionAddRouteResponse struct { + Action Action `json:"action"` +} + +// NetworkActionDeleteRouteRequest defines the schema of the request to +// delete a route from a network. +type NetworkActionDeleteRouteRequest struct { + Destination string `json:"destination"` + Gateway string `json:"gateway"` +} + +// NetworkActionDeleteRouteResponse defines the schema of the response when +// deleting a route from a network. +type NetworkActionDeleteRouteResponse struct { + Action Action `json:"action"` +} + +// NetworkActionChangeProtectionRequest defines the schema of the request to +// change the resource protection of a network. +type NetworkActionChangeProtectionRequest struct { + Delete *bool `json:"delete,omitempty"` +} + +// NetworkActionChangeProtectionResponse defines the schema of the response when +// changing the resource protection of a network. +type NetworkActionChangeProtectionResponse struct { + Action Action `json:"action"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/placement_group.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/placement_group.go new file mode 100644 index 000000000..671bd6bed --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/placement_group.go @@ -0,0 +1,40 @@ +package schema + +import "time" + +type PlacementGroup struct { + ID int64 `json:"id"` + Name string `json:"name"` + Labels map[string]string `json:"labels"` + Created time.Time `json:"created"` + Servers []int64 `json:"servers"` + Type string `json:"type"` +} + +type PlacementGroupListResponse struct { + PlacementGroups []PlacementGroup `json:"placement_groups"` +} + +type PlacementGroupGetResponse struct { + PlacementGroup PlacementGroup `json:"placement_group"` +} + +type PlacementGroupCreateRequest struct { + Name string `json:"name"` + Labels *map[string]string `json:"labels,omitempty"` + Type string `json:"type"` +} + +type PlacementGroupCreateResponse struct { + PlacementGroup PlacementGroup `json:"placement_group"` + Action *Action `json:"action"` +} + +type PlacementGroupUpdateRequest struct { + Name *string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +type PlacementGroupUpdateResponse struct { + PlacementGroup PlacementGroup `json:"placement_group"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/pricing.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/pricing.go new file mode 100644 index 000000000..192352f5d --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/pricing.go @@ -0,0 +1,110 @@ +package schema + +// Pricing defines the schema for pricing information. +type Pricing struct { + Currency string `json:"currency"` + VATRate string `json:"vat_rate"` + Image PricingImage `json:"image"` + FloatingIP PricingFloatingIP `json:"floating_ip"` + FloatingIPs []PricingFloatingIPType `json:"floating_ips"` + PrimaryIPs []PricingPrimaryIP `json:"primary_ips"` + Traffic PricingTraffic `json:"traffic"` + ServerBackup PricingServerBackup `json:"server_backup"` + ServerTypes []PricingServerType `json:"server_types"` + LoadBalancerTypes []PricingLoadBalancerType `json:"load_balancer_types"` + Volume PricingVolume `json:"volume"` +} + +// Price defines the schema of a single price with net and gross amount. +type Price struct { + Net string `json:"net"` + Gross string `json:"gross"` +} + +// PricingImage defines the schema of pricing information for an image. +type PricingImage struct { + PricePerGBMonth Price `json:"price_per_gb_month"` +} + +// PricingFloatingIP defines the schema of pricing information for a Floating IP. +type PricingFloatingIP struct { + PriceMonthly Price `json:"price_monthly"` +} + +// PricingFloatingIPType defines the schema of pricing information for a Floating IP per type. +type PricingFloatingIPType struct { + Type string `json:"type"` + Prices []PricingFloatingIPTypePrice `json:"prices"` +} + +// PricingFloatingIPTypePrice defines the schema of pricing information for a Floating IP +// type at a location. +type PricingFloatingIPTypePrice struct { + Location string `json:"location"` + PriceMonthly Price `json:"price_monthly"` +} + +// PricingTraffic defines the schema of pricing information for traffic. +type PricingTraffic struct { + PricePerTB Price `json:"price_per_tb"` +} + +// PricingVolume defines the schema of pricing information for a Volume. +type PricingVolume struct { + PricePerGBPerMonth Price `json:"price_per_gb_month"` +} + +// PricingServerBackup defines the schema of pricing information for server backups. +type PricingServerBackup struct { + Percentage string `json:"percentage"` +} + +// PricingServerType defines the schema of pricing information for a server type. +type PricingServerType struct { + ID int64 `json:"id"` + Name string `json:"name"` + Prices []PricingServerTypePrice `json:"prices"` +} + +// PricingServerTypePrice defines the schema of pricing information for a server +// type at a location. +type PricingServerTypePrice struct { + Location string `json:"location"` + PriceHourly Price `json:"price_hourly"` + PriceMonthly Price `json:"price_monthly"` +} + +// PricingLoadBalancerType defines the schema of pricing information for a Load Balancer type. +type PricingLoadBalancerType struct { + ID int64 `json:"id"` + Name string `json:"name"` + Prices []PricingLoadBalancerTypePrice `json:"prices"` +} + +// PricingLoadBalancerTypePrice defines the schema of pricing information for a Load Balancer +// type at a location. +type PricingLoadBalancerTypePrice struct { + Location string `json:"location"` + PriceHourly Price `json:"price_hourly"` + PriceMonthly Price `json:"price_monthly"` +} + +// PricingGetResponse defines the schema of the response when retrieving pricing information. +type PricingGetResponse struct { + Pricing Pricing `json:"pricing"` +} + +// PricingPrimaryIPTypePrice defines the schema of pricing information for a primary IP. +// type at a datacenter. +type PricingPrimaryIPTypePrice struct { + Datacenter string `json:"datacenter"` // Deprecated: the API does not return pricing for the individual DCs anymore + Location string `json:"location"` + PriceHourly Price `json:"price_hourly"` + PriceMonthly Price `json:"price_monthly"` +} + +// PricingPrimaryIP define the schema of pricing information for a primary IP at a datacenter. +type PricingPrimaryIP struct { + Type string `json:"type"` + Prices []PricingPrimaryIPTypePrice `json:"prices"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/primary_ip.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/primary_ip.go new file mode 100644 index 000000000..1901ce800 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/primary_ip.go @@ -0,0 +1,62 @@ +package schema + +import "time" + +// PrimaryIP defines a Primary IP. +type PrimaryIP struct { + ID int64 `json:"id"` + IP string `json:"ip"` + Labels map[string]string `json:"labels"` + Name string `json:"name"` + Type string `json:"type"` + Protection PrimaryIPProtection `json:"protection"` + DNSPtr []PrimaryIPDNSPTR `json:"dns_ptr"` + AssigneeID *int64 `json:"assignee_id"` + AssigneeType string `json:"assignee_type"` + AutoDelete bool `json:"auto_delete"` + Blocked bool `json:"blocked"` + Created time.Time `json:"created"` + Datacenter Datacenter `json:"datacenter"` +} + +// PrimaryIPProtection represents the protection level of a Primary IP. +type PrimaryIPProtection struct { + Delete bool `json:"delete"` +} + +// PrimaryIPDNSPTR contains reverse DNS information for a +// IPv4 or IPv6 Primary IP. +type PrimaryIPDNSPTR struct { + DNSPtr string `json:"dns_ptr"` + IP string `json:"ip"` +} + +// PrimaryIPCreateResponse defines the schema of the response +// when creating a Primary IP. +type PrimaryIPCreateResponse struct { + PrimaryIP PrimaryIP `json:"primary_ip"` + Action *Action `json:"action"` +} + +// PrimaryIPGetResult defines the response when retrieving a single Primary IP. +type PrimaryIPGetResult struct { + PrimaryIP PrimaryIP `json:"primary_ip"` +} + +// PrimaryIPListResult defines the response when listing Primary IPs. +type PrimaryIPListResult struct { + PrimaryIPs []PrimaryIP `json:"primary_ips"` +} + +// PrimaryIPUpdateResult defines the response +// when updating a Primary IP. +type PrimaryIPUpdateResult struct { + PrimaryIP PrimaryIP `json:"primary_ip"` +} + +// PrimaryIPActionChangeDNSPtrRequest defines the schema for the request to +// change a Primary IP's reverse DNS pointer. +type PrimaryIPActionChangeDNSPtrRequest struct { + IP string `json:"ip"` + DNSPtr *string `json:"dns_ptr"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server.go new file mode 100644 index 000000000..068b3e81f --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server.go @@ -0,0 +1,436 @@ +package schema + +import "time" + +// Server defines the schema of a server. +type Server struct { + ID int64 `json:"id"` + Name string `json:"name"` + Status string `json:"status"` + Created time.Time `json:"created"` + PublicNet ServerPublicNet `json:"public_net"` + PrivateNet []ServerPrivateNet `json:"private_net"` + ServerType ServerType `json:"server_type"` + IncludedTraffic uint64 `json:"included_traffic"` + OutgoingTraffic *uint64 `json:"outgoing_traffic"` + IngoingTraffic *uint64 `json:"ingoing_traffic"` + BackupWindow *string `json:"backup_window"` + RescueEnabled bool `json:"rescue_enabled"` + ISO *ISO `json:"iso"` + Locked bool `json:"locked"` + Datacenter Datacenter `json:"datacenter"` + Image *Image `json:"image"` + Protection ServerProtection `json:"protection"` + Labels map[string]string `json:"labels"` + Volumes []int64 `json:"volumes"` + PrimaryDiskSize int `json:"primary_disk_size"` + PlacementGroup *PlacementGroup `json:"placement_group"` + LoadBalancers []int64 `json:"load_balancers"` +} + +// ServerProtection defines the schema of a server's resource protection. +type ServerProtection struct { + Delete bool `json:"delete"` + Rebuild bool `json:"rebuild"` +} + +// ServerPublicNet defines the schema of a server's +// public network information. +type ServerPublicNet struct { + IPv4 ServerPublicNetIPv4 `json:"ipv4"` + IPv6 ServerPublicNetIPv6 `json:"ipv6"` + FloatingIPs []int64 `json:"floating_ips"` + Firewalls []ServerFirewall `json:"firewalls"` +} + +// ServerPublicNetIPv4 defines the schema of a server's public +// network information for an IPv4. +type ServerPublicNetIPv4 struct { + ID int64 `json:"id"` + IP string `json:"ip"` + Blocked bool `json:"blocked"` + DNSPtr string `json:"dns_ptr"` +} + +// ServerPublicNetIPv6 defines the schema of a server's public +// network information for an IPv6. +type ServerPublicNetIPv6 struct { + ID int64 `json:"id"` + IP string `json:"ip"` + Blocked bool `json:"blocked"` + DNSPtr []ServerPublicNetIPv6DNSPtr `json:"dns_ptr"` +} + +// ServerPublicNetIPv6DNSPtr defines the schema of a server's +// public network information for an IPv6 reverse DNS. +type ServerPublicNetIPv6DNSPtr struct { + IP string `json:"ip"` + DNSPtr string `json:"dns_ptr"` +} + +// ServerFirewall defines the schema of a Server's Firewalls on +// a certain network interface. +type ServerFirewall struct { + ID int64 `json:"id"` + Status string `json:"status"` +} + +// ServerPrivateNet defines the schema of a server's private network information. +type ServerPrivateNet struct { + Network int64 `json:"network"` + IP string `json:"ip"` + AliasIPs []string `json:"alias_ips"` + MACAddress string `json:"mac_address"` +} + +// ServerGetResponse defines the schema of the response when +// retrieving a single server. +type ServerGetResponse struct { + Server Server `json:"server"` +} + +// ServerListResponse defines the schema of the response when +// listing servers. +type ServerListResponse struct { + Servers []Server `json:"servers"` +} + +// ServerCreateRequest defines the schema for the request to +// create a server. +type ServerCreateRequest struct { + Name string `json:"name"` + ServerType interface{} `json:"server_type"` // int or string + Image interface{} `json:"image"` // int or string + SSHKeys []int64 `json:"ssh_keys,omitempty"` + Location string `json:"location,omitempty"` + Datacenter string `json:"datacenter,omitempty"` + UserData string `json:"user_data,omitempty"` + StartAfterCreate *bool `json:"start_after_create,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` + Automount *bool `json:"automount,omitempty"` + Volumes []int64 `json:"volumes,omitempty"` + Networks []int64 `json:"networks,omitempty"` + Firewalls []ServerCreateFirewalls `json:"firewalls,omitempty"` + PlacementGroup int64 `json:"placement_group,omitempty"` + PublicNet *ServerCreatePublicNet `json:"public_net,omitempty"` +} + +// ServerCreatePublicNet defines the public network configuration of a server. +type ServerCreatePublicNet struct { + EnableIPv4 bool `json:"enable_ipv4"` + EnableIPv6 bool `json:"enable_ipv6"` + IPv4ID int64 `json:"ipv4,omitempty"` + IPv6ID int64 `json:"ipv6,omitempty"` +} + +// ServerCreateFirewalls defines which Firewalls to apply when creating a Server. +type ServerCreateFirewalls struct { + Firewall int64 `json:"firewall"` +} + +// ServerCreateResponse defines the schema of the response when +// creating a server. +type ServerCreateResponse struct { + Server Server `json:"server"` + Action Action `json:"action"` + RootPassword *string `json:"root_password"` + NextActions []Action `json:"next_actions"` +} + +// ServerDeleteResponse defines the schema of the response when +// deleting a server. +type ServerDeleteResponse struct { + Action Action `json:"action"` +} + +// ServerUpdateRequest defines the schema of the request to update a server. +type ServerUpdateRequest struct { + Name string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// ServerUpdateResponse defines the schema of the response when updating a server. +type ServerUpdateResponse struct { + Server Server `json:"server"` +} + +// ServerActionPoweronRequest defines the schema for the request to +// create a poweron server action. +type ServerActionPoweronRequest struct{} + +// ServerActionPoweronResponse defines the schema of the response when +// creating a poweron server action. +type ServerActionPoweronResponse struct { + Action Action `json:"action"` +} + +// ServerActionPoweroffRequest defines the schema for the request to +// create a poweroff server action. +type ServerActionPoweroffRequest struct{} + +// ServerActionPoweroffResponse defines the schema of the response when +// creating a poweroff server action. +type ServerActionPoweroffResponse struct { + Action Action `json:"action"` +} + +// ServerActionRebootRequest defines the schema for the request to +// create a reboot server action. +type ServerActionRebootRequest struct{} + +// ServerActionRebootResponse defines the schema of the response when +// creating a reboot server action. +type ServerActionRebootResponse struct { + Action Action `json:"action"` +} + +// ServerActionResetRequest defines the schema for the request to +// create a reset server action. +type ServerActionResetRequest struct{} + +// ServerActionResetResponse defines the schema of the response when +// creating a reset server action. +type ServerActionResetResponse struct { + Action Action `json:"action"` +} + +// ServerActionShutdownRequest defines the schema for the request to +// create a shutdown server action. +type ServerActionShutdownRequest struct{} + +// ServerActionShutdownResponse defines the schema of the response when +// creating a shutdown server action. +type ServerActionShutdownResponse struct { + Action Action `json:"action"` +} + +// ServerActionResetPasswordRequest defines the schema for the request to +// create a reset_password server action. +type ServerActionResetPasswordRequest struct{} + +// ServerActionResetPasswordResponse defines the schema of the response when +// creating a reset_password server action. +type ServerActionResetPasswordResponse struct { + Action Action `json:"action"` + RootPassword string `json:"root_password"` +} + +// ServerActionCreateImageRequest defines the schema for the request to +// create a create_image server action. +type ServerActionCreateImageRequest struct { + Type *string `json:"type"` + Description *string `json:"description"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// ServerActionCreateImageResponse defines the schema of the response when +// creating a create_image server action. +type ServerActionCreateImageResponse struct { + Action Action `json:"action"` + Image Image `json:"image"` +} + +// ServerActionEnableRescueRequest defines the schema for the request to +// create a enable_rescue server action. +type ServerActionEnableRescueRequest struct { + Type *string `json:"type,omitempty"` + SSHKeys []int64 `json:"ssh_keys,omitempty"` +} + +// ServerActionEnableRescueResponse defines the schema of the response when +// creating a enable_rescue server action. +type ServerActionEnableRescueResponse struct { + Action Action `json:"action"` + RootPassword string `json:"root_password"` +} + +// ServerActionDisableRescueRequest defines the schema for the request to +// create a disable_rescue server action. +type ServerActionDisableRescueRequest struct{} + +// ServerActionDisableRescueResponse defines the schema of the response when +// creating a disable_rescue server action. +type ServerActionDisableRescueResponse struct { + Action Action `json:"action"` +} + +// ServerActionRebuildRequest defines the schema for the request to +// rebuild a server. +type ServerActionRebuildRequest struct { + Image interface{} `json:"image"` // int or string +} + +// ServerActionRebuildResponse defines the schema of the response when +// creating a rebuild server action. +type ServerActionRebuildResponse struct { + Action Action `json:"action"` + RootPassword *string `json:"root_password"` +} + +// ServerActionAttachISORequest defines the schema for the request to +// attach an ISO to a server. +type ServerActionAttachISORequest struct { + ISO interface{} `json:"iso"` // int or string +} + +// ServerActionAttachISOResponse defines the schema of the response when +// creating a attach_iso server action. +type ServerActionAttachISOResponse struct { + Action Action `json:"action"` +} + +// ServerActionDetachISORequest defines the schema for the request to +// detach an ISO from a server. +type ServerActionDetachISORequest struct{} + +// ServerActionDetachISOResponse defines the schema of the response when +// creating a detach_iso server action. +type ServerActionDetachISOResponse struct { + Action Action `json:"action"` +} + +// ServerActionEnableBackupRequest defines the schema for the request to +// enable backup for a server. +type ServerActionEnableBackupRequest struct { + BackupWindow *string `json:"backup_window,omitempty"` +} + +// ServerActionEnableBackupResponse defines the schema of the response when +// creating a enable_backup server action. +type ServerActionEnableBackupResponse struct { + Action Action `json:"action"` +} + +// ServerActionDisableBackupRequest defines the schema for the request to +// disable backup for a server. +type ServerActionDisableBackupRequest struct{} + +// ServerActionDisableBackupResponse defines the schema of the response when +// creating a disable_backup server action. +type ServerActionDisableBackupResponse struct { + Action Action `json:"action"` +} + +// ServerActionChangeTypeRequest defines the schema for the request to +// change a server's type. +type ServerActionChangeTypeRequest struct { + ServerType interface{} `json:"server_type"` // int or string + UpgradeDisk bool `json:"upgrade_disk"` +} + +// ServerActionChangeTypeResponse defines the schema of the response when +// creating a change_type server action. +type ServerActionChangeTypeResponse struct { + Action Action `json:"action"` +} + +// ServerActionChangeDNSPtrRequest defines the schema for the request to +// change a server's reverse DNS pointer. +type ServerActionChangeDNSPtrRequest struct { + IP string `json:"ip"` + DNSPtr *string `json:"dns_ptr"` +} + +// ServerActionChangeDNSPtrResponse defines the schema of the response when +// creating a change_dns_ptr server action. +type ServerActionChangeDNSPtrResponse struct { + Action Action `json:"action"` +} + +// ServerActionChangeProtectionRequest defines the schema of the request to +// change the resource protection of a server. +type ServerActionChangeProtectionRequest struct { + Rebuild *bool `json:"rebuild,omitempty"` + Delete *bool `json:"delete,omitempty"` +} + +// ServerActionChangeProtectionResponse defines the schema of the response when +// changing the resource protection of a server. +type ServerActionChangeProtectionResponse struct { + Action Action `json:"action"` +} + +// ServerActionRequestConsoleRequest defines the schema of the request to +// request a WebSocket VNC console. +type ServerActionRequestConsoleRequest struct{} + +// ServerActionRequestConsoleResponse defines the schema of the response when +// requesting a WebSocket VNC console. +type ServerActionRequestConsoleResponse struct { + Action Action `json:"action"` + WSSURL string `json:"wss_url"` + Password string `json:"password"` +} + +// ServerActionAttachToNetworkRequest defines the schema for the request to +// attach a network to a server. +type ServerActionAttachToNetworkRequest struct { + Network int64 `json:"network"` + IP *string `json:"ip,omitempty"` + AliasIPs []*string `json:"alias_ips,omitempty"` +} + +// ServerActionAttachToNetworkResponse defines the schema of the response when +// creating an attach_to_network server action. +type ServerActionAttachToNetworkResponse struct { + Action Action `json:"action"` +} + +// ServerActionDetachFromNetworkRequest defines the schema for the request to +// detach a network from a server. +type ServerActionDetachFromNetworkRequest struct { + Network int64 `json:"network"` +} + +// ServerActionDetachFromNetworkResponse defines the schema of the response when +// creating a detach_from_network server action. +type ServerActionDetachFromNetworkResponse struct { + Action Action `json:"action"` +} + +// ServerActionChangeAliasIPsRequest defines the schema for the request to +// change a server's alias IPs in a network. +type ServerActionChangeAliasIPsRequest struct { + Network int64 `json:"network"` + AliasIPs []string `json:"alias_ips"` +} + +// ServerActionChangeAliasIPsResponse defines the schema of the response when +// creating an change_alias_ips server action. +type ServerActionChangeAliasIPsResponse struct { + Action Action `json:"action"` +} + +// ServerGetMetricsResponse defines the schema of the response when requesting +// metrics for a server. +type ServerGetMetricsResponse struct { + Metrics struct { + Start time.Time `json:"start"` + End time.Time `json:"end"` + Step float64 `json:"step"` + TimeSeries map[string]ServerTimeSeriesVals `json:"time_series"` + } `json:"metrics"` +} + +// ServerTimeSeriesVals contains the values for a Server time series. +type ServerTimeSeriesVals struct { + Values []interface{} `json:"values"` +} + +// ServerActionAddToPlacementGroupRequest defines the schema for the request to +// add a server to a placement group. +type ServerActionAddToPlacementGroupRequest struct { + PlacementGroup int64 `json:"placement_group"` +} + +// ServerActionAddToPlacementGroupResponse defines the schema of the response when +// creating an add_to_placement_group server action. +type ServerActionAddToPlacementGroupResponse struct { + Action Action `json:"action"` +} + +// ServerActionRemoveFromPlacementGroupResponse defines the schema of the response when +// creating a remove_from_placement_group server action. +type ServerActionRemoveFromPlacementGroupResponse struct { + Action Action `json:"action"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server_type.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server_type.go new file mode 100644 index 000000000..21a87da9a --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/server_type.go @@ -0,0 +1,30 @@ +package schema + +// ServerType defines the schema of a server type. +type ServerType struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Cores int `json:"cores"` + Memory float32 `json:"memory"` + Disk int `json:"disk"` + StorageType string `json:"storage_type"` + CPUType string `json:"cpu_type"` + Architecture string `json:"architecture"` + IncludedTraffic int64 `json:"included_traffic"` + Prices []PricingServerTypePrice `json:"prices"` + Deprecated bool `json:"deprecated"` + DeprecatableResource +} + +// ServerTypeListResponse defines the schema of the response when +// listing server types. +type ServerTypeListResponse struct { + ServerTypes []ServerType `json:"server_types"` +} + +// ServerTypeGetResponse defines the schema of the response when +// retrieving a single server type. +type ServerTypeGetResponse struct { + ServerType ServerType `json:"server_type"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/ssh_key.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/ssh_key.go new file mode 100644 index 000000000..7e095bc5a --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/ssh_key.go @@ -0,0 +1,50 @@ +package schema + +import "time" + +// SSHKey defines the schema of a SSH key. +type SSHKey struct { + ID int64 `json:"id"` + Name string `json:"name"` + Fingerprint string `json:"fingerprint"` + PublicKey string `json:"public_key"` + Labels map[string]string `json:"labels"` + Created time.Time `json:"created"` +} + +// SSHKeyCreateRequest defines the schema of the request +// to create a SSH key. +type SSHKeyCreateRequest struct { + Name string `json:"name"` + PublicKey string `json:"public_key"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// SSHKeyCreateResponse defines the schema of the response +// when creating a SSH key. +type SSHKeyCreateResponse struct { + SSHKey SSHKey `json:"ssh_key"` +} + +// SSHKeyListResponse defines the schema of the response +// when listing SSH keys. +type SSHKeyListResponse struct { + SSHKeys []SSHKey `json:"ssh_keys"` +} + +// SSHKeyGetResponse defines the schema of the response +// when retrieving a single SSH key. +type SSHKeyGetResponse struct { + SSHKey SSHKey `json:"ssh_key"` +} + +// SSHKeyUpdateRequest defines the schema of the request to update a SSH key. +type SSHKeyUpdateRequest struct { + Name string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// SSHKeyUpdateResponse defines the schema of the response when updating a SSH key. +type SSHKeyUpdateResponse struct { + SSHKey SSHKey `json:"ssh_key"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/volume.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/volume.go new file mode 100644 index 000000000..1de645955 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema/volume.go @@ -0,0 +1,111 @@ +package schema + +import "time" + +// Volume defines the schema of a volume. +type Volume struct { + ID int64 `json:"id"` + Name string `json:"name"` + Server *int64 `json:"server"` + Status string `json:"status"` + Location Location `json:"location"` + Size int `json:"size"` + Format *string `json:"format"` + Protection VolumeProtection `json:"protection"` + Labels map[string]string `json:"labels"` + LinuxDevice string `json:"linux_device"` + Created time.Time `json:"created"` +} + +// VolumeCreateRequest defines the schema of the request +// to create a volume. +type VolumeCreateRequest struct { + Name string `json:"name"` + Size int `json:"size"` + Server *int64 `json:"server,omitempty"` + Location interface{} `json:"location,omitempty"` // int, string, or nil + Labels *map[string]string `json:"labels,omitempty"` + Automount *bool `json:"automount,omitempty"` + Format *string `json:"format,omitempty"` +} + +// VolumeCreateResponse defines the schema of the response +// when creating a volume. +type VolumeCreateResponse struct { + Volume Volume `json:"volume"` + Action *Action `json:"action"` + NextActions []Action `json:"next_actions"` +} + +// VolumeListResponse defines the schema of the response +// when listing volumes. +type VolumeListResponse struct { + Volumes []Volume `json:"volumes"` +} + +// VolumeGetResponse defines the schema of the response +// when retrieving a single volume. +type VolumeGetResponse struct { + Volume Volume `json:"volume"` +} + +// VolumeUpdateRequest defines the schema of the request to update a volume. +type VolumeUpdateRequest struct { + Name string `json:"name,omitempty"` + Labels *map[string]string `json:"labels,omitempty"` +} + +// VolumeUpdateResponse defines the schema of the response when updating a volume. +type VolumeUpdateResponse struct { + Volume Volume `json:"volume"` +} + +// VolumeProtection defines the schema of a volume's resource protection. +type VolumeProtection struct { + Delete bool `json:"delete"` +} + +// VolumeActionChangeProtectionRequest defines the schema of the request to +// change the resource protection of a volume. +type VolumeActionChangeProtectionRequest struct { + Delete *bool `json:"delete,omitempty"` +} + +// VolumeActionChangeProtectionResponse defines the schema of the response when +// changing the resource protection of a volume. +type VolumeActionChangeProtectionResponse struct { + Action Action `json:"action"` +} + +// VolumeActionAttachVolumeRequest defines the schema of the request to +// attach a volume to a server. +type VolumeActionAttachVolumeRequest struct { + Server int64 `json:"server"` + Automount *bool `json:"automount,omitempty"` +} + +// VolumeActionAttachVolumeResponse defines the schema of the response when +// attaching a volume to a server. +type VolumeActionAttachVolumeResponse struct { + Action Action `json:"action"` +} + +// VolumeActionDetachVolumeRequest defines the schema of the request to +// create an detach volume action. +type VolumeActionDetachVolumeRequest struct{} + +// VolumeActionDetachVolumeResponse defines the schema of the response when +// creating an detach volume action. +type VolumeActionDetachVolumeResponse struct { + Action Action `json:"action"` +} + +// VolumeActionResizeVolumeRequest defines the schema of the request to resize a volume. +type VolumeActionResizeVolumeRequest struct { + Size int `json:"size"` +} + +// VolumeActionResizeVolumeResponse defines the schema of the response when resizing a volume. +type VolumeActionResizeVolumeResponse struct { + Action Action `json:"action"` +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_assign.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_assign.go new file mode 100644 index 000000000..8894e3506 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_assign.go @@ -0,0 +1,15 @@ +//go:build !goverter + +package hcloud + +/* +This file is needed so that c is assigned to a converterImpl{}. +If we did this in schema.go, goverter would fail because of a +compiler error (converterImpl might not be defined). +Because this file is not compiled by goverter, we can safely +assign c here. +*/ + +func init() { + c = &converterImpl{} +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_gen.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_gen.go new file mode 100644 index 000000000..ea002cce7 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/schema_gen.go @@ -0,0 +1,957 @@ +package hcloud + +import ( + "encoding/json" + "fmt" + "net" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +//go:generate go run github.com/jmattheis/goverter/cmd/goverter gen ./... + +/* +This file generates conversions methods between the schema and the hcloud package. +Goverter (https://github.com/jmattheis/goverter) is used to generate these conversion +methods. Goverter is configured using comments in and on the [converter] interface. +A struct implementing the interface methods, [converterImpl], is generated in zz_schema.go. +The generated methods are then wrapped in schema.go to be exported. + +You can find a documentation of goverter here: https://goverter.jmattheis.de/ +*/ + +// goverter:converter +// +// Specify where and in which package to output the generated +// conversion methods. +// goverter:output:file zz_schema.go +// goverter:output:package github.com/hetznercloud/hcloud-go/v2/hcloud +// +// In case of *T -> T conversion, use zero value if *T is nil. +// goverter:useZeroValueOnPointerInconsistency yes +// +// Do not deep copy in case of *T -> *T conversion. +// goverter:skipCopySameType yes +// +// Explicit conversion methods are needed for non-trivial cases +// where the target, source or both are of primitive types. Struct +// to struct conversions can be handled by goverter directly. +// goverter:extend ipFromString +// goverter:extend stringFromIP +// goverter:extend ipNetFromString +// goverter:extend stringFromIPNet +// goverter:extend timeToTimePtr +// goverter:extend serverFromInt64 +// goverter:extend int64FromServer +// goverter:extend networkFromInt64 +// goverter:extend int64FromNetwork +// goverter:extend loadBalancerFromInt64 +// goverter:extend int64FromLoadBalancer +// goverter:extend volumeFromInt64 +// goverter:extend int64FromVolume +// goverter:extend certificateFromInt64 +// goverter:extend int64FromCertificate +// goverter:extend locationFromString +// goverter:extend stringFromLocation +// goverter:extend serverTypeFromInt64 +// goverter:extend int64FromServerType +// goverter:extend floatingIPFromInt64 +// goverter:extend int64FromFloatingIP +// goverter:extend mapFromFloatingIPDNSPtrSchema +// goverter:extend floatingIPDNSPtrSchemaFromMap +// goverter:extend mapFromPrimaryIPDNSPtrSchema +// goverter:extend primaryIPDNSPtrSchemaFromMap +// goverter:extend mapFromServerPublicNetIPv6DNSPtrSchema +// goverter:extend serverPublicNetIPv6DNSPtrSchemaFromMap +// goverter:extend firewallStatusFromSchemaServerFirewall +// goverter:extend serverFirewallSchemaFromFirewallStatus +// goverter:extend durationFromIntSeconds +// goverter:extend intSecondsFromDuration +// goverter:extend serverFromImageCreatedFromSchema +// goverter:extend anyFromLoadBalancerType +// goverter:extend serverMetricsTimeSeriesFromSchema +// goverter:extend loadBalancerMetricsTimeSeriesFromSchema +// goverter:extend stringPtrFromLoadBalancerServiceProtocol +// goverter:extend stringPtrFromNetworkZone +// goverter:extend schemaFromLoadBalancerCreateOptsTargetLabelSelector +// goverter:extend schemaFromLoadBalancerCreateOptsTargetServer +// goverter:extend schemaFromLoadBalancerCreateOptsTargetIP +// goverter:extend stringMapToStringMapPtr +// goverter:extend int64SlicePtrFromCertificatePtrSlice +// goverter:extend stringSlicePtrFromStringSlice +type converter interface { + + // goverter:map Error.Code ErrorCode + // goverter:map Error.Message ErrorMessage + ActionFromSchema(schema.Action) *Action + + // goverter:map . Error | schemaActionErrorFromAction + SchemaFromAction(*Action) schema.Action + + ActionsFromSchema([]schema.Action) []*Action + + SchemaFromActions([]*Action) []schema.Action + + // goverter:map . IP | ipFromFloatingIPSchema + // goverter:map . Network | networkFromFloatingIPSchema + FloatingIPFromSchema(schema.FloatingIP) *FloatingIP + + // goverter:map . IP | floatingIPToIPString + SchemaFromFloatingIP(*FloatingIP) schema.FloatingIP + + // goverter:map . IP | ipFromPrimaryIPSchema + // goverter:map . Network | networkFromPrimaryIPSchema + PrimaryIPFromSchema(schema.PrimaryIP) *PrimaryIP + + // goverter:map . IP | primaryIPToIPString + // goverter:map AssigneeID | mapZeroInt64ToNil + SchemaFromPrimaryIP(*PrimaryIP) schema.PrimaryIP + + ISOFromSchema(schema.ISO) *ISO + + // We cannot use goverter settings when mapping a struct to a struct pointer + // See [converter.ISOFromSchema] + // See https://github.com/jmattheis/goverter/issues/114 + // goverter:map DeprecatableResource.Deprecation.UnavailableAfter Deprecated + intISOFromSchema(schema.ISO) ISO + + SchemaFromISO(*ISO) schema.ISO + + LocationFromSchema(schema.Location) *Location + + SchemaFromLocation(*Location) schema.Location + + DatacenterFromSchema(schema.Datacenter) *Datacenter + + SchemaFromDatacenter(*Datacenter) schema.Datacenter + + ServerFromSchema(schema.Server) *Server + + // goverter:map OutgoingTraffic | mapZeroUint64ToNil + // goverter:map IngoingTraffic | mapZeroUint64ToNil + // goverter:map BackupWindow | mapEmptyStringToNil + SchemaFromServer(*Server) schema.Server + + ServerPublicNetFromSchema(schema.ServerPublicNet) ServerPublicNet + + SchemaFromServerPublicNet(ServerPublicNet) schema.ServerPublicNet + + ServerPublicNetIPv4FromSchema(schema.ServerPublicNetIPv4) ServerPublicNetIPv4 + + SchemaFromServerPublicNetIPv4(ServerPublicNetIPv4) schema.ServerPublicNetIPv4 + + // goverter:map . IP | ipFromServerPublicNetIPv6Schema + // goverter:map . Network | ipNetFromServerPublicNetIPv6Schema + ServerPublicNetIPv6FromSchema(schema.ServerPublicNetIPv6) ServerPublicNetIPv6 + + // goverter:map Network IP + SchemaFromServerPublicNetIPv6(ServerPublicNetIPv6) schema.ServerPublicNetIPv6 + + // goverter:map AliasIPs Aliases + ServerPrivateNetFromSchema(schema.ServerPrivateNet) ServerPrivateNet + + // goverter:map Aliases AliasIPs + SchemaFromServerPrivateNet(ServerPrivateNet) schema.ServerPrivateNet + + // goverter:map Prices Pricings + ServerTypeFromSchema(schema.ServerType) *ServerType + + // goverter:map Pricings Prices + // goverter:map DeprecatableResource.Deprecation Deprecated | isDeprecationNotNil + SchemaFromServerType(*ServerType) schema.ServerType + + ImageFromSchema(schema.Image) *Image + + SchemaFromImage(*Image) schema.Image + + // Needed because of how goverter works internally, see https://github.com/jmattheis/goverter/issues/114 + // goverter:map ImageSize | mapZeroFloat32ToNil + intSchemaFromImage(Image) schema.Image + + // goverter:ignore Currency + // goverter:ignore VATRate + PriceFromSchema(schema.Price) Price + + SSHKeyFromSchema(schema.SSHKey) *SSHKey + + SchemaFromSSHKey(*SSHKey) schema.SSHKey + + VolumeFromSchema(schema.Volume) *Volume + + SchemaFromVolume(*Volume) schema.Volume + + NetworkFromSchema(schema.Network) *Network + + SchemaFromNetwork(*Network) schema.Network + + NetworkSubnetFromSchema(schema.NetworkSubnet) NetworkSubnet + + SchemaFromNetworkSubnet(NetworkSubnet) schema.NetworkSubnet + + NetworkRouteFromSchema(schema.NetworkRoute) NetworkRoute + + SchemaFromNetworkRoute(NetworkRoute) schema.NetworkRoute + + LoadBalancerFromSchema(schema.LoadBalancer) *LoadBalancer + + // goverter:map OutgoingTraffic | mapZeroUint64ToNil + // goverter:map IngoingTraffic | mapZeroUint64ToNil + SchemaFromLoadBalancer(*LoadBalancer) schema.LoadBalancer + + // goverter:map Prices Pricings + LoadBalancerTypeFromSchema(schema.LoadBalancerType) *LoadBalancerType + + // goverter:map Pricings Prices + SchemaFromLoadBalancerType(*LoadBalancerType) schema.LoadBalancerType + + // goverter:map PriceHourly Hourly + // goverter:map PriceMonthly Monthly + LoadBalancerTypeLocationPricingFromSchema(schema.PricingLoadBalancerTypePrice) LoadBalancerTypeLocationPricing + + // goverter:map Hourly PriceHourly + // goverter:map Monthly PriceMonthly + SchemaFromLoadBalancerTypeLocationPricing(LoadBalancerTypeLocationPricing) schema.PricingLoadBalancerTypePrice + + LoadBalancerServiceFromSchema(schema.LoadBalancerService) LoadBalancerService + + SchemaFromLoadBalancerService(LoadBalancerService) schema.LoadBalancerService + + LoadBalancerServiceHealthCheckFromSchema(*schema.LoadBalancerServiceHealthCheck) LoadBalancerServiceHealthCheck + + SchemaFromLoadBalancerServiceHealthCheck(LoadBalancerServiceHealthCheck) *schema.LoadBalancerServiceHealthCheck + + LoadBalancerTargetFromSchema(schema.LoadBalancerTarget) LoadBalancerTarget + + SchemaFromLoadBalancerTarget(LoadBalancerTarget) schema.LoadBalancerTarget + + // goverter:map ID Server + LoadBalancerTargetServerFromSchema(schema.LoadBalancerTargetServer) LoadBalancerTargetServer + + // goverter:map Server ID + SchemaFromLoadBalancerServerTarget(LoadBalancerTargetServer) schema.LoadBalancerTargetServer + + LoadBalancerTargetHealthStatusFromSchema(schema.LoadBalancerTargetHealthStatus) LoadBalancerTargetHealthStatus + + SchemaFromLoadBalancerTargetHealthStatus(LoadBalancerTargetHealthStatus) schema.LoadBalancerTargetHealthStatus + + CertificateFromSchema(schema.Certificate) *Certificate + + SchemaFromCertificate(*Certificate) schema.Certificate + + PaginationFromSchema(schema.MetaPagination) Pagination + + SchemaFromPagination(Pagination) schema.MetaPagination + + // goverter:ignore response + // goverter:map Details | errorDetailsFromSchema + ErrorFromSchema(schema.Error) Error + + // goverter:map Details | schemaFromErrorDetails + // goverter:map Details DetailsRaw | rawSchemaFromErrorDetails + SchemaFromError(Error) schema.Error + + // goverter:map . Image | imagePricingFromSchema + // goverter:map . FloatingIP | floatingIPPricingFromSchema + // goverter:map . FloatingIPs | floatingIPTypePricingFromSchema + // goverter:map . PrimaryIPs | primaryIPPricingFromSchema + // goverter:map . Traffic | trafficPricingFromSchema + // goverter:map . ServerTypes | serverTypePricingFromSchema + // goverter:map . LoadBalancerTypes | loadBalancerTypePricingFromSchema + // goverter:map . Volume | volumePricingFromSchema + PricingFromSchema(schema.Pricing) Pricing + + // goverter:map PriceHourly Hourly + // goverter:map PriceMonthly Monthly + serverTypePricingFromSchema(schema.PricingServerTypePrice) ServerTypeLocationPricing + + // goverter:map Image.PerGBMonth.Currency Currency + // goverter:map Image.PerGBMonth.VATRate VATRate + SchemaFromPricing(Pricing) schema.Pricing + + // goverter:map PerGBMonth PricePerGBMonth + schemaFromImagePricing(ImagePricing) schema.PricingImage + + // goverter:map Monthly PriceMonthly + schemaFromFloatingIPPricing(FloatingIPPricing) schema.PricingFloatingIP + + // goverter:map Pricings Prices + schemaFromFloatingIPTypePricing(FloatingIPTypePricing) schema.PricingFloatingIPType + + // goverter:map Monthly PriceMonthly + schemaFromFloatingIPTypeLocationPricing(FloatingIPTypeLocationPricing) schema.PricingFloatingIPTypePrice + + // goverter:map Pricings Prices + schemaFromPrimaryIPPricing(PrimaryIPPricing) schema.PricingPrimaryIP + + // goverter:map Monthly PriceMonthly + // goverter:map Hourly PriceHourly + schemaFromPrimaryIPTypePricing(PrimaryIPTypePricing) schema.PricingPrimaryIPTypePrice + + // goverter:map PerTB PricePerTB + schemaFromTrafficPricing(TrafficPricing) schema.PricingTraffic + + // goverter:map Pricings Prices + // goverter:map ServerType.ID ID + // goverter:map ServerType.Name Name + schemaFromServerTypePricing(ServerTypePricing) schema.PricingServerType + + // goverter:map Pricings Prices + // goverter:map LoadBalancerType.ID ID + // goverter:map LoadBalancerType.Name Name + schemaFromLoadBalancerTypePricing(LoadBalancerTypePricing) schema.PricingLoadBalancerType + + // goverter:map PerGBMonthly PricePerGBPerMonth + schemaFromVolumePricing(VolumePricing) schema.PricingVolume + + // goverter:map Monthly PriceMonthly + // goverter:map Hourly PriceHourly + schemaFromServerTypeLocationPricing(ServerTypeLocationPricing) schema.PricingServerTypePrice + + FirewallFromSchema(schema.Firewall) *Firewall + + SchemaFromFirewall(*Firewall) schema.Firewall + + PlacementGroupFromSchema(schema.PlacementGroup) *PlacementGroup + + SchemaFromPlacementGroup(*PlacementGroup) schema.PlacementGroup + + SchemaFromPlacementGroupCreateOpts(PlacementGroupCreateOpts) schema.PlacementGroupCreateRequest + + SchemaFromLoadBalancerCreateOpts(LoadBalancerCreateOpts) schema.LoadBalancerCreateRequest + + // goverter:map Server.ID ID + SchemaFromLoadBalancerCreateOptsTargetServer(LoadBalancerCreateOptsTargetServer) schema.LoadBalancerCreateRequestTargetServer + + SchemaFromLoadBalancerAddServiceOpts(LoadBalancerAddServiceOpts) schema.LoadBalancerActionAddServiceRequest + + // goverter:ignore ListenPort + SchemaFromLoadBalancerUpdateServiceOpts(LoadBalancerUpdateServiceOpts) schema.LoadBalancerActionUpdateServiceRequest + + SchemaFromFirewallCreateOpts(FirewallCreateOpts) schema.FirewallCreateRequest + + SchemaFromFirewallSetRulesOpts(FirewallSetRulesOpts) schema.FirewallActionSetRulesRequest + + SchemaFromFirewallResource(FirewallResource) schema.FirewallResource + + // goverter:autoMap Metrics + ServerMetricsFromSchema(*schema.ServerGetMetricsResponse) (*ServerMetrics, error) + + // goverter:autoMap Metrics + LoadBalancerMetricsFromSchema(*schema.LoadBalancerGetMetricsResponse) (*LoadBalancerMetrics, error) + + DeprecationFromSchema(*schema.DeprecationInfo) *DeprecationInfo + + SchemaFromDeprecation(*DeprecationInfo) *schema.DeprecationInfo +} + +func schemaActionErrorFromAction(a Action) *schema.ActionError { + if a.ErrorCode != "" && a.ErrorMessage != "" { + return &schema.ActionError{ + Code: a.ErrorCode, + Message: a.ErrorMessage, + } + } + return nil +} + +func ipFromFloatingIPSchema(s schema.FloatingIP) net.IP { + if s.Type == string(FloatingIPTypeIPv4) { + return net.ParseIP(s.IP) + } + ip, _, _ := net.ParseCIDR(s.IP) + return ip +} + +func networkFromFloatingIPSchema(s schema.FloatingIP) *net.IPNet { + if s.Type == string(FloatingIPTypeIPv4) { + return nil + } + _, n, _ := net.ParseCIDR(s.IP) + return n +} + +func ipFromPrimaryIPSchema(s schema.PrimaryIP) net.IP { + if s.Type == string(FloatingIPTypeIPv4) { + return net.ParseIP(s.IP) + } + ip, _, _ := net.ParseCIDR(s.IP) + return ip +} + +func networkFromPrimaryIPSchema(s schema.PrimaryIP) *net.IPNet { + if s.Type == string(FloatingIPTypeIPv4) { + return nil + } + _, n, _ := net.ParseCIDR(s.IP) + return n +} + +func serverFromInt64(id int64) Server { + return Server{ID: id} +} + +func int64FromServer(s Server) int64 { + return s.ID +} + +func networkFromInt64(id int64) Network { + return Network{ID: id} +} + +func int64FromNetwork(network Network) int64 { + return network.ID +} + +func loadBalancerFromInt64(id int64) LoadBalancer { + return LoadBalancer{ID: id} +} + +func int64FromLoadBalancer(lb LoadBalancer) int64 { + return lb.ID +} + +func volumeFromInt64(id int64) *Volume { + return &Volume{ID: id} +} + +func int64FromVolume(volume *Volume) int64 { + if volume == nil { + return 0 + } + return volume.ID +} + +func serverTypeFromInt64(id int64) *ServerType { + return &ServerType{ID: id} +} + +func int64FromServerType(s *ServerType) int64 { + if s == nil { + return 0 + } + return s.ID +} + +func certificateFromInt64(id int64) *Certificate { + return &Certificate{ID: id} +} + +func int64FromCertificate(c *Certificate) int64 { + if c == nil { + return 0 + } + return c.ID +} + +func locationFromString(s string) Location { + return Location{Name: s} +} + +func stringFromLocation(l Location) string { + return l.Name +} + +func mapFromFloatingIPDNSPtrSchema(dnsPtr []schema.FloatingIPDNSPtr) map[string]string { + m := make(map[string]string, len(dnsPtr)) + for _, entry := range dnsPtr { + m[entry.IP] = entry.DNSPtr + } + return m +} + +func floatingIPDNSPtrSchemaFromMap(m map[string]string) []schema.FloatingIPDNSPtr { + dnsPtr := make([]schema.FloatingIPDNSPtr, 0, len(m)) + for ip, ptr := range m { + dnsPtr = append(dnsPtr, schema.FloatingIPDNSPtr{ + IP: ip, + DNSPtr: ptr, + }) + } + return dnsPtr +} + +func mapFromPrimaryIPDNSPtrSchema(dnsPtr []schema.PrimaryIPDNSPTR) map[string]string { + m := make(map[string]string, len(dnsPtr)) + for _, entry := range dnsPtr { + m[entry.IP] = entry.DNSPtr + } + return m +} + +func primaryIPDNSPtrSchemaFromMap(m map[string]string) []schema.PrimaryIPDNSPTR { + dnsPtr := make([]schema.PrimaryIPDNSPTR, 0, len(m)) + for ip, ptr := range m { + dnsPtr = append(dnsPtr, schema.PrimaryIPDNSPTR{ + IP: ip, + DNSPtr: ptr, + }) + } + return dnsPtr +} + +func mapFromServerPublicNetIPv6DNSPtrSchema(dnsPtr []schema.ServerPublicNetIPv6DNSPtr) map[string]string { + m := make(map[string]string, len(dnsPtr)) + for _, entry := range dnsPtr { + m[entry.IP] = entry.DNSPtr + } + return m +} + +func serverPublicNetIPv6DNSPtrSchemaFromMap(m map[string]string) []schema.ServerPublicNetIPv6DNSPtr { + dnsPtr := make([]schema.ServerPublicNetIPv6DNSPtr, 0, len(m)) + for ip, ptr := range m { + dnsPtr = append(dnsPtr, schema.ServerPublicNetIPv6DNSPtr{ + IP: ip, + DNSPtr: ptr, + }) + } + return dnsPtr +} + +func floatingIPToIPString(ip FloatingIP) string { + if ip.Type == FloatingIPTypeIPv4 { + return ip.IP.String() + } + return ip.Network.String() +} + +func primaryIPToIPString(ip PrimaryIP) string { + if ip.Type == PrimaryIPTypeIPv4 { + return ip.IP.String() + } + return ip.Network.String() +} + +func floatingIPFromInt64(id int64) *FloatingIP { + return &FloatingIP{ID: id} +} + +func int64FromFloatingIP(f *FloatingIP) int64 { + if f == nil { + return 0 + } + return f.ID +} + +func firewallStatusFromSchemaServerFirewall(fw schema.ServerFirewall) *ServerFirewallStatus { + return &ServerFirewallStatus{ + Firewall: Firewall{ID: fw.ID}, + Status: FirewallStatus(fw.Status), + } +} + +func serverFirewallSchemaFromFirewallStatus(s *ServerFirewallStatus) schema.ServerFirewall { + return schema.ServerFirewall{ + ID: s.Firewall.ID, + Status: string(s.Status), + } +} + +func ipFromServerPublicNetIPv6Schema(s schema.ServerPublicNetIPv6) net.IP { + ip, _, _ := net.ParseCIDR(s.IP) + return ip +} + +func ipNetFromServerPublicNetIPv6Schema(s schema.ServerPublicNetIPv6) *net.IPNet { + _, n, _ := net.ParseCIDR(s.IP) + return n +} + +func serverFromImageCreatedFromSchema(s schema.ImageCreatedFrom) Server { + return Server{ + ID: s.ID, + Name: s.Name, + } +} + +func ipFromString(s string) net.IP { + return net.ParseIP(s) +} + +func stringFromIP(ip net.IP) string { + if ip == nil { + return "" + } + return ip.String() +} + +func ipNetFromString(s string) net.IPNet { + _, n, _ := net.ParseCIDR(s) + if n == nil { + return net.IPNet{} + } + return *n +} + +func stringFromIPNet(ip net.IPNet) string { + return ip.String() +} + +func timeToTimePtr(t time.Time) *time.Time { + // Some hcloud structs don't use pointers for nullable times, so the zero value + // should be treated as nil. + if t == (time.Time{}) { + return nil + } + return &t +} + +func durationFromIntSeconds(s int) time.Duration { + return time.Duration(s) * time.Second +} + +func intSecondsFromDuration(d time.Duration) int { + return int(d.Seconds()) +} + +func errorDetailsFromSchema(d interface{}) interface{} { + if d, ok := d.(schema.ErrorDetailsInvalidInput); ok { + details := ErrorDetailsInvalidInput{ + Fields: make([]ErrorDetailsInvalidInputField, len(d.Fields)), + } + for i, field := range d.Fields { + details.Fields[i] = ErrorDetailsInvalidInputField{ + Name: field.Name, + Messages: field.Messages, + } + } + return details + } + return nil +} + +func schemaFromErrorDetails(d interface{}) interface{} { + if d, ok := d.(ErrorDetailsInvalidInput); ok { + details := schema.ErrorDetailsInvalidInput{ + Fields: make([]struct { + Name string `json:"name"` + Messages []string `json:"messages"` + }, len(d.Fields)), + } + for i, field := range d.Fields { + details.Fields[i] = struct { + Name string `json:"name"` + Messages []string `json:"messages"` + }{Name: field.Name, Messages: field.Messages} + } + return details + } + return nil +} + +func imagePricingFromSchema(s schema.Pricing) ImagePricing { + return ImagePricing{ + PerGBMonth: Price{ + Net: s.Image.PricePerGBMonth.Net, + Gross: s.Image.PricePerGBMonth.Gross, + Currency: s.Currency, + VATRate: s.VATRate, + }, + } +} + +func floatingIPPricingFromSchema(s schema.Pricing) FloatingIPPricing { + return FloatingIPPricing{ + Monthly: Price{ + Net: s.FloatingIP.PriceMonthly.Net, + Gross: s.FloatingIP.PriceMonthly.Gross, + Currency: s.Currency, + VATRate: s.VATRate, + }, + } +} + +func floatingIPTypePricingFromSchema(s schema.Pricing) []FloatingIPTypePricing { + p := make([]FloatingIPTypePricing, len(s.FloatingIPs)) + for i, floatingIPType := range s.FloatingIPs { + var pricings = make([]FloatingIPTypeLocationPricing, len(floatingIPType.Prices)) + for i, price := range floatingIPType.Prices { + pricings[i] = FloatingIPTypeLocationPricing{ + Location: &Location{Name: price.Location}, + Monthly: Price{ + Currency: s.Currency, + VATRate: s.VATRate, + Net: price.PriceMonthly.Net, + Gross: price.PriceMonthly.Gross, + }, + } + } + p[i] = FloatingIPTypePricing{Type: FloatingIPType(floatingIPType.Type), Pricings: pricings} + } + return p +} + +func primaryIPPricingFromSchema(s schema.Pricing) []PrimaryIPPricing { + p := make([]PrimaryIPPricing, len(s.FloatingIPs)) + for i, primaryIPType := range s.PrimaryIPs { + var pricings = make([]PrimaryIPTypePricing, len(primaryIPType.Prices)) + for i, price := range primaryIPType.Prices { + pricings[i] = PrimaryIPTypePricing{ + Location: price.Location, + Monthly: PrimaryIPPrice{ + Net: price.PriceMonthly.Net, + Gross: price.PriceMonthly.Gross, + }, + Hourly: PrimaryIPPrice{ + Net: price.PriceHourly.Net, + Gross: price.PriceHourly.Gross, + }, + } + } + p[i] = PrimaryIPPricing{Type: primaryIPType.Type, Pricings: pricings} + } + return p +} + +func trafficPricingFromSchema(s schema.Pricing) TrafficPricing { + return TrafficPricing{ + PerTB: Price{ + Net: s.Traffic.PricePerTB.Net, + Gross: s.Traffic.PricePerTB.Gross, + Currency: s.Currency, + VATRate: s.VATRate, + }, + } +} + +func serverTypePricingFromSchema(s schema.Pricing) []ServerTypePricing { + p := make([]ServerTypePricing, len(s.ServerTypes)) + for i, serverType := range s.ServerTypes { + var pricings = make([]ServerTypeLocationPricing, len(serverType.Prices)) + for i, price := range serverType.Prices { + pricings[i] = ServerTypeLocationPricing{ + Location: &Location{Name: price.Location}, + Hourly: Price{ + Currency: s.Currency, + VATRate: s.VATRate, + Net: price.PriceHourly.Net, + Gross: price.PriceHourly.Gross, + }, + Monthly: Price{ + Currency: s.Currency, + VATRate: s.VATRate, + Net: price.PriceMonthly.Net, + Gross: price.PriceMonthly.Gross, + }, + } + } + p[i] = ServerTypePricing{ + ServerType: &ServerType{ + ID: serverType.ID, + Name: serverType.Name, + }, + Pricings: pricings, + } + } + return p +} + +func loadBalancerTypePricingFromSchema(s schema.Pricing) []LoadBalancerTypePricing { + p := make([]LoadBalancerTypePricing, len(s.LoadBalancerTypes)) + for i, loadBalancerType := range s.LoadBalancerTypes { + var pricings = make([]LoadBalancerTypeLocationPricing, len(loadBalancerType.Prices)) + for i, price := range loadBalancerType.Prices { + pricings[i] = LoadBalancerTypeLocationPricing{ + Location: &Location{Name: price.Location}, + Hourly: Price{ + Currency: s.Currency, + VATRate: s.VATRate, + Net: price.PriceHourly.Net, + Gross: price.PriceHourly.Gross, + }, + Monthly: Price{ + Currency: s.Currency, + VATRate: s.VATRate, + Net: price.PriceMonthly.Net, + Gross: price.PriceMonthly.Gross, + }, + } + } + p[i] = LoadBalancerTypePricing{ + LoadBalancerType: &LoadBalancerType{ + ID: loadBalancerType.ID, + Name: loadBalancerType.Name, + }, + Pricings: pricings, + } + } + return p +} + +func volumePricingFromSchema(s schema.Pricing) VolumePricing { + return VolumePricing{ + PerGBMonthly: Price{ + Net: s.Volume.PricePerGBPerMonth.Net, + Gross: s.Volume.PricePerGBPerMonth.Gross, + Currency: s.Currency, + VATRate: s.VATRate, + }, + } +} + +func anyFromLoadBalancerType(t *LoadBalancerType) interface{} { + if t == nil { + return nil + } + if t.ID != 0 { + return t.ID + } + return t.Name +} + +func serverMetricsTimeSeriesFromSchema(s schema.ServerTimeSeriesVals) ([]ServerMetricsValue, error) { + vals := make([]ServerMetricsValue, len(s.Values)) + + for i, rawVal := range s.Values { + var val ServerMetricsValue + + tup, ok := rawVal.([]interface{}) + if !ok { + return nil, fmt.Errorf("failed to convert value to tuple: %v", rawVal) + } + if len(tup) != 2 { + return nil, fmt.Errorf("invalid tuple size: %d: %v", len(tup), rawVal) + } + ts, ok := tup[0].(float64) + if !ok { + return nil, fmt.Errorf("convert to float64: %v", tup[0]) + } + val.Timestamp = ts + + v, ok := tup[1].(string) + if !ok { + return nil, fmt.Errorf("not a string: %v", tup[1]) + } + val.Value = v + vals[i] = val + } + + return vals, nil +} + +func loadBalancerMetricsTimeSeriesFromSchema(s schema.LoadBalancerTimeSeriesVals) ([]LoadBalancerMetricsValue, error) { + vals := make([]LoadBalancerMetricsValue, len(s.Values)) + + for i, rawVal := range s.Values { + var val LoadBalancerMetricsValue + + tup, ok := rawVal.([]interface{}) + if !ok { + return nil, fmt.Errorf("failed to convert value to tuple: %v", rawVal) + } + if len(tup) != 2 { + return nil, fmt.Errorf("invalid tuple size: %d: %v", len(tup), rawVal) + } + ts, ok := tup[0].(float64) + if !ok { + return nil, fmt.Errorf("convert to float64: %v", tup[0]) + } + val.Timestamp = ts + + v, ok := tup[1].(string) + if !ok { + return nil, fmt.Errorf("not a string: %v", tup[1]) + } + val.Value = v + vals[i] = val + } + + return vals, nil +} + +func mapEmptyStringToNil(s string) *string { + if s == "" { + return nil + } + return &s +} + +func stringPtrFromLoadBalancerServiceProtocol(p LoadBalancerServiceProtocol) *string { + return mapEmptyStringToNil(string(p)) +} + +func stringPtrFromNetworkZone(z NetworkZone) *string { + return mapEmptyStringToNil(string(z)) +} + +func mapZeroInt64ToNil(i int64) *int64 { + if i == 0 { + return nil + } + return &i +} + +func mapZeroUint64ToNil(i uint64) *uint64 { + if i == 0 { + return nil + } + return &i +} + +func schemaFromLoadBalancerCreateOptsTargetLabelSelector(l LoadBalancerCreateOptsTargetLabelSelector) *schema.LoadBalancerCreateRequestTargetLabelSelector { + if l.Selector == "" { + return nil + } + return &schema.LoadBalancerCreateRequestTargetLabelSelector{Selector: l.Selector} +} + +func schemaFromLoadBalancerCreateOptsTargetIP(l LoadBalancerCreateOptsTargetIP) *schema.LoadBalancerCreateRequestTargetIP { + if l.IP == "" { + return nil + } + return &schema.LoadBalancerCreateRequestTargetIP{IP: l.IP} +} + +func schemaFromLoadBalancerCreateOptsTargetServer(l LoadBalancerCreateOptsTargetServer) *schema.LoadBalancerCreateRequestTargetServer { + if l.Server == nil { + return nil + } + return &schema.LoadBalancerCreateRequestTargetServer{ID: l.Server.ID} +} + +func stringMapToStringMapPtr(m map[string]string) *map[string]string { + if m == nil { + return nil + } + return &m +} + +func rawSchemaFromErrorDetails(v interface{}) json.RawMessage { + d := schemaFromErrorDetails(v) + if v == nil { + return nil + } + msg, _ := json.Marshal(d) + return msg +} + +func mapZeroFloat32ToNil(f float32) *float32 { + if f == 0 { + return nil + } + return &f +} + +func isDeprecationNotNil(d *DeprecationInfo) bool { + return d != nil +} + +// int64SlicePtrFromCertificatePtrSlice is needed so that a nil slice is mapped to nil instead of &nil. +func int64SlicePtrFromCertificatePtrSlice(s []*Certificate) *[]int64 { + if s == nil { + return nil + } + var ids = make([]int64, len(s)) + for i, cert := range s { + ids[i] = cert.ID + } + return &ids +} + +func stringSlicePtrFromStringSlice(s []string) *[]string { + if s == nil { + return nil + } + return &s +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go new file mode 100644 index 000000000..a9f1cb95f --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server.go @@ -0,0 +1,1224 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net" + "net/http" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// Server represents a server in the Hetzner Cloud. +type Server struct { + ID int64 + Name string + Status ServerStatus + Created time.Time + PublicNet ServerPublicNet + PrivateNet []ServerPrivateNet + ServerType *ServerType + Datacenter *Datacenter + IncludedTraffic uint64 + OutgoingTraffic uint64 + IngoingTraffic uint64 + BackupWindow string + RescueEnabled bool + Locked bool + ISO *ISO + Image *Image + Protection ServerProtection + Labels map[string]string + Volumes []*Volume + PrimaryDiskSize int + PlacementGroup *PlacementGroup + LoadBalancers []*LoadBalancer +} + +// ServerProtection represents the protection level of a server. +type ServerProtection struct { + Delete, Rebuild bool +} + +// ServerStatus specifies a server's status. +type ServerStatus string + +const ( + // ServerStatusInitializing is the status when a server is initializing. + ServerStatusInitializing ServerStatus = "initializing" + + // ServerStatusOff is the status when a server is off. + ServerStatusOff ServerStatus = "off" + + // ServerStatusRunning is the status when a server is running. + ServerStatusRunning ServerStatus = "running" + + // ServerStatusStarting is the status when a server is being started. + ServerStatusStarting ServerStatus = "starting" + + // ServerStatusStopping is the status when a server is being stopped. + ServerStatusStopping ServerStatus = "stopping" + + // ServerStatusMigrating is the status when a server is being migrated. + ServerStatusMigrating ServerStatus = "migrating" + + // ServerStatusRebuilding is the status when a server is being rebuilt. + ServerStatusRebuilding ServerStatus = "rebuilding" + + // ServerStatusDeleting is the status when a server is being deleted. + ServerStatusDeleting ServerStatus = "deleting" + + // ServerStatusUnknown is the status when a server's state is unknown. + ServerStatusUnknown ServerStatus = "unknown" +) + +// FirewallStatus specifies a Firewall's status. +type FirewallStatus string + +const ( + // FirewallStatusPending is the status when a Firewall is pending. + FirewallStatusPending FirewallStatus = "pending" + + // FirewallStatusApplied is the status when a Firewall is applied. + FirewallStatusApplied FirewallStatus = "applied" +) + +// ServerPublicNet represents a server's public network. +type ServerPublicNet struct { + IPv4 ServerPublicNetIPv4 + IPv6 ServerPublicNetIPv6 + FloatingIPs []*FloatingIP + Firewalls []*ServerFirewallStatus +} + +// ServerPublicNetIPv4 represents a server's public IPv4 address. +type ServerPublicNetIPv4 struct { + ID int64 + IP net.IP + Blocked bool + DNSPtr string +} + +func (n *ServerPublicNetIPv4) IsUnspecified() bool { + return n.IP == nil || n.IP.Equal(net.IPv4zero) +} + +// ServerPublicNetIPv6 represents a Server's public IPv6 network and address. +type ServerPublicNetIPv6 struct { + ID int64 + IP net.IP + Network *net.IPNet + Blocked bool + DNSPtr map[string]string +} + +func (n *ServerPublicNetIPv6) IsUnspecified() bool { + return n.IP == nil || n.IP.Equal(net.IPv6unspecified) +} + +// ServerPrivateNet defines the schema of a Server's private network information. +type ServerPrivateNet struct { + Network *Network + IP net.IP + Aliases []net.IP + MACAddress string +} + +// DNSPtrForIP returns the reverse dns pointer of the ip address. +func (n *ServerPublicNetIPv6) DNSPtrForIP(ip net.IP) string { + return n.DNSPtr[ip.String()] +} + +// ServerFirewallStatus represents a Firewall and its status on a Server's +// network interface. +type ServerFirewallStatus struct { + Firewall Firewall + Status FirewallStatus +} + +// ServerRescueType represents rescue types. +type ServerRescueType string + +// List of rescue types. +const ( + // Deprecated: Use ServerRescueTypeLinux64 instead. + ServerRescueTypeLinux32 ServerRescueType = "linux32" + ServerRescueTypeLinux64 ServerRescueType = "linux64" +) + +// changeDNSPtr changes or resets the reverse DNS pointer for a IP address. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (s *Server) changeDNSPtr(ctx context.Context, client *Client, ip net.IP, ptr *string) (*Action, *Response, error) { + reqBody := schema.ServerActionChangeDNSPtrRequest{ + IP: ip.String(), + DNSPtr: ptr, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/change_dns_ptr", s.ID) + req, err := client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionChangeDNSPtrResponse{} + resp, err := client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// GetDNSPtrForIP searches for the dns assigned to the given IP address. +// It returns an error if there is no dns set for the given IP address. +func (s *Server) GetDNSPtrForIP(ip net.IP) (string, error) { + if net.IP.Equal(s.PublicNet.IPv4.IP, ip) { + return s.PublicNet.IPv4.DNSPtr, nil + } else if dns, ok := s.PublicNet.IPv6.DNSPtr[ip.String()]; ok { + return dns, nil + } + + return "", DNSNotFoundError{ip} +} + +// ServerClient is a client for the servers API. +type ServerClient struct { + client *Client + Action *ResourceActionClient +} + +// GetByID retrieves a server by its ID. If the server does not exist, nil is returned. +func (c *ServerClient) GetByID(ctx context.Context, id int64) (*Server, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/servers/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.ServerGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return ServerFromSchema(body.Server), resp, nil +} + +// GetByName retrieves a server by its name. If the server does not exist, nil is returned. +func (c *ServerClient) GetByName(ctx context.Context, name string) (*Server, *Response, error) { + if name == "" { + return nil, nil, nil + } + servers, response, err := c.List(ctx, ServerListOpts{Name: name}) + if len(servers) == 0 { + return nil, response, err + } + return servers[0], response, err +} + +// Get retrieves a server by its ID if the input can be parsed as an integer, otherwise it +// retrieves a server by its name. If the server does not exist, nil is returned. +func (c *ServerClient) Get(ctx context.Context, idOrName string) (*Server, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// ServerListOpts specifies options for listing servers. +type ServerListOpts struct { + ListOpts + Name string + Status []ServerStatus + Sort []string +} + +func (l ServerListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, status := range l.Status { + vals.Add("status", string(status)) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of servers for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *ServerClient) List(ctx context.Context, opts ServerListOpts) ([]*Server, *Response, error) { + path := "/servers?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.ServerListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + servers := make([]*Server, 0, len(body.Servers)) + for _, s := range body.Servers { + servers = append(servers, ServerFromSchema(s)) + } + return servers, resp, nil +} + +// All returns all servers. +func (c *ServerClient) All(ctx context.Context) ([]*Server, error) { + return c.AllWithOpts(ctx, ServerListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all servers for the given options. +func (c *ServerClient) AllWithOpts(ctx context.Context, opts ServerListOpts) ([]*Server, error) { + allServers := []*Server{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + servers, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allServers = append(allServers, servers...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allServers, nil +} + +// ServerCreateOpts specifies options for creating a new server. +type ServerCreateOpts struct { + Name string + ServerType *ServerType + Image *Image + SSHKeys []*SSHKey + Location *Location + Datacenter *Datacenter + UserData string + StartAfterCreate *bool + Labels map[string]string + Automount *bool + Volumes []*Volume + Networks []*Network + Firewalls []*ServerCreateFirewall + PlacementGroup *PlacementGroup + PublicNet *ServerCreatePublicNet +} + +type ServerCreatePublicNet struct { + EnableIPv4 bool + EnableIPv6 bool + IPv4 *PrimaryIP + IPv6 *PrimaryIP +} + +// ServerCreateFirewall defines which Firewalls to apply when creating a Server. +type ServerCreateFirewall struct { + Firewall Firewall +} + +// Validate checks if options are valid. +func (o ServerCreateOpts) Validate() error { + if o.Name == "" { + return errors.New("missing name") + } + if o.ServerType == nil || (o.ServerType.ID == 0 && o.ServerType.Name == "") { + return errors.New("missing server type") + } + if o.Image == nil || (o.Image.ID == 0 && o.Image.Name == "") { + return errors.New("missing image") + } + if o.Location != nil && o.Datacenter != nil { + return errors.New("location and datacenter are mutually exclusive") + } + if o.PublicNet != nil { + if !o.PublicNet.EnableIPv4 && !o.PublicNet.EnableIPv6 && + len(o.Networks) == 0 && (o.StartAfterCreate == nil || *o.StartAfterCreate) { + return errors.New("missing networks or StartAfterCreate == false when EnableIPv4 and EnableIPv6 is false") + } + } + return nil +} + +// ServerCreateResult is the result of a create server call. +type ServerCreateResult struct { + Server *Server + Action *Action + RootPassword string + NextActions []*Action +} + +// Create creates a new server. +func (c *ServerClient) Create(ctx context.Context, opts ServerCreateOpts) (ServerCreateResult, *Response, error) { + if err := opts.Validate(); err != nil { + return ServerCreateResult{}, nil, err + } + + var reqBody schema.ServerCreateRequest + reqBody.UserData = opts.UserData + reqBody.Name = opts.Name + reqBody.Automount = opts.Automount + reqBody.StartAfterCreate = opts.StartAfterCreate + if opts.ServerType.ID != 0 { + reqBody.ServerType = opts.ServerType.ID + } else if opts.ServerType.Name != "" { + reqBody.ServerType = opts.ServerType.Name + } + if opts.Image.ID != 0 { + reqBody.Image = opts.Image.ID + } else if opts.Image.Name != "" { + reqBody.Image = opts.Image.Name + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + for _, sshKey := range opts.SSHKeys { + reqBody.SSHKeys = append(reqBody.SSHKeys, sshKey.ID) + } + for _, volume := range opts.Volumes { + reqBody.Volumes = append(reqBody.Volumes, volume.ID) + } + for _, network := range opts.Networks { + reqBody.Networks = append(reqBody.Networks, network.ID) + } + for _, firewall := range opts.Firewalls { + reqBody.Firewalls = append(reqBody.Firewalls, schema.ServerCreateFirewalls{ + Firewall: firewall.Firewall.ID, + }) + } + + if opts.PublicNet != nil { + reqBody.PublicNet = &schema.ServerCreatePublicNet{ + EnableIPv4: opts.PublicNet.EnableIPv4, + EnableIPv6: opts.PublicNet.EnableIPv6, + } + if opts.PublicNet.IPv4 != nil { + reqBody.PublicNet.IPv4ID = opts.PublicNet.IPv4.ID + } + if opts.PublicNet.IPv6 != nil { + reqBody.PublicNet.IPv6ID = opts.PublicNet.IPv6.ID + } + } + if opts.Location != nil { + if opts.Location.ID != 0 { + reqBody.Location = strconv.FormatInt(opts.Location.ID, 10) + } else { + reqBody.Location = opts.Location.Name + } + } + if opts.Datacenter != nil { + if opts.Datacenter.ID != 0 { + reqBody.Datacenter = strconv.FormatInt(opts.Datacenter.ID, 10) + } else { + reqBody.Datacenter = opts.Datacenter.Name + } + } + if opts.PlacementGroup != nil { + reqBody.PlacementGroup = opts.PlacementGroup.ID + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return ServerCreateResult{}, nil, err + } + + req, err := c.client.NewRequest(ctx, "POST", "/servers", bytes.NewReader(reqBodyData)) + if err != nil { + return ServerCreateResult{}, nil, err + } + + var respBody schema.ServerCreateResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return ServerCreateResult{}, resp, err + } + result := ServerCreateResult{ + Server: ServerFromSchema(respBody.Server), + Action: ActionFromSchema(respBody.Action), + NextActions: ActionsFromSchema(respBody.NextActions), + } + if respBody.RootPassword != nil { + result.RootPassword = *respBody.RootPassword + } + return result, resp, nil +} + +// ServerDeleteResult is the result of a delete server call. +type ServerDeleteResult struct { + Action *Action +} + +// Delete deletes a server. +// +// Deprecated: Use [ServerClient.DeleteWithResult] instead. +func (c *ServerClient) Delete(ctx context.Context, server *Server) (*Response, error) { + _, resp, err := c.DeleteWithResult(ctx, server) + return resp, err +} + +// DeleteWithResult deletes a server and returns the parsed response containing the action. +func (c *ServerClient) DeleteWithResult(ctx context.Context, server *Server) (*ServerDeleteResult, *Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/servers/%d", server.ID), nil) + if err != nil { + return &ServerDeleteResult{}, nil, err + } + + var respBody schema.ServerDeleteResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return &ServerDeleteResult{}, resp, err + } + + return &ServerDeleteResult{ + Action: ActionFromSchema(respBody.Action), + }, resp, nil +} + +// ServerUpdateOpts specifies options for updating a server. +type ServerUpdateOpts struct { + Name string + Labels map[string]string +} + +// Update updates a server. +func (c *ServerClient) Update(ctx context.Context, server *Server, opts ServerUpdateOpts) (*Server, *Response, error) { + reqBody := schema.ServerUpdateRequest{ + Name: opts.Name, + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d", server.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ServerFromSchema(respBody.Server), resp, nil +} + +// Poweron starts a server. +func (c *ServerClient) Poweron(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/poweron", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionPoweronResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// Reboot reboots a server. +func (c *ServerClient) Reboot(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/reboot", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionRebootResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// Reset resets a server. +func (c *ServerClient) Reset(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/reset", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionResetResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// Shutdown shuts down a server. +func (c *ServerClient) Shutdown(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/shutdown", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionShutdownResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// Poweroff stops a server. +func (c *ServerClient) Poweroff(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/poweroff", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionPoweroffResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// ServerResetPasswordResult is the result of resetting a server's password. +type ServerResetPasswordResult struct { + Action *Action + RootPassword string +} + +// ResetPassword resets a server's password. +func (c *ServerClient) ResetPassword(ctx context.Context, server *Server) (ServerResetPasswordResult, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/reset_password", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return ServerResetPasswordResult{}, nil, err + } + + respBody := schema.ServerActionResetPasswordResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return ServerResetPasswordResult{}, resp, err + } + return ServerResetPasswordResult{ + Action: ActionFromSchema(respBody.Action), + RootPassword: respBody.RootPassword, + }, resp, nil +} + +// ServerCreateImageOpts specifies options for creating an image from a server. +type ServerCreateImageOpts struct { + Type ImageType + Description *string + Labels map[string]string +} + +// Validate checks if options are valid. +func (o ServerCreateImageOpts) Validate() error { + switch o.Type { + case ImageTypeSnapshot, ImageTypeBackup: + break + case "": + break + default: + return errors.New("invalid type") + } + + return nil +} + +// ServerCreateImageResult is the result of creating an image from a server. +type ServerCreateImageResult struct { + Action *Action + Image *Image +} + +// CreateImage creates an image from a server. +func (c *ServerClient) CreateImage(ctx context.Context, server *Server, opts *ServerCreateImageOpts) (ServerCreateImageResult, *Response, error) { + var reqBody schema.ServerActionCreateImageRequest + if opts != nil { + if err := opts.Validate(); err != nil { + return ServerCreateImageResult{}, nil, fmt.Errorf("invalid options: %s", err) + } + if opts.Description != nil { + reqBody.Description = opts.Description + } + if opts.Type != "" { + reqBody.Type = Ptr(string(opts.Type)) + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return ServerCreateImageResult{}, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/create_image", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return ServerCreateImageResult{}, nil, err + } + + respBody := schema.ServerActionCreateImageResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return ServerCreateImageResult{}, resp, err + } + return ServerCreateImageResult{ + Action: ActionFromSchema(respBody.Action), + Image: ImageFromSchema(respBody.Image), + }, resp, nil +} + +// ServerEnableRescueOpts specifies options for enabling rescue mode for a server. +type ServerEnableRescueOpts struct { + Type ServerRescueType + SSHKeys []*SSHKey +} + +// ServerEnableRescueResult is the result of enabling rescue mode for a server. +type ServerEnableRescueResult struct { + Action *Action + RootPassword string +} + +// EnableRescue enables rescue mode for a server. +func (c *ServerClient) EnableRescue(ctx context.Context, server *Server, opts ServerEnableRescueOpts) (ServerEnableRescueResult, *Response, error) { + reqBody := schema.ServerActionEnableRescueRequest{ + Type: Ptr(string(opts.Type)), + } + for _, sshKey := range opts.SSHKeys { + reqBody.SSHKeys = append(reqBody.SSHKeys, sshKey.ID) + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return ServerEnableRescueResult{}, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/enable_rescue", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return ServerEnableRescueResult{}, nil, err + } + + respBody := schema.ServerActionEnableRescueResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return ServerEnableRescueResult{}, resp, err + } + result := ServerEnableRescueResult{ + Action: ActionFromSchema(respBody.Action), + RootPassword: respBody.RootPassword, + } + return result, resp, nil +} + +// DisableRescue disables rescue mode for a server. +func (c *ServerClient) DisableRescue(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/disable_rescue", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionDisableRescueResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// ServerRebuildOpts specifies options for rebuilding a server. +type ServerRebuildOpts struct { + Image *Image +} + +// ServerRebuildResult is the result of a create server call. +type ServerRebuildResult struct { + Action *Action + RootPassword string +} + +// Rebuild rebuilds a server. +// +// Deprecated: Use [ServerClient.RebuildWithResult] instead. +func (c *ServerClient) Rebuild(ctx context.Context, server *Server, opts ServerRebuildOpts) (*Action, *Response, error) { + result, resp, err := c.RebuildWithResult(ctx, server, opts) + + return result.Action, resp, err +} + +// RebuildWithResult rebuilds a server. +func (c *ServerClient) RebuildWithResult(ctx context.Context, server *Server, opts ServerRebuildOpts) (ServerRebuildResult, *Response, error) { + reqBody := schema.ServerActionRebuildRequest{} + if opts.Image.ID != 0 { + reqBody.Image = opts.Image.ID + } else { + reqBody.Image = opts.Image.Name + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return ServerRebuildResult{}, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/rebuild", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return ServerRebuildResult{}, nil, err + } + + respBody := schema.ServerActionRebuildResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return ServerRebuildResult{}, resp, err + } + + result := ServerRebuildResult{ + Action: ActionFromSchema(respBody.Action), + } + if respBody.RootPassword != nil { + result.RootPassword = *respBody.RootPassword + } + + return result, resp, nil +} + +// AttachISO attaches an ISO to a server. +func (c *ServerClient) AttachISO(ctx context.Context, server *Server, iso *ISO) (*Action, *Response, error) { + reqBody := schema.ServerActionAttachISORequest{} + if iso.ID != 0 { + reqBody.ISO = iso.ID + } else { + reqBody.ISO = iso.Name + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/attach_iso", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionAttachISOResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// DetachISO detaches the currently attached ISO from a server. +func (c *ServerClient) DetachISO(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/detach_iso", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionDetachISOResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// EnableBackup enables backup for a server. Pass in an empty backup window to let the +// API pick a window for you. See the API documentation at docs.hetzner.cloud for a list +// of valid backup windows. +func (c *ServerClient) EnableBackup(ctx context.Context, server *Server, window string) (*Action, *Response, error) { + reqBody := schema.ServerActionEnableBackupRequest{} + if window != "" { + reqBody.BackupWindow = Ptr(window) + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/enable_backup", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionEnableBackupResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// DisableBackup disables backup for a server. +func (c *ServerClient) DisableBackup(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/disable_backup", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionDisableBackupResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// ServerChangeTypeOpts specifies options for changing a server's type. +type ServerChangeTypeOpts struct { + ServerType *ServerType // new server type + UpgradeDisk bool // whether disk should be upgraded +} + +// ChangeType changes a server's type. +func (c *ServerClient) ChangeType(ctx context.Context, server *Server, opts ServerChangeTypeOpts) (*Action, *Response, error) { + reqBody := schema.ServerActionChangeTypeRequest{ + UpgradeDisk: opts.UpgradeDisk, + } + if opts.ServerType.ID != 0 { + reqBody.ServerType = opts.ServerType.ID + } else { + reqBody.ServerType = opts.ServerType.Name + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/change_type", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionChangeTypeResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// ChangeDNSPtr changes or resets the reverse DNS pointer for a server IP address. +// Pass a nil ptr to reset the reverse DNS pointer to its default value. +func (c *ServerClient) ChangeDNSPtr(ctx context.Context, server *Server, ip string, ptr *string) (*Action, *Response, error) { + netIP := net.ParseIP(ip) + if netIP == nil { + return nil, nil, InvalidIPError{ip} + } + return server.changeDNSPtr(ctx, c.client, net.ParseIP(ip), ptr) +} + +// ServerChangeProtectionOpts specifies options for changing the resource protection level of a server. +type ServerChangeProtectionOpts struct { + Rebuild *bool + Delete *bool +} + +// ChangeProtection changes the resource protection level of a server. +func (c *ServerClient) ChangeProtection(ctx context.Context, server *Server, opts ServerChangeProtectionOpts) (*Action, *Response, error) { + reqBody := schema.ServerActionChangeProtectionRequest{ + Rebuild: opts.Rebuild, + Delete: opts.Delete, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/change_protection", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionChangeProtectionResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// ServerRequestConsoleResult is the result of requesting a WebSocket VNC console. +type ServerRequestConsoleResult struct { + Action *Action + WSSURL string + Password string +} + +// RequestConsole requests a WebSocket VNC console. +func (c *ServerClient) RequestConsole(ctx context.Context, server *Server) (ServerRequestConsoleResult, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/request_console", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return ServerRequestConsoleResult{}, nil, err + } + + respBody := schema.ServerActionRequestConsoleResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return ServerRequestConsoleResult{}, resp, err + } + return ServerRequestConsoleResult{ + Action: ActionFromSchema(respBody.Action), + WSSURL: respBody.WSSURL, + Password: respBody.Password, + }, resp, nil +} + +// ServerAttachToNetworkOpts specifies options for attaching a server to a network. +type ServerAttachToNetworkOpts struct { + Network *Network + IP net.IP + AliasIPs []net.IP +} + +// AttachToNetwork attaches a server to a network. +func (c *ServerClient) AttachToNetwork(ctx context.Context, server *Server, opts ServerAttachToNetworkOpts) (*Action, *Response, error) { + reqBody := schema.ServerActionAttachToNetworkRequest{ + Network: opts.Network.ID, + } + if opts.IP != nil { + reqBody.IP = Ptr(opts.IP.String()) + } + for _, aliasIP := range opts.AliasIPs { + reqBody.AliasIPs = append(reqBody.AliasIPs, Ptr(aliasIP.String())) + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/attach_to_network", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionAttachToNetworkResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// ServerDetachFromNetworkOpts specifies options for detaching a server from a network. +type ServerDetachFromNetworkOpts struct { + Network *Network +} + +// DetachFromNetwork detaches a server from a network. +func (c *ServerClient) DetachFromNetwork(ctx context.Context, server *Server, opts ServerDetachFromNetworkOpts) (*Action, *Response, error) { + reqBody := schema.ServerActionDetachFromNetworkRequest{ + Network: opts.Network.ID, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/servers/%d/actions/detach_from_network", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionDetachFromNetworkResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// ServerChangeAliasIPsOpts specifies options for changing the alias ips of an already attached network. +type ServerChangeAliasIPsOpts struct { + Network *Network + AliasIPs []net.IP +} + +// ChangeAliasIPs changes a server's alias IPs in a network. +func (c *ServerClient) ChangeAliasIPs(ctx context.Context, server *Server, opts ServerChangeAliasIPsOpts) (*Action, *Response, error) { + reqBody := schema.ServerActionChangeAliasIPsRequest{ + Network: opts.Network.ID, + AliasIPs: []string{}, + } + for _, aliasIP := range opts.AliasIPs { + reqBody.AliasIPs = append(reqBody.AliasIPs, aliasIP.String()) + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("/servers/%d/actions/change_alias_ips", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionDetachFromNetworkResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// ServerMetricType is the type of available metrics for servers. +type ServerMetricType string + +// Available types of server metrics. See Hetzner Cloud API documentation for +// details. +const ( + ServerMetricCPU ServerMetricType = "cpu" + ServerMetricDisk ServerMetricType = "disk" + ServerMetricNetwork ServerMetricType = "network" +) + +// ServerGetMetricsOpts configures the call to get metrics for a Server. +type ServerGetMetricsOpts struct { + Types []ServerMetricType + Start time.Time + End time.Time + Step int +} + +func (o *ServerGetMetricsOpts) addQueryParams(req *http.Request) error { + query := req.URL.Query() + + if len(o.Types) == 0 { + return fmt.Errorf("no metric types specified") + } + for _, typ := range o.Types { + query.Add("type", string(typ)) + } + + if o.Start.IsZero() { + return fmt.Errorf("no start time specified") + } + query.Add("start", o.Start.Format(time.RFC3339)) + + if o.End.IsZero() { + return fmt.Errorf("no end time specified") + } + query.Add("end", o.End.Format(time.RFC3339)) + + if o.Step > 0 { + query.Add("step", strconv.Itoa(o.Step)) + } + req.URL.RawQuery = query.Encode() + + return nil +} + +// ServerMetrics contains the metrics requested for a Server. +type ServerMetrics struct { + Start time.Time + End time.Time + Step float64 + TimeSeries map[string][]ServerMetricsValue +} + +// ServerMetricsValue represents a single value in a time series of metrics. +type ServerMetricsValue struct { + Timestamp float64 + Value string +} + +// GetMetrics obtains metrics for Server. +func (c *ServerClient) GetMetrics(ctx context.Context, server *Server, opts ServerGetMetricsOpts) (*ServerMetrics, *Response, error) { + var respBody schema.ServerGetMetricsResponse + + if server == nil { + return nil, nil, fmt.Errorf("illegal argument: server is nil") + } + + path := fmt.Sprintf("/servers/%d/metrics", server.ID) + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, fmt.Errorf("new request: %v", err) + } + if err := opts.addQueryParams(req); err != nil { + return nil, nil, fmt.Errorf("add query params: %v", err) + } + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, nil, fmt.Errorf("get metrics: %v", err) + } + ms, err := serverMetricsFromSchema(&respBody) + if err != nil { + return nil, nil, fmt.Errorf("convert response body: %v", err) + } + return ms, resp, nil +} + +func (c *ServerClient) AddToPlacementGroup(ctx context.Context, server *Server, placementGroup *PlacementGroup) (*Action, *Response, error) { + reqBody := schema.ServerActionAddToPlacementGroupRequest{ + PlacementGroup: placementGroup.ID, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("/servers/%d/actions/add_to_placement_group", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionAddToPlacementGroupResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +func (c *ServerClient) RemoveFromPlacementGroup(ctx context.Context, server *Server) (*Action, *Response, error) { + path := fmt.Sprintf("/servers/%d/actions/remove_from_placement_group", server.ID) + req, err := c.client.NewRequest(ctx, "POST", path, nil) + if err != nil { + return nil, nil, err + } + + respBody := schema.ServerActionRemoveFromPlacementGroupResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server_type.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server_type.go new file mode 100644 index 000000000..029fe1ff6 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/server_type.go @@ -0,0 +1,159 @@ +package hcloud + +import ( + "context" + "fmt" + "net/url" + "strconv" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// ServerType represents a server type in the Hetzner Cloud. +type ServerType struct { + ID int64 + Name string + Description string + Cores int + Memory float32 + Disk int + StorageType StorageType + CPUType CPUType + Architecture Architecture + // IncludedTraffic is the free traffic per month in bytes + IncludedTraffic int64 + Pricings []ServerTypeLocationPricing + DeprecatableResource +} + +// StorageType specifies the type of storage. +type StorageType string + +const ( + // StorageTypeLocal is the type for local storage. + StorageTypeLocal StorageType = "local" + + // StorageTypeCeph is the type for remote storage. + StorageTypeCeph StorageType = "ceph" +) + +// CPUType specifies the type of the CPU. +type CPUType string + +const ( + // CPUTypeShared is the type for shared CPU. + CPUTypeShared CPUType = "shared" + + // CPUTypeDedicated is the type for dedicated CPU. + CPUTypeDedicated CPUType = "dedicated" +) + +// ServerTypeClient is a client for the server types API. +type ServerTypeClient struct { + client *Client +} + +// GetByID retrieves a server type by its ID. If the server type does not exist, nil is returned. +func (c *ServerTypeClient) GetByID(ctx context.Context, id int64) (*ServerType, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/server_types/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.ServerTypeGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return ServerTypeFromSchema(body.ServerType), resp, nil +} + +// GetByName retrieves a server type by its name. If the server type does not exist, nil is returned. +func (c *ServerTypeClient) GetByName(ctx context.Context, name string) (*ServerType, *Response, error) { + if name == "" { + return nil, nil, nil + } + serverTypes, response, err := c.List(ctx, ServerTypeListOpts{Name: name}) + if len(serverTypes) == 0 { + return nil, response, err + } + return serverTypes[0], response, err +} + +// Get retrieves a server type by its ID if the input can be parsed as an integer, otherwise it +// retrieves a server type by its name. If the server type does not exist, nil is returned. +func (c *ServerTypeClient) Get(ctx context.Context, idOrName string) (*ServerType, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// ServerTypeListOpts specifies options for listing server types. +type ServerTypeListOpts struct { + ListOpts + Name string + Sort []string +} + +func (l ServerTypeListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of server types for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *ServerTypeClient) List(ctx context.Context, opts ServerTypeListOpts) ([]*ServerType, *Response, error) { + path := "/server_types?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.ServerTypeListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + serverTypes := make([]*ServerType, 0, len(body.ServerTypes)) + for _, s := range body.ServerTypes { + serverTypes = append(serverTypes, ServerTypeFromSchema(s)) + } + return serverTypes, resp, nil +} + +// All returns all server types. +func (c *ServerTypeClient) All(ctx context.Context) ([]*ServerType, error) { + return c.AllWithOpts(ctx, ServerTypeListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all server types for the given options. +func (c *ServerTypeClient) AllWithOpts(ctx context.Context, opts ServerTypeListOpts) ([]*ServerType, error) { + allServerTypes := []*ServerType{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + serverTypes, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allServerTypes = append(allServerTypes, serverTypes...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allServerTypes, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/ssh_key.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/ssh_key.go new file mode 100644 index 000000000..45d4558f9 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/ssh_key.go @@ -0,0 +1,237 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// SSHKey represents a SSH key in the Hetzner Cloud. +type SSHKey struct { + ID int64 + Name string + Fingerprint string + PublicKey string + Labels map[string]string + Created time.Time +} + +// SSHKeyClient is a client for the SSH keys API. +type SSHKeyClient struct { + client *Client +} + +// GetByID retrieves a SSH key by its ID. If the SSH key does not exist, nil is returned. +func (c *SSHKeyClient) GetByID(ctx context.Context, id int64) (*SSHKey, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/ssh_keys/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.SSHKeyGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return SSHKeyFromSchema(body.SSHKey), resp, nil +} + +// GetByName retrieves a SSH key by its name. If the SSH key does not exist, nil is returned. +func (c *SSHKeyClient) GetByName(ctx context.Context, name string) (*SSHKey, *Response, error) { + if name == "" { + return nil, nil, nil + } + sshKeys, response, err := c.List(ctx, SSHKeyListOpts{Name: name}) + if len(sshKeys) == 0 { + return nil, response, err + } + return sshKeys[0], response, err +} + +// GetByFingerprint retreives a SSH key by its fingerprint. If the SSH key does not exist, nil is returned. +func (c *SSHKeyClient) GetByFingerprint(ctx context.Context, fingerprint string) (*SSHKey, *Response, error) { + sshKeys, response, err := c.List(ctx, SSHKeyListOpts{Fingerprint: fingerprint}) + if len(sshKeys) == 0 { + return nil, response, err + } + return sshKeys[0], response, err +} + +// Get retrieves a SSH key by its ID if the input can be parsed as an integer, otherwise it +// retrieves a SSH key by its name. If the SSH key does not exist, nil is returned. +func (c *SSHKeyClient) Get(ctx context.Context, idOrName string) (*SSHKey, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// SSHKeyListOpts specifies options for listing SSH keys. +type SSHKeyListOpts struct { + ListOpts + Name string + Fingerprint string + Sort []string +} + +func (l SSHKeyListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + if l.Fingerprint != "" { + vals.Add("fingerprint", l.Fingerprint) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of SSH keys for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *SSHKeyClient) List(ctx context.Context, opts SSHKeyListOpts) ([]*SSHKey, *Response, error) { + path := "/ssh_keys?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.SSHKeyListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + sshKeys := make([]*SSHKey, 0, len(body.SSHKeys)) + for _, s := range body.SSHKeys { + sshKeys = append(sshKeys, SSHKeyFromSchema(s)) + } + return sshKeys, resp, nil +} + +// All returns all SSH keys. +func (c *SSHKeyClient) All(ctx context.Context) ([]*SSHKey, error) { + return c.AllWithOpts(ctx, SSHKeyListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all SSH keys with the given options. +func (c *SSHKeyClient) AllWithOpts(ctx context.Context, opts SSHKeyListOpts) ([]*SSHKey, error) { + allSSHKeys := []*SSHKey{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + sshKeys, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allSSHKeys = append(allSSHKeys, sshKeys...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allSSHKeys, nil +} + +// SSHKeyCreateOpts specifies parameters for creating a SSH key. +type SSHKeyCreateOpts struct { + Name string + PublicKey string + Labels map[string]string +} + +// Validate checks if options are valid. +func (o SSHKeyCreateOpts) Validate() error { + if o.Name == "" { + return errors.New("missing name") + } + if o.PublicKey == "" { + return errors.New("missing public key") + } + return nil +} + +// Create creates a new SSH key with the given options. +func (c *SSHKeyClient) Create(ctx context.Context, opts SSHKeyCreateOpts) (*SSHKey, *Response, error) { + if err := opts.Validate(); err != nil { + return nil, nil, err + } + reqBody := schema.SSHKeyCreateRequest{ + Name: opts.Name, + PublicKey: opts.PublicKey, + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + req, err := c.client.NewRequest(ctx, "POST", "/ssh_keys", bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.SSHKeyCreateResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return SSHKeyFromSchema(respBody.SSHKey), resp, nil +} + +// Delete deletes a SSH key. +func (c *SSHKeyClient) Delete(ctx context.Context, sshKey *SSHKey) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/ssh_keys/%d", sshKey.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +// SSHKeyUpdateOpts specifies options for updating a SSH key. +type SSHKeyUpdateOpts struct { + Name string + Labels map[string]string +} + +// Update updates a SSH key. +func (c *SSHKeyClient) Update(ctx context.Context, sshKey *SSHKey, opts SSHKeyUpdateOpts) (*SSHKey, *Response, error) { + reqBody := schema.SSHKeyUpdateRequest{ + Name: opts.Name, + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/ssh_keys/%d", sshKey.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.SSHKeyUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return SSHKeyFromSchema(respBody.SSHKey), resp, nil +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/testing.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/testing.go new file mode 100644 index 000000000..63cd92f7b --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/testing.go @@ -0,0 +1,16 @@ +package hcloud + +import ( + "testing" + "time" +) + +func mustParseTime(t *testing.T, value string) time.Time { + t.Helper() + + ts, err := time.Parse(time.RFC3339, value) + if err != nil { + t.Fatalf("parse time: value %v: %v", value, err) + } + return ts +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go new file mode 100644 index 000000000..c744b5a8c --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/volume.go @@ -0,0 +1,410 @@ +package hcloud + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "net/url" + "strconv" + "time" + + "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" +) + +// Volume represents a volume in the Hetzner Cloud. +type Volume struct { + ID int64 + Name string + Status VolumeStatus + Server *Server + Location *Location + Size int + Format *string + Protection VolumeProtection + Labels map[string]string + LinuxDevice string + Created time.Time +} + +const ( + VolumeFormatExt4 = "ext4" + VolumeFormatXFS = "xfs" +) + +// VolumeProtection represents the protection level of a volume. +type VolumeProtection struct { + Delete bool +} + +// VolumeClient is a client for the volume API. +type VolumeClient struct { + client *Client + Action *ResourceActionClient +} + +// VolumeStatus specifies a volume's status. +type VolumeStatus string + +const ( + // VolumeStatusCreating is the status when a volume is being created. + VolumeStatusCreating VolumeStatus = "creating" + + // VolumeStatusAvailable is the status when a volume is available. + VolumeStatusAvailable VolumeStatus = "available" +) + +// GetByID retrieves a volume by its ID. If the volume does not exist, nil is returned. +func (c *VolumeClient) GetByID(ctx context.Context, id int64) (*Volume, *Response, error) { + req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/volumes/%d", id), nil) + if err != nil { + return nil, nil, err + } + + var body schema.VolumeGetResponse + resp, err := c.client.Do(req, &body) + if err != nil { + if IsError(err, ErrorCodeNotFound) { + return nil, resp, nil + } + return nil, nil, err + } + return VolumeFromSchema(body.Volume), resp, nil +} + +// GetByName retrieves a volume by its name. If the volume does not exist, nil is returned. +func (c *VolumeClient) GetByName(ctx context.Context, name string) (*Volume, *Response, error) { + if name == "" { + return nil, nil, nil + } + volumes, response, err := c.List(ctx, VolumeListOpts{Name: name}) + if len(volumes) == 0 { + return nil, response, err + } + return volumes[0], response, err +} + +// Get retrieves a volume by its ID if the input can be parsed as an integer, otherwise it +// retrieves a volume by its name. If the volume does not exist, nil is returned. +func (c *VolumeClient) Get(ctx context.Context, idOrName string) (*Volume, *Response, error) { + if id, err := strconv.ParseInt(idOrName, 10, 64); err == nil { + return c.GetByID(ctx, id) + } + return c.GetByName(ctx, idOrName) +} + +// VolumeListOpts specifies options for listing volumes. +type VolumeListOpts struct { + ListOpts + Name string + Status []VolumeStatus + Sort []string +} + +func (l VolumeListOpts) values() url.Values { + vals := l.ListOpts.Values() + if l.Name != "" { + vals.Add("name", l.Name) + } + for _, status := range l.Status { + vals.Add("status", string(status)) + } + for _, sort := range l.Sort { + vals.Add("sort", sort) + } + return vals +} + +// List returns a list of volumes for a specific page. +// +// Please note that filters specified in opts are not taken into account +// when their value corresponds to their zero value or when they are empty. +func (c *VolumeClient) List(ctx context.Context, opts VolumeListOpts) ([]*Volume, *Response, error) { + path := "/volumes?" + opts.values().Encode() + req, err := c.client.NewRequest(ctx, "GET", path, nil) + if err != nil { + return nil, nil, err + } + + var body schema.VolumeListResponse + resp, err := c.client.Do(req, &body) + if err != nil { + return nil, nil, err + } + volumes := make([]*Volume, 0, len(body.Volumes)) + for _, s := range body.Volumes { + volumes = append(volumes, VolumeFromSchema(s)) + } + return volumes, resp, nil +} + +// All returns all volumes. +func (c *VolumeClient) All(ctx context.Context) ([]*Volume, error) { + return c.AllWithOpts(ctx, VolumeListOpts{ListOpts: ListOpts{PerPage: 50}}) +} + +// AllWithOpts returns all volumes with the given options. +func (c *VolumeClient) AllWithOpts(ctx context.Context, opts VolumeListOpts) ([]*Volume, error) { + allVolumes := []*Volume{} + + err := c.client.all(func(page int) (*Response, error) { + opts.Page = page + volumes, resp, err := c.List(ctx, opts) + if err != nil { + return resp, err + } + allVolumes = append(allVolumes, volumes...) + return resp, nil + }) + if err != nil { + return nil, err + } + + return allVolumes, nil +} + +// VolumeCreateOpts specifies parameters for creating a volume. +type VolumeCreateOpts struct { + Name string + Size int + Server *Server + Location *Location + Labels map[string]string + Automount *bool + Format *string +} + +// Validate checks if options are valid. +func (o VolumeCreateOpts) Validate() error { + if o.Name == "" { + return errors.New("missing name") + } + if o.Size <= 0 { + return errors.New("size must be greater than 0") + } + if o.Server == nil && o.Location == nil { + return errors.New("one of server or location must be provided") + } + if o.Server != nil && o.Location != nil { + return errors.New("only one of server or location must be provided") + } + if o.Server == nil && (o.Automount != nil && *o.Automount) { + return errors.New("server must be provided when automount is true") + } + return nil +} + +// VolumeCreateResult is the result of creating a volume. +type VolumeCreateResult struct { + Volume *Volume + Action *Action + NextActions []*Action +} + +// Create creates a new volume with the given options. +func (c *VolumeClient) Create(ctx context.Context, opts VolumeCreateOpts) (VolumeCreateResult, *Response, error) { + if err := opts.Validate(); err != nil { + return VolumeCreateResult{}, nil, err + } + reqBody := schema.VolumeCreateRequest{ + Name: opts.Name, + Size: opts.Size, + Automount: opts.Automount, + Format: opts.Format, + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + if opts.Server != nil { + reqBody.Server = Ptr(opts.Server.ID) + } + if opts.Location != nil { + if opts.Location.ID != 0 { + reqBody.Location = opts.Location.ID + } else { + reqBody.Location = opts.Location.Name + } + } + + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return VolumeCreateResult{}, nil, err + } + + req, err := c.client.NewRequest(ctx, "POST", "/volumes", bytes.NewReader(reqBodyData)) + if err != nil { + return VolumeCreateResult{}, nil, err + } + + var respBody schema.VolumeCreateResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return VolumeCreateResult{}, resp, err + } + + var action *Action + if respBody.Action != nil { + action = ActionFromSchema(*respBody.Action) + } + + return VolumeCreateResult{ + Volume: VolumeFromSchema(respBody.Volume), + Action: action, + NextActions: ActionsFromSchema(respBody.NextActions), + }, resp, nil +} + +// Delete deletes a volume. +func (c *VolumeClient) Delete(ctx context.Context, volume *Volume) (*Response, error) { + req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/volumes/%d", volume.ID), nil) + if err != nil { + return nil, err + } + return c.client.Do(req, nil) +} + +// VolumeUpdateOpts specifies options for updating a volume. +type VolumeUpdateOpts struct { + Name string + Labels map[string]string +} + +// Update updates a volume. +func (c *VolumeClient) Update(ctx context.Context, volume *Volume, opts VolumeUpdateOpts) (*Volume, *Response, error) { + reqBody := schema.VolumeUpdateRequest{ + Name: opts.Name, + } + if opts.Labels != nil { + reqBody.Labels = &opts.Labels + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/volumes/%d", volume.ID) + req, err := c.client.NewRequest(ctx, "PUT", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.VolumeUpdateResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return VolumeFromSchema(respBody.Volume), resp, nil +} + +// VolumeAttachOpts specifies options for attaching a volume. +type VolumeAttachOpts struct { + Server *Server + Automount *bool +} + +// AttachWithOpts attaches a volume to a server. +func (c *VolumeClient) AttachWithOpts(ctx context.Context, volume *Volume, opts VolumeAttachOpts) (*Action, *Response, error) { + reqBody := schema.VolumeActionAttachVolumeRequest{ + Server: opts.Server.ID, + Automount: opts.Automount, + } + + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/volumes/%d/actions/attach", volume.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.VolumeActionAttachVolumeResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// Attach attaches a volume to a server. +func (c *VolumeClient) Attach(ctx context.Context, volume *Volume, server *Server) (*Action, *Response, error) { + return c.AttachWithOpts(ctx, volume, VolumeAttachOpts{Server: server}) +} + +// Detach detaches a volume from a server. +func (c *VolumeClient) Detach(ctx context.Context, volume *Volume) (*Action, *Response, error) { + var reqBody schema.VolumeActionDetachVolumeRequest + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/volumes/%d/actions/detach", volume.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + var respBody schema.VolumeActionDetachVolumeResponse + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, nil +} + +// VolumeChangeProtectionOpts specifies options for changing the resource protection level of a volume. +type VolumeChangeProtectionOpts struct { + Delete *bool +} + +// ChangeProtection changes the resource protection level of a volume. +func (c *VolumeClient) ChangeProtection(ctx context.Context, volume *Volume, opts VolumeChangeProtectionOpts) (*Action, *Response, error) { + reqBody := schema.VolumeActionChangeProtectionRequest{ + Delete: opts.Delete, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/volumes/%d/actions/change_protection", volume.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.VolumeActionChangeProtectionResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} + +// Resize changes the size of a volume. +func (c *VolumeClient) Resize(ctx context.Context, volume *Volume, size int) (*Action, *Response, error) { + reqBody := schema.VolumeActionResizeVolumeRequest{ + Size: size, + } + reqBodyData, err := json.Marshal(reqBody) + if err != nil { + return nil, nil, err + } + + path := fmt.Sprintf("/volumes/%d/actions/resize", volume.ID) + req, err := c.client.NewRequest(ctx, "POST", path, bytes.NewReader(reqBodyData)) + if err != nil { + return nil, nil, err + } + + respBody := schema.VolumeActionResizeVolumeResponse{} + resp, err := c.client.Do(req, &respBody) + if err != nil { + return nil, resp, err + } + return ActionFromSchema(respBody.Action), resp, err +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go new file mode 100644 index 000000000..13f8665df --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_action_client_iface.go @@ -0,0 +1,79 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IActionClient ... +type IActionClient interface { + // GetByID retrieves an action by its ID. If the action does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Action, *Response, error) + // List returns a list of actions for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts ActionListOpts) ([]*Action, *Response, error) + // All returns all actions. + All(ctx context.Context) ([]*Action, error) + // AllWithOpts returns all actions for the given options. + AllWithOpts(ctx context.Context, opts ActionListOpts) ([]*Action, error) + // WatchOverallProgress watches several actions' progress until they complete + // with success or error. This watching happens in a goroutine and updates are + // provided through the two returned channels: + // + // - The first channel receives percentage updates of the progress, based on + // the number of completed versus total watched actions. The return value + // is an int between 0 and 100. + // - The second channel returned receives errors for actions that did not + // complete successfully, as well as any errors that happened while + // querying the API. + // + // By default, the method keeps watching until all actions have finished + // processing. If you want to be able to cancel the method or configure a + // timeout, use the [context.Context]. Once the method has stopped watching, + // both returned channels are closed. + // + // WatchOverallProgress uses the [WithPollBackoffFunc] of the [Client] to wait + // until sending the next request. + // + // Deprecated: WatchOverallProgress is deprecated, use [WaitForFunc] instead. + WatchOverallProgress(ctx context.Context, actions []*Action) (<-chan int, <-chan error) + // WatchProgress watches one action's progress until it completes with success + // or error. This watching happens in a goroutine and updates are provided + // through the two returned channels: + // + // - The first channel receives percentage updates of the progress, based on + // the progress percentage indicated by the API. The return value is an int + // between 0 and 100. + // - The second channel receives any errors that happened while querying the + // API, as well as the error of the action if it did not complete + // successfully, or nil if it did. + // + // By default, the method keeps watching until the action has finished + // processing. If you want to be able to cancel the method or configure a + // timeout, use the [context.Context]. Once the method has stopped watching, + // both returned channels are closed. + // + // WatchProgress uses the [WithPollBackoffFunc] of the [Client] to wait until + // sending the next request. + // + // Deprecated: WatchProgress is deprecated, use [WaitForFunc] instead. + WatchProgress(ctx context.Context, action *Action) (<-chan int, <-chan error) + // WaitForFunc waits until all actions are completed by polling the API at the interval + // defined by [WithPollBackoffFunc]. An action is considered as complete when its status is + // either [ActionStatusSuccess] or [ActionStatusError]. + // + // The handleUpdate callback is called every time an action is updated. + WaitForFunc(ctx context.Context, handleUpdate func(update *Action) error, actions ...*Action) error + // WaitFor waits until all actions succeed by polling the API at the interval defined by + // [WithPollBackoffFunc]. An action is considered as succeeded when its status is either + // [ActionStatusSuccess]. + // + // If a single action fails, the function will stop waiting and the error set in the + // action will be returned as an [ActionError]. + // + // For more flexibility, see the [ActionClient.WaitForFunc] function. + WaitFor(ctx context.Context, actions ...*Action) error +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_certificate_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_certificate_client_iface.go new file mode 100644 index 000000000..94583925f --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_certificate_client_iface.go @@ -0,0 +1,40 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// ICertificateClient ... +type ICertificateClient interface { + // GetByID retrieves a Certificate by its ID. If the Certificate does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Certificate, *Response, error) + // GetByName retrieves a Certificate by its name. If the Certificate does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*Certificate, *Response, error) + // Get retrieves a Certificate by its ID if the input can be parsed as an integer, otherwise it + // retrieves a Certificate by its name. If the Certificate does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*Certificate, *Response, error) + // List returns a list of Certificates for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts CertificateListOpts) ([]*Certificate, *Response, error) + // All returns all Certificates. + All(ctx context.Context) ([]*Certificate, error) + // AllWithOpts returns all Certificates for the given options. + AllWithOpts(ctx context.Context, opts CertificateListOpts) ([]*Certificate, error) + // Create creates a new uploaded certificate. + // + // Create returns an error for certificates of any other type. Use + // CreateCertificate to create such certificates. + Create(ctx context.Context, opts CertificateCreateOpts) (*Certificate, *Response, error) + // CreateCertificate creates a new certificate of any type. + CreateCertificate(ctx context.Context, opts CertificateCreateOpts) (CertificateCreateResult, *Response, error) + // Update updates a Certificate. + Update(ctx context.Context, certificate *Certificate, opts CertificateUpdateOpts) (*Certificate, *Response, error) + // Delete deletes a certificate. + Delete(ctx context.Context, certificate *Certificate) (*Response, error) + // RetryIssuance retries the issuance of a failed managed certificate. + RetryIssuance(ctx context.Context, certificate *Certificate) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_datacenter_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_datacenter_client_iface.go new file mode 100644 index 000000000..f93767567 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_datacenter_client_iface.go @@ -0,0 +1,27 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IDatacenterClient ... +type IDatacenterClient interface { + // GetByID retrieves a datacenter by its ID. If the datacenter does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Datacenter, *Response, error) + // GetByName retrieves a datacenter by its name. If the datacenter does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*Datacenter, *Response, error) + // Get retrieves a datacenter by its ID if the input can be parsed as an integer, otherwise it + // retrieves a datacenter by its name. If the datacenter does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*Datacenter, *Response, error) + // List returns a list of datacenters for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts DatacenterListOpts) ([]*Datacenter, *Response, error) + // All returns all datacenters. + All(ctx context.Context) ([]*Datacenter, error) + // AllWithOpts returns all datacenters for the given options. + AllWithOpts(ctx context.Context, opts DatacenterListOpts) ([]*Datacenter, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_firewall_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_firewall_client_iface.go new file mode 100644 index 000000000..ce6481158 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_firewall_client_iface.go @@ -0,0 +1,37 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IFirewallClient ... +type IFirewallClient interface { + // GetByID retrieves a Firewall by its ID. If the Firewall does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Firewall, *Response, error) + // GetByName retrieves a Firewall by its name. If the Firewall does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*Firewall, *Response, error) + // Get retrieves a Firewall by its ID if the input can be parsed as an integer, otherwise it + // retrieves a Firewall by its name. If the Firewall does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*Firewall, *Response, error) + // List returns a list of Firewalls for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts FirewallListOpts) ([]*Firewall, *Response, error) + // All returns all Firewalls. + All(ctx context.Context) ([]*Firewall, error) + // AllWithOpts returns all Firewalls for the given options. + AllWithOpts(ctx context.Context, opts FirewallListOpts) ([]*Firewall, error) + // Create creates a new Firewall. + Create(ctx context.Context, opts FirewallCreateOpts) (FirewallCreateResult, *Response, error) + // Update updates a Firewall. + Update(ctx context.Context, firewall *Firewall, opts FirewallUpdateOpts) (*Firewall, *Response, error) + // Delete deletes a Firewall. + Delete(ctx context.Context, firewall *Firewall) (*Response, error) + // SetRules sets the rules of a Firewall. + SetRules(ctx context.Context, firewall *Firewall, opts FirewallSetRulesOpts) ([]*Action, *Response, error) + ApplyResources(ctx context.Context, firewall *Firewall, resources []FirewallResource) ([]*Action, *Response, error) + RemoveResources(ctx context.Context, firewall *Firewall, resources []FirewallResource) ([]*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_floating_ip_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_floating_ip_client_iface.go new file mode 100644 index 000000000..4d71be269 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_floating_ip_client_iface.go @@ -0,0 +1,43 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IFloatingIPClient ... +type IFloatingIPClient interface { + // GetByID retrieves a Floating IP by its ID. If the Floating IP does not exist, + // nil is returned. + GetByID(ctx context.Context, id int64) (*FloatingIP, *Response, error) + // GetByName retrieves a Floating IP by its name. If the Floating IP does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*FloatingIP, *Response, error) + // Get retrieves a Floating IP by its ID if the input can be parsed as an integer, otherwise it + // retrieves a Floating IP by its name. If the Floating IP does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*FloatingIP, *Response, error) + // List returns a list of Floating IPs for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts FloatingIPListOpts) ([]*FloatingIP, *Response, error) + // All returns all Floating IPs. + All(ctx context.Context) ([]*FloatingIP, error) + // AllWithOpts returns all Floating IPs for the given options. + AllWithOpts(ctx context.Context, opts FloatingIPListOpts) ([]*FloatingIP, error) + // Create creates a Floating IP. + Create(ctx context.Context, opts FloatingIPCreateOpts) (FloatingIPCreateResult, *Response, error) + // Delete deletes a Floating IP. + Delete(ctx context.Context, floatingIP *FloatingIP) (*Response, error) + // Update updates a Floating IP. + Update(ctx context.Context, floatingIP *FloatingIP, opts FloatingIPUpdateOpts) (*FloatingIP, *Response, error) + // Assign assigns a Floating IP to a server. + Assign(ctx context.Context, floatingIP *FloatingIP, server *Server) (*Action, *Response, error) + // Unassign unassigns a Floating IP from the currently assigned server. + Unassign(ctx context.Context, floatingIP *FloatingIP) (*Action, *Response, error) + // ChangeDNSPtr changes or resets the reverse DNS pointer for a Floating IP address. + // Pass a nil ptr to reset the reverse DNS pointer to its default value. + ChangeDNSPtr(ctx context.Context, floatingIP *FloatingIP, ip string, ptr *string) (*Action, *Response, error) + // ChangeProtection changes the resource protection level of a Floating IP. + ChangeProtection(ctx context.Context, floatingIP *FloatingIP, opts FloatingIPChangeProtectionOpts) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_image_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_image_client_iface.go new file mode 100644 index 000000000..17fbcd929 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_image_client_iface.go @@ -0,0 +1,48 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IImageClient ... +type IImageClient interface { + // GetByID retrieves an image by its ID. If the image does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Image, *Response, error) + // GetByName retrieves an image by its name. If the image does not exist, nil is returned. + // + // Deprecated: Use [ImageClient.GetByNameAndArchitecture] instead. + GetByName(ctx context.Context, name string) (*Image, *Response, error) + // GetByNameAndArchitecture retrieves an image by its name and architecture. If the image does not exist, + // nil is returned. + // In contrast to [ImageClient.Get], this method also returns deprecated images. Depending on your needs you should + // check for this in your calling method. + GetByNameAndArchitecture(ctx context.Context, name string, architecture Architecture) (*Image, *Response, error) + // Get retrieves an image by its ID if the input can be parsed as an integer, otherwise it + // retrieves an image by its name. If the image does not exist, nil is returned. + // + // Deprecated: Use [ImageClient.GetForArchitecture] instead. + Get(ctx context.Context, idOrName string) (*Image, *Response, error) + // GetForArchitecture retrieves an image by its ID if the input can be parsed as an integer, otherwise it + // retrieves an image by its name and architecture. If the image does not exist, nil is returned. + // + // In contrast to [ImageClient.Get], this method also returns deprecated images. Depending on your needs you should + // check for this in your calling method. + GetForArchitecture(ctx context.Context, idOrName string, architecture Architecture) (*Image, *Response, error) + // List returns a list of images for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts ImageListOpts) ([]*Image, *Response, error) + // All returns all images. + All(ctx context.Context) ([]*Image, error) + // AllWithOpts returns all images for the given options. + AllWithOpts(ctx context.Context, opts ImageListOpts) ([]*Image, error) + // Delete deletes an image. + Delete(ctx context.Context, image *Image) (*Response, error) + // Update updates an image. + Update(ctx context.Context, image *Image, opts ImageUpdateOpts) (*Image, *Response, error) + // ChangeProtection changes the resource protection level of an image. + ChangeProtection(ctx context.Context, image *Image, opts ImageChangeProtectionOpts) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_iso_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_iso_client_iface.go new file mode 100644 index 000000000..aff450edf --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_iso_client_iface.go @@ -0,0 +1,26 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IISOClient ... +type IISOClient interface { + // GetByID retrieves an ISO by its ID. + GetByID(ctx context.Context, id int64) (*ISO, *Response, error) + // GetByName retrieves an ISO by its name. + GetByName(ctx context.Context, name string) (*ISO, *Response, error) + // Get retrieves an ISO by its ID if the input can be parsed as an integer, otherwise it retrieves an ISO by its name. + Get(ctx context.Context, idOrName string) (*ISO, *Response, error) + // List returns a list of ISOs for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts ISOListOpts) ([]*ISO, *Response, error) + // All returns all ISOs. + All(ctx context.Context) ([]*ISO, error) + // AllWithOpts returns all ISOs for the given options. + AllWithOpts(ctx context.Context, opts ISOListOpts) ([]*ISO, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_client_iface.go new file mode 100644 index 000000000..2665f22b0 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_client_iface.go @@ -0,0 +1,71 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" + "net" +) + +// ILoadBalancerClient ... +type ILoadBalancerClient interface { + // GetByID retrieves a Load Balancer by its ID. If the Load Balancer does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*LoadBalancer, *Response, error) + // GetByName retrieves a Load Balancer by its name. If the Load Balancer does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*LoadBalancer, *Response, error) + // Get retrieves a Load Balancer by its ID if the input can be parsed as an integer, otherwise it + // retrieves a Load Balancer by its name. If the Load Balancer does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*LoadBalancer, *Response, error) + // List returns a list of Load Balancers for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts LoadBalancerListOpts) ([]*LoadBalancer, *Response, error) + // All returns all Load Balancers. + All(ctx context.Context) ([]*LoadBalancer, error) + // AllWithOpts returns all Load Balancers for the given options. + AllWithOpts(ctx context.Context, opts LoadBalancerListOpts) ([]*LoadBalancer, error) + // Update updates a Load Balancer. + Update(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerUpdateOpts) (*LoadBalancer, *Response, error) + // Create creates a new Load Balancer. + Create(ctx context.Context, opts LoadBalancerCreateOpts) (LoadBalancerCreateResult, *Response, error) + // Delete deletes a Load Balancer. + Delete(ctx context.Context, loadBalancer *LoadBalancer) (*Response, error) + // AddServerTarget adds a server target to a Load Balancer. + AddServerTarget(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddServerTargetOpts) (*Action, *Response, error) + // RemoveServerTarget removes a server target from a Load Balancer. + RemoveServerTarget(ctx context.Context, loadBalancer *LoadBalancer, server *Server) (*Action, *Response, error) + // AddLabelSelectorTarget adds a label selector target to a Load Balancer. + AddLabelSelectorTarget(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddLabelSelectorTargetOpts) (*Action, *Response, error) + // RemoveLabelSelectorTarget removes a label selector target from a Load Balancer. + RemoveLabelSelectorTarget(ctx context.Context, loadBalancer *LoadBalancer, labelSelector string) (*Action, *Response, error) + // AddIPTarget adds an IP target to a Load Balancer. + AddIPTarget(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddIPTargetOpts) (*Action, *Response, error) + // RemoveIPTarget removes an IP target from a Load Balancer. + RemoveIPTarget(ctx context.Context, loadBalancer *LoadBalancer, ip net.IP) (*Action, *Response, error) + // AddService adds a service to a Load Balancer. + AddService(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAddServiceOpts) (*Action, *Response, error) + // UpdateService updates a Load Balancer service. + UpdateService(ctx context.Context, loadBalancer *LoadBalancer, listenPort int, opts LoadBalancerUpdateServiceOpts) (*Action, *Response, error) + // DeleteService deletes a Load Balancer service. + DeleteService(ctx context.Context, loadBalancer *LoadBalancer, listenPort int) (*Action, *Response, error) + // ChangeProtection changes the resource protection level of a Load Balancer. + ChangeProtection(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerChangeProtectionOpts) (*Action, *Response, error) + // ChangeAlgorithm changes the algorithm of a Load Balancer. + ChangeAlgorithm(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerChangeAlgorithmOpts) (*Action, *Response, error) + // AttachToNetwork attaches a Load Balancer to a network. + AttachToNetwork(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerAttachToNetworkOpts) (*Action, *Response, error) + // DetachFromNetwork detaches a Load Balancer from a network. + DetachFromNetwork(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerDetachFromNetworkOpts) (*Action, *Response, error) + // EnablePublicInterface enables the Load Balancer's public network interface. + EnablePublicInterface(ctx context.Context, loadBalancer *LoadBalancer) (*Action, *Response, error) + // DisablePublicInterface disables the Load Balancer's public network interface. + DisablePublicInterface(ctx context.Context, loadBalancer *LoadBalancer) (*Action, *Response, error) + // ChangeType changes a Load Balancer's type. + ChangeType(ctx context.Context, loadBalancer *LoadBalancer, opts LoadBalancerChangeTypeOpts) (*Action, *Response, error) + // GetMetrics obtains metrics for a Load Balancer. + GetMetrics(ctx context.Context, lb *LoadBalancer, opts LoadBalancerGetMetricsOpts) (*LoadBalancerMetrics, *Response, error) + // ChangeDNSPtr changes or resets the reverse DNS pointer for a Load Balancer. + // Pass a nil ptr to reset the reverse DNS pointer to its default value. + ChangeDNSPtr(ctx context.Context, lb *LoadBalancer, ip string, ptr *string) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_type_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_type_client_iface.go new file mode 100644 index 000000000..fd3289d4d --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_load_balancer_type_client_iface.go @@ -0,0 +1,27 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// ILoadBalancerTypeClient ... +type ILoadBalancerTypeClient interface { + // GetByID retrieves a Load Balancer type by its ID. If the Load Balancer type does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*LoadBalancerType, *Response, error) + // GetByName retrieves a Load Balancer type by its name. If the Load Balancer type does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*LoadBalancerType, *Response, error) + // Get retrieves a Load Balancer type by its ID if the input can be parsed as an integer, otherwise it + // retrieves a Load Balancer type by its name. If the Load Balancer type does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*LoadBalancerType, *Response, error) + // List returns a list of Load Balancer types for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts LoadBalancerTypeListOpts) ([]*LoadBalancerType, *Response, error) + // All returns all Load Balancer types. + All(ctx context.Context) ([]*LoadBalancerType, error) + // AllWithOpts returns all Load Balancer types for the given options. + AllWithOpts(ctx context.Context, opts LoadBalancerTypeListOpts) ([]*LoadBalancerType, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_location_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_location_client_iface.go new file mode 100644 index 000000000..9da4d5f6b --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_location_client_iface.go @@ -0,0 +1,27 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// ILocationClient ... +type ILocationClient interface { + // GetByID retrieves a location by its ID. If the location does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Location, *Response, error) + // GetByName retrieves an location by its name. If the location does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*Location, *Response, error) + // Get retrieves a location by its ID if the input can be parsed as an integer, otherwise it + // retrieves a location by its name. If the location does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*Location, *Response, error) + // List returns a list of locations for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts LocationListOpts) ([]*Location, *Response, error) + // All returns all locations. + All(ctx context.Context) ([]*Location, error) + // AllWithOpts returns all locations for the given options. + AllWithOpts(ctx context.Context, opts LocationListOpts) ([]*Location, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_network_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_network_client_iface.go new file mode 100644 index 000000000..f8b752e34 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_network_client_iface.go @@ -0,0 +1,45 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// INetworkClient ... +type INetworkClient interface { + // GetByID retrieves a network by its ID. If the network does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Network, *Response, error) + // GetByName retrieves a network by its name. If the network does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*Network, *Response, error) + // Get retrieves a network by its ID if the input can be parsed as an integer, otherwise it + // retrieves a network by its name. If the network does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*Network, *Response, error) + // List returns a list of networks for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts NetworkListOpts) ([]*Network, *Response, error) + // All returns all networks. + All(ctx context.Context) ([]*Network, error) + // AllWithOpts returns all networks for the given options. + AllWithOpts(ctx context.Context, opts NetworkListOpts) ([]*Network, error) + // Delete deletes a network. + Delete(ctx context.Context, network *Network) (*Response, error) + // Update updates a network. + Update(ctx context.Context, network *Network, opts NetworkUpdateOpts) (*Network, *Response, error) + // Create creates a new network. + Create(ctx context.Context, opts NetworkCreateOpts) (*Network, *Response, error) + // ChangeIPRange changes the IP range of a network. + ChangeIPRange(ctx context.Context, network *Network, opts NetworkChangeIPRangeOpts) (*Action, *Response, error) + // AddSubnet adds a subnet to a network. + AddSubnet(ctx context.Context, network *Network, opts NetworkAddSubnetOpts) (*Action, *Response, error) + // DeleteSubnet deletes a subnet from a network. + DeleteSubnet(ctx context.Context, network *Network, opts NetworkDeleteSubnetOpts) (*Action, *Response, error) + // AddRoute adds a route to a network. + AddRoute(ctx context.Context, network *Network, opts NetworkAddRouteOpts) (*Action, *Response, error) + // DeleteRoute deletes a route from a network. + DeleteRoute(ctx context.Context, network *Network, opts NetworkDeleteRouteOpts) (*Action, *Response, error) + // ChangeProtection changes the resource protection level of a network. + ChangeProtection(ctx context.Context, network *Network, opts NetworkChangeProtectionOpts) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_placement_group_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_placement_group_client_iface.go new file mode 100644 index 000000000..9fadd4f2c --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_placement_group_client_iface.go @@ -0,0 +1,33 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IPlacementGroupClient ... +type IPlacementGroupClient interface { + // GetByID retrieves a PlacementGroup by its ID. If the PlacementGroup does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*PlacementGroup, *Response, error) + // GetByName retrieves a PlacementGroup by its name. If the PlacementGroup does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*PlacementGroup, *Response, error) + // Get retrieves a PlacementGroup by its ID if the input can be parsed as an integer, otherwise it + // retrieves a PlacementGroup by its name. If the PlacementGroup does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*PlacementGroup, *Response, error) + // List returns a list of PlacementGroups for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts PlacementGroupListOpts) ([]*PlacementGroup, *Response, error) + // All returns all PlacementGroups. + All(ctx context.Context) ([]*PlacementGroup, error) + // AllWithOpts returns all PlacementGroups for the given options. + AllWithOpts(ctx context.Context, opts PlacementGroupListOpts) ([]*PlacementGroup, error) + // Create creates a new PlacementGroup. + Create(ctx context.Context, opts PlacementGroupCreateOpts) (PlacementGroupCreateResult, *Response, error) + // Update updates a PlacementGroup. + Update(ctx context.Context, placementGroup *PlacementGroup, opts PlacementGroupUpdateOpts) (*PlacementGroup, *Response, error) + // Delete deletes a PlacementGroup. + Delete(ctx context.Context, placementGroup *PlacementGroup) (*Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_pricing_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_pricing_client_iface.go new file mode 100644 index 000000000..cd4068c62 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_pricing_client_iface.go @@ -0,0 +1,13 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IPricingClient ... +type IPricingClient interface { + // Get retrieves pricing information. + Get(ctx context.Context) (Pricing, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_primary_ip_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_primary_ip_client_iface.go new file mode 100644 index 000000000..6b8e617e2 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_primary_ip_client_iface.go @@ -0,0 +1,43 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IPrimaryIPClient ... +type IPrimaryIPClient interface { + // GetByID retrieves a Primary IP by its ID. If the Primary IP does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*PrimaryIP, *Response, error) + // GetByIP retrieves a Primary IP by its IP Address. If the Primary IP does not exist, nil is returned. + GetByIP(ctx context.Context, ip string) (*PrimaryIP, *Response, error) + // GetByName retrieves a Primary IP by its name. If the Primary IP does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*PrimaryIP, *Response, error) + // Get retrieves a Primary IP by its ID if the input can be parsed as an integer, otherwise it + // retrieves a Primary IP by its name. If the Primary IP does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*PrimaryIP, *Response, error) + // List returns a list of Primary IPs for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts PrimaryIPListOpts) ([]*PrimaryIP, *Response, error) + // All returns all Primary IPs. + All(ctx context.Context) ([]*PrimaryIP, error) + // AllWithOpts returns all Primary IPs for the given options. + AllWithOpts(ctx context.Context, opts PrimaryIPListOpts) ([]*PrimaryIP, error) + // Create creates a Primary IP. + Create(ctx context.Context, reqBody PrimaryIPCreateOpts) (*PrimaryIPCreateResult, *Response, error) + // Delete deletes a Primary IP. + Delete(ctx context.Context, primaryIP *PrimaryIP) (*Response, error) + // Update updates a Primary IP. + Update(ctx context.Context, primaryIP *PrimaryIP, reqBody PrimaryIPUpdateOpts) (*PrimaryIP, *Response, error) + // Assign a Primary IP to a resource. + Assign(ctx context.Context, opts PrimaryIPAssignOpts) (*Action, *Response, error) + // Unassign a Primary IP from a resource. + Unassign(ctx context.Context, id int64) (*Action, *Response, error) + // ChangeDNSPtr Change the reverse DNS from a Primary IP. + ChangeDNSPtr(ctx context.Context, opts PrimaryIPChangeDNSPtrOpts) (*Action, *Response, error) + // ChangeProtection Changes the protection configuration of a Primary IP. + ChangeProtection(ctx context.Context, opts PrimaryIPChangeProtectionOpts) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_rdns_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_rdns_client_iface.go new file mode 100644 index 000000000..f92f18677 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_rdns_client_iface.go @@ -0,0 +1,15 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" + "net" +) + +// IRDNSClient ... +type IRDNSClient interface { + // ChangeDNSPtr changes or resets the reverse DNS pointer for a IP address. + // Pass a nil ptr to reset the reverse DNS pointer to its default value. + ChangeDNSPtr(ctx context.Context, rdns RDNSSupporter, ip net.IP, ptr *string) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go new file mode 100644 index 000000000..67910ab22 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_resource_action_client_iface.go @@ -0,0 +1,20 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IResourceActionClient ... +type IResourceActionClient interface { + // GetByID retrieves an action by its ID. If the action does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Action, *Response, error) + // List returns a list of actions for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts ActionListOpts) ([]*Action, *Response, error) + // All returns all actions for the given options. + All(ctx context.Context, opts ActionListOpts) ([]*Action, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go new file mode 100644 index 000000000..c6ca97cab --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_schema.go @@ -0,0 +1,2491 @@ +// Code generated by github.com/jmattheis/goverter, DO NOT EDIT. +//go:build !goverter + +package hcloud + +import ( + schema "github.com/hetznercloud/hcloud-go/v2/hcloud/schema" + "net" + "time" +) + +type converterImpl struct{} + +func (c *converterImpl) ActionFromSchema(source schema.Action) *Action { + var hcloudAction Action + hcloudAction.ID = source.ID + hcloudAction.Status = ActionStatus(source.Status) + hcloudAction.Command = source.Command + hcloudAction.Progress = source.Progress + hcloudAction.Started = source.Started + hcloudAction.Finished = c.pTimeTimeToTimeTime(source.Finished) + var pString *string + if source.Error != nil { + pString = &source.Error.Code + } + var xstring string + if pString != nil { + xstring = *pString + } + hcloudAction.ErrorCode = xstring + var pString2 *string + if source.Error != nil { + pString2 = &source.Error.Message + } + var xstring2 string + if pString2 != nil { + xstring2 = *pString2 + } + hcloudAction.ErrorMessage = xstring2 + var pHcloudActionResourceList []*ActionResource + if source.Resources != nil { + pHcloudActionResourceList = make([]*ActionResource, len(source.Resources)) + for i := 0; i < len(source.Resources); i++ { + pHcloudActionResourceList[i] = c.schemaActionResourceReferenceToPHcloudActionResource(source.Resources[i]) + } + } + hcloudAction.Resources = pHcloudActionResourceList + return &hcloudAction +} +func (c *converterImpl) ActionsFromSchema(source []schema.Action) []*Action { + var pHcloudActionList []*Action + if source != nil { + pHcloudActionList = make([]*Action, len(source)) + for i := 0; i < len(source); i++ { + pHcloudActionList[i] = c.ActionFromSchema(source[i]) + } + } + return pHcloudActionList +} +func (c *converterImpl) CertificateFromSchema(source schema.Certificate) *Certificate { + var hcloudCertificate Certificate + hcloudCertificate.ID = source.ID + hcloudCertificate.Name = source.Name + hcloudCertificate.Labels = source.Labels + hcloudCertificate.Type = CertificateType(source.Type) + hcloudCertificate.Certificate = source.Certificate + hcloudCertificate.Created = c.timeTimeToTimeTime(source.Created) + hcloudCertificate.NotValidBefore = c.timeTimeToTimeTime(source.NotValidBefore) + hcloudCertificate.NotValidAfter = c.timeTimeToTimeTime(source.NotValidAfter) + hcloudCertificate.DomainNames = source.DomainNames + hcloudCertificate.Fingerprint = source.Fingerprint + hcloudCertificate.Status = c.pSchemaCertificateStatusRefToPHcloudCertificateStatus(source.Status) + var hcloudCertificateUsedByRefList []CertificateUsedByRef + if source.UsedBy != nil { + hcloudCertificateUsedByRefList = make([]CertificateUsedByRef, len(source.UsedBy)) + for i := 0; i < len(source.UsedBy); i++ { + hcloudCertificateUsedByRefList[i] = c.schemaCertificateUsedByRefToHcloudCertificateUsedByRef(source.UsedBy[i]) + } + } + hcloudCertificate.UsedBy = hcloudCertificateUsedByRefList + return &hcloudCertificate +} +func (c *converterImpl) DatacenterFromSchema(source schema.Datacenter) *Datacenter { + var hcloudDatacenter Datacenter + hcloudDatacenter.ID = source.ID + hcloudDatacenter.Name = source.Name + hcloudDatacenter.Description = source.Description + hcloudDatacenter.Location = c.LocationFromSchema(source.Location) + hcloudDatacenter.ServerTypes = c.schemaDatacenterServerTypesToHcloudDatacenterServerTypes(source.ServerTypes) + return &hcloudDatacenter +} +func (c *converterImpl) DeprecationFromSchema(source *schema.DeprecationInfo) *DeprecationInfo { + var pHcloudDeprecationInfo *DeprecationInfo + if source != nil { + var hcloudDeprecationInfo DeprecationInfo + hcloudDeprecationInfo.Announced = c.timeTimeToTimeTime((*source).Announced) + hcloudDeprecationInfo.UnavailableAfter = c.timeTimeToTimeTime((*source).UnavailableAfter) + pHcloudDeprecationInfo = &hcloudDeprecationInfo + } + return pHcloudDeprecationInfo +} +func (c *converterImpl) ErrorFromSchema(source schema.Error) Error { + var hcloudError Error + hcloudError.Code = ErrorCode(source.Code) + hcloudError.Message = source.Message + hcloudError.Details = errorDetailsFromSchema(source.Details) + return hcloudError +} +func (c *converterImpl) FirewallFromSchema(source schema.Firewall) *Firewall { + var hcloudFirewall Firewall + hcloudFirewall.ID = source.ID + hcloudFirewall.Name = source.Name + hcloudFirewall.Labels = source.Labels + hcloudFirewall.Created = c.timeTimeToTimeTime(source.Created) + var hcloudFirewallRuleList []FirewallRule + if source.Rules != nil { + hcloudFirewallRuleList = make([]FirewallRule, len(source.Rules)) + for i := 0; i < len(source.Rules); i++ { + hcloudFirewallRuleList[i] = c.schemaFirewallRuleToHcloudFirewallRule(source.Rules[i]) + } + } + hcloudFirewall.Rules = hcloudFirewallRuleList + var hcloudFirewallResourceList []FirewallResource + if source.AppliedTo != nil { + hcloudFirewallResourceList = make([]FirewallResource, len(source.AppliedTo)) + for j := 0; j < len(source.AppliedTo); j++ { + hcloudFirewallResourceList[j] = c.schemaFirewallResourceToHcloudFirewallResource(source.AppliedTo[j]) + } + } + hcloudFirewall.AppliedTo = hcloudFirewallResourceList + return &hcloudFirewall +} +func (c *converterImpl) FloatingIPFromSchema(source schema.FloatingIP) *FloatingIP { + var hcloudFloatingIP FloatingIP + hcloudFloatingIP.ID = source.ID + var xstring string + if source.Description != nil { + xstring = *source.Description + } + hcloudFloatingIP.Description = xstring + hcloudFloatingIP.Created = c.timeTimeToTimeTime(source.Created) + hcloudFloatingIP.IP = ipFromFloatingIPSchema(source) + hcloudFloatingIP.Network = networkFromFloatingIPSchema(source) + hcloudFloatingIP.Type = FloatingIPType(source.Type) + var pHcloudServer *Server + if source.Server != nil { + hcloudServer := serverFromInt64(*source.Server) + pHcloudServer = &hcloudServer + } + hcloudFloatingIP.Server = pHcloudServer + hcloudFloatingIP.DNSPtr = mapFromFloatingIPDNSPtrSchema(source.DNSPtr) + hcloudFloatingIP.HomeLocation = c.LocationFromSchema(source.HomeLocation) + hcloudFloatingIP.Blocked = source.Blocked + hcloudFloatingIP.Protection = c.schemaFloatingIPProtectionToHcloudFloatingIPProtection(source.Protection) + hcloudFloatingIP.Labels = source.Labels + hcloudFloatingIP.Name = source.Name + return &hcloudFloatingIP +} +func (c *converterImpl) ISOFromSchema(source schema.ISO) *ISO { + hcloudISO := c.intISOFromSchema(source) + return &hcloudISO +} +func (c *converterImpl) ImageFromSchema(source schema.Image) *Image { + var hcloudImage Image + hcloudImage.ID = source.ID + var xstring string + if source.Name != nil { + xstring = *source.Name + } + hcloudImage.Name = xstring + hcloudImage.Type = ImageType(source.Type) + hcloudImage.Status = ImageStatus(source.Status) + hcloudImage.Description = source.Description + var xfloat32 float32 + if source.ImageSize != nil { + xfloat32 = *source.ImageSize + } + hcloudImage.ImageSize = xfloat32 + hcloudImage.DiskSize = source.DiskSize + hcloudImage.Created = c.pTimeTimeToTimeTime(source.Created) + hcloudImage.CreatedFrom = c.pSchemaImageCreatedFromToPHcloudServer(source.CreatedFrom) + var pHcloudServer *Server + if source.BoundTo != nil { + hcloudServer := serverFromInt64(*source.BoundTo) + pHcloudServer = &hcloudServer + } + hcloudImage.BoundTo = pHcloudServer + hcloudImage.RapidDeploy = source.RapidDeploy + hcloudImage.OSFlavor = source.OSFlavor + var xstring2 string + if source.OSVersion != nil { + xstring2 = *source.OSVersion + } + hcloudImage.OSVersion = xstring2 + hcloudImage.Architecture = Architecture(source.Architecture) + hcloudImage.Protection = c.schemaImageProtectionToHcloudImageProtection(source.Protection) + hcloudImage.Deprecated = c.pTimeTimeToTimeTime(source.Deprecated) + hcloudImage.Labels = source.Labels + hcloudImage.Deleted = c.pTimeTimeToTimeTime(source.Deleted) + return &hcloudImage +} +func (c *converterImpl) LoadBalancerFromSchema(source schema.LoadBalancer) *LoadBalancer { + var hcloudLoadBalancer LoadBalancer + hcloudLoadBalancer.ID = source.ID + hcloudLoadBalancer.Name = source.Name + hcloudLoadBalancer.PublicNet = c.schemaLoadBalancerPublicNetToHcloudLoadBalancerPublicNet(source.PublicNet) + var hcloudLoadBalancerPrivateNetList []LoadBalancerPrivateNet + if source.PrivateNet != nil { + hcloudLoadBalancerPrivateNetList = make([]LoadBalancerPrivateNet, len(source.PrivateNet)) + for i := 0; i < len(source.PrivateNet); i++ { + hcloudLoadBalancerPrivateNetList[i] = c.schemaLoadBalancerPrivateNetToHcloudLoadBalancerPrivateNet(source.PrivateNet[i]) + } + } + hcloudLoadBalancer.PrivateNet = hcloudLoadBalancerPrivateNetList + hcloudLoadBalancer.Location = c.LocationFromSchema(source.Location) + hcloudLoadBalancer.LoadBalancerType = c.LoadBalancerTypeFromSchema(source.LoadBalancerType) + hcloudLoadBalancer.Algorithm = c.schemaLoadBalancerAlgorithmToHcloudLoadBalancerAlgorithm(source.Algorithm) + var hcloudLoadBalancerServiceList []LoadBalancerService + if source.Services != nil { + hcloudLoadBalancerServiceList = make([]LoadBalancerService, len(source.Services)) + for j := 0; j < len(source.Services); j++ { + hcloudLoadBalancerServiceList[j] = c.LoadBalancerServiceFromSchema(source.Services[j]) + } + } + hcloudLoadBalancer.Services = hcloudLoadBalancerServiceList + var hcloudLoadBalancerTargetList []LoadBalancerTarget + if source.Targets != nil { + hcloudLoadBalancerTargetList = make([]LoadBalancerTarget, len(source.Targets)) + for k := 0; k < len(source.Targets); k++ { + hcloudLoadBalancerTargetList[k] = c.LoadBalancerTargetFromSchema(source.Targets[k]) + } + } + hcloudLoadBalancer.Targets = hcloudLoadBalancerTargetList + hcloudLoadBalancer.Protection = c.schemaLoadBalancerProtectionToHcloudLoadBalancerProtection(source.Protection) + hcloudLoadBalancer.Labels = source.Labels + hcloudLoadBalancer.Created = c.timeTimeToTimeTime(source.Created) + hcloudLoadBalancer.IncludedTraffic = source.IncludedTraffic + var xuint64 uint64 + if source.OutgoingTraffic != nil { + xuint64 = *source.OutgoingTraffic + } + hcloudLoadBalancer.OutgoingTraffic = xuint64 + var xuint642 uint64 + if source.IngoingTraffic != nil { + xuint642 = *source.IngoingTraffic + } + hcloudLoadBalancer.IngoingTraffic = xuint642 + return &hcloudLoadBalancer +} +func (c *converterImpl) LoadBalancerMetricsFromSchema(source *schema.LoadBalancerGetMetricsResponse) (*LoadBalancerMetrics, error) { + var pHcloudLoadBalancerMetrics *LoadBalancerMetrics + if source != nil { + var hcloudLoadBalancerMetrics LoadBalancerMetrics + hcloudLoadBalancerMetrics.Start = c.timeTimeToTimeTime((*source).Metrics.Start) + hcloudLoadBalancerMetrics.End = c.timeTimeToTimeTime((*source).Metrics.End) + hcloudLoadBalancerMetrics.Step = (*source).Metrics.Step + var mapStringHcloudLoadBalancerMetricsValueList map[string][]LoadBalancerMetricsValue + if (*source).Metrics.TimeSeries != nil { + mapStringHcloudLoadBalancerMetricsValueList = make(map[string][]LoadBalancerMetricsValue, len((*source).Metrics.TimeSeries)) + for key, value := range (*source).Metrics.TimeSeries { + hcloudLoadBalancerMetricsValueList, err := loadBalancerMetricsTimeSeriesFromSchema(value) + if err != nil { + return nil, err + } + mapStringHcloudLoadBalancerMetricsValueList[key] = hcloudLoadBalancerMetricsValueList + } + } + hcloudLoadBalancerMetrics.TimeSeries = mapStringHcloudLoadBalancerMetricsValueList + pHcloudLoadBalancerMetrics = &hcloudLoadBalancerMetrics + } + return pHcloudLoadBalancerMetrics, nil +} +func (c *converterImpl) LoadBalancerServiceFromSchema(source schema.LoadBalancerService) LoadBalancerService { + var hcloudLoadBalancerService LoadBalancerService + hcloudLoadBalancerService.Protocol = LoadBalancerServiceProtocol(source.Protocol) + hcloudLoadBalancerService.ListenPort = source.ListenPort + hcloudLoadBalancerService.DestinationPort = source.DestinationPort + hcloudLoadBalancerService.Proxyprotocol = source.Proxyprotocol + hcloudLoadBalancerService.HTTP = c.pSchemaLoadBalancerServiceHTTPToHcloudLoadBalancerServiceHTTP(source.HTTP) + hcloudLoadBalancerService.HealthCheck = c.LoadBalancerServiceHealthCheckFromSchema(source.HealthCheck) + return hcloudLoadBalancerService +} +func (c *converterImpl) LoadBalancerServiceHealthCheckFromSchema(source *schema.LoadBalancerServiceHealthCheck) LoadBalancerServiceHealthCheck { + var hcloudLoadBalancerServiceHealthCheck LoadBalancerServiceHealthCheck + if source != nil { + var hcloudLoadBalancerServiceHealthCheck2 LoadBalancerServiceHealthCheck + hcloudLoadBalancerServiceHealthCheck2.Protocol = LoadBalancerServiceProtocol((*source).Protocol) + hcloudLoadBalancerServiceHealthCheck2.Port = (*source).Port + hcloudLoadBalancerServiceHealthCheck2.Interval = durationFromIntSeconds((*source).Interval) + hcloudLoadBalancerServiceHealthCheck2.Timeout = durationFromIntSeconds((*source).Timeout) + hcloudLoadBalancerServiceHealthCheck2.Retries = (*source).Retries + hcloudLoadBalancerServiceHealthCheck2.HTTP = c.pSchemaLoadBalancerServiceHealthCheckHTTPToPHcloudLoadBalancerServiceHealthCheckHTTP((*source).HTTP) + hcloudLoadBalancerServiceHealthCheck = hcloudLoadBalancerServiceHealthCheck2 + } + return hcloudLoadBalancerServiceHealthCheck +} +func (c *converterImpl) LoadBalancerTargetFromSchema(source schema.LoadBalancerTarget) LoadBalancerTarget { + var hcloudLoadBalancerTarget LoadBalancerTarget + hcloudLoadBalancerTarget.Type = LoadBalancerTargetType(source.Type) + hcloudLoadBalancerTarget.Server = c.pSchemaLoadBalancerTargetServerToPHcloudLoadBalancerTargetServer(source.Server) + hcloudLoadBalancerTarget.LabelSelector = c.pSchemaLoadBalancerTargetLabelSelectorToPHcloudLoadBalancerTargetLabelSelector(source.LabelSelector) + hcloudLoadBalancerTarget.IP = c.pSchemaLoadBalancerTargetIPToPHcloudLoadBalancerTargetIP(source.IP) + var hcloudLoadBalancerTargetHealthStatusList []LoadBalancerTargetHealthStatus + if source.HealthStatus != nil { + hcloudLoadBalancerTargetHealthStatusList = make([]LoadBalancerTargetHealthStatus, len(source.HealthStatus)) + for i := 0; i < len(source.HealthStatus); i++ { + hcloudLoadBalancerTargetHealthStatusList[i] = c.LoadBalancerTargetHealthStatusFromSchema(source.HealthStatus[i]) + } + } + hcloudLoadBalancerTarget.HealthStatus = hcloudLoadBalancerTargetHealthStatusList + var hcloudLoadBalancerTargetList []LoadBalancerTarget + if source.Targets != nil { + hcloudLoadBalancerTargetList = make([]LoadBalancerTarget, len(source.Targets)) + for j := 0; j < len(source.Targets); j++ { + hcloudLoadBalancerTargetList[j] = c.LoadBalancerTargetFromSchema(source.Targets[j]) + } + } + hcloudLoadBalancerTarget.Targets = hcloudLoadBalancerTargetList + hcloudLoadBalancerTarget.UsePrivateIP = source.UsePrivateIP + return hcloudLoadBalancerTarget +} +func (c *converterImpl) LoadBalancerTargetHealthStatusFromSchema(source schema.LoadBalancerTargetHealthStatus) LoadBalancerTargetHealthStatus { + var hcloudLoadBalancerTargetHealthStatus LoadBalancerTargetHealthStatus + hcloudLoadBalancerTargetHealthStatus.ListenPort = source.ListenPort + hcloudLoadBalancerTargetHealthStatus.Status = LoadBalancerTargetHealthStatusStatus(source.Status) + return hcloudLoadBalancerTargetHealthStatus +} +func (c *converterImpl) LoadBalancerTargetServerFromSchema(source schema.LoadBalancerTargetServer) LoadBalancerTargetServer { + var hcloudLoadBalancerTargetServer LoadBalancerTargetServer + hcloudServer := serverFromInt64(source.ID) + hcloudLoadBalancerTargetServer.Server = &hcloudServer + return hcloudLoadBalancerTargetServer +} +func (c *converterImpl) LoadBalancerTypeFromSchema(source schema.LoadBalancerType) *LoadBalancerType { + var hcloudLoadBalancerType LoadBalancerType + hcloudLoadBalancerType.ID = source.ID + hcloudLoadBalancerType.Name = source.Name + hcloudLoadBalancerType.Description = source.Description + hcloudLoadBalancerType.MaxConnections = source.MaxConnections + hcloudLoadBalancerType.MaxServices = source.MaxServices + hcloudLoadBalancerType.MaxTargets = source.MaxTargets + hcloudLoadBalancerType.MaxAssignedCertificates = source.MaxAssignedCertificates + var hcloudLoadBalancerTypeLocationPricingList []LoadBalancerTypeLocationPricing + if source.Prices != nil { + hcloudLoadBalancerTypeLocationPricingList = make([]LoadBalancerTypeLocationPricing, len(source.Prices)) + for i := 0; i < len(source.Prices); i++ { + hcloudLoadBalancerTypeLocationPricingList[i] = c.LoadBalancerTypeLocationPricingFromSchema(source.Prices[i]) + } + } + hcloudLoadBalancerType.Pricings = hcloudLoadBalancerTypeLocationPricingList + hcloudLoadBalancerType.Deprecated = source.Deprecated + return &hcloudLoadBalancerType +} +func (c *converterImpl) LoadBalancerTypeLocationPricingFromSchema(source schema.PricingLoadBalancerTypePrice) LoadBalancerTypeLocationPricing { + var hcloudLoadBalancerTypeLocationPricing LoadBalancerTypeLocationPricing + hcloudLocation := locationFromString(source.Location) + hcloudLoadBalancerTypeLocationPricing.Location = &hcloudLocation + hcloudLoadBalancerTypeLocationPricing.Hourly = c.PriceFromSchema(source.PriceHourly) + hcloudLoadBalancerTypeLocationPricing.Monthly = c.PriceFromSchema(source.PriceMonthly) + return hcloudLoadBalancerTypeLocationPricing +} +func (c *converterImpl) LocationFromSchema(source schema.Location) *Location { + var hcloudLocation Location + hcloudLocation.ID = source.ID + hcloudLocation.Name = source.Name + hcloudLocation.Description = source.Description + hcloudLocation.Country = source.Country + hcloudLocation.City = source.City + hcloudLocation.Latitude = source.Latitude + hcloudLocation.Longitude = source.Longitude + hcloudLocation.NetworkZone = NetworkZone(source.NetworkZone) + return &hcloudLocation +} +func (c *converterImpl) NetworkFromSchema(source schema.Network) *Network { + var hcloudNetwork Network + hcloudNetwork.ID = source.ID + hcloudNetwork.Name = source.Name + hcloudNetwork.Created = c.timeTimeToTimeTime(source.Created) + netIPNet := ipNetFromString(source.IPRange) + hcloudNetwork.IPRange = &netIPNet + var hcloudNetworkSubnetList []NetworkSubnet + if source.Subnets != nil { + hcloudNetworkSubnetList = make([]NetworkSubnet, len(source.Subnets)) + for i := 0; i < len(source.Subnets); i++ { + hcloudNetworkSubnetList[i] = c.NetworkSubnetFromSchema(source.Subnets[i]) + } + } + hcloudNetwork.Subnets = hcloudNetworkSubnetList + var hcloudNetworkRouteList []NetworkRoute + if source.Routes != nil { + hcloudNetworkRouteList = make([]NetworkRoute, len(source.Routes)) + for j := 0; j < len(source.Routes); j++ { + hcloudNetworkRouteList[j] = c.NetworkRouteFromSchema(source.Routes[j]) + } + } + hcloudNetwork.Routes = hcloudNetworkRouteList + var pHcloudServerList []*Server + if source.Servers != nil { + pHcloudServerList = make([]*Server, len(source.Servers)) + for k := 0; k < len(source.Servers); k++ { + hcloudServer := serverFromInt64(source.Servers[k]) + pHcloudServerList[k] = &hcloudServer + } + } + hcloudNetwork.Servers = pHcloudServerList + hcloudNetwork.Protection = c.schemaNetworkProtectionToHcloudNetworkProtection(source.Protection) + hcloudNetwork.Labels = source.Labels + hcloudNetwork.ExposeRoutesToVSwitch = source.ExposeRoutesToVSwitch + return &hcloudNetwork +} +func (c *converterImpl) NetworkRouteFromSchema(source schema.NetworkRoute) NetworkRoute { + var hcloudNetworkRoute NetworkRoute + netIPNet := ipNetFromString(source.Destination) + hcloudNetworkRoute.Destination = &netIPNet + hcloudNetworkRoute.Gateway = ipFromString(source.Gateway) + return hcloudNetworkRoute +} +func (c *converterImpl) NetworkSubnetFromSchema(source schema.NetworkSubnet) NetworkSubnet { + var hcloudNetworkSubnet NetworkSubnet + hcloudNetworkSubnet.Type = NetworkSubnetType(source.Type) + netIPNet := ipNetFromString(source.IPRange) + hcloudNetworkSubnet.IPRange = &netIPNet + hcloudNetworkSubnet.NetworkZone = NetworkZone(source.NetworkZone) + hcloudNetworkSubnet.Gateway = ipFromString(source.Gateway) + hcloudNetworkSubnet.VSwitchID = source.VSwitchID + return hcloudNetworkSubnet +} +func (c *converterImpl) PaginationFromSchema(source schema.MetaPagination) Pagination { + var hcloudPagination Pagination + hcloudPagination.Page = source.Page + hcloudPagination.PerPage = source.PerPage + hcloudPagination.PreviousPage = source.PreviousPage + hcloudPagination.NextPage = source.NextPage + hcloudPagination.LastPage = source.LastPage + hcloudPagination.TotalEntries = source.TotalEntries + return hcloudPagination +} +func (c *converterImpl) PlacementGroupFromSchema(source schema.PlacementGroup) *PlacementGroup { + var hcloudPlacementGroup PlacementGroup + hcloudPlacementGroup.ID = source.ID + hcloudPlacementGroup.Name = source.Name + hcloudPlacementGroup.Labels = source.Labels + hcloudPlacementGroup.Created = c.timeTimeToTimeTime(source.Created) + hcloudPlacementGroup.Servers = source.Servers + hcloudPlacementGroup.Type = PlacementGroupType(source.Type) + return &hcloudPlacementGroup +} +func (c *converterImpl) PriceFromSchema(source schema.Price) Price { + var hcloudPrice Price + hcloudPrice.Net = source.Net + hcloudPrice.Gross = source.Gross + return hcloudPrice +} +func (c *converterImpl) PricingFromSchema(source schema.Pricing) Pricing { + var hcloudPricing Pricing + hcloudPricing.Image = imagePricingFromSchema(source) + hcloudPricing.FloatingIP = floatingIPPricingFromSchema(source) + hcloudPricing.FloatingIPs = floatingIPTypePricingFromSchema(source) + hcloudPricing.PrimaryIPs = primaryIPPricingFromSchema(source) + hcloudPricing.Traffic = trafficPricingFromSchema(source) + hcloudPricing.ServerBackup = c.schemaPricingServerBackupToHcloudServerBackupPricing(source.ServerBackup) + hcloudPricing.ServerTypes = serverTypePricingFromSchema(source) + hcloudPricing.LoadBalancerTypes = loadBalancerTypePricingFromSchema(source) + hcloudPricing.Volume = volumePricingFromSchema(source) + return hcloudPricing +} +func (c *converterImpl) PrimaryIPFromSchema(source schema.PrimaryIP) *PrimaryIP { + var hcloudPrimaryIP PrimaryIP + hcloudPrimaryIP.ID = source.ID + hcloudPrimaryIP.IP = ipFromPrimaryIPSchema(source) + hcloudPrimaryIP.Network = networkFromPrimaryIPSchema(source) + hcloudPrimaryIP.Labels = source.Labels + hcloudPrimaryIP.Name = source.Name + hcloudPrimaryIP.Type = PrimaryIPType(source.Type) + hcloudPrimaryIP.Protection = c.schemaPrimaryIPProtectionToHcloudPrimaryIPProtection(source.Protection) + hcloudPrimaryIP.DNSPtr = mapFromPrimaryIPDNSPtrSchema(source.DNSPtr) + var xint64 int64 + if source.AssigneeID != nil { + xint64 = *source.AssigneeID + } + hcloudPrimaryIP.AssigneeID = xint64 + hcloudPrimaryIP.AssigneeType = source.AssigneeType + hcloudPrimaryIP.AutoDelete = source.AutoDelete + hcloudPrimaryIP.Blocked = source.Blocked + hcloudPrimaryIP.Created = c.timeTimeToTimeTime(source.Created) + hcloudPrimaryIP.Datacenter = c.DatacenterFromSchema(source.Datacenter) + return &hcloudPrimaryIP +} +func (c *converterImpl) SSHKeyFromSchema(source schema.SSHKey) *SSHKey { + var hcloudSSHKey SSHKey + hcloudSSHKey.ID = source.ID + hcloudSSHKey.Name = source.Name + hcloudSSHKey.Fingerprint = source.Fingerprint + hcloudSSHKey.PublicKey = source.PublicKey + hcloudSSHKey.Labels = source.Labels + hcloudSSHKey.Created = c.timeTimeToTimeTime(source.Created) + return &hcloudSSHKey +} +func (c *converterImpl) SchemaFromAction(source *Action) schema.Action { + var schemaAction schema.Action + if source != nil { + var schemaAction2 schema.Action + schemaAction2.ID = (*source).ID + schemaAction2.Status = string((*source).Status) + schemaAction2.Command = (*source).Command + schemaAction2.Progress = (*source).Progress + schemaAction2.Started = c.timeTimeToTimeTime((*source).Started) + schemaAction2.Finished = timeToTimePtr((*source).Finished) + schemaAction2.Error = schemaActionErrorFromAction((*source)) + var schemaActionResourceReferenceList []schema.ActionResourceReference + if (*source).Resources != nil { + schemaActionResourceReferenceList = make([]schema.ActionResourceReference, len((*source).Resources)) + for i := 0; i < len((*source).Resources); i++ { + schemaActionResourceReferenceList[i] = c.pHcloudActionResourceToSchemaActionResourceReference((*source).Resources[i]) + } + } + schemaAction2.Resources = schemaActionResourceReferenceList + schemaAction = schemaAction2 + } + return schemaAction +} +func (c *converterImpl) SchemaFromActions(source []*Action) []schema.Action { + var schemaActionList []schema.Action + if source != nil { + schemaActionList = make([]schema.Action, len(source)) + for i := 0; i < len(source); i++ { + schemaActionList[i] = c.SchemaFromAction(source[i]) + } + } + return schemaActionList +} +func (c *converterImpl) SchemaFromCertificate(source *Certificate) schema.Certificate { + var schemaCertificate schema.Certificate + if source != nil { + var schemaCertificate2 schema.Certificate + schemaCertificate2.ID = (*source).ID + schemaCertificate2.Name = (*source).Name + schemaCertificate2.Labels = (*source).Labels + schemaCertificate2.Type = string((*source).Type) + schemaCertificate2.Certificate = (*source).Certificate + schemaCertificate2.Created = c.timeTimeToTimeTime((*source).Created) + schemaCertificate2.NotValidBefore = c.timeTimeToTimeTime((*source).NotValidBefore) + schemaCertificate2.NotValidAfter = c.timeTimeToTimeTime((*source).NotValidAfter) + schemaCertificate2.DomainNames = (*source).DomainNames + schemaCertificate2.Fingerprint = (*source).Fingerprint + schemaCertificate2.Status = c.pHcloudCertificateStatusToPSchemaCertificateStatusRef((*source).Status) + var schemaCertificateUsedByRefList []schema.CertificateUsedByRef + if (*source).UsedBy != nil { + schemaCertificateUsedByRefList = make([]schema.CertificateUsedByRef, len((*source).UsedBy)) + for i := 0; i < len((*source).UsedBy); i++ { + schemaCertificateUsedByRefList[i] = c.hcloudCertificateUsedByRefToSchemaCertificateUsedByRef((*source).UsedBy[i]) + } + } + schemaCertificate2.UsedBy = schemaCertificateUsedByRefList + schemaCertificate = schemaCertificate2 + } + return schemaCertificate +} +func (c *converterImpl) SchemaFromDatacenter(source *Datacenter) schema.Datacenter { + var schemaDatacenter schema.Datacenter + if source != nil { + var schemaDatacenter2 schema.Datacenter + schemaDatacenter2.ID = (*source).ID + schemaDatacenter2.Name = (*source).Name + schemaDatacenter2.Description = (*source).Description + schemaDatacenter2.Location = c.SchemaFromLocation((*source).Location) + schemaDatacenter2.ServerTypes = c.hcloudDatacenterServerTypesToSchemaDatacenterServerTypes((*source).ServerTypes) + schemaDatacenter = schemaDatacenter2 + } + return schemaDatacenter +} +func (c *converterImpl) SchemaFromDeprecation(source *DeprecationInfo) *schema.DeprecationInfo { + var pSchemaDeprecationInfo *schema.DeprecationInfo + if source != nil { + var schemaDeprecationInfo schema.DeprecationInfo + schemaDeprecationInfo.Announced = c.timeTimeToTimeTime((*source).Announced) + schemaDeprecationInfo.UnavailableAfter = c.timeTimeToTimeTime((*source).UnavailableAfter) + pSchemaDeprecationInfo = &schemaDeprecationInfo + } + return pSchemaDeprecationInfo +} +func (c *converterImpl) SchemaFromError(source Error) schema.Error { + var schemaError schema.Error + schemaError.Code = string(source.Code) + schemaError.Message = source.Message + schemaError.DetailsRaw = rawSchemaFromErrorDetails(source.Details) + schemaError.Details = schemaFromErrorDetails(source.Details) + return schemaError +} +func (c *converterImpl) SchemaFromFirewall(source *Firewall) schema.Firewall { + var schemaFirewall schema.Firewall + if source != nil { + var schemaFirewall2 schema.Firewall + schemaFirewall2.ID = (*source).ID + schemaFirewall2.Name = (*source).Name + schemaFirewall2.Labels = (*source).Labels + schemaFirewall2.Created = c.timeTimeToTimeTime((*source).Created) + var schemaFirewallRuleList []schema.FirewallRule + if (*source).Rules != nil { + schemaFirewallRuleList = make([]schema.FirewallRule, len((*source).Rules)) + for i := 0; i < len((*source).Rules); i++ { + schemaFirewallRuleList[i] = c.hcloudFirewallRuleToSchemaFirewallRule((*source).Rules[i]) + } + } + schemaFirewall2.Rules = schemaFirewallRuleList + var schemaFirewallResourceList []schema.FirewallResource + if (*source).AppliedTo != nil { + schemaFirewallResourceList = make([]schema.FirewallResource, len((*source).AppliedTo)) + for j := 0; j < len((*source).AppliedTo); j++ { + schemaFirewallResourceList[j] = c.SchemaFromFirewallResource((*source).AppliedTo[j]) + } + } + schemaFirewall2.AppliedTo = schemaFirewallResourceList + schemaFirewall = schemaFirewall2 + } + return schemaFirewall +} +func (c *converterImpl) SchemaFromFirewallCreateOpts(source FirewallCreateOpts) schema.FirewallCreateRequest { + var schemaFirewallCreateRequest schema.FirewallCreateRequest + schemaFirewallCreateRequest.Name = source.Name + schemaFirewallCreateRequest.Labels = stringMapToStringMapPtr(source.Labels) + var schemaFirewallRuleRequestList []schema.FirewallRuleRequest + if source.Rules != nil { + schemaFirewallRuleRequestList = make([]schema.FirewallRuleRequest, len(source.Rules)) + for i := 0; i < len(source.Rules); i++ { + schemaFirewallRuleRequestList[i] = c.hcloudFirewallRuleToSchemaFirewallRuleRequest(source.Rules[i]) + } + } + schemaFirewallCreateRequest.Rules = schemaFirewallRuleRequestList + var schemaFirewallResourceList []schema.FirewallResource + if source.ApplyTo != nil { + schemaFirewallResourceList = make([]schema.FirewallResource, len(source.ApplyTo)) + for j := 0; j < len(source.ApplyTo); j++ { + schemaFirewallResourceList[j] = c.SchemaFromFirewallResource(source.ApplyTo[j]) + } + } + schemaFirewallCreateRequest.ApplyTo = schemaFirewallResourceList + return schemaFirewallCreateRequest +} +func (c *converterImpl) SchemaFromFirewallResource(source FirewallResource) schema.FirewallResource { + var schemaFirewallResource schema.FirewallResource + schemaFirewallResource.Type = string(source.Type) + schemaFirewallResource.Server = c.pHcloudFirewallResourceServerToPSchemaFirewallResourceServer(source.Server) + schemaFirewallResource.LabelSelector = c.pHcloudFirewallResourceLabelSelectorToPSchemaFirewallResourceLabelSelector(source.LabelSelector) + return schemaFirewallResource +} +func (c *converterImpl) SchemaFromFirewallSetRulesOpts(source FirewallSetRulesOpts) schema.FirewallActionSetRulesRequest { + var schemaFirewallActionSetRulesRequest schema.FirewallActionSetRulesRequest + var schemaFirewallRuleRequestList []schema.FirewallRuleRequest + if source.Rules != nil { + schemaFirewallRuleRequestList = make([]schema.FirewallRuleRequest, len(source.Rules)) + for i := 0; i < len(source.Rules); i++ { + schemaFirewallRuleRequestList[i] = c.hcloudFirewallRuleToSchemaFirewallRuleRequest(source.Rules[i]) + } + } + schemaFirewallActionSetRulesRequest.Rules = schemaFirewallRuleRequestList + return schemaFirewallActionSetRulesRequest +} +func (c *converterImpl) SchemaFromFloatingIP(source *FloatingIP) schema.FloatingIP { + var schemaFloatingIP schema.FloatingIP + if source != nil { + var schemaFloatingIP2 schema.FloatingIP + schemaFloatingIP2.ID = (*source).ID + pString := (*source).Description + schemaFloatingIP2.Description = &pString + schemaFloatingIP2.Created = c.timeTimeToTimeTime((*source).Created) + schemaFloatingIP2.IP = floatingIPToIPString((*source)) + schemaFloatingIP2.Type = string((*source).Type) + schemaFloatingIP2.Server = c.pHcloudServerToPInt64((*source).Server) + schemaFloatingIP2.DNSPtr = floatingIPDNSPtrSchemaFromMap((*source).DNSPtr) + schemaFloatingIP2.HomeLocation = c.SchemaFromLocation((*source).HomeLocation) + schemaFloatingIP2.Blocked = (*source).Blocked + schemaFloatingIP2.Protection = c.hcloudFloatingIPProtectionToSchemaFloatingIPProtection((*source).Protection) + schemaFloatingIP2.Labels = (*source).Labels + schemaFloatingIP2.Name = (*source).Name + schemaFloatingIP = schemaFloatingIP2 + } + return schemaFloatingIP +} +func (c *converterImpl) SchemaFromISO(source *ISO) schema.ISO { + var schemaISO schema.ISO + if source != nil { + var schemaISO2 schema.ISO + schemaISO2.ID = (*source).ID + schemaISO2.Name = (*source).Name + schemaISO2.Description = (*source).Description + schemaISO2.Type = string((*source).Type) + var pString *string + if (*source).Architecture != nil { + xstring := string(*(*source).Architecture) + pString = &xstring + } + schemaISO2.Architecture = pString + schemaISO2.DeprecatableResource = c.hcloudDeprecatableResourceToSchemaDeprecatableResource((*source).DeprecatableResource) + schemaISO = schemaISO2 + } + return schemaISO +} +func (c *converterImpl) SchemaFromImage(source *Image) schema.Image { + var schemaImage schema.Image + if source != nil { + schemaImage = c.intSchemaFromImage((*source)) + } + return schemaImage +} +func (c *converterImpl) SchemaFromLoadBalancer(source *LoadBalancer) schema.LoadBalancer { + var schemaLoadBalancer schema.LoadBalancer + if source != nil { + var schemaLoadBalancer2 schema.LoadBalancer + schemaLoadBalancer2.ID = (*source).ID + schemaLoadBalancer2.Name = (*source).Name + schemaLoadBalancer2.PublicNet = c.hcloudLoadBalancerPublicNetToSchemaLoadBalancerPublicNet((*source).PublicNet) + var schemaLoadBalancerPrivateNetList []schema.LoadBalancerPrivateNet + if (*source).PrivateNet != nil { + schemaLoadBalancerPrivateNetList = make([]schema.LoadBalancerPrivateNet, len((*source).PrivateNet)) + for i := 0; i < len((*source).PrivateNet); i++ { + schemaLoadBalancerPrivateNetList[i] = c.hcloudLoadBalancerPrivateNetToSchemaLoadBalancerPrivateNet((*source).PrivateNet[i]) + } + } + schemaLoadBalancer2.PrivateNet = schemaLoadBalancerPrivateNetList + schemaLoadBalancer2.Location = c.SchemaFromLocation((*source).Location) + schemaLoadBalancer2.LoadBalancerType = c.SchemaFromLoadBalancerType((*source).LoadBalancerType) + schemaLoadBalancer2.Protection = c.hcloudLoadBalancerProtectionToSchemaLoadBalancerProtection((*source).Protection) + schemaLoadBalancer2.Labels = (*source).Labels + schemaLoadBalancer2.Created = c.timeTimeToTimeTime((*source).Created) + var schemaLoadBalancerServiceList []schema.LoadBalancerService + if (*source).Services != nil { + schemaLoadBalancerServiceList = make([]schema.LoadBalancerService, len((*source).Services)) + for j := 0; j < len((*source).Services); j++ { + schemaLoadBalancerServiceList[j] = c.SchemaFromLoadBalancerService((*source).Services[j]) + } + } + schemaLoadBalancer2.Services = schemaLoadBalancerServiceList + var schemaLoadBalancerTargetList []schema.LoadBalancerTarget + if (*source).Targets != nil { + schemaLoadBalancerTargetList = make([]schema.LoadBalancerTarget, len((*source).Targets)) + for k := 0; k < len((*source).Targets); k++ { + schemaLoadBalancerTargetList[k] = c.SchemaFromLoadBalancerTarget((*source).Targets[k]) + } + } + schemaLoadBalancer2.Targets = schemaLoadBalancerTargetList + schemaLoadBalancer2.Algorithm = c.hcloudLoadBalancerAlgorithmToSchemaLoadBalancerAlgorithm((*source).Algorithm) + schemaLoadBalancer2.IncludedTraffic = (*source).IncludedTraffic + schemaLoadBalancer2.OutgoingTraffic = mapZeroUint64ToNil((*source).OutgoingTraffic) + schemaLoadBalancer2.IngoingTraffic = mapZeroUint64ToNil((*source).IngoingTraffic) + schemaLoadBalancer = schemaLoadBalancer2 + } + return schemaLoadBalancer +} +func (c *converterImpl) SchemaFromLoadBalancerAddServiceOpts(source LoadBalancerAddServiceOpts) schema.LoadBalancerActionAddServiceRequest { + var schemaLoadBalancerActionAddServiceRequest schema.LoadBalancerActionAddServiceRequest + schemaLoadBalancerActionAddServiceRequest.Protocol = string(source.Protocol) + schemaLoadBalancerActionAddServiceRequest.ListenPort = source.ListenPort + schemaLoadBalancerActionAddServiceRequest.DestinationPort = source.DestinationPort + schemaLoadBalancerActionAddServiceRequest.Proxyprotocol = source.Proxyprotocol + schemaLoadBalancerActionAddServiceRequest.HTTP = c.pHcloudLoadBalancerAddServiceOptsHTTPToPSchemaLoadBalancerActionAddServiceRequestHTTP(source.HTTP) + schemaLoadBalancerActionAddServiceRequest.HealthCheck = c.pHcloudLoadBalancerAddServiceOptsHealthCheckToPSchemaLoadBalancerActionAddServiceRequestHealthCheck(source.HealthCheck) + return schemaLoadBalancerActionAddServiceRequest +} +func (c *converterImpl) SchemaFromLoadBalancerCreateOpts(source LoadBalancerCreateOpts) schema.LoadBalancerCreateRequest { + var schemaLoadBalancerCreateRequest schema.LoadBalancerCreateRequest + schemaLoadBalancerCreateRequest.Name = source.Name + schemaLoadBalancerCreateRequest.LoadBalancerType = anyFromLoadBalancerType(source.LoadBalancerType) + schemaLoadBalancerCreateRequest.Algorithm = c.pHcloudLoadBalancerAlgorithmToPSchemaLoadBalancerCreateRequestAlgorithm(source.Algorithm) + schemaLoadBalancerCreateRequest.Location = c.pHcloudLocationToPString(source.Location) + schemaLoadBalancerCreateRequest.NetworkZone = stringPtrFromNetworkZone(source.NetworkZone) + schemaLoadBalancerCreateRequest.Labels = stringMapToStringMapPtr(source.Labels) + var schemaLoadBalancerCreateRequestTargetList []schema.LoadBalancerCreateRequestTarget + if source.Targets != nil { + schemaLoadBalancerCreateRequestTargetList = make([]schema.LoadBalancerCreateRequestTarget, len(source.Targets)) + for i := 0; i < len(source.Targets); i++ { + schemaLoadBalancerCreateRequestTargetList[i] = c.hcloudLoadBalancerCreateOptsTargetToSchemaLoadBalancerCreateRequestTarget(source.Targets[i]) + } + } + schemaLoadBalancerCreateRequest.Targets = schemaLoadBalancerCreateRequestTargetList + var schemaLoadBalancerCreateRequestServiceList []schema.LoadBalancerCreateRequestService + if source.Services != nil { + schemaLoadBalancerCreateRequestServiceList = make([]schema.LoadBalancerCreateRequestService, len(source.Services)) + for j := 0; j < len(source.Services); j++ { + schemaLoadBalancerCreateRequestServiceList[j] = c.hcloudLoadBalancerCreateOptsServiceToSchemaLoadBalancerCreateRequestService(source.Services[j]) + } + } + schemaLoadBalancerCreateRequest.Services = schemaLoadBalancerCreateRequestServiceList + schemaLoadBalancerCreateRequest.PublicInterface = source.PublicInterface + schemaLoadBalancerCreateRequest.Network = c.pHcloudNetworkToPInt64(source.Network) + return schemaLoadBalancerCreateRequest +} +func (c *converterImpl) SchemaFromLoadBalancerCreateOptsTargetServer(source LoadBalancerCreateOptsTargetServer) schema.LoadBalancerCreateRequestTargetServer { + var schemaLoadBalancerCreateRequestTargetServer schema.LoadBalancerCreateRequestTargetServer + var pInt64 *int64 + if source.Server != nil { + pInt64 = &source.Server.ID + } + var xint64 int64 + if pInt64 != nil { + xint64 = *pInt64 + } + schemaLoadBalancerCreateRequestTargetServer.ID = xint64 + return schemaLoadBalancerCreateRequestTargetServer +} +func (c *converterImpl) SchemaFromLoadBalancerServerTarget(source LoadBalancerTargetServer) schema.LoadBalancerTargetServer { + var schemaLoadBalancerTargetServer schema.LoadBalancerTargetServer + schemaLoadBalancerTargetServer.ID = c.pHcloudServerToInt64(source.Server) + return schemaLoadBalancerTargetServer +} +func (c *converterImpl) SchemaFromLoadBalancerService(source LoadBalancerService) schema.LoadBalancerService { + var schemaLoadBalancerService schema.LoadBalancerService + schemaLoadBalancerService.Protocol = string(source.Protocol) + schemaLoadBalancerService.ListenPort = source.ListenPort + schemaLoadBalancerService.DestinationPort = source.DestinationPort + schemaLoadBalancerService.Proxyprotocol = source.Proxyprotocol + schemaLoadBalancerService.HTTP = c.hcloudLoadBalancerServiceHTTPToPSchemaLoadBalancerServiceHTTP(source.HTTP) + schemaLoadBalancerService.HealthCheck = c.SchemaFromLoadBalancerServiceHealthCheck(source.HealthCheck) + return schemaLoadBalancerService +} +func (c *converterImpl) SchemaFromLoadBalancerServiceHealthCheck(source LoadBalancerServiceHealthCheck) *schema.LoadBalancerServiceHealthCheck { + var schemaLoadBalancerServiceHealthCheck schema.LoadBalancerServiceHealthCheck + schemaLoadBalancerServiceHealthCheck.Protocol = string(source.Protocol) + schemaLoadBalancerServiceHealthCheck.Port = source.Port + schemaLoadBalancerServiceHealthCheck.Interval = intSecondsFromDuration(source.Interval) + schemaLoadBalancerServiceHealthCheck.Timeout = intSecondsFromDuration(source.Timeout) + schemaLoadBalancerServiceHealthCheck.Retries = source.Retries + schemaLoadBalancerServiceHealthCheck.HTTP = c.pHcloudLoadBalancerServiceHealthCheckHTTPToPSchemaLoadBalancerServiceHealthCheckHTTP(source.HTTP) + return &schemaLoadBalancerServiceHealthCheck +} +func (c *converterImpl) SchemaFromLoadBalancerTarget(source LoadBalancerTarget) schema.LoadBalancerTarget { + var schemaLoadBalancerTarget schema.LoadBalancerTarget + schemaLoadBalancerTarget.Type = string(source.Type) + schemaLoadBalancerTarget.Server = c.pHcloudLoadBalancerTargetServerToPSchemaLoadBalancerTargetServer(source.Server) + schemaLoadBalancerTarget.LabelSelector = c.pHcloudLoadBalancerTargetLabelSelectorToPSchemaLoadBalancerTargetLabelSelector(source.LabelSelector) + schemaLoadBalancerTarget.IP = c.pHcloudLoadBalancerTargetIPToPSchemaLoadBalancerTargetIP(source.IP) + var schemaLoadBalancerTargetHealthStatusList []schema.LoadBalancerTargetHealthStatus + if source.HealthStatus != nil { + schemaLoadBalancerTargetHealthStatusList = make([]schema.LoadBalancerTargetHealthStatus, len(source.HealthStatus)) + for i := 0; i < len(source.HealthStatus); i++ { + schemaLoadBalancerTargetHealthStatusList[i] = c.SchemaFromLoadBalancerTargetHealthStatus(source.HealthStatus[i]) + } + } + schemaLoadBalancerTarget.HealthStatus = schemaLoadBalancerTargetHealthStatusList + schemaLoadBalancerTarget.UsePrivateIP = source.UsePrivateIP + var schemaLoadBalancerTargetList []schema.LoadBalancerTarget + if source.Targets != nil { + schemaLoadBalancerTargetList = make([]schema.LoadBalancerTarget, len(source.Targets)) + for j := 0; j < len(source.Targets); j++ { + schemaLoadBalancerTargetList[j] = c.SchemaFromLoadBalancerTarget(source.Targets[j]) + } + } + schemaLoadBalancerTarget.Targets = schemaLoadBalancerTargetList + return schemaLoadBalancerTarget +} +func (c *converterImpl) SchemaFromLoadBalancerTargetHealthStatus(source LoadBalancerTargetHealthStatus) schema.LoadBalancerTargetHealthStatus { + var schemaLoadBalancerTargetHealthStatus schema.LoadBalancerTargetHealthStatus + schemaLoadBalancerTargetHealthStatus.ListenPort = source.ListenPort + schemaLoadBalancerTargetHealthStatus.Status = string(source.Status) + return schemaLoadBalancerTargetHealthStatus +} +func (c *converterImpl) SchemaFromLoadBalancerType(source *LoadBalancerType) schema.LoadBalancerType { + var schemaLoadBalancerType schema.LoadBalancerType + if source != nil { + var schemaLoadBalancerType2 schema.LoadBalancerType + schemaLoadBalancerType2.ID = (*source).ID + schemaLoadBalancerType2.Name = (*source).Name + schemaLoadBalancerType2.Description = (*source).Description + schemaLoadBalancerType2.MaxConnections = (*source).MaxConnections + schemaLoadBalancerType2.MaxServices = (*source).MaxServices + schemaLoadBalancerType2.MaxTargets = (*source).MaxTargets + schemaLoadBalancerType2.MaxAssignedCertificates = (*source).MaxAssignedCertificates + var schemaPricingLoadBalancerTypePriceList []schema.PricingLoadBalancerTypePrice + if (*source).Pricings != nil { + schemaPricingLoadBalancerTypePriceList = make([]schema.PricingLoadBalancerTypePrice, len((*source).Pricings)) + for i := 0; i < len((*source).Pricings); i++ { + schemaPricingLoadBalancerTypePriceList[i] = c.SchemaFromLoadBalancerTypeLocationPricing((*source).Pricings[i]) + } + } + schemaLoadBalancerType2.Prices = schemaPricingLoadBalancerTypePriceList + schemaLoadBalancerType2.Deprecated = (*source).Deprecated + schemaLoadBalancerType = schemaLoadBalancerType2 + } + return schemaLoadBalancerType +} +func (c *converterImpl) SchemaFromLoadBalancerTypeLocationPricing(source LoadBalancerTypeLocationPricing) schema.PricingLoadBalancerTypePrice { + var schemaPricingLoadBalancerTypePrice schema.PricingLoadBalancerTypePrice + schemaPricingLoadBalancerTypePrice.Location = c.pHcloudLocationToString(source.Location) + schemaPricingLoadBalancerTypePrice.PriceHourly = c.hcloudPriceToSchemaPrice(source.Hourly) + schemaPricingLoadBalancerTypePrice.PriceMonthly = c.hcloudPriceToSchemaPrice(source.Monthly) + return schemaPricingLoadBalancerTypePrice +} +func (c *converterImpl) SchemaFromLoadBalancerUpdateServiceOpts(source LoadBalancerUpdateServiceOpts) schema.LoadBalancerActionUpdateServiceRequest { + var schemaLoadBalancerActionUpdateServiceRequest schema.LoadBalancerActionUpdateServiceRequest + schemaLoadBalancerActionUpdateServiceRequest.Protocol = stringPtrFromLoadBalancerServiceProtocol(source.Protocol) + schemaLoadBalancerActionUpdateServiceRequest.DestinationPort = source.DestinationPort + schemaLoadBalancerActionUpdateServiceRequest.Proxyprotocol = source.Proxyprotocol + schemaLoadBalancerActionUpdateServiceRequest.HTTP = c.pHcloudLoadBalancerUpdateServiceOptsHTTPToPSchemaLoadBalancerActionUpdateServiceRequestHTTP(source.HTTP) + schemaLoadBalancerActionUpdateServiceRequest.HealthCheck = c.pHcloudLoadBalancerUpdateServiceOptsHealthCheckToPSchemaLoadBalancerActionUpdateServiceRequestHealthCheck(source.HealthCheck) + return schemaLoadBalancerActionUpdateServiceRequest +} +func (c *converterImpl) SchemaFromLocation(source *Location) schema.Location { + var schemaLocation schema.Location + if source != nil { + var schemaLocation2 schema.Location + schemaLocation2.ID = (*source).ID + schemaLocation2.Name = (*source).Name + schemaLocation2.Description = (*source).Description + schemaLocation2.Country = (*source).Country + schemaLocation2.City = (*source).City + schemaLocation2.Latitude = (*source).Latitude + schemaLocation2.Longitude = (*source).Longitude + schemaLocation2.NetworkZone = string((*source).NetworkZone) + schemaLocation = schemaLocation2 + } + return schemaLocation +} +func (c *converterImpl) SchemaFromNetwork(source *Network) schema.Network { + var schemaNetwork schema.Network + if source != nil { + var schemaNetwork2 schema.Network + schemaNetwork2.ID = (*source).ID + schemaNetwork2.Name = (*source).Name + schemaNetwork2.Created = c.timeTimeToTimeTime((*source).Created) + schemaNetwork2.IPRange = c.pNetIPNetToString((*source).IPRange) + var schemaNetworkSubnetList []schema.NetworkSubnet + if (*source).Subnets != nil { + schemaNetworkSubnetList = make([]schema.NetworkSubnet, len((*source).Subnets)) + for i := 0; i < len((*source).Subnets); i++ { + schemaNetworkSubnetList[i] = c.SchemaFromNetworkSubnet((*source).Subnets[i]) + } + } + schemaNetwork2.Subnets = schemaNetworkSubnetList + var schemaNetworkRouteList []schema.NetworkRoute + if (*source).Routes != nil { + schemaNetworkRouteList = make([]schema.NetworkRoute, len((*source).Routes)) + for j := 0; j < len((*source).Routes); j++ { + schemaNetworkRouteList[j] = c.SchemaFromNetworkRoute((*source).Routes[j]) + } + } + schemaNetwork2.Routes = schemaNetworkRouteList + var int64List []int64 + if (*source).Servers != nil { + int64List = make([]int64, len((*source).Servers)) + for k := 0; k < len((*source).Servers); k++ { + int64List[k] = c.pHcloudServerToInt64((*source).Servers[k]) + } + } + schemaNetwork2.Servers = int64List + schemaNetwork2.Protection = c.hcloudNetworkProtectionToSchemaNetworkProtection((*source).Protection) + schemaNetwork2.Labels = (*source).Labels + schemaNetwork2.ExposeRoutesToVSwitch = (*source).ExposeRoutesToVSwitch + schemaNetwork = schemaNetwork2 + } + return schemaNetwork +} +func (c *converterImpl) SchemaFromNetworkRoute(source NetworkRoute) schema.NetworkRoute { + var schemaNetworkRoute schema.NetworkRoute + schemaNetworkRoute.Destination = c.pNetIPNetToString(source.Destination) + schemaNetworkRoute.Gateway = stringFromIP(source.Gateway) + return schemaNetworkRoute +} +func (c *converterImpl) SchemaFromNetworkSubnet(source NetworkSubnet) schema.NetworkSubnet { + var schemaNetworkSubnet schema.NetworkSubnet + schemaNetworkSubnet.Type = string(source.Type) + schemaNetworkSubnet.IPRange = c.pNetIPNetToString(source.IPRange) + schemaNetworkSubnet.NetworkZone = string(source.NetworkZone) + schemaNetworkSubnet.Gateway = stringFromIP(source.Gateway) + schemaNetworkSubnet.VSwitchID = source.VSwitchID + return schemaNetworkSubnet +} +func (c *converterImpl) SchemaFromPagination(source Pagination) schema.MetaPagination { + var schemaMetaPagination schema.MetaPagination + schemaMetaPagination.Page = source.Page + schemaMetaPagination.PerPage = source.PerPage + schemaMetaPagination.PreviousPage = source.PreviousPage + schemaMetaPagination.NextPage = source.NextPage + schemaMetaPagination.LastPage = source.LastPage + schemaMetaPagination.TotalEntries = source.TotalEntries + return schemaMetaPagination +} +func (c *converterImpl) SchemaFromPlacementGroup(source *PlacementGroup) schema.PlacementGroup { + var schemaPlacementGroup schema.PlacementGroup + if source != nil { + var schemaPlacementGroup2 schema.PlacementGroup + schemaPlacementGroup2.ID = (*source).ID + schemaPlacementGroup2.Name = (*source).Name + schemaPlacementGroup2.Labels = (*source).Labels + schemaPlacementGroup2.Created = c.timeTimeToTimeTime((*source).Created) + schemaPlacementGroup2.Servers = (*source).Servers + schemaPlacementGroup2.Type = string((*source).Type) + schemaPlacementGroup = schemaPlacementGroup2 + } + return schemaPlacementGroup +} +func (c *converterImpl) SchemaFromPlacementGroupCreateOpts(source PlacementGroupCreateOpts) schema.PlacementGroupCreateRequest { + var schemaPlacementGroupCreateRequest schema.PlacementGroupCreateRequest + schemaPlacementGroupCreateRequest.Name = source.Name + schemaPlacementGroupCreateRequest.Labels = stringMapToStringMapPtr(source.Labels) + schemaPlacementGroupCreateRequest.Type = string(source.Type) + return schemaPlacementGroupCreateRequest +} +func (c *converterImpl) SchemaFromPricing(source Pricing) schema.Pricing { + var schemaPricing schema.Pricing + schemaPricing.Currency = source.Image.PerGBMonth.Currency + schemaPricing.VATRate = source.Image.PerGBMonth.VATRate + schemaPricing.Image = c.schemaFromImagePricing(source.Image) + schemaPricing.FloatingIP = c.schemaFromFloatingIPPricing(source.FloatingIP) + var schemaPricingFloatingIPTypeList []schema.PricingFloatingIPType + if source.FloatingIPs != nil { + schemaPricingFloatingIPTypeList = make([]schema.PricingFloatingIPType, len(source.FloatingIPs)) + for i := 0; i < len(source.FloatingIPs); i++ { + schemaPricingFloatingIPTypeList[i] = c.schemaFromFloatingIPTypePricing(source.FloatingIPs[i]) + } + } + schemaPricing.FloatingIPs = schemaPricingFloatingIPTypeList + var schemaPricingPrimaryIPList []schema.PricingPrimaryIP + if source.PrimaryIPs != nil { + schemaPricingPrimaryIPList = make([]schema.PricingPrimaryIP, len(source.PrimaryIPs)) + for j := 0; j < len(source.PrimaryIPs); j++ { + schemaPricingPrimaryIPList[j] = c.schemaFromPrimaryIPPricing(source.PrimaryIPs[j]) + } + } + schemaPricing.PrimaryIPs = schemaPricingPrimaryIPList + schemaPricing.Traffic = c.schemaFromTrafficPricing(source.Traffic) + schemaPricing.ServerBackup = c.hcloudServerBackupPricingToSchemaPricingServerBackup(source.ServerBackup) + var schemaPricingServerTypeList []schema.PricingServerType + if source.ServerTypes != nil { + schemaPricingServerTypeList = make([]schema.PricingServerType, len(source.ServerTypes)) + for k := 0; k < len(source.ServerTypes); k++ { + schemaPricingServerTypeList[k] = c.schemaFromServerTypePricing(source.ServerTypes[k]) + } + } + schemaPricing.ServerTypes = schemaPricingServerTypeList + var schemaPricingLoadBalancerTypeList []schema.PricingLoadBalancerType + if source.LoadBalancerTypes != nil { + schemaPricingLoadBalancerTypeList = make([]schema.PricingLoadBalancerType, len(source.LoadBalancerTypes)) + for l := 0; l < len(source.LoadBalancerTypes); l++ { + schemaPricingLoadBalancerTypeList[l] = c.schemaFromLoadBalancerTypePricing(source.LoadBalancerTypes[l]) + } + } + schemaPricing.LoadBalancerTypes = schemaPricingLoadBalancerTypeList + schemaPricing.Volume = c.schemaFromVolumePricing(source.Volume) + return schemaPricing +} +func (c *converterImpl) SchemaFromPrimaryIP(source *PrimaryIP) schema.PrimaryIP { + var schemaPrimaryIP schema.PrimaryIP + if source != nil { + var schemaPrimaryIP2 schema.PrimaryIP + schemaPrimaryIP2.ID = (*source).ID + schemaPrimaryIP2.IP = primaryIPToIPString((*source)) + schemaPrimaryIP2.Labels = (*source).Labels + schemaPrimaryIP2.Name = (*source).Name + schemaPrimaryIP2.Type = string((*source).Type) + schemaPrimaryIP2.Protection = c.hcloudPrimaryIPProtectionToSchemaPrimaryIPProtection((*source).Protection) + schemaPrimaryIP2.DNSPtr = primaryIPDNSPtrSchemaFromMap((*source).DNSPtr) + schemaPrimaryIP2.AssigneeID = mapZeroInt64ToNil((*source).AssigneeID) + schemaPrimaryIP2.AssigneeType = (*source).AssigneeType + schemaPrimaryIP2.AutoDelete = (*source).AutoDelete + schemaPrimaryIP2.Blocked = (*source).Blocked + schemaPrimaryIP2.Created = c.timeTimeToTimeTime((*source).Created) + schemaPrimaryIP2.Datacenter = c.SchemaFromDatacenter((*source).Datacenter) + schemaPrimaryIP = schemaPrimaryIP2 + } + return schemaPrimaryIP +} +func (c *converterImpl) SchemaFromSSHKey(source *SSHKey) schema.SSHKey { + var schemaSSHKey schema.SSHKey + if source != nil { + var schemaSSHKey2 schema.SSHKey + schemaSSHKey2.ID = (*source).ID + schemaSSHKey2.Name = (*source).Name + schemaSSHKey2.Fingerprint = (*source).Fingerprint + schemaSSHKey2.PublicKey = (*source).PublicKey + schemaSSHKey2.Labels = (*source).Labels + schemaSSHKey2.Created = c.timeTimeToTimeTime((*source).Created) + schemaSSHKey = schemaSSHKey2 + } + return schemaSSHKey +} +func (c *converterImpl) SchemaFromServer(source *Server) schema.Server { + var schemaServer schema.Server + if source != nil { + var schemaServer2 schema.Server + schemaServer2.ID = (*source).ID + schemaServer2.Name = (*source).Name + schemaServer2.Status = string((*source).Status) + schemaServer2.Created = c.timeTimeToTimeTime((*source).Created) + schemaServer2.PublicNet = c.SchemaFromServerPublicNet((*source).PublicNet) + var schemaServerPrivateNetList []schema.ServerPrivateNet + if (*source).PrivateNet != nil { + schemaServerPrivateNetList = make([]schema.ServerPrivateNet, len((*source).PrivateNet)) + for i := 0; i < len((*source).PrivateNet); i++ { + schemaServerPrivateNetList[i] = c.SchemaFromServerPrivateNet((*source).PrivateNet[i]) + } + } + schemaServer2.PrivateNet = schemaServerPrivateNetList + schemaServer2.ServerType = c.SchemaFromServerType((*source).ServerType) + schemaServer2.IncludedTraffic = (*source).IncludedTraffic + schemaServer2.OutgoingTraffic = mapZeroUint64ToNil((*source).OutgoingTraffic) + schemaServer2.IngoingTraffic = mapZeroUint64ToNil((*source).IngoingTraffic) + schemaServer2.BackupWindow = mapEmptyStringToNil((*source).BackupWindow) + schemaServer2.RescueEnabled = (*source).RescueEnabled + schemaServer2.ISO = c.pHcloudISOToPSchemaISO((*source).ISO) + schemaServer2.Locked = (*source).Locked + schemaServer2.Datacenter = c.SchemaFromDatacenter((*source).Datacenter) + schemaServer2.Image = c.pHcloudImageToPSchemaImage((*source).Image) + schemaServer2.Protection = c.hcloudServerProtectionToSchemaServerProtection((*source).Protection) + schemaServer2.Labels = (*source).Labels + var int64List []int64 + if (*source).Volumes != nil { + int64List = make([]int64, len((*source).Volumes)) + for j := 0; j < len((*source).Volumes); j++ { + int64List[j] = int64FromVolume((*source).Volumes[j]) + } + } + schemaServer2.Volumes = int64List + schemaServer2.PrimaryDiskSize = (*source).PrimaryDiskSize + schemaServer2.PlacementGroup = c.pHcloudPlacementGroupToPSchemaPlacementGroup((*source).PlacementGroup) + var int64List2 []int64 + if (*source).LoadBalancers != nil { + int64List2 = make([]int64, len((*source).LoadBalancers)) + for k := 0; k < len((*source).LoadBalancers); k++ { + int64List2[k] = c.pHcloudLoadBalancerToInt64((*source).LoadBalancers[k]) + } + } + schemaServer2.LoadBalancers = int64List2 + schemaServer = schemaServer2 + } + return schemaServer +} +func (c *converterImpl) SchemaFromServerPrivateNet(source ServerPrivateNet) schema.ServerPrivateNet { + var schemaServerPrivateNet schema.ServerPrivateNet + schemaServerPrivateNet.Network = c.pHcloudNetworkToInt64(source.Network) + schemaServerPrivateNet.IP = stringFromIP(source.IP) + var stringList []string + if source.Aliases != nil { + stringList = make([]string, len(source.Aliases)) + for i := 0; i < len(source.Aliases); i++ { + stringList[i] = stringFromIP(source.Aliases[i]) + } + } + schemaServerPrivateNet.AliasIPs = stringList + schemaServerPrivateNet.MACAddress = source.MACAddress + return schemaServerPrivateNet +} +func (c *converterImpl) SchemaFromServerPublicNet(source ServerPublicNet) schema.ServerPublicNet { + var schemaServerPublicNet schema.ServerPublicNet + schemaServerPublicNet.IPv4 = c.SchemaFromServerPublicNetIPv4(source.IPv4) + schemaServerPublicNet.IPv6 = c.SchemaFromServerPublicNetIPv6(source.IPv6) + var int64List []int64 + if source.FloatingIPs != nil { + int64List = make([]int64, len(source.FloatingIPs)) + for i := 0; i < len(source.FloatingIPs); i++ { + int64List[i] = int64FromFloatingIP(source.FloatingIPs[i]) + } + } + schemaServerPublicNet.FloatingIPs = int64List + var schemaServerFirewallList []schema.ServerFirewall + if source.Firewalls != nil { + schemaServerFirewallList = make([]schema.ServerFirewall, len(source.Firewalls)) + for j := 0; j < len(source.Firewalls); j++ { + schemaServerFirewallList[j] = serverFirewallSchemaFromFirewallStatus(source.Firewalls[j]) + } + } + schemaServerPublicNet.Firewalls = schemaServerFirewallList + return schemaServerPublicNet +} +func (c *converterImpl) SchemaFromServerPublicNetIPv4(source ServerPublicNetIPv4) schema.ServerPublicNetIPv4 { + var schemaServerPublicNetIPv4 schema.ServerPublicNetIPv4 + schemaServerPublicNetIPv4.ID = source.ID + schemaServerPublicNetIPv4.IP = stringFromIP(source.IP) + schemaServerPublicNetIPv4.Blocked = source.Blocked + schemaServerPublicNetIPv4.DNSPtr = source.DNSPtr + return schemaServerPublicNetIPv4 +} +func (c *converterImpl) SchemaFromServerPublicNetIPv6(source ServerPublicNetIPv6) schema.ServerPublicNetIPv6 { + var schemaServerPublicNetIPv6 schema.ServerPublicNetIPv6 + schemaServerPublicNetIPv6.ID = source.ID + schemaServerPublicNetIPv6.IP = c.pNetIPNetToString(source.Network) + schemaServerPublicNetIPv6.Blocked = source.Blocked + schemaServerPublicNetIPv6.DNSPtr = serverPublicNetIPv6DNSPtrSchemaFromMap(source.DNSPtr) + return schemaServerPublicNetIPv6 +} +func (c *converterImpl) SchemaFromServerType(source *ServerType) schema.ServerType { + var schemaServerType schema.ServerType + if source != nil { + var schemaServerType2 schema.ServerType + schemaServerType2.ID = (*source).ID + schemaServerType2.Name = (*source).Name + schemaServerType2.Description = (*source).Description + schemaServerType2.Cores = (*source).Cores + schemaServerType2.Memory = (*source).Memory + schemaServerType2.Disk = (*source).Disk + schemaServerType2.StorageType = string((*source).StorageType) + schemaServerType2.CPUType = string((*source).CPUType) + schemaServerType2.Architecture = string((*source).Architecture) + schemaServerType2.IncludedTraffic = (*source).IncludedTraffic + var schemaPricingServerTypePriceList []schema.PricingServerTypePrice + if (*source).Pricings != nil { + schemaPricingServerTypePriceList = make([]schema.PricingServerTypePrice, len((*source).Pricings)) + for i := 0; i < len((*source).Pricings); i++ { + schemaPricingServerTypePriceList[i] = c.schemaFromServerTypeLocationPricing((*source).Pricings[i]) + } + } + schemaServerType2.Prices = schemaPricingServerTypePriceList + schemaServerType2.Deprecated = isDeprecationNotNil((*source).DeprecatableResource.Deprecation) + schemaServerType2.DeprecatableResource = c.hcloudDeprecatableResourceToSchemaDeprecatableResource((*source).DeprecatableResource) + schemaServerType = schemaServerType2 + } + return schemaServerType +} +func (c *converterImpl) SchemaFromVolume(source *Volume) schema.Volume { + var schemaVolume schema.Volume + if source != nil { + var schemaVolume2 schema.Volume + schemaVolume2.ID = (*source).ID + schemaVolume2.Name = (*source).Name + schemaVolume2.Server = c.pHcloudServerToPInt64((*source).Server) + schemaVolume2.Status = string((*source).Status) + schemaVolume2.Location = c.SchemaFromLocation((*source).Location) + schemaVolume2.Size = (*source).Size + schemaVolume2.Format = (*source).Format + schemaVolume2.Protection = c.hcloudVolumeProtectionToSchemaVolumeProtection((*source).Protection) + schemaVolume2.Labels = (*source).Labels + schemaVolume2.LinuxDevice = (*source).LinuxDevice + schemaVolume2.Created = c.timeTimeToTimeTime((*source).Created) + schemaVolume = schemaVolume2 + } + return schemaVolume +} +func (c *converterImpl) ServerFromSchema(source schema.Server) *Server { + var hcloudServer Server + hcloudServer.ID = source.ID + hcloudServer.Name = source.Name + hcloudServer.Status = ServerStatus(source.Status) + hcloudServer.Created = c.timeTimeToTimeTime(source.Created) + hcloudServer.PublicNet = c.ServerPublicNetFromSchema(source.PublicNet) + var hcloudServerPrivateNetList []ServerPrivateNet + if source.PrivateNet != nil { + hcloudServerPrivateNetList = make([]ServerPrivateNet, len(source.PrivateNet)) + for i := 0; i < len(source.PrivateNet); i++ { + hcloudServerPrivateNetList[i] = c.ServerPrivateNetFromSchema(source.PrivateNet[i]) + } + } + hcloudServer.PrivateNet = hcloudServerPrivateNetList + hcloudServer.ServerType = c.ServerTypeFromSchema(source.ServerType) + hcloudServer.Datacenter = c.DatacenterFromSchema(source.Datacenter) + hcloudServer.IncludedTraffic = source.IncludedTraffic + var xuint64 uint64 + if source.OutgoingTraffic != nil { + xuint64 = *source.OutgoingTraffic + } + hcloudServer.OutgoingTraffic = xuint64 + var xuint642 uint64 + if source.IngoingTraffic != nil { + xuint642 = *source.IngoingTraffic + } + hcloudServer.IngoingTraffic = xuint642 + var xstring string + if source.BackupWindow != nil { + xstring = *source.BackupWindow + } + hcloudServer.BackupWindow = xstring + hcloudServer.RescueEnabled = source.RescueEnabled + hcloudServer.Locked = source.Locked + hcloudServer.ISO = c.pSchemaISOToPHcloudISO(source.ISO) + hcloudServer.Image = c.pSchemaImageToPHcloudImage(source.Image) + hcloudServer.Protection = c.schemaServerProtectionToHcloudServerProtection(source.Protection) + hcloudServer.Labels = source.Labels + var pHcloudVolumeList []*Volume + if source.Volumes != nil { + pHcloudVolumeList = make([]*Volume, len(source.Volumes)) + for j := 0; j < len(source.Volumes); j++ { + pHcloudVolumeList[j] = volumeFromInt64(source.Volumes[j]) + } + } + hcloudServer.Volumes = pHcloudVolumeList + hcloudServer.PrimaryDiskSize = source.PrimaryDiskSize + hcloudServer.PlacementGroup = c.pSchemaPlacementGroupToPHcloudPlacementGroup(source.PlacementGroup) + var pHcloudLoadBalancerList []*LoadBalancer + if source.LoadBalancers != nil { + pHcloudLoadBalancerList = make([]*LoadBalancer, len(source.LoadBalancers)) + for k := 0; k < len(source.LoadBalancers); k++ { + hcloudLoadBalancer := loadBalancerFromInt64(source.LoadBalancers[k]) + pHcloudLoadBalancerList[k] = &hcloudLoadBalancer + } + } + hcloudServer.LoadBalancers = pHcloudLoadBalancerList + return &hcloudServer +} +func (c *converterImpl) ServerMetricsFromSchema(source *schema.ServerGetMetricsResponse) (*ServerMetrics, error) { + var pHcloudServerMetrics *ServerMetrics + if source != nil { + var hcloudServerMetrics ServerMetrics + hcloudServerMetrics.Start = c.timeTimeToTimeTime((*source).Metrics.Start) + hcloudServerMetrics.End = c.timeTimeToTimeTime((*source).Metrics.End) + hcloudServerMetrics.Step = (*source).Metrics.Step + var mapStringHcloudServerMetricsValueList map[string][]ServerMetricsValue + if (*source).Metrics.TimeSeries != nil { + mapStringHcloudServerMetricsValueList = make(map[string][]ServerMetricsValue, len((*source).Metrics.TimeSeries)) + for key, value := range (*source).Metrics.TimeSeries { + hcloudServerMetricsValueList, err := serverMetricsTimeSeriesFromSchema(value) + if err != nil { + return nil, err + } + mapStringHcloudServerMetricsValueList[key] = hcloudServerMetricsValueList + } + } + hcloudServerMetrics.TimeSeries = mapStringHcloudServerMetricsValueList + pHcloudServerMetrics = &hcloudServerMetrics + } + return pHcloudServerMetrics, nil +} +func (c *converterImpl) ServerPrivateNetFromSchema(source schema.ServerPrivateNet) ServerPrivateNet { + var hcloudServerPrivateNet ServerPrivateNet + hcloudNetwork := networkFromInt64(source.Network) + hcloudServerPrivateNet.Network = &hcloudNetwork + hcloudServerPrivateNet.IP = ipFromString(source.IP) + var netIPList []net.IP + if source.AliasIPs != nil { + netIPList = make([]net.IP, len(source.AliasIPs)) + for i := 0; i < len(source.AliasIPs); i++ { + netIPList[i] = ipFromString(source.AliasIPs[i]) + } + } + hcloudServerPrivateNet.Aliases = netIPList + hcloudServerPrivateNet.MACAddress = source.MACAddress + return hcloudServerPrivateNet +} +func (c *converterImpl) ServerPublicNetFromSchema(source schema.ServerPublicNet) ServerPublicNet { + var hcloudServerPublicNet ServerPublicNet + hcloudServerPublicNet.IPv4 = c.ServerPublicNetIPv4FromSchema(source.IPv4) + hcloudServerPublicNet.IPv6 = c.ServerPublicNetIPv6FromSchema(source.IPv6) + var pHcloudFloatingIPList []*FloatingIP + if source.FloatingIPs != nil { + pHcloudFloatingIPList = make([]*FloatingIP, len(source.FloatingIPs)) + for i := 0; i < len(source.FloatingIPs); i++ { + pHcloudFloatingIPList[i] = floatingIPFromInt64(source.FloatingIPs[i]) + } + } + hcloudServerPublicNet.FloatingIPs = pHcloudFloatingIPList + var pHcloudServerFirewallStatusList []*ServerFirewallStatus + if source.Firewalls != nil { + pHcloudServerFirewallStatusList = make([]*ServerFirewallStatus, len(source.Firewalls)) + for j := 0; j < len(source.Firewalls); j++ { + pHcloudServerFirewallStatusList[j] = firewallStatusFromSchemaServerFirewall(source.Firewalls[j]) + } + } + hcloudServerPublicNet.Firewalls = pHcloudServerFirewallStatusList + return hcloudServerPublicNet +} +func (c *converterImpl) ServerPublicNetIPv4FromSchema(source schema.ServerPublicNetIPv4) ServerPublicNetIPv4 { + var hcloudServerPublicNetIPv4 ServerPublicNetIPv4 + hcloudServerPublicNetIPv4.ID = source.ID + hcloudServerPublicNetIPv4.IP = ipFromString(source.IP) + hcloudServerPublicNetIPv4.Blocked = source.Blocked + hcloudServerPublicNetIPv4.DNSPtr = source.DNSPtr + return hcloudServerPublicNetIPv4 +} +func (c *converterImpl) ServerPublicNetIPv6FromSchema(source schema.ServerPublicNetIPv6) ServerPublicNetIPv6 { + var hcloudServerPublicNetIPv6 ServerPublicNetIPv6 + hcloudServerPublicNetIPv6.ID = source.ID + hcloudServerPublicNetIPv6.IP = ipFromServerPublicNetIPv6Schema(source) + hcloudServerPublicNetIPv6.Network = ipNetFromServerPublicNetIPv6Schema(source) + hcloudServerPublicNetIPv6.Blocked = source.Blocked + hcloudServerPublicNetIPv6.DNSPtr = mapFromServerPublicNetIPv6DNSPtrSchema(source.DNSPtr) + return hcloudServerPublicNetIPv6 +} +func (c *converterImpl) ServerTypeFromSchema(source schema.ServerType) *ServerType { + var hcloudServerType ServerType + hcloudServerType.ID = source.ID + hcloudServerType.Name = source.Name + hcloudServerType.Description = source.Description + hcloudServerType.Cores = source.Cores + hcloudServerType.Memory = source.Memory + hcloudServerType.Disk = source.Disk + hcloudServerType.StorageType = StorageType(source.StorageType) + hcloudServerType.CPUType = CPUType(source.CPUType) + hcloudServerType.Architecture = Architecture(source.Architecture) + hcloudServerType.IncludedTraffic = source.IncludedTraffic + var hcloudServerTypeLocationPricingList []ServerTypeLocationPricing + if source.Prices != nil { + hcloudServerTypeLocationPricingList = make([]ServerTypeLocationPricing, len(source.Prices)) + for i := 0; i < len(source.Prices); i++ { + hcloudServerTypeLocationPricingList[i] = c.serverTypePricingFromSchema(source.Prices[i]) + } + } + hcloudServerType.Pricings = hcloudServerTypeLocationPricingList + hcloudServerType.DeprecatableResource = c.schemaDeprecatableResourceToHcloudDeprecatableResource(source.DeprecatableResource) + return &hcloudServerType +} +func (c *converterImpl) VolumeFromSchema(source schema.Volume) *Volume { + var hcloudVolume Volume + hcloudVolume.ID = source.ID + hcloudVolume.Name = source.Name + hcloudVolume.Status = VolumeStatus(source.Status) + var pHcloudServer *Server + if source.Server != nil { + hcloudServer := serverFromInt64(*source.Server) + pHcloudServer = &hcloudServer + } + hcloudVolume.Server = pHcloudServer + hcloudVolume.Location = c.LocationFromSchema(source.Location) + hcloudVolume.Size = source.Size + hcloudVolume.Format = source.Format + hcloudVolume.Protection = c.schemaVolumeProtectionToHcloudVolumeProtection(source.Protection) + hcloudVolume.Labels = source.Labels + hcloudVolume.LinuxDevice = source.LinuxDevice + hcloudVolume.Created = c.timeTimeToTimeTime(source.Created) + return &hcloudVolume +} +func (c *converterImpl) hcloudCertificateStatusTypeToString(source CertificateStatusType) string { + return string(source) +} +func (c *converterImpl) hcloudCertificateUsedByRefToSchemaCertificateUsedByRef(source CertificateUsedByRef) schema.CertificateUsedByRef { + var schemaCertificateUsedByRef schema.CertificateUsedByRef + schemaCertificateUsedByRef.ID = source.ID + schemaCertificateUsedByRef.Type = string(source.Type) + return schemaCertificateUsedByRef +} +func (c *converterImpl) hcloudDatacenterServerTypesToSchemaDatacenterServerTypes(source DatacenterServerTypes) schema.DatacenterServerTypes { + var schemaDatacenterServerTypes schema.DatacenterServerTypes + var int64List []int64 + if source.Supported != nil { + int64List = make([]int64, len(source.Supported)) + for i := 0; i < len(source.Supported); i++ { + int64List[i] = int64FromServerType(source.Supported[i]) + } + } + schemaDatacenterServerTypes.Supported = int64List + var int64List2 []int64 + if source.AvailableForMigration != nil { + int64List2 = make([]int64, len(source.AvailableForMigration)) + for j := 0; j < len(source.AvailableForMigration); j++ { + int64List2[j] = int64FromServerType(source.AvailableForMigration[j]) + } + } + schemaDatacenterServerTypes.AvailableForMigration = int64List2 + var int64List3 []int64 + if source.Available != nil { + int64List3 = make([]int64, len(source.Available)) + for k := 0; k < len(source.Available); k++ { + int64List3[k] = int64FromServerType(source.Available[k]) + } + } + schemaDatacenterServerTypes.Available = int64List3 + return schemaDatacenterServerTypes +} +func (c *converterImpl) hcloudDeprecatableResourceToSchemaDeprecatableResource(source DeprecatableResource) schema.DeprecatableResource { + var schemaDeprecatableResource schema.DeprecatableResource + schemaDeprecatableResource.Deprecation = c.SchemaFromDeprecation(source.Deprecation) + return schemaDeprecatableResource +} +func (c *converterImpl) hcloudFirewallRuleToSchemaFirewallRule(source FirewallRule) schema.FirewallRule { + var schemaFirewallRule schema.FirewallRule + schemaFirewallRule.Direction = string(source.Direction) + var stringList []string + if source.SourceIPs != nil { + stringList = make([]string, len(source.SourceIPs)) + for i := 0; i < len(source.SourceIPs); i++ { + stringList[i] = stringFromIPNet(source.SourceIPs[i]) + } + } + schemaFirewallRule.SourceIPs = stringList + var stringList2 []string + if source.DestinationIPs != nil { + stringList2 = make([]string, len(source.DestinationIPs)) + for j := 0; j < len(source.DestinationIPs); j++ { + stringList2[j] = stringFromIPNet(source.DestinationIPs[j]) + } + } + schemaFirewallRule.DestinationIPs = stringList2 + schemaFirewallRule.Protocol = string(source.Protocol) + schemaFirewallRule.Port = source.Port + schemaFirewallRule.Description = source.Description + return schemaFirewallRule +} +func (c *converterImpl) hcloudFirewallRuleToSchemaFirewallRuleRequest(source FirewallRule) schema.FirewallRuleRequest { + var schemaFirewallRuleRequest schema.FirewallRuleRequest + schemaFirewallRuleRequest.Direction = string(source.Direction) + var stringList []string + if source.SourceIPs != nil { + stringList = make([]string, len(source.SourceIPs)) + for i := 0; i < len(source.SourceIPs); i++ { + stringList[i] = stringFromIPNet(source.SourceIPs[i]) + } + } + schemaFirewallRuleRequest.SourceIPs = stringList + var stringList2 []string + if source.DestinationIPs != nil { + stringList2 = make([]string, len(source.DestinationIPs)) + for j := 0; j < len(source.DestinationIPs); j++ { + stringList2[j] = stringFromIPNet(source.DestinationIPs[j]) + } + } + schemaFirewallRuleRequest.DestinationIPs = stringList2 + schemaFirewallRuleRequest.Protocol = string(source.Protocol) + schemaFirewallRuleRequest.Port = source.Port + schemaFirewallRuleRequest.Description = source.Description + return schemaFirewallRuleRequest +} +func (c *converterImpl) hcloudFloatingIPProtectionToSchemaFloatingIPProtection(source FloatingIPProtection) schema.FloatingIPProtection { + var schemaFloatingIPProtection schema.FloatingIPProtection + schemaFloatingIPProtection.Delete = source.Delete + return schemaFloatingIPProtection +} +func (c *converterImpl) hcloudImageProtectionToSchemaImageProtection(source ImageProtection) schema.ImageProtection { + var schemaImageProtection schema.ImageProtection + schemaImageProtection.Delete = source.Delete + return schemaImageProtection +} +func (c *converterImpl) hcloudLoadBalancerAlgorithmToSchemaLoadBalancerAlgorithm(source LoadBalancerAlgorithm) schema.LoadBalancerAlgorithm { + var schemaLoadBalancerAlgorithm schema.LoadBalancerAlgorithm + schemaLoadBalancerAlgorithm.Type = string(source.Type) + return schemaLoadBalancerAlgorithm +} +func (c *converterImpl) hcloudLoadBalancerCreateOptsServiceToSchemaLoadBalancerCreateRequestService(source LoadBalancerCreateOptsService) schema.LoadBalancerCreateRequestService { + var schemaLoadBalancerCreateRequestService schema.LoadBalancerCreateRequestService + schemaLoadBalancerCreateRequestService.Protocol = string(source.Protocol) + schemaLoadBalancerCreateRequestService.ListenPort = source.ListenPort + schemaLoadBalancerCreateRequestService.DestinationPort = source.DestinationPort + schemaLoadBalancerCreateRequestService.Proxyprotocol = source.Proxyprotocol + schemaLoadBalancerCreateRequestService.HTTP = c.pHcloudLoadBalancerCreateOptsServiceHTTPToPSchemaLoadBalancerCreateRequestServiceHTTP(source.HTTP) + schemaLoadBalancerCreateRequestService.HealthCheck = c.pHcloudLoadBalancerCreateOptsServiceHealthCheckToPSchemaLoadBalancerCreateRequestServiceHealthCheck(source.HealthCheck) + return schemaLoadBalancerCreateRequestService +} +func (c *converterImpl) hcloudLoadBalancerCreateOptsTargetToSchemaLoadBalancerCreateRequestTarget(source LoadBalancerCreateOptsTarget) schema.LoadBalancerCreateRequestTarget { + var schemaLoadBalancerCreateRequestTarget schema.LoadBalancerCreateRequestTarget + schemaLoadBalancerCreateRequestTarget.Type = string(source.Type) + schemaLoadBalancerCreateRequestTarget.Server = schemaFromLoadBalancerCreateOptsTargetServer(source.Server) + schemaLoadBalancerCreateRequestTarget.LabelSelector = schemaFromLoadBalancerCreateOptsTargetLabelSelector(source.LabelSelector) + schemaLoadBalancerCreateRequestTarget.IP = schemaFromLoadBalancerCreateOptsTargetIP(source.IP) + schemaLoadBalancerCreateRequestTarget.UsePrivateIP = source.UsePrivateIP + return schemaLoadBalancerCreateRequestTarget +} +func (c *converterImpl) hcloudLoadBalancerPrivateNetToSchemaLoadBalancerPrivateNet(source LoadBalancerPrivateNet) schema.LoadBalancerPrivateNet { + var schemaLoadBalancerPrivateNet schema.LoadBalancerPrivateNet + schemaLoadBalancerPrivateNet.Network = c.pHcloudNetworkToInt64(source.Network) + schemaLoadBalancerPrivateNet.IP = stringFromIP(source.IP) + return schemaLoadBalancerPrivateNet +} +func (c *converterImpl) hcloudLoadBalancerProtectionToSchemaLoadBalancerProtection(source LoadBalancerProtection) schema.LoadBalancerProtection { + var schemaLoadBalancerProtection schema.LoadBalancerProtection + schemaLoadBalancerProtection.Delete = source.Delete + return schemaLoadBalancerProtection +} +func (c *converterImpl) hcloudLoadBalancerPublicNetIPv4ToSchemaLoadBalancerPublicNetIPv4(source LoadBalancerPublicNetIPv4) schema.LoadBalancerPublicNetIPv4 { + var schemaLoadBalancerPublicNetIPv4 schema.LoadBalancerPublicNetIPv4 + schemaLoadBalancerPublicNetIPv4.IP = stringFromIP(source.IP) + schemaLoadBalancerPublicNetIPv4.DNSPtr = source.DNSPtr + return schemaLoadBalancerPublicNetIPv4 +} +func (c *converterImpl) hcloudLoadBalancerPublicNetIPv6ToSchemaLoadBalancerPublicNetIPv6(source LoadBalancerPublicNetIPv6) schema.LoadBalancerPublicNetIPv6 { + var schemaLoadBalancerPublicNetIPv6 schema.LoadBalancerPublicNetIPv6 + schemaLoadBalancerPublicNetIPv6.IP = stringFromIP(source.IP) + schemaLoadBalancerPublicNetIPv6.DNSPtr = source.DNSPtr + return schemaLoadBalancerPublicNetIPv6 +} +func (c *converterImpl) hcloudLoadBalancerPublicNetToSchemaLoadBalancerPublicNet(source LoadBalancerPublicNet) schema.LoadBalancerPublicNet { + var schemaLoadBalancerPublicNet schema.LoadBalancerPublicNet + schemaLoadBalancerPublicNet.Enabled = source.Enabled + schemaLoadBalancerPublicNet.IPv4 = c.hcloudLoadBalancerPublicNetIPv4ToSchemaLoadBalancerPublicNetIPv4(source.IPv4) + schemaLoadBalancerPublicNet.IPv6 = c.hcloudLoadBalancerPublicNetIPv6ToSchemaLoadBalancerPublicNetIPv6(source.IPv6) + return schemaLoadBalancerPublicNet +} +func (c *converterImpl) hcloudLoadBalancerServiceHTTPToPSchemaLoadBalancerServiceHTTP(source LoadBalancerServiceHTTP) *schema.LoadBalancerServiceHTTP { + var schemaLoadBalancerServiceHTTP schema.LoadBalancerServiceHTTP + schemaLoadBalancerServiceHTTP.CookieName = source.CookieName + schemaLoadBalancerServiceHTTP.CookieLifetime = intSecondsFromDuration(source.CookieLifetime) + var int64List []int64 + if source.Certificates != nil { + int64List = make([]int64, len(source.Certificates)) + for i := 0; i < len(source.Certificates); i++ { + int64List[i] = int64FromCertificate(source.Certificates[i]) + } + } + schemaLoadBalancerServiceHTTP.Certificates = int64List + schemaLoadBalancerServiceHTTP.RedirectHTTP = source.RedirectHTTP + schemaLoadBalancerServiceHTTP.StickySessions = source.StickySessions + return &schemaLoadBalancerServiceHTTP +} +func (c *converterImpl) hcloudNetworkProtectionToSchemaNetworkProtection(source NetworkProtection) schema.NetworkProtection { + var schemaNetworkProtection schema.NetworkProtection + schemaNetworkProtection.Delete = source.Delete + return schemaNetworkProtection +} +func (c *converterImpl) hcloudPriceToSchemaPrice(source Price) schema.Price { + var schemaPrice schema.Price + schemaPrice.Net = source.Net + schemaPrice.Gross = source.Gross + return schemaPrice +} +func (c *converterImpl) hcloudPrimaryIPPriceToSchemaPrice(source PrimaryIPPrice) schema.Price { + var schemaPrice schema.Price + schemaPrice.Net = source.Net + schemaPrice.Gross = source.Gross + return schemaPrice +} +func (c *converterImpl) hcloudPrimaryIPProtectionToSchemaPrimaryIPProtection(source PrimaryIPProtection) schema.PrimaryIPProtection { + var schemaPrimaryIPProtection schema.PrimaryIPProtection + schemaPrimaryIPProtection.Delete = source.Delete + return schemaPrimaryIPProtection +} +func (c *converterImpl) hcloudServerBackupPricingToSchemaPricingServerBackup(source ServerBackupPricing) schema.PricingServerBackup { + var schemaPricingServerBackup schema.PricingServerBackup + schemaPricingServerBackup.Percentage = source.Percentage + return schemaPricingServerBackup +} +func (c *converterImpl) hcloudServerProtectionToSchemaServerProtection(source ServerProtection) schema.ServerProtection { + var schemaServerProtection schema.ServerProtection + schemaServerProtection.Delete = source.Delete + schemaServerProtection.Rebuild = source.Rebuild + return schemaServerProtection +} +func (c *converterImpl) hcloudVolumeProtectionToSchemaVolumeProtection(source VolumeProtection) schema.VolumeProtection { + var schemaVolumeProtection schema.VolumeProtection + schemaVolumeProtection.Delete = source.Delete + return schemaVolumeProtection +} +func (c *converterImpl) intISOFromSchema(source schema.ISO) ISO { + var hcloudISO ISO + hcloudISO.ID = source.ID + hcloudISO.Name = source.Name + hcloudISO.Description = source.Description + hcloudISO.Type = ISOType(source.Type) + var pHcloudArchitecture *Architecture + if source.Architecture != nil { + hcloudArchitecture := Architecture(*source.Architecture) + pHcloudArchitecture = &hcloudArchitecture + } + hcloudISO.Architecture = pHcloudArchitecture + var pTimeTime *time.Time + if source.DeprecatableResource.Deprecation != nil { + pTimeTime = &source.DeprecatableResource.Deprecation.UnavailableAfter + } + hcloudISO.Deprecated = c.pTimeTimeToTimeTime(pTimeTime) + hcloudISO.DeprecatableResource = c.schemaDeprecatableResourceToHcloudDeprecatableResource(source.DeprecatableResource) + return hcloudISO +} +func (c *converterImpl) intSchemaFromImage(source Image) schema.Image { + var schemaImage schema.Image + schemaImage.ID = source.ID + schemaImage.Status = string(source.Status) + schemaImage.Type = string(source.Type) + pString := source.Name + schemaImage.Name = &pString + schemaImage.Description = source.Description + schemaImage.ImageSize = mapZeroFloat32ToNil(source.ImageSize) + schemaImage.DiskSize = source.DiskSize + schemaImage.Created = timeToTimePtr(source.Created) + schemaImage.CreatedFrom = c.pHcloudServerToPSchemaImageCreatedFrom(source.CreatedFrom) + schemaImage.BoundTo = c.pHcloudServerToPInt64(source.BoundTo) + schemaImage.OSFlavor = source.OSFlavor + pString2 := source.OSVersion + schemaImage.OSVersion = &pString2 + schemaImage.Architecture = string(source.Architecture) + schemaImage.RapidDeploy = source.RapidDeploy + schemaImage.Protection = c.hcloudImageProtectionToSchemaImageProtection(source.Protection) + schemaImage.Deprecated = timeToTimePtr(source.Deprecated) + schemaImage.Deleted = timeToTimePtr(source.Deleted) + schemaImage.Labels = source.Labels + return schemaImage +} +func (c *converterImpl) pHcloudActionResourceToSchemaActionResourceReference(source *ActionResource) schema.ActionResourceReference { + var schemaActionResourceReference schema.ActionResourceReference + if source != nil { + var schemaActionResourceReference2 schema.ActionResourceReference + schemaActionResourceReference2.ID = (*source).ID + schemaActionResourceReference2.Type = string((*source).Type) + schemaActionResourceReference = schemaActionResourceReference2 + } + return schemaActionResourceReference +} +func (c *converterImpl) pHcloudCertificateStatusToPSchemaCertificateStatusRef(source *CertificateStatus) *schema.CertificateStatusRef { + var pSchemaCertificateStatusRef *schema.CertificateStatusRef + if source != nil { + var schemaCertificateStatusRef schema.CertificateStatusRef + schemaCertificateStatusRef.Issuance = c.hcloudCertificateStatusTypeToString((*source).Issuance) + schemaCertificateStatusRef.Renewal = c.hcloudCertificateStatusTypeToString((*source).Renewal) + schemaCertificateStatusRef.Error = c.pHcloudErrorToPSchemaError((*source).Error) + pSchemaCertificateStatusRef = &schemaCertificateStatusRef + } + return pSchemaCertificateStatusRef +} +func (c *converterImpl) pHcloudErrorToPSchemaError(source *Error) *schema.Error { + var pSchemaError *schema.Error + if source != nil { + schemaError := c.SchemaFromError((*source)) + pSchemaError = &schemaError + } + return pSchemaError +} +func (c *converterImpl) pHcloudFirewallResourceLabelSelectorToPSchemaFirewallResourceLabelSelector(source *FirewallResourceLabelSelector) *schema.FirewallResourceLabelSelector { + var pSchemaFirewallResourceLabelSelector *schema.FirewallResourceLabelSelector + if source != nil { + var schemaFirewallResourceLabelSelector schema.FirewallResourceLabelSelector + schemaFirewallResourceLabelSelector.Selector = (*source).Selector + pSchemaFirewallResourceLabelSelector = &schemaFirewallResourceLabelSelector + } + return pSchemaFirewallResourceLabelSelector +} +func (c *converterImpl) pHcloudFirewallResourceServerToPSchemaFirewallResourceServer(source *FirewallResourceServer) *schema.FirewallResourceServer { + var pSchemaFirewallResourceServer *schema.FirewallResourceServer + if source != nil { + var schemaFirewallResourceServer schema.FirewallResourceServer + schemaFirewallResourceServer.ID = (*source).ID + pSchemaFirewallResourceServer = &schemaFirewallResourceServer + } + return pSchemaFirewallResourceServer +} +func (c *converterImpl) pHcloudISOToPSchemaISO(source *ISO) *schema.ISO { + var pSchemaISO *schema.ISO + if source != nil { + var schemaISO schema.ISO + schemaISO.ID = (*source).ID + schemaISO.Name = (*source).Name + schemaISO.Description = (*source).Description + schemaISO.Type = string((*source).Type) + var pString *string + if (*source).Architecture != nil { + xstring := string(*(*source).Architecture) + pString = &xstring + } + schemaISO.Architecture = pString + schemaISO.DeprecatableResource = c.hcloudDeprecatableResourceToSchemaDeprecatableResource((*source).DeprecatableResource) + pSchemaISO = &schemaISO + } + return pSchemaISO +} +func (c *converterImpl) pHcloudImageToPSchemaImage(source *Image) *schema.Image { + var pSchemaImage *schema.Image + if source != nil { + schemaImage := c.intSchemaFromImage((*source)) + pSchemaImage = &schemaImage + } + return pSchemaImage +} +func (c *converterImpl) pHcloudLoadBalancerAddServiceOptsHTTPToPSchemaLoadBalancerActionAddServiceRequestHTTP(source *LoadBalancerAddServiceOptsHTTP) *schema.LoadBalancerActionAddServiceRequestHTTP { + var pSchemaLoadBalancerActionAddServiceRequestHTTP *schema.LoadBalancerActionAddServiceRequestHTTP + if source != nil { + var schemaLoadBalancerActionAddServiceRequestHTTP schema.LoadBalancerActionAddServiceRequestHTTP + schemaLoadBalancerActionAddServiceRequestHTTP.CookieName = (*source).CookieName + var pInt *int + if (*source).CookieLifetime != nil { + xint := intSecondsFromDuration(*(*source).CookieLifetime) + pInt = &xint + } + schemaLoadBalancerActionAddServiceRequestHTTP.CookieLifetime = pInt + schemaLoadBalancerActionAddServiceRequestHTTP.Certificates = int64SlicePtrFromCertificatePtrSlice((*source).Certificates) + schemaLoadBalancerActionAddServiceRequestHTTP.RedirectHTTP = (*source).RedirectHTTP + schemaLoadBalancerActionAddServiceRequestHTTP.StickySessions = (*source).StickySessions + pSchemaLoadBalancerActionAddServiceRequestHTTP = &schemaLoadBalancerActionAddServiceRequestHTTP + } + return pSchemaLoadBalancerActionAddServiceRequestHTTP +} +func (c *converterImpl) pHcloudLoadBalancerAddServiceOptsHealthCheckHTTPToPSchemaLoadBalancerActionAddServiceRequestHealthCheckHTTP(source *LoadBalancerAddServiceOptsHealthCheckHTTP) *schema.LoadBalancerActionAddServiceRequestHealthCheckHTTP { + var pSchemaLoadBalancerActionAddServiceRequestHealthCheckHTTP *schema.LoadBalancerActionAddServiceRequestHealthCheckHTTP + if source != nil { + var schemaLoadBalancerActionAddServiceRequestHealthCheckHTTP schema.LoadBalancerActionAddServiceRequestHealthCheckHTTP + schemaLoadBalancerActionAddServiceRequestHealthCheckHTTP.Domain = (*source).Domain + schemaLoadBalancerActionAddServiceRequestHealthCheckHTTP.Path = (*source).Path + schemaLoadBalancerActionAddServiceRequestHealthCheckHTTP.Response = (*source).Response + schemaLoadBalancerActionAddServiceRequestHealthCheckHTTP.StatusCodes = stringSlicePtrFromStringSlice((*source).StatusCodes) + schemaLoadBalancerActionAddServiceRequestHealthCheckHTTP.TLS = (*source).TLS + pSchemaLoadBalancerActionAddServiceRequestHealthCheckHTTP = &schemaLoadBalancerActionAddServiceRequestHealthCheckHTTP + } + return pSchemaLoadBalancerActionAddServiceRequestHealthCheckHTTP +} +func (c *converterImpl) pHcloudLoadBalancerAddServiceOptsHealthCheckToPSchemaLoadBalancerActionAddServiceRequestHealthCheck(source *LoadBalancerAddServiceOptsHealthCheck) *schema.LoadBalancerActionAddServiceRequestHealthCheck { + var pSchemaLoadBalancerActionAddServiceRequestHealthCheck *schema.LoadBalancerActionAddServiceRequestHealthCheck + if source != nil { + var schemaLoadBalancerActionAddServiceRequestHealthCheck schema.LoadBalancerActionAddServiceRequestHealthCheck + schemaLoadBalancerActionAddServiceRequestHealthCheck.Protocol = string((*source).Protocol) + schemaLoadBalancerActionAddServiceRequestHealthCheck.Port = (*source).Port + var pInt *int + if (*source).Interval != nil { + xint := intSecondsFromDuration(*(*source).Interval) + pInt = &xint + } + schemaLoadBalancerActionAddServiceRequestHealthCheck.Interval = pInt + var pInt2 *int + if (*source).Timeout != nil { + xint2 := intSecondsFromDuration(*(*source).Timeout) + pInt2 = &xint2 + } + schemaLoadBalancerActionAddServiceRequestHealthCheck.Timeout = pInt2 + schemaLoadBalancerActionAddServiceRequestHealthCheck.Retries = (*source).Retries + schemaLoadBalancerActionAddServiceRequestHealthCheck.HTTP = c.pHcloudLoadBalancerAddServiceOptsHealthCheckHTTPToPSchemaLoadBalancerActionAddServiceRequestHealthCheckHTTP((*source).HTTP) + pSchemaLoadBalancerActionAddServiceRequestHealthCheck = &schemaLoadBalancerActionAddServiceRequestHealthCheck + } + return pSchemaLoadBalancerActionAddServiceRequestHealthCheck +} +func (c *converterImpl) pHcloudLoadBalancerAlgorithmToPSchemaLoadBalancerCreateRequestAlgorithm(source *LoadBalancerAlgorithm) *schema.LoadBalancerCreateRequestAlgorithm { + var pSchemaLoadBalancerCreateRequestAlgorithm *schema.LoadBalancerCreateRequestAlgorithm + if source != nil { + var schemaLoadBalancerCreateRequestAlgorithm schema.LoadBalancerCreateRequestAlgorithm + schemaLoadBalancerCreateRequestAlgorithm.Type = string((*source).Type) + pSchemaLoadBalancerCreateRequestAlgorithm = &schemaLoadBalancerCreateRequestAlgorithm + } + return pSchemaLoadBalancerCreateRequestAlgorithm +} +func (c *converterImpl) pHcloudLoadBalancerCreateOptsServiceHTTPToPSchemaLoadBalancerCreateRequestServiceHTTP(source *LoadBalancerCreateOptsServiceHTTP) *schema.LoadBalancerCreateRequestServiceHTTP { + var pSchemaLoadBalancerCreateRequestServiceHTTP *schema.LoadBalancerCreateRequestServiceHTTP + if source != nil { + var schemaLoadBalancerCreateRequestServiceHTTP schema.LoadBalancerCreateRequestServiceHTTP + schemaLoadBalancerCreateRequestServiceHTTP.CookieName = (*source).CookieName + var pInt *int + if (*source).CookieLifetime != nil { + xint := intSecondsFromDuration(*(*source).CookieLifetime) + pInt = &xint + } + schemaLoadBalancerCreateRequestServiceHTTP.CookieLifetime = pInt + schemaLoadBalancerCreateRequestServiceHTTP.Certificates = int64SlicePtrFromCertificatePtrSlice((*source).Certificates) + schemaLoadBalancerCreateRequestServiceHTTP.RedirectHTTP = (*source).RedirectHTTP + schemaLoadBalancerCreateRequestServiceHTTP.StickySessions = (*source).StickySessions + pSchemaLoadBalancerCreateRequestServiceHTTP = &schemaLoadBalancerCreateRequestServiceHTTP + } + return pSchemaLoadBalancerCreateRequestServiceHTTP +} +func (c *converterImpl) pHcloudLoadBalancerCreateOptsServiceHealthCheckHTTPToPSchemaLoadBalancerCreateRequestServiceHealthCheckHTTP(source *LoadBalancerCreateOptsServiceHealthCheckHTTP) *schema.LoadBalancerCreateRequestServiceHealthCheckHTTP { + var pSchemaLoadBalancerCreateRequestServiceHealthCheckHTTP *schema.LoadBalancerCreateRequestServiceHealthCheckHTTP + if source != nil { + var schemaLoadBalancerCreateRequestServiceHealthCheckHTTP schema.LoadBalancerCreateRequestServiceHealthCheckHTTP + schemaLoadBalancerCreateRequestServiceHealthCheckHTTP.Domain = (*source).Domain + schemaLoadBalancerCreateRequestServiceHealthCheckHTTP.Path = (*source).Path + schemaLoadBalancerCreateRequestServiceHealthCheckHTTP.Response = (*source).Response + schemaLoadBalancerCreateRequestServiceHealthCheckHTTP.StatusCodes = stringSlicePtrFromStringSlice((*source).StatusCodes) + schemaLoadBalancerCreateRequestServiceHealthCheckHTTP.TLS = (*source).TLS + pSchemaLoadBalancerCreateRequestServiceHealthCheckHTTP = &schemaLoadBalancerCreateRequestServiceHealthCheckHTTP + } + return pSchemaLoadBalancerCreateRequestServiceHealthCheckHTTP +} +func (c *converterImpl) pHcloudLoadBalancerCreateOptsServiceHealthCheckToPSchemaLoadBalancerCreateRequestServiceHealthCheck(source *LoadBalancerCreateOptsServiceHealthCheck) *schema.LoadBalancerCreateRequestServiceHealthCheck { + var pSchemaLoadBalancerCreateRequestServiceHealthCheck *schema.LoadBalancerCreateRequestServiceHealthCheck + if source != nil { + var schemaLoadBalancerCreateRequestServiceHealthCheck schema.LoadBalancerCreateRequestServiceHealthCheck + schemaLoadBalancerCreateRequestServiceHealthCheck.Protocol = string((*source).Protocol) + schemaLoadBalancerCreateRequestServiceHealthCheck.Port = (*source).Port + var pInt *int + if (*source).Interval != nil { + xint := intSecondsFromDuration(*(*source).Interval) + pInt = &xint + } + schemaLoadBalancerCreateRequestServiceHealthCheck.Interval = pInt + var pInt2 *int + if (*source).Timeout != nil { + xint2 := intSecondsFromDuration(*(*source).Timeout) + pInt2 = &xint2 + } + schemaLoadBalancerCreateRequestServiceHealthCheck.Timeout = pInt2 + schemaLoadBalancerCreateRequestServiceHealthCheck.Retries = (*source).Retries + schemaLoadBalancerCreateRequestServiceHealthCheck.HTTP = c.pHcloudLoadBalancerCreateOptsServiceHealthCheckHTTPToPSchemaLoadBalancerCreateRequestServiceHealthCheckHTTP((*source).HTTP) + pSchemaLoadBalancerCreateRequestServiceHealthCheck = &schemaLoadBalancerCreateRequestServiceHealthCheck + } + return pSchemaLoadBalancerCreateRequestServiceHealthCheck +} +func (c *converterImpl) pHcloudLoadBalancerServiceHealthCheckHTTPToPSchemaLoadBalancerServiceHealthCheckHTTP(source *LoadBalancerServiceHealthCheckHTTP) *schema.LoadBalancerServiceHealthCheckHTTP { + var pSchemaLoadBalancerServiceHealthCheckHTTP *schema.LoadBalancerServiceHealthCheckHTTP + if source != nil { + var schemaLoadBalancerServiceHealthCheckHTTP schema.LoadBalancerServiceHealthCheckHTTP + schemaLoadBalancerServiceHealthCheckHTTP.Domain = (*source).Domain + schemaLoadBalancerServiceHealthCheckHTTP.Path = (*source).Path + schemaLoadBalancerServiceHealthCheckHTTP.Response = (*source).Response + schemaLoadBalancerServiceHealthCheckHTTP.StatusCodes = (*source).StatusCodes + schemaLoadBalancerServiceHealthCheckHTTP.TLS = (*source).TLS + pSchemaLoadBalancerServiceHealthCheckHTTP = &schemaLoadBalancerServiceHealthCheckHTTP + } + return pSchemaLoadBalancerServiceHealthCheckHTTP +} +func (c *converterImpl) pHcloudLoadBalancerTargetIPToPSchemaLoadBalancerTargetIP(source *LoadBalancerTargetIP) *schema.LoadBalancerTargetIP { + var pSchemaLoadBalancerTargetIP *schema.LoadBalancerTargetIP + if source != nil { + var schemaLoadBalancerTargetIP schema.LoadBalancerTargetIP + schemaLoadBalancerTargetIP.IP = (*source).IP + pSchemaLoadBalancerTargetIP = &schemaLoadBalancerTargetIP + } + return pSchemaLoadBalancerTargetIP +} +func (c *converterImpl) pHcloudLoadBalancerTargetLabelSelectorToPSchemaLoadBalancerTargetLabelSelector(source *LoadBalancerTargetLabelSelector) *schema.LoadBalancerTargetLabelSelector { + var pSchemaLoadBalancerTargetLabelSelector *schema.LoadBalancerTargetLabelSelector + if source != nil { + var schemaLoadBalancerTargetLabelSelector schema.LoadBalancerTargetLabelSelector + schemaLoadBalancerTargetLabelSelector.Selector = (*source).Selector + pSchemaLoadBalancerTargetLabelSelector = &schemaLoadBalancerTargetLabelSelector + } + return pSchemaLoadBalancerTargetLabelSelector +} +func (c *converterImpl) pHcloudLoadBalancerTargetServerToPSchemaLoadBalancerTargetServer(source *LoadBalancerTargetServer) *schema.LoadBalancerTargetServer { + var pSchemaLoadBalancerTargetServer *schema.LoadBalancerTargetServer + if source != nil { + schemaLoadBalancerTargetServer := c.SchemaFromLoadBalancerServerTarget((*source)) + pSchemaLoadBalancerTargetServer = &schemaLoadBalancerTargetServer + } + return pSchemaLoadBalancerTargetServer +} +func (c *converterImpl) pHcloudLoadBalancerToInt64(source *LoadBalancer) int64 { + var xint64 int64 + if source != nil { + xint64 = int64FromLoadBalancer((*source)) + } + return xint64 +} +func (c *converterImpl) pHcloudLoadBalancerUpdateServiceOptsHTTPToPSchemaLoadBalancerActionUpdateServiceRequestHTTP(source *LoadBalancerUpdateServiceOptsHTTP) *schema.LoadBalancerActionUpdateServiceRequestHTTP { + var pSchemaLoadBalancerActionUpdateServiceRequestHTTP *schema.LoadBalancerActionUpdateServiceRequestHTTP + if source != nil { + var schemaLoadBalancerActionUpdateServiceRequestHTTP schema.LoadBalancerActionUpdateServiceRequestHTTP + schemaLoadBalancerActionUpdateServiceRequestHTTP.CookieName = (*source).CookieName + var pInt *int + if (*source).CookieLifetime != nil { + xint := intSecondsFromDuration(*(*source).CookieLifetime) + pInt = &xint + } + schemaLoadBalancerActionUpdateServiceRequestHTTP.CookieLifetime = pInt + schemaLoadBalancerActionUpdateServiceRequestHTTP.Certificates = int64SlicePtrFromCertificatePtrSlice((*source).Certificates) + schemaLoadBalancerActionUpdateServiceRequestHTTP.RedirectHTTP = (*source).RedirectHTTP + schemaLoadBalancerActionUpdateServiceRequestHTTP.StickySessions = (*source).StickySessions + pSchemaLoadBalancerActionUpdateServiceRequestHTTP = &schemaLoadBalancerActionUpdateServiceRequestHTTP + } + return pSchemaLoadBalancerActionUpdateServiceRequestHTTP +} +func (c *converterImpl) pHcloudLoadBalancerUpdateServiceOptsHealthCheckHTTPToPSchemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP(source *LoadBalancerUpdateServiceOptsHealthCheckHTTP) *schema.LoadBalancerActionUpdateServiceRequestHealthCheckHTTP { + var pSchemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP *schema.LoadBalancerActionUpdateServiceRequestHealthCheckHTTP + if source != nil { + var schemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP schema.LoadBalancerActionUpdateServiceRequestHealthCheckHTTP + schemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP.Domain = (*source).Domain + schemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP.Path = (*source).Path + schemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP.Response = (*source).Response + schemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP.StatusCodes = stringSlicePtrFromStringSlice((*source).StatusCodes) + schemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP.TLS = (*source).TLS + pSchemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP = &schemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP + } + return pSchemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP +} +func (c *converterImpl) pHcloudLoadBalancerUpdateServiceOptsHealthCheckToPSchemaLoadBalancerActionUpdateServiceRequestHealthCheck(source *LoadBalancerUpdateServiceOptsHealthCheck) *schema.LoadBalancerActionUpdateServiceRequestHealthCheck { + var pSchemaLoadBalancerActionUpdateServiceRequestHealthCheck *schema.LoadBalancerActionUpdateServiceRequestHealthCheck + if source != nil { + var schemaLoadBalancerActionUpdateServiceRequestHealthCheck schema.LoadBalancerActionUpdateServiceRequestHealthCheck + schemaLoadBalancerActionUpdateServiceRequestHealthCheck.Protocol = stringPtrFromLoadBalancerServiceProtocol((*source).Protocol) + schemaLoadBalancerActionUpdateServiceRequestHealthCheck.Port = (*source).Port + var pInt *int + if (*source).Interval != nil { + xint := intSecondsFromDuration(*(*source).Interval) + pInt = &xint + } + schemaLoadBalancerActionUpdateServiceRequestHealthCheck.Interval = pInt + var pInt2 *int + if (*source).Timeout != nil { + xint2 := intSecondsFromDuration(*(*source).Timeout) + pInt2 = &xint2 + } + schemaLoadBalancerActionUpdateServiceRequestHealthCheck.Timeout = pInt2 + schemaLoadBalancerActionUpdateServiceRequestHealthCheck.Retries = (*source).Retries + schemaLoadBalancerActionUpdateServiceRequestHealthCheck.HTTP = c.pHcloudLoadBalancerUpdateServiceOptsHealthCheckHTTPToPSchemaLoadBalancerActionUpdateServiceRequestHealthCheckHTTP((*source).HTTP) + pSchemaLoadBalancerActionUpdateServiceRequestHealthCheck = &schemaLoadBalancerActionUpdateServiceRequestHealthCheck + } + return pSchemaLoadBalancerActionUpdateServiceRequestHealthCheck +} +func (c *converterImpl) pHcloudLocationToPString(source *Location) *string { + var pString *string + if source != nil { + xstring := stringFromLocation((*source)) + pString = &xstring + } + return pString +} +func (c *converterImpl) pHcloudLocationToString(source *Location) string { + var xstring string + if source != nil { + xstring = stringFromLocation((*source)) + } + return xstring +} +func (c *converterImpl) pHcloudNetworkToInt64(source *Network) int64 { + var xint64 int64 + if source != nil { + xint64 = int64FromNetwork((*source)) + } + return xint64 +} +func (c *converterImpl) pHcloudNetworkToPInt64(source *Network) *int64 { + var pInt64 *int64 + if source != nil { + xint64 := int64FromNetwork((*source)) + pInt64 = &xint64 + } + return pInt64 +} +func (c *converterImpl) pHcloudPlacementGroupToPSchemaPlacementGroup(source *PlacementGroup) *schema.PlacementGroup { + var pSchemaPlacementGroup *schema.PlacementGroup + if source != nil { + var schemaPlacementGroup schema.PlacementGroup + schemaPlacementGroup.ID = (*source).ID + schemaPlacementGroup.Name = (*source).Name + schemaPlacementGroup.Labels = (*source).Labels + schemaPlacementGroup.Created = c.timeTimeToTimeTime((*source).Created) + schemaPlacementGroup.Servers = (*source).Servers + schemaPlacementGroup.Type = string((*source).Type) + pSchemaPlacementGroup = &schemaPlacementGroup + } + return pSchemaPlacementGroup +} +func (c *converterImpl) pHcloudServerToInt64(source *Server) int64 { + var xint64 int64 + if source != nil { + xint64 = int64FromServer((*source)) + } + return xint64 +} +func (c *converterImpl) pHcloudServerToPInt64(source *Server) *int64 { + var pInt64 *int64 + if source != nil { + xint64 := int64FromServer((*source)) + pInt64 = &xint64 + } + return pInt64 +} +func (c *converterImpl) pHcloudServerToPSchemaImageCreatedFrom(source *Server) *schema.ImageCreatedFrom { + var pSchemaImageCreatedFrom *schema.ImageCreatedFrom + if source != nil { + var schemaImageCreatedFrom schema.ImageCreatedFrom + schemaImageCreatedFrom.ID = (*source).ID + schemaImageCreatedFrom.Name = (*source).Name + pSchemaImageCreatedFrom = &schemaImageCreatedFrom + } + return pSchemaImageCreatedFrom +} +func (c *converterImpl) pNetIPNetToString(source *net.IPNet) string { + var xstring string + if source != nil { + xstring = stringFromIPNet((*source)) + } + return xstring +} +func (c *converterImpl) pSchemaCertificateStatusRefToPHcloudCertificateStatus(source *schema.CertificateStatusRef) *CertificateStatus { + var pHcloudCertificateStatus *CertificateStatus + if source != nil { + var hcloudCertificateStatus CertificateStatus + hcloudCertificateStatus.Issuance = CertificateStatusType((*source).Issuance) + hcloudCertificateStatus.Renewal = CertificateStatusType((*source).Renewal) + hcloudCertificateStatus.Error = c.pSchemaErrorToPHcloudError((*source).Error) + pHcloudCertificateStatus = &hcloudCertificateStatus + } + return pHcloudCertificateStatus +} +func (c *converterImpl) pSchemaErrorToPHcloudError(source *schema.Error) *Error { + var pHcloudError *Error + if source != nil { + hcloudError := c.ErrorFromSchema((*source)) + pHcloudError = &hcloudError + } + return pHcloudError +} +func (c *converterImpl) pSchemaFirewallResourceLabelSelectorToPHcloudFirewallResourceLabelSelector(source *schema.FirewallResourceLabelSelector) *FirewallResourceLabelSelector { + var pHcloudFirewallResourceLabelSelector *FirewallResourceLabelSelector + if source != nil { + var hcloudFirewallResourceLabelSelector FirewallResourceLabelSelector + hcloudFirewallResourceLabelSelector.Selector = (*source).Selector + pHcloudFirewallResourceLabelSelector = &hcloudFirewallResourceLabelSelector + } + return pHcloudFirewallResourceLabelSelector +} +func (c *converterImpl) pSchemaFirewallResourceServerToPHcloudFirewallResourceServer(source *schema.FirewallResourceServer) *FirewallResourceServer { + var pHcloudFirewallResourceServer *FirewallResourceServer + if source != nil { + var hcloudFirewallResourceServer FirewallResourceServer + hcloudFirewallResourceServer.ID = (*source).ID + pHcloudFirewallResourceServer = &hcloudFirewallResourceServer + } + return pHcloudFirewallResourceServer +} +func (c *converterImpl) pSchemaISOToPHcloudISO(source *schema.ISO) *ISO { + var pHcloudISO *ISO + if source != nil { + hcloudISO := c.intISOFromSchema((*source)) + pHcloudISO = &hcloudISO + } + return pHcloudISO +} +func (c *converterImpl) pSchemaImageCreatedFromToPHcloudServer(source *schema.ImageCreatedFrom) *Server { + var pHcloudServer *Server + if source != nil { + hcloudServer := serverFromImageCreatedFromSchema((*source)) + pHcloudServer = &hcloudServer + } + return pHcloudServer +} +func (c *converterImpl) pSchemaImageToPHcloudImage(source *schema.Image) *Image { + var pHcloudImage *Image + if source != nil { + var hcloudImage Image + hcloudImage.ID = (*source).ID + var xstring string + if (*source).Name != nil { + xstring = *(*source).Name + } + hcloudImage.Name = xstring + hcloudImage.Type = ImageType((*source).Type) + hcloudImage.Status = ImageStatus((*source).Status) + hcloudImage.Description = (*source).Description + var xfloat32 float32 + if (*source).ImageSize != nil { + xfloat32 = *(*source).ImageSize + } + hcloudImage.ImageSize = xfloat32 + hcloudImage.DiskSize = (*source).DiskSize + hcloudImage.Created = c.pTimeTimeToTimeTime((*source).Created) + hcloudImage.CreatedFrom = c.pSchemaImageCreatedFromToPHcloudServer((*source).CreatedFrom) + var pHcloudServer *Server + if (*source).BoundTo != nil { + hcloudServer := serverFromInt64(*(*source).BoundTo) + pHcloudServer = &hcloudServer + } + hcloudImage.BoundTo = pHcloudServer + hcloudImage.RapidDeploy = (*source).RapidDeploy + hcloudImage.OSFlavor = (*source).OSFlavor + var xstring2 string + if (*source).OSVersion != nil { + xstring2 = *(*source).OSVersion + } + hcloudImage.OSVersion = xstring2 + hcloudImage.Architecture = Architecture((*source).Architecture) + hcloudImage.Protection = c.schemaImageProtectionToHcloudImageProtection((*source).Protection) + hcloudImage.Deprecated = c.pTimeTimeToTimeTime((*source).Deprecated) + hcloudImage.Labels = (*source).Labels + hcloudImage.Deleted = c.pTimeTimeToTimeTime((*source).Deleted) + pHcloudImage = &hcloudImage + } + return pHcloudImage +} +func (c *converterImpl) pSchemaLoadBalancerServiceHTTPToHcloudLoadBalancerServiceHTTP(source *schema.LoadBalancerServiceHTTP) LoadBalancerServiceHTTP { + var hcloudLoadBalancerServiceHTTP LoadBalancerServiceHTTP + if source != nil { + var hcloudLoadBalancerServiceHTTP2 LoadBalancerServiceHTTP + hcloudLoadBalancerServiceHTTP2.CookieName = (*source).CookieName + hcloudLoadBalancerServiceHTTP2.CookieLifetime = durationFromIntSeconds((*source).CookieLifetime) + var pHcloudCertificateList []*Certificate + if (*source).Certificates != nil { + pHcloudCertificateList = make([]*Certificate, len((*source).Certificates)) + for i := 0; i < len((*source).Certificates); i++ { + pHcloudCertificateList[i] = certificateFromInt64((*source).Certificates[i]) + } + } + hcloudLoadBalancerServiceHTTP2.Certificates = pHcloudCertificateList + hcloudLoadBalancerServiceHTTP2.RedirectHTTP = (*source).RedirectHTTP + hcloudLoadBalancerServiceHTTP2.StickySessions = (*source).StickySessions + hcloudLoadBalancerServiceHTTP = hcloudLoadBalancerServiceHTTP2 + } + return hcloudLoadBalancerServiceHTTP +} +func (c *converterImpl) pSchemaLoadBalancerServiceHealthCheckHTTPToPHcloudLoadBalancerServiceHealthCheckHTTP(source *schema.LoadBalancerServiceHealthCheckHTTP) *LoadBalancerServiceHealthCheckHTTP { + var pHcloudLoadBalancerServiceHealthCheckHTTP *LoadBalancerServiceHealthCheckHTTP + if source != nil { + var hcloudLoadBalancerServiceHealthCheckHTTP LoadBalancerServiceHealthCheckHTTP + hcloudLoadBalancerServiceHealthCheckHTTP.Domain = (*source).Domain + hcloudLoadBalancerServiceHealthCheckHTTP.Path = (*source).Path + hcloudLoadBalancerServiceHealthCheckHTTP.Response = (*source).Response + hcloudLoadBalancerServiceHealthCheckHTTP.StatusCodes = (*source).StatusCodes + hcloudLoadBalancerServiceHealthCheckHTTP.TLS = (*source).TLS + pHcloudLoadBalancerServiceHealthCheckHTTP = &hcloudLoadBalancerServiceHealthCheckHTTP + } + return pHcloudLoadBalancerServiceHealthCheckHTTP +} +func (c *converterImpl) pSchemaLoadBalancerTargetIPToPHcloudLoadBalancerTargetIP(source *schema.LoadBalancerTargetIP) *LoadBalancerTargetIP { + var pHcloudLoadBalancerTargetIP *LoadBalancerTargetIP + if source != nil { + var hcloudLoadBalancerTargetIP LoadBalancerTargetIP + hcloudLoadBalancerTargetIP.IP = (*source).IP + pHcloudLoadBalancerTargetIP = &hcloudLoadBalancerTargetIP + } + return pHcloudLoadBalancerTargetIP +} +func (c *converterImpl) pSchemaLoadBalancerTargetLabelSelectorToPHcloudLoadBalancerTargetLabelSelector(source *schema.LoadBalancerTargetLabelSelector) *LoadBalancerTargetLabelSelector { + var pHcloudLoadBalancerTargetLabelSelector *LoadBalancerTargetLabelSelector + if source != nil { + var hcloudLoadBalancerTargetLabelSelector LoadBalancerTargetLabelSelector + hcloudLoadBalancerTargetLabelSelector.Selector = (*source).Selector + pHcloudLoadBalancerTargetLabelSelector = &hcloudLoadBalancerTargetLabelSelector + } + return pHcloudLoadBalancerTargetLabelSelector +} +func (c *converterImpl) pSchemaLoadBalancerTargetServerToPHcloudLoadBalancerTargetServer(source *schema.LoadBalancerTargetServer) *LoadBalancerTargetServer { + var pHcloudLoadBalancerTargetServer *LoadBalancerTargetServer + if source != nil { + hcloudLoadBalancerTargetServer := c.LoadBalancerTargetServerFromSchema((*source)) + pHcloudLoadBalancerTargetServer = &hcloudLoadBalancerTargetServer + } + return pHcloudLoadBalancerTargetServer +} +func (c *converterImpl) pSchemaPlacementGroupToPHcloudPlacementGroup(source *schema.PlacementGroup) *PlacementGroup { + var pHcloudPlacementGroup *PlacementGroup + if source != nil { + var hcloudPlacementGroup PlacementGroup + hcloudPlacementGroup.ID = (*source).ID + hcloudPlacementGroup.Name = (*source).Name + hcloudPlacementGroup.Labels = (*source).Labels + hcloudPlacementGroup.Created = c.timeTimeToTimeTime((*source).Created) + hcloudPlacementGroup.Servers = (*source).Servers + hcloudPlacementGroup.Type = PlacementGroupType((*source).Type) + pHcloudPlacementGroup = &hcloudPlacementGroup + } + return pHcloudPlacementGroup +} +func (c *converterImpl) pTimeTimeToTimeTime(source *time.Time) time.Time { + var timeTime time.Time + if source != nil { + timeTime = (*source) + } + return timeTime +} +func (c *converterImpl) schemaActionResourceReferenceToPHcloudActionResource(source schema.ActionResourceReference) *ActionResource { + var hcloudActionResource ActionResource + hcloudActionResource.ID = source.ID + hcloudActionResource.Type = ActionResourceType(source.Type) + return &hcloudActionResource +} +func (c *converterImpl) schemaCertificateUsedByRefToHcloudCertificateUsedByRef(source schema.CertificateUsedByRef) CertificateUsedByRef { + var hcloudCertificateUsedByRef CertificateUsedByRef + hcloudCertificateUsedByRef.ID = source.ID + hcloudCertificateUsedByRef.Type = CertificateUsedByRefType(source.Type) + return hcloudCertificateUsedByRef +} +func (c *converterImpl) schemaDatacenterServerTypesToHcloudDatacenterServerTypes(source schema.DatacenterServerTypes) DatacenterServerTypes { + var hcloudDatacenterServerTypes DatacenterServerTypes + var pHcloudServerTypeList []*ServerType + if source.Supported != nil { + pHcloudServerTypeList = make([]*ServerType, len(source.Supported)) + for i := 0; i < len(source.Supported); i++ { + pHcloudServerTypeList[i] = serverTypeFromInt64(source.Supported[i]) + } + } + hcloudDatacenterServerTypes.Supported = pHcloudServerTypeList + var pHcloudServerTypeList2 []*ServerType + if source.AvailableForMigration != nil { + pHcloudServerTypeList2 = make([]*ServerType, len(source.AvailableForMigration)) + for j := 0; j < len(source.AvailableForMigration); j++ { + pHcloudServerTypeList2[j] = serverTypeFromInt64(source.AvailableForMigration[j]) + } + } + hcloudDatacenterServerTypes.AvailableForMigration = pHcloudServerTypeList2 + var pHcloudServerTypeList3 []*ServerType + if source.Available != nil { + pHcloudServerTypeList3 = make([]*ServerType, len(source.Available)) + for k := 0; k < len(source.Available); k++ { + pHcloudServerTypeList3[k] = serverTypeFromInt64(source.Available[k]) + } + } + hcloudDatacenterServerTypes.Available = pHcloudServerTypeList3 + return hcloudDatacenterServerTypes +} +func (c *converterImpl) schemaDeprecatableResourceToHcloudDeprecatableResource(source schema.DeprecatableResource) DeprecatableResource { + var hcloudDeprecatableResource DeprecatableResource + hcloudDeprecatableResource.Deprecation = c.DeprecationFromSchema(source.Deprecation) + return hcloudDeprecatableResource +} +func (c *converterImpl) schemaFirewallResourceToHcloudFirewallResource(source schema.FirewallResource) FirewallResource { + var hcloudFirewallResource FirewallResource + hcloudFirewallResource.Type = FirewallResourceType(source.Type) + hcloudFirewallResource.Server = c.pSchemaFirewallResourceServerToPHcloudFirewallResourceServer(source.Server) + hcloudFirewallResource.LabelSelector = c.pSchemaFirewallResourceLabelSelectorToPHcloudFirewallResourceLabelSelector(source.LabelSelector) + return hcloudFirewallResource +} +func (c *converterImpl) schemaFirewallRuleToHcloudFirewallRule(source schema.FirewallRule) FirewallRule { + var hcloudFirewallRule FirewallRule + hcloudFirewallRule.Direction = FirewallRuleDirection(source.Direction) + var netIPNetList []net.IPNet + if source.SourceIPs != nil { + netIPNetList = make([]net.IPNet, len(source.SourceIPs)) + for i := 0; i < len(source.SourceIPs); i++ { + netIPNetList[i] = ipNetFromString(source.SourceIPs[i]) + } + } + hcloudFirewallRule.SourceIPs = netIPNetList + var netIPNetList2 []net.IPNet + if source.DestinationIPs != nil { + netIPNetList2 = make([]net.IPNet, len(source.DestinationIPs)) + for j := 0; j < len(source.DestinationIPs); j++ { + netIPNetList2[j] = ipNetFromString(source.DestinationIPs[j]) + } + } + hcloudFirewallRule.DestinationIPs = netIPNetList2 + hcloudFirewallRule.Protocol = FirewallRuleProtocol(source.Protocol) + hcloudFirewallRule.Port = source.Port + hcloudFirewallRule.Description = source.Description + return hcloudFirewallRule +} +func (c *converterImpl) schemaFloatingIPProtectionToHcloudFloatingIPProtection(source schema.FloatingIPProtection) FloatingIPProtection { + var hcloudFloatingIPProtection FloatingIPProtection + hcloudFloatingIPProtection.Delete = source.Delete + return hcloudFloatingIPProtection +} +func (c *converterImpl) schemaFromFloatingIPPricing(source FloatingIPPricing) schema.PricingFloatingIP { + var schemaPricingFloatingIP schema.PricingFloatingIP + schemaPricingFloatingIP.PriceMonthly = c.hcloudPriceToSchemaPrice(source.Monthly) + return schemaPricingFloatingIP +} +func (c *converterImpl) schemaFromFloatingIPTypeLocationPricing(source FloatingIPTypeLocationPricing) schema.PricingFloatingIPTypePrice { + var schemaPricingFloatingIPTypePrice schema.PricingFloatingIPTypePrice + schemaPricingFloatingIPTypePrice.Location = c.pHcloudLocationToString(source.Location) + schemaPricingFloatingIPTypePrice.PriceMonthly = c.hcloudPriceToSchemaPrice(source.Monthly) + return schemaPricingFloatingIPTypePrice +} +func (c *converterImpl) schemaFromFloatingIPTypePricing(source FloatingIPTypePricing) schema.PricingFloatingIPType { + var schemaPricingFloatingIPType schema.PricingFloatingIPType + schemaPricingFloatingIPType.Type = string(source.Type) + var schemaPricingFloatingIPTypePriceList []schema.PricingFloatingIPTypePrice + if source.Pricings != nil { + schemaPricingFloatingIPTypePriceList = make([]schema.PricingFloatingIPTypePrice, len(source.Pricings)) + for i := 0; i < len(source.Pricings); i++ { + schemaPricingFloatingIPTypePriceList[i] = c.schemaFromFloatingIPTypeLocationPricing(source.Pricings[i]) + } + } + schemaPricingFloatingIPType.Prices = schemaPricingFloatingIPTypePriceList + return schemaPricingFloatingIPType +} +func (c *converterImpl) schemaFromImagePricing(source ImagePricing) schema.PricingImage { + var schemaPricingImage schema.PricingImage + schemaPricingImage.PricePerGBMonth = c.hcloudPriceToSchemaPrice(source.PerGBMonth) + return schemaPricingImage +} +func (c *converterImpl) schemaFromLoadBalancerTypePricing(source LoadBalancerTypePricing) schema.PricingLoadBalancerType { + var schemaPricingLoadBalancerType schema.PricingLoadBalancerType + var pInt64 *int64 + if source.LoadBalancerType != nil { + pInt64 = &source.LoadBalancerType.ID + } + var xint64 int64 + if pInt64 != nil { + xint64 = *pInt64 + } + schemaPricingLoadBalancerType.ID = xint64 + var pString *string + if source.LoadBalancerType != nil { + pString = &source.LoadBalancerType.Name + } + var xstring string + if pString != nil { + xstring = *pString + } + schemaPricingLoadBalancerType.Name = xstring + var schemaPricingLoadBalancerTypePriceList []schema.PricingLoadBalancerTypePrice + if source.Pricings != nil { + schemaPricingLoadBalancerTypePriceList = make([]schema.PricingLoadBalancerTypePrice, len(source.Pricings)) + for i := 0; i < len(source.Pricings); i++ { + schemaPricingLoadBalancerTypePriceList[i] = c.SchemaFromLoadBalancerTypeLocationPricing(source.Pricings[i]) + } + } + schemaPricingLoadBalancerType.Prices = schemaPricingLoadBalancerTypePriceList + return schemaPricingLoadBalancerType +} +func (c *converterImpl) schemaFromPrimaryIPPricing(source PrimaryIPPricing) schema.PricingPrimaryIP { + var schemaPricingPrimaryIP schema.PricingPrimaryIP + schemaPricingPrimaryIP.Type = source.Type + var schemaPricingPrimaryIPTypePriceList []schema.PricingPrimaryIPTypePrice + if source.Pricings != nil { + schemaPricingPrimaryIPTypePriceList = make([]schema.PricingPrimaryIPTypePrice, len(source.Pricings)) + for i := 0; i < len(source.Pricings); i++ { + schemaPricingPrimaryIPTypePriceList[i] = c.schemaFromPrimaryIPTypePricing(source.Pricings[i]) + } + } + schemaPricingPrimaryIP.Prices = schemaPricingPrimaryIPTypePriceList + return schemaPricingPrimaryIP +} +func (c *converterImpl) schemaFromPrimaryIPTypePricing(source PrimaryIPTypePricing) schema.PricingPrimaryIPTypePrice { + var schemaPricingPrimaryIPTypePrice schema.PricingPrimaryIPTypePrice + schemaPricingPrimaryIPTypePrice.Datacenter = source.Datacenter + schemaPricingPrimaryIPTypePrice.Location = source.Location + schemaPricingPrimaryIPTypePrice.PriceHourly = c.hcloudPrimaryIPPriceToSchemaPrice(source.Hourly) + schemaPricingPrimaryIPTypePrice.PriceMonthly = c.hcloudPrimaryIPPriceToSchemaPrice(source.Monthly) + return schemaPricingPrimaryIPTypePrice +} +func (c *converterImpl) schemaFromServerTypeLocationPricing(source ServerTypeLocationPricing) schema.PricingServerTypePrice { + var schemaPricingServerTypePrice schema.PricingServerTypePrice + schemaPricingServerTypePrice.Location = c.pHcloudLocationToString(source.Location) + schemaPricingServerTypePrice.PriceHourly = c.hcloudPriceToSchemaPrice(source.Hourly) + schemaPricingServerTypePrice.PriceMonthly = c.hcloudPriceToSchemaPrice(source.Monthly) + return schemaPricingServerTypePrice +} +func (c *converterImpl) schemaFromServerTypePricing(source ServerTypePricing) schema.PricingServerType { + var schemaPricingServerType schema.PricingServerType + var pInt64 *int64 + if source.ServerType != nil { + pInt64 = &source.ServerType.ID + } + var xint64 int64 + if pInt64 != nil { + xint64 = *pInt64 + } + schemaPricingServerType.ID = xint64 + var pString *string + if source.ServerType != nil { + pString = &source.ServerType.Name + } + var xstring string + if pString != nil { + xstring = *pString + } + schemaPricingServerType.Name = xstring + var schemaPricingServerTypePriceList []schema.PricingServerTypePrice + if source.Pricings != nil { + schemaPricingServerTypePriceList = make([]schema.PricingServerTypePrice, len(source.Pricings)) + for i := 0; i < len(source.Pricings); i++ { + schemaPricingServerTypePriceList[i] = c.schemaFromServerTypeLocationPricing(source.Pricings[i]) + } + } + schemaPricingServerType.Prices = schemaPricingServerTypePriceList + return schemaPricingServerType +} +func (c *converterImpl) schemaFromTrafficPricing(source TrafficPricing) schema.PricingTraffic { + var schemaPricingTraffic schema.PricingTraffic + schemaPricingTraffic.PricePerTB = c.hcloudPriceToSchemaPrice(source.PerTB) + return schemaPricingTraffic +} +func (c *converterImpl) schemaFromVolumePricing(source VolumePricing) schema.PricingVolume { + var schemaPricingVolume schema.PricingVolume + schemaPricingVolume.PricePerGBPerMonth = c.hcloudPriceToSchemaPrice(source.PerGBMonthly) + return schemaPricingVolume +} +func (c *converterImpl) schemaImageProtectionToHcloudImageProtection(source schema.ImageProtection) ImageProtection { + var hcloudImageProtection ImageProtection + hcloudImageProtection.Delete = source.Delete + return hcloudImageProtection +} +func (c *converterImpl) schemaLoadBalancerAlgorithmToHcloudLoadBalancerAlgorithm(source schema.LoadBalancerAlgorithm) LoadBalancerAlgorithm { + var hcloudLoadBalancerAlgorithm LoadBalancerAlgorithm + hcloudLoadBalancerAlgorithm.Type = LoadBalancerAlgorithmType(source.Type) + return hcloudLoadBalancerAlgorithm +} +func (c *converterImpl) schemaLoadBalancerPrivateNetToHcloudLoadBalancerPrivateNet(source schema.LoadBalancerPrivateNet) LoadBalancerPrivateNet { + var hcloudLoadBalancerPrivateNet LoadBalancerPrivateNet + hcloudNetwork := networkFromInt64(source.Network) + hcloudLoadBalancerPrivateNet.Network = &hcloudNetwork + hcloudLoadBalancerPrivateNet.IP = ipFromString(source.IP) + return hcloudLoadBalancerPrivateNet +} +func (c *converterImpl) schemaLoadBalancerProtectionToHcloudLoadBalancerProtection(source schema.LoadBalancerProtection) LoadBalancerProtection { + var hcloudLoadBalancerProtection LoadBalancerProtection + hcloudLoadBalancerProtection.Delete = source.Delete + return hcloudLoadBalancerProtection +} +func (c *converterImpl) schemaLoadBalancerPublicNetIPv4ToHcloudLoadBalancerPublicNetIPv4(source schema.LoadBalancerPublicNetIPv4) LoadBalancerPublicNetIPv4 { + var hcloudLoadBalancerPublicNetIPv4 LoadBalancerPublicNetIPv4 + hcloudLoadBalancerPublicNetIPv4.IP = ipFromString(source.IP) + hcloudLoadBalancerPublicNetIPv4.DNSPtr = source.DNSPtr + return hcloudLoadBalancerPublicNetIPv4 +} +func (c *converterImpl) schemaLoadBalancerPublicNetIPv6ToHcloudLoadBalancerPublicNetIPv6(source schema.LoadBalancerPublicNetIPv6) LoadBalancerPublicNetIPv6 { + var hcloudLoadBalancerPublicNetIPv6 LoadBalancerPublicNetIPv6 + hcloudLoadBalancerPublicNetIPv6.IP = ipFromString(source.IP) + hcloudLoadBalancerPublicNetIPv6.DNSPtr = source.DNSPtr + return hcloudLoadBalancerPublicNetIPv6 +} +func (c *converterImpl) schemaLoadBalancerPublicNetToHcloudLoadBalancerPublicNet(source schema.LoadBalancerPublicNet) LoadBalancerPublicNet { + var hcloudLoadBalancerPublicNet LoadBalancerPublicNet + hcloudLoadBalancerPublicNet.Enabled = source.Enabled + hcloudLoadBalancerPublicNet.IPv4 = c.schemaLoadBalancerPublicNetIPv4ToHcloudLoadBalancerPublicNetIPv4(source.IPv4) + hcloudLoadBalancerPublicNet.IPv6 = c.schemaLoadBalancerPublicNetIPv6ToHcloudLoadBalancerPublicNetIPv6(source.IPv6) + return hcloudLoadBalancerPublicNet +} +func (c *converterImpl) schemaNetworkProtectionToHcloudNetworkProtection(source schema.NetworkProtection) NetworkProtection { + var hcloudNetworkProtection NetworkProtection + hcloudNetworkProtection.Delete = source.Delete + return hcloudNetworkProtection +} +func (c *converterImpl) schemaPricingServerBackupToHcloudServerBackupPricing(source schema.PricingServerBackup) ServerBackupPricing { + var hcloudServerBackupPricing ServerBackupPricing + hcloudServerBackupPricing.Percentage = source.Percentage + return hcloudServerBackupPricing +} +func (c *converterImpl) schemaPrimaryIPProtectionToHcloudPrimaryIPProtection(source schema.PrimaryIPProtection) PrimaryIPProtection { + var hcloudPrimaryIPProtection PrimaryIPProtection + hcloudPrimaryIPProtection.Delete = source.Delete + return hcloudPrimaryIPProtection +} +func (c *converterImpl) schemaServerProtectionToHcloudServerProtection(source schema.ServerProtection) ServerProtection { + var hcloudServerProtection ServerProtection + hcloudServerProtection.Delete = source.Delete + hcloudServerProtection.Rebuild = source.Rebuild + return hcloudServerProtection +} +func (c *converterImpl) schemaVolumeProtectionToHcloudVolumeProtection(source schema.VolumeProtection) VolumeProtection { + var hcloudVolumeProtection VolumeProtection + hcloudVolumeProtection.Delete = source.Delete + return hcloudVolumeProtection +} +func (c *converterImpl) serverTypePricingFromSchema(source schema.PricingServerTypePrice) ServerTypeLocationPricing { + var hcloudServerTypeLocationPricing ServerTypeLocationPricing + hcloudLocation := locationFromString(source.Location) + hcloudServerTypeLocationPricing.Location = &hcloudLocation + hcloudServerTypeLocationPricing.Hourly = c.PriceFromSchema(source.PriceHourly) + hcloudServerTypeLocationPricing.Monthly = c.PriceFromSchema(source.PriceMonthly) + return hcloudServerTypeLocationPricing +} +func (c *converterImpl) timeTimeToTimeTime(source time.Time) time.Time { + return source +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_client_iface.go new file mode 100644 index 000000000..82038a30c --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_client_iface.go @@ -0,0 +1,90 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IServerClient ... +type IServerClient interface { + // GetByID retrieves a server by its ID. If the server does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Server, *Response, error) + // GetByName retrieves a server by its name. If the server does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*Server, *Response, error) + // Get retrieves a server by its ID if the input can be parsed as an integer, otherwise it + // retrieves a server by its name. If the server does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*Server, *Response, error) + // List returns a list of servers for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts ServerListOpts) ([]*Server, *Response, error) + // All returns all servers. + All(ctx context.Context) ([]*Server, error) + // AllWithOpts returns all servers for the given options. + AllWithOpts(ctx context.Context, opts ServerListOpts) ([]*Server, error) + // Create creates a new server. + Create(ctx context.Context, opts ServerCreateOpts) (ServerCreateResult, *Response, error) + // Delete deletes a server. + // + // Deprecated: Use [ServerClient.DeleteWithResult] instead. + Delete(ctx context.Context, server *Server) (*Response, error) + // DeleteWithResult deletes a server and returns the parsed response containing the action. + DeleteWithResult(ctx context.Context, server *Server) (*ServerDeleteResult, *Response, error) + // Update updates a server. + Update(ctx context.Context, server *Server, opts ServerUpdateOpts) (*Server, *Response, error) + // Poweron starts a server. + Poweron(ctx context.Context, server *Server) (*Action, *Response, error) + // Reboot reboots a server. + Reboot(ctx context.Context, server *Server) (*Action, *Response, error) + // Reset resets a server. + Reset(ctx context.Context, server *Server) (*Action, *Response, error) + // Shutdown shuts down a server. + Shutdown(ctx context.Context, server *Server) (*Action, *Response, error) + // Poweroff stops a server. + Poweroff(ctx context.Context, server *Server) (*Action, *Response, error) + // ResetPassword resets a server's password. + ResetPassword(ctx context.Context, server *Server) (ServerResetPasswordResult, *Response, error) + // CreateImage creates an image from a server. + CreateImage(ctx context.Context, server *Server, opts *ServerCreateImageOpts) (ServerCreateImageResult, *Response, error) + // EnableRescue enables rescue mode for a server. + EnableRescue(ctx context.Context, server *Server, opts ServerEnableRescueOpts) (ServerEnableRescueResult, *Response, error) + // DisableRescue disables rescue mode for a server. + DisableRescue(ctx context.Context, server *Server) (*Action, *Response, error) + // Rebuild rebuilds a server. + // + // Deprecated: Use [ServerClient.RebuildWithResult] instead. + Rebuild(ctx context.Context, server *Server, opts ServerRebuildOpts) (*Action, *Response, error) + // RebuildWithResult rebuilds a server. + RebuildWithResult(ctx context.Context, server *Server, opts ServerRebuildOpts) (ServerRebuildResult, *Response, error) + // AttachISO attaches an ISO to a server. + AttachISO(ctx context.Context, server *Server, iso *ISO) (*Action, *Response, error) + // DetachISO detaches the currently attached ISO from a server. + DetachISO(ctx context.Context, server *Server) (*Action, *Response, error) + // EnableBackup enables backup for a server. Pass in an empty backup window to let the + // API pick a window for you. See the API documentation at docs.hetzner.cloud for a list + // of valid backup windows. + EnableBackup(ctx context.Context, server *Server, window string) (*Action, *Response, error) + // DisableBackup disables backup for a server. + DisableBackup(ctx context.Context, server *Server) (*Action, *Response, error) + // ChangeType changes a server's type. + ChangeType(ctx context.Context, server *Server, opts ServerChangeTypeOpts) (*Action, *Response, error) + // ChangeDNSPtr changes or resets the reverse DNS pointer for a server IP address. + // Pass a nil ptr to reset the reverse DNS pointer to its default value. + ChangeDNSPtr(ctx context.Context, server *Server, ip string, ptr *string) (*Action, *Response, error) + // ChangeProtection changes the resource protection level of a server. + ChangeProtection(ctx context.Context, server *Server, opts ServerChangeProtectionOpts) (*Action, *Response, error) + // RequestConsole requests a WebSocket VNC console. + RequestConsole(ctx context.Context, server *Server) (ServerRequestConsoleResult, *Response, error) + // AttachToNetwork attaches a server to a network. + AttachToNetwork(ctx context.Context, server *Server, opts ServerAttachToNetworkOpts) (*Action, *Response, error) + // DetachFromNetwork detaches a server from a network. + DetachFromNetwork(ctx context.Context, server *Server, opts ServerDetachFromNetworkOpts) (*Action, *Response, error) + // ChangeAliasIPs changes a server's alias IPs in a network. + ChangeAliasIPs(ctx context.Context, server *Server, opts ServerChangeAliasIPsOpts) (*Action, *Response, error) + // GetMetrics obtains metrics for Server. + GetMetrics(ctx context.Context, server *Server, opts ServerGetMetricsOpts) (*ServerMetrics, *Response, error) + AddToPlacementGroup(ctx context.Context, server *Server, placementGroup *PlacementGroup) (*Action, *Response, error) + RemoveFromPlacementGroup(ctx context.Context, server *Server) (*Action, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_type_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_type_client_iface.go new file mode 100644 index 000000000..57c57afa0 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_server_type_client_iface.go @@ -0,0 +1,27 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IServerTypeClient ... +type IServerTypeClient interface { + // GetByID retrieves a server type by its ID. If the server type does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*ServerType, *Response, error) + // GetByName retrieves a server type by its name. If the server type does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*ServerType, *Response, error) + // Get retrieves a server type by its ID if the input can be parsed as an integer, otherwise it + // retrieves a server type by its name. If the server type does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*ServerType, *Response, error) + // List returns a list of server types for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts ServerTypeListOpts) ([]*ServerType, *Response, error) + // All returns all server types. + All(ctx context.Context) ([]*ServerType, error) + // AllWithOpts returns all server types for the given options. + AllWithOpts(ctx context.Context, opts ServerTypeListOpts) ([]*ServerType, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_ssh_key_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_ssh_key_client_iface.go new file mode 100644 index 000000000..d2c6988d9 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_ssh_key_client_iface.go @@ -0,0 +1,35 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// ISSHKeyClient ... +type ISSHKeyClient interface { + // GetByID retrieves a SSH key by its ID. If the SSH key does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*SSHKey, *Response, error) + // GetByName retrieves a SSH key by its name. If the SSH key does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*SSHKey, *Response, error) + // GetByFingerprint retreives a SSH key by its fingerprint. If the SSH key does not exist, nil is returned. + GetByFingerprint(ctx context.Context, fingerprint string) (*SSHKey, *Response, error) + // Get retrieves a SSH key by its ID if the input can be parsed as an integer, otherwise it + // retrieves a SSH key by its name. If the SSH key does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*SSHKey, *Response, error) + // List returns a list of SSH keys for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts SSHKeyListOpts) ([]*SSHKey, *Response, error) + // All returns all SSH keys. + All(ctx context.Context) ([]*SSHKey, error) + // AllWithOpts returns all SSH keys with the given options. + AllWithOpts(ctx context.Context, opts SSHKeyListOpts) ([]*SSHKey, error) + // Create creates a new SSH key with the given options. + Create(ctx context.Context, opts SSHKeyCreateOpts) (*SSHKey, *Response, error) + // Delete deletes a SSH key. + Delete(ctx context.Context, sshKey *SSHKey) (*Response, error) + // Update updates a SSH key. + Update(ctx context.Context, sshKey *SSHKey, opts SSHKeyUpdateOpts) (*SSHKey, *Response, error) +} diff --git a/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_volume_client_iface.go b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_volume_client_iface.go new file mode 100644 index 000000000..28edb7a27 --- /dev/null +++ b/vendor/github.com/hetznercloud/hcloud-go/v2/hcloud/zz_volume_client_iface.go @@ -0,0 +1,43 @@ +// Code generated by ifacemaker; DO NOT EDIT. + +package hcloud + +import ( + "context" +) + +// IVolumeClient ... +type IVolumeClient interface { + // GetByID retrieves a volume by its ID. If the volume does not exist, nil is returned. + GetByID(ctx context.Context, id int64) (*Volume, *Response, error) + // GetByName retrieves a volume by its name. If the volume does not exist, nil is returned. + GetByName(ctx context.Context, name string) (*Volume, *Response, error) + // Get retrieves a volume by its ID if the input can be parsed as an integer, otherwise it + // retrieves a volume by its name. If the volume does not exist, nil is returned. + Get(ctx context.Context, idOrName string) (*Volume, *Response, error) + // List returns a list of volumes for a specific page. + // + // Please note that filters specified in opts are not taken into account + // when their value corresponds to their zero value or when they are empty. + List(ctx context.Context, opts VolumeListOpts) ([]*Volume, *Response, error) + // All returns all volumes. + All(ctx context.Context) ([]*Volume, error) + // AllWithOpts returns all volumes with the given options. + AllWithOpts(ctx context.Context, opts VolumeListOpts) ([]*Volume, error) + // Create creates a new volume with the given options. + Create(ctx context.Context, opts VolumeCreateOpts) (VolumeCreateResult, *Response, error) + // Delete deletes a volume. + Delete(ctx context.Context, volume *Volume) (*Response, error) + // Update updates a volume. + Update(ctx context.Context, volume *Volume, opts VolumeUpdateOpts) (*Volume, *Response, error) + // AttachWithOpts attaches a volume to a server. + AttachWithOpts(ctx context.Context, volume *Volume, opts VolumeAttachOpts) (*Action, *Response, error) + // Attach attaches a volume to a server. + Attach(ctx context.Context, volume *Volume, server *Server) (*Action, *Response, error) + // Detach detaches a volume from a server. + Detach(ctx context.Context, volume *Volume) (*Action, *Response, error) + // ChangeProtection changes the resource protection level of a volume. + ChangeProtection(ctx context.Context, volume *Volume, opts VolumeChangeProtectionOpts) (*Action, *Response, error) + // Resize changes the size of a volume. + Resize(ctx context.Context, volume *Volume, size int) (*Action, *Response, error) +} diff --git a/vendor/github.com/json-iterator/go/README.md b/vendor/github.com/json-iterator/go/README.md index 52b111d5f..c589addf9 100644 --- a/vendor/github.com/json-iterator/go/README.md +++ b/vendor/github.com/json-iterator/go/README.md @@ -8,8 +8,6 @@ A high-performance 100% compatible drop-in replacement of "encoding/json" -You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go) - # Benchmark ![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png) diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE b/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE deleted file mode 100644 index 8dada3eda..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE b/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE deleted file mode 100644 index 5d8cb5b72..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE +++ /dev/null @@ -1 +0,0 @@ -Copyright 2012 Matt T. Proud (matt.proud@gmail.com) diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore deleted file mode 100644 index e16fb946b..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore +++ /dev/null @@ -1 +0,0 @@ -cover.dat diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile deleted file mode 100644 index 81be21437..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - -cover: - go test -cover -v -coverprofile=cover.dat ./... - go tool cover -func cover.dat - -.PHONY: cover diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go deleted file mode 100644 index 258c0636a..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2013 Matt T. Proud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pbutil - -import ( - "encoding/binary" - "errors" - "io" - - "github.com/golang/protobuf/proto" -) - -var errInvalidVarint = errors.New("invalid varint32 encountered") - -// ReadDelimited decodes a message from the provided length-delimited stream, -// where the length is encoded as 32-bit varint prefix to the message body. -// It returns the total number of bytes read and any applicable error. This is -// roughly equivalent to the companion Java API's -// MessageLite#parseDelimitedFrom. As per the reader contract, this function -// calls r.Read repeatedly as required until exactly one message including its -// prefix is read and decoded (or an error has occurred). The function never -// reads more bytes from the stream than required. The function never returns -// an error if a message has been read and decoded correctly, even if the end -// of the stream has been reached in doing so. In that case, any subsequent -// calls return (0, io.EOF). -func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) { - // Per AbstractParser#parsePartialDelimitedFrom with - // CodedInputStream#readRawVarint32. - var headerBuf [binary.MaxVarintLen32]byte - var bytesRead, varIntBytes int - var messageLength uint64 - for varIntBytes == 0 { // i.e. no varint has been decoded yet. - if bytesRead >= len(headerBuf) { - return bytesRead, errInvalidVarint - } - // We have to read byte by byte here to avoid reading more bytes - // than required. Each read byte is appended to what we have - // read before. - newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1]) - if newBytesRead == 0 { - if err != nil { - return bytesRead, err - } - // A Reader should not return (0, nil), but if it does, - // it should be treated as no-op (according to the - // Reader contract). So let's go on... - continue - } - bytesRead += newBytesRead - // Now present everything read so far to the varint decoder and - // see if a varint can be decoded already. - messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead]) - } - - messageBuf := make([]byte, messageLength) - newBytesRead, err := io.ReadFull(r, messageBuf) - bytesRead += newBytesRead - if err != nil { - return bytesRead, err - } - - return bytesRead, proto.Unmarshal(messageBuf, m) -} diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go b/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go deleted file mode 100644 index 8fb59ad22..000000000 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 Matt T. Proud -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package pbutil - -import ( - "encoding/binary" - "io" - - "github.com/golang/protobuf/proto" -) - -// WriteDelimited encodes and dumps a message to the provided writer prefixed -// with a 32-bit varint indicating the length of the encoded message, producing -// a length-delimited record stream, which can be used to chain together -// encoded messages of the same type together in a file. It returns the total -// number of bytes written and any applicable error. This is roughly -// equivalent to the companion Java API's MessageLite#writeDelimitedTo. -func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) { - buffer, err := proto.Marshal(m) - if err != nil { - return 0, err - } - - var buf [binary.MaxVarintLen32]byte - encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer))) - - sync, err := w.Write(buf[:encodedLength]) - if err != nil { - return sync, err - } - - n, err = w.Write(buffer) - return n + sync, err -} diff --git a/vendor/github.com/modern-go/reflect2/.travis.yml b/vendor/github.com/modern-go/reflect2/.travis.yml index fbb43744d..b097728db 100644 --- a/vendor/github.com/modern-go/reflect2/.travis.yml +++ b/vendor/github.com/modern-go/reflect2/.travis.yml @@ -1,7 +1,7 @@ language: go go: - - 1.8.x + - 1.9.x - 1.x before_install: diff --git a/vendor/github.com/modern-go/reflect2/Gopkg.lock b/vendor/github.com/modern-go/reflect2/Gopkg.lock index 2a3a69893..10ef81118 100644 --- a/vendor/github.com/modern-go/reflect2/Gopkg.lock +++ b/vendor/github.com/modern-go/reflect2/Gopkg.lock @@ -1,15 +1,9 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. -[[projects]] - name = "github.com/modern-go/concurrent" - packages = ["."] - revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a" - version = "1.0.0" - [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "daee8a88b3498b61c5640056665b8b9eea062006f5e596bbb6a3ed9119a11ec7" + input-imports = [] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/modern-go/reflect2/Gopkg.toml b/vendor/github.com/modern-go/reflect2/Gopkg.toml index 2f4f4dbdc..a9bc5061b 100644 --- a/vendor/github.com/modern-go/reflect2/Gopkg.toml +++ b/vendor/github.com/modern-go/reflect2/Gopkg.toml @@ -26,10 +26,6 @@ ignored = [] -[[constraint]] - name = "github.com/modern-go/concurrent" - version = "1.0.0" - [prune] go-tests = true unused-packages = true diff --git a/vendor/github.com/modern-go/reflect2/go_above_118.go b/vendor/github.com/modern-go/reflect2/go_above_118.go new file mode 100644 index 000000000..2b4116f6c --- /dev/null +++ b/vendor/github.com/modern-go/reflect2/go_above_118.go @@ -0,0 +1,23 @@ +//+build go1.18 + +package reflect2 + +import ( + "unsafe" +) + +// m escapes into the return value, but the caller of mapiterinit +// doesn't let the return value escape. +//go:noescape +//go:linkname mapiterinit reflect.mapiterinit +func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer, it *hiter) + +func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator { + var it hiter + mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj), &it) + return &UnsafeMapIterator{ + hiter: &it, + pKeyRType: type2.pKeyRType, + pElemRType: type2.pElemRType, + } +} \ No newline at end of file diff --git a/vendor/github.com/modern-go/reflect2/go_above_17.go b/vendor/github.com/modern-go/reflect2/go_above_17.go deleted file mode 100644 index 5c1cea868..000000000 --- a/vendor/github.com/modern-go/reflect2/go_above_17.go +++ /dev/null @@ -1,8 +0,0 @@ -//+build go1.7 - -package reflect2 - -import "unsafe" - -//go:linkname resolveTypeOff reflect.resolveTypeOff -func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer diff --git a/vendor/github.com/modern-go/reflect2/go_above_19.go b/vendor/github.com/modern-go/reflect2/go_above_19.go index c7e3b7801..974f7685e 100644 --- a/vendor/github.com/modern-go/reflect2/go_above_19.go +++ b/vendor/github.com/modern-go/reflect2/go_above_19.go @@ -6,6 +6,9 @@ import ( "unsafe" ) +//go:linkname resolveTypeOff reflect.resolveTypeOff +func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer + //go:linkname makemap reflect.makemap func makemap(rtype unsafe.Pointer, cap int) (m unsafe.Pointer) diff --git a/vendor/github.com/modern-go/reflect2/go_below_118.go b/vendor/github.com/modern-go/reflect2/go_below_118.go new file mode 100644 index 000000000..00003dbd7 --- /dev/null +++ b/vendor/github.com/modern-go/reflect2/go_below_118.go @@ -0,0 +1,21 @@ +//+build !go1.18 + +package reflect2 + +import ( + "unsafe" +) + +// m escapes into the return value, but the caller of mapiterinit +// doesn't let the return value escape. +//go:noescape +//go:linkname mapiterinit reflect.mapiterinit +func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) (val *hiter) + +func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator { + return &UnsafeMapIterator{ + hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)), + pKeyRType: type2.pKeyRType, + pElemRType: type2.pElemRType, + } +} \ No newline at end of file diff --git a/vendor/github.com/modern-go/reflect2/go_below_17.go b/vendor/github.com/modern-go/reflect2/go_below_17.go deleted file mode 100644 index 65a93c889..000000000 --- a/vendor/github.com/modern-go/reflect2/go_below_17.go +++ /dev/null @@ -1,9 +0,0 @@ -//+build !go1.7 - -package reflect2 - -import "unsafe" - -func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer { - return nil -} diff --git a/vendor/github.com/modern-go/reflect2/go_below_19.go b/vendor/github.com/modern-go/reflect2/go_below_19.go deleted file mode 100644 index b050ef70c..000000000 --- a/vendor/github.com/modern-go/reflect2/go_below_19.go +++ /dev/null @@ -1,14 +0,0 @@ -//+build !go1.9 - -package reflect2 - -import ( - "unsafe" -) - -//go:linkname makemap reflect.makemap -func makemap(rtype unsafe.Pointer) (m unsafe.Pointer) - -func makeMapWithSize(rtype unsafe.Pointer, cap int) unsafe.Pointer { - return makemap(rtype) -} diff --git a/vendor/github.com/modern-go/reflect2/reflect2.go b/vendor/github.com/modern-go/reflect2/reflect2.go index 63b49c799..c43c8b9d6 100644 --- a/vendor/github.com/modern-go/reflect2/reflect2.go +++ b/vendor/github.com/modern-go/reflect2/reflect2.go @@ -1,8 +1,9 @@ package reflect2 import ( - "github.com/modern-go/concurrent" "reflect" + "runtime" + "sync" "unsafe" ) @@ -130,13 +131,13 @@ var ConfigSafe = Config{UseSafeImplementation: true}.Froze() type frozenConfig struct { useSafeImplementation bool - cache *concurrent.Map + cache *sync.Map } func (cfg Config) Froze() *frozenConfig { return &frozenConfig{ useSafeImplementation: cfg.UseSafeImplementation, - cache: concurrent.NewMap(), + cache: new(sync.Map), } } @@ -288,11 +289,12 @@ func NoEscape(p unsafe.Pointer) unsafe.Pointer { } func UnsafeCastString(str string) []byte { + bytes := make([]byte, 0) stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str)) - sliceHeader := &reflect.SliceHeader{ - Data: stringHeader.Data, - Cap: stringHeader.Len, - Len: stringHeader.Len, - } - return *(*[]byte)(unsafe.Pointer(sliceHeader)) + sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&bytes)) + sliceHeader.Data = stringHeader.Data + sliceHeader.Cap = stringHeader.Len + sliceHeader.Len = stringHeader.Len + runtime.KeepAlive(str) + return bytes } diff --git a/vendor/github.com/modern-go/reflect2/test.sh b/vendor/github.com/modern-go/reflect2/test.sh deleted file mode 100644 index 3d2b9768c..000000000 --- a/vendor/github.com/modern-go/reflect2/test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list github.com/modern-go/reflect2-tests/... | grep -v vendor); do - go test -coverprofile=profile.out -coverpkg=github.com/modern-go/reflect2 $d - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/modern-go/reflect2/type_map.go b/vendor/github.com/modern-go/reflect2/type_map.go index 3acfb5580..4b13c3155 100644 --- a/vendor/github.com/modern-go/reflect2/type_map.go +++ b/vendor/github.com/modern-go/reflect2/type_map.go @@ -1,17 +1,13 @@ +// +build !gccgo + package reflect2 import ( "reflect" - "runtime" - "strings" "sync" "unsafe" ) -// typelinks1 for 1.5 ~ 1.6 -//go:linkname typelinks1 reflect.typelinks -func typelinks1() [][]unsafe.Pointer - // typelinks2 for 1.7 ~ //go:linkname typelinks2 reflect.typelinks func typelinks2() (sections []unsafe.Pointer, offset [][]int32) @@ -27,49 +23,10 @@ func discoverTypes() { types = make(map[string]reflect.Type) packages = make(map[string]map[string]reflect.Type) - ver := runtime.Version() - if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") { - loadGo15Types() - } else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") { - loadGo15Types() - } else { - loadGo17Types() - } -} - -func loadGo15Types() { - var obj interface{} = reflect.TypeOf(0) - typePtrss := typelinks1() - for _, typePtrs := range typePtrss { - for _, typePtr := range typePtrs { - (*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr - typ := obj.(reflect.Type) - if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct { - loadedType := typ.Elem() - pkgTypes := packages[loadedType.PkgPath()] - if pkgTypes == nil { - pkgTypes = map[string]reflect.Type{} - packages[loadedType.PkgPath()] = pkgTypes - } - types[loadedType.String()] = loadedType - pkgTypes[loadedType.Name()] = loadedType - } - if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr && - typ.Elem().Elem().Kind() == reflect.Struct { - loadedType := typ.Elem().Elem() - pkgTypes := packages[loadedType.PkgPath()] - if pkgTypes == nil { - pkgTypes = map[string]reflect.Type{} - packages[loadedType.PkgPath()] = pkgTypes - } - types[loadedType.String()] = loadedType - pkgTypes[loadedType.Name()] = loadedType - } - } - } + loadGoTypes() } -func loadGo17Types() { +func loadGoTypes() { var obj interface{} = reflect.TypeOf(0) sections, offset := typelinks2() for i, offs := range offset { diff --git a/vendor/github.com/modern-go/reflect2/unsafe_link.go b/vendor/github.com/modern-go/reflect2/unsafe_link.go index 57229c8db..b49f614ef 100644 --- a/vendor/github.com/modern-go/reflect2/unsafe_link.go +++ b/vendor/github.com/modern-go/reflect2/unsafe_link.go @@ -19,18 +19,12 @@ func typedslicecopy(elemType unsafe.Pointer, dst, src sliceHeader) int //go:linkname mapassign reflect.mapassign //go:noescape -func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key, val unsafe.Pointer) +func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer, val unsafe.Pointer) //go:linkname mapaccess reflect.mapaccess //go:noescape func mapaccess(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer) -// m escapes into the return value, but the caller of mapiterinit -// doesn't let the return value escape. -//go:noescape -//go:linkname mapiterinit reflect.mapiterinit -func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) *hiter - //go:noescape //go:linkname mapiternext reflect.mapiternext func mapiternext(it *hiter) @@ -42,9 +36,21 @@ func ifaceE2I(rtype unsafe.Pointer, src interface{}, dst unsafe.Pointer) // If you modify hiter, also change cmd/internal/gc/reflect.go to indicate // the layout of this structure. type hiter struct { - key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/internal/gc/range.go). - value unsafe.Pointer // Must be in second position (see cmd/internal/gc/range.go). - // rest fields are ignored + key unsafe.Pointer + value unsafe.Pointer + t unsafe.Pointer + h unsafe.Pointer + buckets unsafe.Pointer + bptr unsafe.Pointer + overflow *[]unsafe.Pointer + oldoverflow *[]unsafe.Pointer + startBucket uintptr + offset uint8 + wrapped bool + B uint8 + i uint8 + bucket uintptr + checkBucket uintptr } // add returns p+x. diff --git a/vendor/github.com/modern-go/reflect2/unsafe_map.go b/vendor/github.com/modern-go/reflect2/unsafe_map.go index f2e76e6bb..37872da81 100644 --- a/vendor/github.com/modern-go/reflect2/unsafe_map.go +++ b/vendor/github.com/modern-go/reflect2/unsafe_map.go @@ -107,14 +107,6 @@ func (type2 *UnsafeMapType) Iterate(obj interface{}) MapIterator { return type2.UnsafeIterate(objEFace.data) } -func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator { - return &UnsafeMapIterator{ - hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)), - pKeyRType: type2.pKeyRType, - pElemRType: type2.pElemRType, - } -} - type UnsafeMapIterator struct { *hiter pKeyRType unsafe.Pointer diff --git a/vendor/github.com/prometheus/client_golang/prometheus/README.md b/vendor/github.com/prometheus/client_golang/prometheus/README.md index 44986bff0..c67ff1b7f 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/README.md +++ b/vendor/github.com/prometheus/client_golang/prometheus/README.md @@ -1 +1 @@ -See [![go-doc](https://godoc.org/github.com/prometheus/client_golang/prometheus?status.svg)](https://godoc.org/github.com/prometheus/client_golang/prometheus). +See [![Go Reference](https://pkg.go.dev/badge/github.com/prometheus/client_golang/prometheus.svg)](https://pkg.go.dev/github.com/prometheus/client_golang/prometheus). diff --git a/vendor/github.com/prometheus/client_golang/prometheus/build_info_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/build_info_collector.go new file mode 100644 index 000000000..450189f35 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/build_info_collector.go @@ -0,0 +1,38 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prometheus + +import "runtime/debug" + +// NewBuildInfoCollector is the obsolete version of collectors.NewBuildInfoCollector. +// See there for documentation. +// +// Deprecated: Use collectors.NewBuildInfoCollector instead. +func NewBuildInfoCollector() Collector { + path, version, sum := "unknown", "unknown", "unknown" + if bi, ok := debug.ReadBuildInfo(); ok { + path = bi.Main.Path + version = bi.Main.Version + sum = bi.Main.Sum + } + c := &selfCollector{MustNewConstMetric( + NewDesc( + "go_build_info", + "Build information about the main Go module.", + nil, Labels{"path": path, "version": version, "checksum": sum}, + ), + GaugeValue, 1)} + c.init(c.self) + return c +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collector.go b/vendor/github.com/prometheus/client_golang/prometheus/collector.go index 1e839650d..cf05079fb 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collector.go @@ -69,9 +69,9 @@ type Collector interface { // If a Collector collects the same metrics throughout its lifetime, its // Describe method can simply be implemented as: // -// func (c customCollector) Describe(ch chan<- *Desc) { -// DescribeByCollect(c, ch) -// } +// func (c customCollector) Describe(ch chan<- *Desc) { +// DescribeByCollect(c, ch) +// } // // However, this will not work if the metrics collected change dynamically over // the lifetime of the Collector in a way that their combined set of descriptors @@ -118,3 +118,11 @@ func (c *selfCollector) Describe(ch chan<- *Desc) { func (c *selfCollector) Collect(ch chan<- Metric) { ch <- c.self } + +// collectorMetric is a metric that is also a collector. +// Because of selfCollector, most (if not all) Metrics in +// this package are also collectors. +type collectorMetric interface { + Metric + Collector +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go index 3f8fd790d..4ce84e7a8 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/counter.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/counter.go @@ -20,6 +20,7 @@ import ( "time" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/types/known/timestamppb" ) // Counter is a Metric that represents a single numerical value that only ever @@ -51,7 +52,7 @@ type Counter interface { // will lead to a valid (label-less) exemplar. But if Labels is nil, the current // exemplar is left in place. AddWithExemplar panics if the value is < 0, if any // of the provided labels are invalid, or if the provided labels contain more -// than 64 runes in total. +// than 128 runes in total. type ExemplarAdder interface { AddWithExemplar(value float64, exemplar Labels) } @@ -59,6 +60,18 @@ type ExemplarAdder interface { // CounterOpts is an alias for Opts. See there for doc comments. type CounterOpts Opts +// CounterVecOpts bundles the options to create a CounterVec metric. +// It is mandatory to set CounterOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type CounterVecOpts struct { + CounterOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Constraint + // function, if provided. + VariableLabels ConstrainableLabels +} + // NewCounter creates a new Counter based on the provided CounterOpts. // // The returned implementation also implements ExemplarAdder. It is safe to @@ -78,8 +91,12 @@ func NewCounter(opts CounterOpts) Counter { nil, opts.ConstLabels, ) - result := &counter{desc: desc, labelPairs: desc.constLabelPairs, now: time.Now} + if opts.now == nil { + opts.now = time.Now + } + result := &counter{desc: desc, labelPairs: desc.constLabelPairs, now: opts.now} result.init(result) // Init self-collection. + result.createdTs = timestamppb.New(opts.now()) return result } @@ -94,10 +111,12 @@ type counter struct { selfCollector desc *Desc + createdTs *timestamppb.Timestamp labelPairs []*dto.LabelPair exemplar atomic.Value // Containing nil or a *dto.Exemplar. - now func() time.Time // To mock out time.Now() for testing. + // now is for testing purposes, by default it's time.Now. + now func() time.Time } func (c *counter) Desc() *Desc { @@ -133,17 +152,21 @@ func (c *counter) Inc() { atomic.AddUint64(&c.valInt, 1) } -func (c *counter) Write(out *dto.Metric) error { +func (c *counter) get() float64 { fval := math.Float64frombits(atomic.LoadUint64(&c.valBits)) ival := atomic.LoadUint64(&c.valInt) - val := fval + float64(ival) + return fval + float64(ival) +} +func (c *counter) Write(out *dto.Metric) error { + // Read the Exemplar first and the value second. This is to avoid a race condition + // where users see an exemplar for a not-yet-existing observation. var exemplar *dto.Exemplar if e := c.exemplar.Load(); e != nil { exemplar = e.(*dto.Exemplar) } - - return populateMetric(CounterValue, val, c.labelPairs, exemplar, out) + val := c.get() + return populateMetric(CounterValue, val, c.labelPairs, exemplar, out, c.createdTs) } func (c *counter) updateExemplar(v float64, l Labels) { @@ -169,19 +192,31 @@ type CounterVec struct { // NewCounterVec creates a new CounterVec based on the provided CounterOpts and // partitioned by the given label names. func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec { - desc := NewDesc( + return V2.NewCounterVec(CounterVecOpts{ + CounterOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewCounterVec creates a new CounterVec based on the provided CounterVecOpts. +func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec { + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) + if opts.now == nil { + opts.now = time.Now + } return &CounterVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { - if len(lvs) != len(desc.variableLabels) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) + if len(lvs) != len(desc.variableLabels.names) { + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, lvs)) } - result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now} + result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: opts.now} result.init(result) // Init self-collection. + result.createdTs = timestamppb.New(opts.now()) return result }), } @@ -241,7 +276,8 @@ func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Add(42) +// +// myVec.WithLabelValues("404", "GET").Add(42) func (v *CounterVec) WithLabelValues(lvs ...string) Counter { c, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -252,7 +288,8 @@ func (v *CounterVec) WithLabelValues(lvs ...string) Counter { // With works as GetMetricWith, but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) func (v *CounterVec) With(labels Labels) Counter { c, err := v.GetMetricWith(labels) if err != nil { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go index 4bb816ab7..68ffe3c24 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/desc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/desc.go @@ -14,17 +14,16 @@ package prometheus import ( - "errors" "fmt" "sort" "strings" "github.com/cespare/xxhash/v2" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" + dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/model" + "google.golang.org/protobuf/proto" - dto "github.com/prometheus/client_model/go" + "github.com/prometheus/client_golang/prometheus/internal" ) // Desc is the descriptor used by every Prometheus Metric. It is essentially @@ -51,9 +50,9 @@ type Desc struct { // constLabelPairs contains precalculated DTO label pairs based on // the constant labels. constLabelPairs []*dto.LabelPair - // variableLabels contains names of labels for which the metric - // maintains variable values. - variableLabels []string + // variableLabels contains names of labels and normalization function for + // which the metric maintains variable values. + variableLabels *compiledLabels // id is a hash of the values of the ConstLabels and fqName. This // must be unique among all registered descriptors and can therefore be // used as an identifier of the descriptor. @@ -77,10 +76,24 @@ type Desc struct { // For constLabels, the label values are constant. Therefore, they are fully // specified in the Desc. See the Collector example for a usage pattern. func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc { + return V2.NewDesc(fqName, help, UnconstrainedLabels(variableLabels), constLabels) +} + +// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc +// and will be reported on registration time. variableLabels and constLabels can +// be nil if no such labels should be set. fqName must not be empty. +// +// variableLabels only contain the label names and normalization functions. Their +// label values are variable and therefore not part of the Desc. (They are managed +// within the Metric.) +// +// For constLabels, the label values are constant. Therefore, they are fully +// specified in the Desc. See the Collector example for a usage pattern. +func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels) *Desc { d := &Desc{ fqName: fqName, help: help, - variableLabels: variableLabels, + variableLabels: variableLabels.compile(), } if !model.IsValidMetricName(model.LabelValue(fqName)) { d.err = fmt.Errorf("%q is not a valid metric name", fqName) @@ -90,7 +103,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * // their sorted label names) plus the fqName (at position 0). labelValues := make([]string, 1, len(constLabels)+1) labelValues[0] = fqName - labelNames := make([]string, 0, len(constLabels)+len(variableLabels)) + labelNames := make([]string, 0, len(constLabels)+len(d.variableLabels.names)) labelNameSet := map[string]struct{}{} // First add only the const label names and sort them... for labelName := range constLabels { @@ -115,16 +128,16 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * // Now add the variable label names, but prefix them with something that // cannot be in a regular label name. That prevents matching the label // dimension with a different mix between preset and variable labels. - for _, labelName := range variableLabels { - if !checkLabelName(labelName) { - d.err = fmt.Errorf("%q is not a valid label name for metric %q", labelName, fqName) + for _, label := range d.variableLabels.names { + if !checkLabelName(label) { + d.err = fmt.Errorf("%q is not a valid label name for metric %q", label, fqName) return d } - labelNames = append(labelNames, "$"+labelName) - labelNameSet[labelName] = struct{}{} + labelNames = append(labelNames, "$"+label) + labelNameSet[label] = struct{}{} } if len(labelNames) != len(labelNameSet) { - d.err = errors.New("duplicate label names") + d.err = fmt.Errorf("duplicate label names in constant and variable labels for metric %q", fqName) return d } @@ -154,7 +167,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * Value: proto.String(v), }) } - sort.Sort(labelPairSorter(d.constLabelPairs)) + sort.Sort(internal.LabelPairSorter(d.constLabelPairs)) return d } @@ -176,11 +189,19 @@ func (d *Desc) String() string { fmt.Sprintf("%s=%q", lp.GetName(), lp.GetValue()), ) } + vlStrings := make([]string, 0, len(d.variableLabels.names)) + for _, vl := range d.variableLabels.names { + if fn, ok := d.variableLabels.labelConstraints[vl]; ok && fn != nil { + vlStrings = append(vlStrings, fmt.Sprintf("c(%s)", vl)) + } else { + vlStrings = append(vlStrings, vl) + } + } return fmt.Sprintf( - "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: %v}", + "Desc{fqName: %q, help: %q, constLabels: {%s}, variableLabels: {%s}}", d.fqName, d.help, strings.Join(lpStrings, ","), - d.variableLabels, + strings.Join(vlStrings, ","), ) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/doc.go b/vendor/github.com/prometheus/client_golang/prometheus/doc.go index 98450125d..962608f02 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/doc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/doc.go @@ -21,55 +21,66 @@ // All exported functions and methods are safe to be used concurrently unless // specified otherwise. // -// A Basic Example +// # A Basic Example // // As a starting point, a very basic usage example: // -// package main -// -// import ( -// "log" -// "net/http" -// -// "github.com/prometheus/client_golang/prometheus" -// "github.com/prometheus/client_golang/prometheus/promhttp" -// ) -// -// var ( -// cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{ -// Name: "cpu_temperature_celsius", -// Help: "Current temperature of the CPU.", -// }) -// hdFailures = prometheus.NewCounterVec( -// prometheus.CounterOpts{ -// Name: "hd_errors_total", -// Help: "Number of hard-disk errors.", -// }, -// []string{"device"}, -// ) -// ) -// -// func init() { -// // Metrics have to be registered to be exposed: -// prometheus.MustRegister(cpuTemp) -// prometheus.MustRegister(hdFailures) -// } -// -// func main() { -// cpuTemp.Set(65.3) -// hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc() -// -// // The Handler function provides a default handler to expose metrics -// // via an HTTP server. "/metrics" is the usual endpoint for that. -// http.Handle("/metrics", promhttp.Handler()) -// log.Fatal(http.ListenAndServe(":8080", nil)) -// } -// +// package main +// +// import ( +// "log" +// "net/http" +// +// "github.com/prometheus/client_golang/prometheus" +// "github.com/prometheus/client_golang/prometheus/promhttp" +// ) +// +// type metrics struct { +// cpuTemp prometheus.Gauge +// hdFailures *prometheus.CounterVec +// } +// +// func NewMetrics(reg prometheus.Registerer) *metrics { +// m := &metrics{ +// cpuTemp: prometheus.NewGauge(prometheus.GaugeOpts{ +// Name: "cpu_temperature_celsius", +// Help: "Current temperature of the CPU.", +// }), +// hdFailures: prometheus.NewCounterVec( +// prometheus.CounterOpts{ +// Name: "hd_errors_total", +// Help: "Number of hard-disk errors.", +// }, +// []string{"device"}, +// ), +// } +// reg.MustRegister(m.cpuTemp) +// reg.MustRegister(m.hdFailures) +// return m +// } +// +// func main() { +// // Create a non-global registry. +// reg := prometheus.NewRegistry() +// +// // Create new metrics and register them using the custom registry. +// m := NewMetrics(reg) +// // Set values for the new created metrics. +// m.cpuTemp.Set(65.3) +// m.hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc() +// +// // Expose metrics and custom registry via an HTTP server +// // using the HandleFor function. "/metrics" is the usual endpoint for that. +// http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) +// log.Fatal(http.ListenAndServe(":8080", nil)) +// } // // This is a complete program that exports two metrics, a Gauge and a Counter, // the latter with a label attached to turn it into a (one-dimensional) vector. +// It register the metrics using a custom registry and exposes them via an HTTP server +// on the /metrics endpoint. // -// Metrics +// # Metrics // // The number of exported identifiers in this package might appear a bit // overwhelming. However, in addition to the basic plumbing shown in the example @@ -100,7 +111,7 @@ // To create instances of Metrics and their vector versions, you need a suitable // …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts, or HistogramOpts. // -// Custom Collectors and constant Metrics +// # Custom Collectors and constant Metrics // // While you could create your own implementations of Metric, most likely you // will only ever implement the Collector interface on your own. At a first @@ -141,7 +152,7 @@ // a metric, GaugeFunc, CounterFunc, or UntypedFunc might be interesting // shortcuts. // -// Advanced Uses of the Registry +// # Advanced Uses of the Registry // // While MustRegister is the by far most common way of registering a Collector, // sometimes you might want to handle the errors the registration might cause. @@ -176,23 +187,23 @@ // NewProcessCollector). With a custom registry, you are in control and decide // yourself about the Collectors to register. // -// HTTP Exposition +// # HTTP Exposition // // The Registry implements the Gatherer interface. The caller of the Gather // method can then expose the gathered metrics in some way. Usually, the metrics // are served via HTTP on the /metrics endpoint. That's happening in the example // above. The tools to expose metrics via HTTP are in the promhttp sub-package. // -// Pushing to the Pushgateway +// # Pushing to the Pushgateway // // Function for pushing to the Pushgateway can be found in the push sub-package. // -// Graphite Bridge +// # Graphite Bridge // // Functions and examples to push metrics from a Gatherer to Graphite can be // found in the graphite sub-package. // -// Other Means of Exposition +// # Other Means of Exposition // // More ways of exposing metrics can easily be added by following the approaches // of the existing implementations. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go index c41ab37f3..de5a85629 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/expvar_collector.go @@ -48,7 +48,7 @@ func (e *expvarCollector) Collect(ch chan<- Metric) { continue } var v interface{} - labels := make([]string, len(desc.variableLabels)) + labels := make([]string, len(desc.variableLabels.names)) if err := json.Unmarshal([]byte(expVar.String()), &v); err != nil { ch <- NewInvalidMetric(desc, err) continue diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go index bd0733d6a..dd2eac940 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go @@ -55,6 +55,18 @@ type Gauge interface { // GaugeOpts is an alias for Opts. See there for doc comments. type GaugeOpts Opts +// GaugeVecOpts bundles the options to create a GaugeVec metric. +// It is mandatory to set GaugeOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type GaugeVecOpts struct { + GaugeOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Constraint + // function, if provided. + VariableLabels ConstrainableLabels +} + // NewGauge creates a new Gauge based on the provided GaugeOpts. // // The returned implementation is optimized for a fast Set method. If you have a @@ -123,7 +135,7 @@ func (g *gauge) Sub(val float64) { func (g *gauge) Write(out *dto.Metric) error { val := math.Float64frombits(atomic.LoadUint64(&g.valBits)) - return populateMetric(GaugeValue, val, g.labelPairs, nil, out) + return populateMetric(GaugeValue, val, g.labelPairs, nil, out, nil) } // GaugeVec is a Collector that bundles a set of Gauges that all share the same @@ -138,16 +150,24 @@ type GaugeVec struct { // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and // partitioned by the given label names. func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { - desc := NewDesc( + return V2.NewGaugeVec(GaugeVecOpts{ + GaugeOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewGaugeVec creates a new GaugeVec based on the provided GaugeVecOpts. +func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec { + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) return &GaugeVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { - if len(lvs) != len(desc.variableLabels) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) + if len(lvs) != len(desc.variableLabels.names) { + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, lvs)) } result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)} result.init(result) // Init self-collection. @@ -210,7 +230,8 @@ func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Add(42) +// +// myVec.WithLabelValues("404", "GET").Add(42) func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge { g, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -221,7 +242,8 @@ func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge { // With works as GetMetricWith, but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) func (v *GaugeVec) With(labels Labels) Gauge { g, err := v.GetMetricWith(labels) if err != nil { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/get_pid.go b/vendor/github.com/prometheus/client_golang/prometheus/get_pid.go new file mode 100644 index 000000000..614fd61be --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/get_pid.go @@ -0,0 +1,26 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !js || wasm +// +build !js wasm + +package prometheus + +import "os" + +func getPIDFn() func() (int, error) { + pid := os.Getpid() + return func() (int, error) { + return pid, nil + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go b/vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go new file mode 100644 index 000000000..eaf8059ee --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go @@ -0,0 +1,23 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build js && !wasm +// +build js,!wasm + +package prometheus + +func getPIDFn() func() (int, error) { + return func() (int, error) { + return 1, nil + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go index a96ed1cee..ad9a71a5e 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go @@ -16,32 +16,205 @@ package prometheus import ( "runtime" "runtime/debug" - "sync" "time" ) -type goCollector struct { +// goRuntimeMemStats provides the metrics initially provided by runtime.ReadMemStats. +// From Go 1.17 those similar (and better) statistics are provided by runtime/metrics, so +// while eval closure works on runtime.MemStats, the struct from Go 1.17+ is +// populated using runtime/metrics. +func goRuntimeMemStats() memStatsMetrics { + return memStatsMetrics{ + { + desc: NewDesc( + memstatNamespace("alloc_bytes"), + "Number of bytes allocated and still in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("alloc_bytes_total"), + "Total number of bytes allocated, even if freed.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("sys_bytes"), + "Number of bytes obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("lookups_total"), + "Total number of pointer lookups.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("mallocs_total"), + "Total number of mallocs.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("frees_total"), + "Total number of frees.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, + valType: CounterValue, + }, { + desc: NewDesc( + memstatNamespace("heap_alloc_bytes"), + "Number of heap bytes allocated and still in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_sys_bytes"), + "Number of heap bytes obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_idle_bytes"), + "Number of heap bytes waiting to be used.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_inuse_bytes"), + "Number of heap bytes that are in use.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_released_bytes"), + "Number of heap bytes released to OS.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("heap_objects"), + "Number of allocated objects.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("stack_inuse_bytes"), + "Number of bytes in use by the stack allocator.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("stack_sys_bytes"), + "Number of bytes obtained from system for stack allocator.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mspan_inuse_bytes"), + "Number of bytes in use by mspan structures.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mspan_sys_bytes"), + "Number of bytes used for mspan structures obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mcache_inuse_bytes"), + "Number of bytes in use by mcache structures.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("mcache_sys_bytes"), + "Number of bytes used for mcache structures obtained from system.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("buck_hash_sys_bytes"), + "Number of bytes used by the profiling bucket hash table.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("gc_sys_bytes"), + "Number of bytes used for garbage collection system metadata.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("other_sys_bytes"), + "Number of bytes used for other system allocations.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, + valType: GaugeValue, + }, { + desc: NewDesc( + memstatNamespace("next_gc_bytes"), + "Number of heap bytes when next garbage collection will take place.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, + valType: GaugeValue, + }, + } +} + +type baseGoCollector struct { goroutinesDesc *Desc threadsDesc *Desc gcDesc *Desc + gcLastTimeDesc *Desc goInfoDesc *Desc - - // ms... are memstats related. - msLast *runtime.MemStats // Previously collected memstats. - msLastTimestamp time.Time - msMtx sync.Mutex // Protects msLast and msLastTimestamp. - msMetrics memStatsMetrics - msRead func(*runtime.MemStats) // For mocking in tests. - msMaxWait time.Duration // Wait time for fresh memstats. - msMaxAge time.Duration // Maximum allowed age of old memstats. } -// NewGoCollector is the obsolete version of collectors.NewGoCollector. -// See there for documentation. -// -// Deprecated: Use collectors.NewGoCollector instead. -func NewGoCollector() Collector { - return &goCollector{ +func newBaseGoCollector() baseGoCollector { + return baseGoCollector{ goroutinesDesc: NewDesc( "go_goroutines", "Number of goroutines that currently exist.", @@ -54,246 +227,32 @@ func NewGoCollector() Collector { "go_gc_duration_seconds", "A summary of the pause duration of garbage collection cycles.", nil, nil), + gcLastTimeDesc: NewDesc( + "go_memstats_last_gc_time_seconds", + "Number of seconds since 1970 of last garbage collection.", + nil, nil), goInfoDesc: NewDesc( "go_info", "Information about the Go environment.", nil, Labels{"version": runtime.Version()}), - msLast: &runtime.MemStats{}, - msRead: runtime.ReadMemStats, - msMaxWait: time.Second, - msMaxAge: 5 * time.Minute, - msMetrics: memStatsMetrics{ - { - desc: NewDesc( - memstatNamespace("alloc_bytes"), - "Number of bytes allocated and still in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("alloc_bytes_total"), - "Total number of bytes allocated, even if freed.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("sys_bytes"), - "Number of bytes obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("lookups_total"), - "Total number of pointer lookups.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("mallocs_total"), - "Total number of mallocs.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("frees_total"), - "Total number of frees.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, - valType: CounterValue, - }, { - desc: NewDesc( - memstatNamespace("heap_alloc_bytes"), - "Number of heap bytes allocated and still in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_sys_bytes"), - "Number of heap bytes obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_idle_bytes"), - "Number of heap bytes waiting to be used.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_inuse_bytes"), - "Number of heap bytes that are in use.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_released_bytes"), - "Number of heap bytes released to OS.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("heap_objects"), - "Number of allocated objects.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("stack_inuse_bytes"), - "Number of bytes in use by the stack allocator.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("stack_sys_bytes"), - "Number of bytes obtained from system for stack allocator.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mspan_inuse_bytes"), - "Number of bytes in use by mspan structures.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mspan_sys_bytes"), - "Number of bytes used for mspan structures obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mcache_inuse_bytes"), - "Number of bytes in use by mcache structures.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("mcache_sys_bytes"), - "Number of bytes used for mcache structures obtained from system.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("buck_hash_sys_bytes"), - "Number of bytes used by the profiling bucket hash table.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("gc_sys_bytes"), - "Number of bytes used for garbage collection system metadata.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("other_sys_bytes"), - "Number of bytes used for other system allocations.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("next_gc_bytes"), - "Number of heap bytes when next garbage collection will take place.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("last_gc_time_seconds"), - "Number of seconds since 1970 of last garbage collection.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 }, - valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("gc_cpu_fraction"), - "The fraction of this program's available CPU time used by the GC since the program started.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction }, - valType: GaugeValue, - }, - }, } } -func memstatNamespace(s string) string { - return "go_memstats_" + s -} - // Describe returns all descriptions of the collector. -func (c *goCollector) Describe(ch chan<- *Desc) { +func (c *baseGoCollector) Describe(ch chan<- *Desc) { ch <- c.goroutinesDesc ch <- c.threadsDesc ch <- c.gcDesc + ch <- c.gcLastTimeDesc ch <- c.goInfoDesc - for _, i := range c.msMetrics { - ch <- i.desc - } } // Collect returns the current state of all metrics of the collector. -func (c *goCollector) Collect(ch chan<- Metric) { - var ( - ms = &runtime.MemStats{} - done = make(chan struct{}) - ) - // Start reading memstats first as it might take a while. - go func() { - c.msRead(ms) - c.msMtx.Lock() - c.msLast = ms - c.msLastTimestamp = time.Now() - c.msMtx.Unlock() - close(done) - }() - +func (c *baseGoCollector) Collect(ch chan<- Metric) { ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine())) - n, _ := runtime.ThreadCreateProfile(nil) - ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n)) + + n := getRuntimeNumThreads() + ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, n) var stats debug.GCStats stats.PauseQuantiles = make([]time.Duration, 5) @@ -305,63 +264,18 @@ func (c *goCollector) Collect(ch chan<- Metric) { } quantiles[0.0] = stats.PauseQuantiles[0].Seconds() ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), stats.PauseTotal.Seconds(), quantiles) - + ch <- MustNewConstMetric(c.gcLastTimeDesc, GaugeValue, float64(stats.LastGC.UnixNano())/1e9) ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1) - - timer := time.NewTimer(c.msMaxWait) - select { - case <-done: // Our own ReadMemStats succeeded in time. Use it. - timer.Stop() // Important for high collection frequencies to not pile up timers. - c.msCollect(ch, ms) - return - case <-timer.C: // Time out, use last memstats if possible. Continue below. - } - c.msMtx.Lock() - if time.Since(c.msLastTimestamp) < c.msMaxAge { - // Last memstats are recent enough. Collect from them under the lock. - c.msCollect(ch, c.msLast) - c.msMtx.Unlock() - return - } - // If we are here, the last memstats are too old or don't exist. We have - // to wait until our own ReadMemStats finally completes. For that to - // happen, we have to release the lock. - c.msMtx.Unlock() - <-done - c.msCollect(ch, ms) } -func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) { - for _, i := range c.msMetrics { - ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms)) - } +func memstatNamespace(s string) string { + return "go_memstats_" + s } -// memStatsMetrics provide description, value, and value type for memstat metrics. +// memStatsMetrics provide description, evaluator, runtime/metrics name, and +// value type for memstat metrics. type memStatsMetrics []struct { desc *Desc eval func(*runtime.MemStats) float64 valType ValueType } - -// NewBuildInfoCollector is the obsolete version of collectors.NewBuildInfoCollector. -// See there for documentation. -// -// Deprecated: Use collectors.NewBuildInfoCollector instead. -func NewBuildInfoCollector() Collector { - path, version, sum := "unknown", "unknown", "unknown" - if bi, ok := debug.ReadBuildInfo(); ok { - path = bi.Main.Path - version = bi.Main.Version - sum = bi.Main.Sum - } - c := &selfCollector{MustNewConstMetric( - NewDesc( - "go_build_info", - "Build information about the main Go module.", - nil, Labels{"path": path, "version": version, "checksum": sum}, - ), - GaugeValue, 1)} - c.init(c.self) - return c -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go new file mode 100644 index 000000000..897a6e906 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_go116.go @@ -0,0 +1,122 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !go1.17 +// +build !go1.17 + +package prometheus + +import ( + "runtime" + "sync" + "time" +) + +type goCollector struct { + base baseGoCollector + + // ms... are memstats related. + msLast *runtime.MemStats // Previously collected memstats. + msLastTimestamp time.Time + msMtx sync.Mutex // Protects msLast and msLastTimestamp. + msMetrics memStatsMetrics + msRead func(*runtime.MemStats) // For mocking in tests. + msMaxWait time.Duration // Wait time for fresh memstats. + msMaxAge time.Duration // Maximum allowed age of old memstats. +} + +// NewGoCollector is the obsolete version of collectors.NewGoCollector. +// See there for documentation. +// +// Deprecated: Use collectors.NewGoCollector instead. +func NewGoCollector() Collector { + msMetrics := goRuntimeMemStats() + msMetrics = append(msMetrics, struct { + desc *Desc + eval func(*runtime.MemStats) float64 + valType ValueType + }{ + // This metric is omitted in Go1.17+, see https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 + desc: NewDesc( + memstatNamespace("gc_cpu_fraction"), + "The fraction of this program's available CPU time used by the GC since the program started.", + nil, nil, + ), + eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction }, + valType: GaugeValue, + }) + return &goCollector{ + base: newBaseGoCollector(), + msLast: &runtime.MemStats{}, + msRead: runtime.ReadMemStats, + msMaxWait: time.Second, + msMaxAge: 5 * time.Minute, + msMetrics: msMetrics, + } +} + +// Describe returns all descriptions of the collector. +func (c *goCollector) Describe(ch chan<- *Desc) { + c.base.Describe(ch) + for _, i := range c.msMetrics { + ch <- i.desc + } +} + +// Collect returns the current state of all metrics of the collector. +func (c *goCollector) Collect(ch chan<- Metric) { + var ( + ms = &runtime.MemStats{} + done = make(chan struct{}) + ) + // Start reading memstats first as it might take a while. + go func() { + c.msRead(ms) + c.msMtx.Lock() + c.msLast = ms + c.msLastTimestamp = time.Now() + c.msMtx.Unlock() + close(done) + }() + + // Collect base non-memory metrics. + c.base.Collect(ch) + + timer := time.NewTimer(c.msMaxWait) + select { + case <-done: // Our own ReadMemStats succeeded in time. Use it. + timer.Stop() // Important for high collection frequencies to not pile up timers. + c.msCollect(ch, ms) + return + case <-timer.C: // Time out, use last memstats if possible. Continue below. + } + c.msMtx.Lock() + if time.Since(c.msLastTimestamp) < c.msMaxAge { + // Last memstats are recent enough. Collect from them under the lock. + c.msCollect(ch, c.msLast) + c.msMtx.Unlock() + return + } + // If we are here, the last memstats are too old or don't exist. We have + // to wait until our own ReadMemStats finally completes. For that to + // happen, we have to release the lock. + c.msMtx.Unlock() + <-done + c.msCollect(ch, ms) +} + +func (c *goCollector) msCollect(ch chan<- Metric, ms *runtime.MemStats) { + for _, i := range c.msMetrics { + ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms)) + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go new file mode 100644 index 000000000..2d8d9f64f --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go @@ -0,0 +1,567 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build go1.17 +// +build go1.17 + +package prometheus + +import ( + "math" + "runtime" + "runtime/metrics" + "strings" + "sync" + + "github.com/prometheus/client_golang/prometheus/internal" + + dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" +) + +const ( + // constants for strings referenced more than once. + goGCHeapTinyAllocsObjects = "/gc/heap/tiny/allocs:objects" + goGCHeapAllocsObjects = "/gc/heap/allocs:objects" + goGCHeapFreesObjects = "/gc/heap/frees:objects" + goGCHeapFreesBytes = "/gc/heap/frees:bytes" + goGCHeapAllocsBytes = "/gc/heap/allocs:bytes" + goGCHeapObjects = "/gc/heap/objects:objects" + goGCHeapGoalBytes = "/gc/heap/goal:bytes" + goMemoryClassesTotalBytes = "/memory/classes/total:bytes" + goMemoryClassesHeapObjectsBytes = "/memory/classes/heap/objects:bytes" + goMemoryClassesHeapUnusedBytes = "/memory/classes/heap/unused:bytes" + goMemoryClassesHeapReleasedBytes = "/memory/classes/heap/released:bytes" + goMemoryClassesHeapFreeBytes = "/memory/classes/heap/free:bytes" + goMemoryClassesHeapStacksBytes = "/memory/classes/heap/stacks:bytes" + goMemoryClassesOSStacksBytes = "/memory/classes/os-stacks:bytes" + goMemoryClassesMetadataMSpanInuseBytes = "/memory/classes/metadata/mspan/inuse:bytes" + goMemoryClassesMetadataMSPanFreeBytes = "/memory/classes/metadata/mspan/free:bytes" + goMemoryClassesMetadataMCacheInuseBytes = "/memory/classes/metadata/mcache/inuse:bytes" + goMemoryClassesMetadataMCacheFreeBytes = "/memory/classes/metadata/mcache/free:bytes" + goMemoryClassesProfilingBucketsBytes = "/memory/classes/profiling/buckets:bytes" + goMemoryClassesMetadataOtherBytes = "/memory/classes/metadata/other:bytes" + goMemoryClassesOtherBytes = "/memory/classes/other:bytes" +) + +// rmNamesForMemStatsMetrics represents runtime/metrics names required to populate goRuntimeMemStats from like logic. +var rmNamesForMemStatsMetrics = []string{ + goGCHeapTinyAllocsObjects, + goGCHeapAllocsObjects, + goGCHeapFreesObjects, + goGCHeapAllocsBytes, + goGCHeapObjects, + goGCHeapGoalBytes, + goMemoryClassesTotalBytes, + goMemoryClassesHeapObjectsBytes, + goMemoryClassesHeapUnusedBytes, + goMemoryClassesHeapReleasedBytes, + goMemoryClassesHeapFreeBytes, + goMemoryClassesHeapStacksBytes, + goMemoryClassesOSStacksBytes, + goMemoryClassesMetadataMSpanInuseBytes, + goMemoryClassesMetadataMSPanFreeBytes, + goMemoryClassesMetadataMCacheInuseBytes, + goMemoryClassesMetadataMCacheFreeBytes, + goMemoryClassesProfilingBucketsBytes, + goMemoryClassesMetadataOtherBytes, + goMemoryClassesOtherBytes, +} + +func bestEffortLookupRM(lookup []string) []metrics.Description { + ret := make([]metrics.Description, 0, len(lookup)) + for _, rm := range metrics.All() { + for _, m := range lookup { + if m == rm.Name { + ret = append(ret, rm) + } + } + } + return ret +} + +type goCollector struct { + base baseGoCollector + + // mu protects updates to all fields ensuring a consistent + // snapshot is always produced by Collect. + mu sync.Mutex + + // Contains all samples that has to retrieved from runtime/metrics (not all of them will be exposed). + sampleBuf []metrics.Sample + // sampleMap allows lookup for MemStats metrics and runtime/metrics histograms for exact sums. + sampleMap map[string]*metrics.Sample + + // rmExposedMetrics represents all runtime/metrics package metrics + // that were configured to be exposed. + rmExposedMetrics []collectorMetric + rmExactSumMapForHist map[string]string + + // With Go 1.17, the runtime/metrics package was introduced. + // From that point on, metric names produced by the runtime/metrics + // package could be generated from runtime/metrics names. However, + // these differ from the old names for the same values. + // + // This field exists to export the same values under the old names + // as well. + msMetrics memStatsMetrics + msMetricsEnabled bool +} + +type rmMetricDesc struct { + metrics.Description +} + +func matchRuntimeMetricsRules(rules []internal.GoCollectorRule) []rmMetricDesc { + var descs []rmMetricDesc + for _, d := range metrics.All() { + var ( + deny = true + desc rmMetricDesc + ) + + for _, r := range rules { + if !r.Matcher.MatchString(d.Name) { + continue + } + deny = r.Deny + } + if deny { + continue + } + + desc.Description = d + descs = append(descs, desc) + } + return descs +} + +func defaultGoCollectorOptions() internal.GoCollectorOptions { + return internal.GoCollectorOptions{ + RuntimeMetricSumForHist: map[string]string{ + "/gc/heap/allocs-by-size:bytes": goGCHeapAllocsBytes, + "/gc/heap/frees-by-size:bytes": goGCHeapFreesBytes, + }, + RuntimeMetricRules: []internal.GoCollectorRule{ + //{Matcher: regexp.MustCompile("")}, + }, + } +} + +// NewGoCollector is the obsolete version of collectors.NewGoCollector. +// See there for documentation. +// +// Deprecated: Use collectors.NewGoCollector instead. +func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { + opt := defaultGoCollectorOptions() + for _, o := range opts { + o(&opt) + } + + exposedDescriptions := matchRuntimeMetricsRules(opt.RuntimeMetricRules) + + // Collect all histogram samples so that we can get their buckets. + // The API guarantees that the buckets are always fixed for the lifetime + // of the process. + var histograms []metrics.Sample + for _, d := range exposedDescriptions { + if d.Kind == metrics.KindFloat64Histogram { + histograms = append(histograms, metrics.Sample{Name: d.Name}) + } + } + + if len(histograms) > 0 { + metrics.Read(histograms) + } + + bucketsMap := make(map[string][]float64) + for i := range histograms { + bucketsMap[histograms[i].Name] = histograms[i].Value.Float64Histogram().Buckets + } + + // Generate a collector for each exposed runtime/metrics metric. + metricSet := make([]collectorMetric, 0, len(exposedDescriptions)) + // SampleBuf is used for reading from runtime/metrics. + // We are assuming the largest case to have stable pointers for sampleMap purposes. + sampleBuf := make([]metrics.Sample, 0, len(exposedDescriptions)+len(opt.RuntimeMetricSumForHist)+len(rmNamesForMemStatsMetrics)) + sampleMap := make(map[string]*metrics.Sample, len(exposedDescriptions)) + for _, d := range exposedDescriptions { + namespace, subsystem, name, ok := internal.RuntimeMetricsToProm(&d.Description) + if !ok { + // Just ignore this metric; we can't do anything with it here. + // If a user decides to use the latest version of Go, we don't want + // to fail here. This condition is tested in TestExpectedRuntimeMetrics. + continue + } + + sampleBuf = append(sampleBuf, metrics.Sample{Name: d.Name}) + sampleMap[d.Name] = &sampleBuf[len(sampleBuf)-1] + + var m collectorMetric + if d.Kind == metrics.KindFloat64Histogram { + _, hasSum := opt.RuntimeMetricSumForHist[d.Name] + unit := d.Name[strings.IndexRune(d.Name, ':')+1:] + m = newBatchHistogram( + NewDesc( + BuildFQName(namespace, subsystem, name), + d.Description.Description, + nil, + nil, + ), + internal.RuntimeMetricsBucketsForUnit(bucketsMap[d.Name], unit), + hasSum, + ) + } else if d.Cumulative { + m = NewCounter(CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: name, + Help: d.Description.Description, + }, + ) + } else { + m = NewGauge(GaugeOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: name, + Help: d.Description.Description, + }) + } + metricSet = append(metricSet, m) + } + + // Add exact sum metrics to sampleBuf if not added before. + for _, h := range histograms { + sumMetric, ok := opt.RuntimeMetricSumForHist[h.Name] + if !ok { + continue + } + + if _, ok := sampleMap[sumMetric]; ok { + continue + } + sampleBuf = append(sampleBuf, metrics.Sample{Name: sumMetric}) + sampleMap[sumMetric] = &sampleBuf[len(sampleBuf)-1] + } + + var ( + msMetrics memStatsMetrics + msDescriptions []metrics.Description + ) + + if !opt.DisableMemStatsLikeMetrics { + msMetrics = goRuntimeMemStats() + msDescriptions = bestEffortLookupRM(rmNamesForMemStatsMetrics) + + // Check if metric was not exposed before and if not, add to sampleBuf. + for _, mdDesc := range msDescriptions { + if _, ok := sampleMap[mdDesc.Name]; ok { + continue + } + sampleBuf = append(sampleBuf, metrics.Sample{Name: mdDesc.Name}) + sampleMap[mdDesc.Name] = &sampleBuf[len(sampleBuf)-1] + } + } + + return &goCollector{ + base: newBaseGoCollector(), + sampleBuf: sampleBuf, + sampleMap: sampleMap, + rmExposedMetrics: metricSet, + rmExactSumMapForHist: opt.RuntimeMetricSumForHist, + msMetrics: msMetrics, + msMetricsEnabled: !opt.DisableMemStatsLikeMetrics, + } +} + +// Describe returns all descriptions of the collector. +func (c *goCollector) Describe(ch chan<- *Desc) { + c.base.Describe(ch) + for _, i := range c.msMetrics { + ch <- i.desc + } + for _, m := range c.rmExposedMetrics { + ch <- m.Desc() + } +} + +// Collect returns the current state of all metrics of the collector. +func (c *goCollector) Collect(ch chan<- Metric) { + // Collect base non-memory metrics. + c.base.Collect(ch) + + if len(c.sampleBuf) == 0 { + return + } + + // Collect must be thread-safe, so prevent concurrent use of + // sampleBuf elements. Just read into sampleBuf but write all the data + // we get into our Metrics or MemStats. + // + // This lock also ensures that the Metrics we send out are all from + // the same updates, ensuring their mutual consistency insofar as + // is guaranteed by the runtime/metrics package. + // + // N.B. This locking is heavy-handed, but Collect is expected to be called + // relatively infrequently. Also the core operation here, metrics.Read, + // is fast (O(tens of microseconds)) so contention should certainly be + // low, though channel operations and any allocations may add to that. + c.mu.Lock() + defer c.mu.Unlock() + + // Populate runtime/metrics sample buffer. + metrics.Read(c.sampleBuf) + + // Collect all our runtime/metrics user chose to expose from sampleBuf (if any). + for i, metric := range c.rmExposedMetrics { + // We created samples for exposed metrics first in order, so indexes match. + sample := c.sampleBuf[i] + + // N.B. switch on concrete type because it's significantly more efficient + // than checking for the Counter and Gauge interface implementations. In + // this case, we control all the types here. + switch m := metric.(type) { + case *counter: + // Guard against decreases. This should never happen, but a failure + // to do so will result in a panic, which is a harsh consequence for + // a metrics collection bug. + v0, v1 := m.get(), unwrapScalarRMValue(sample.Value) + if v1 > v0 { + m.Add(unwrapScalarRMValue(sample.Value) - m.get()) + } + m.Collect(ch) + case *gauge: + m.Set(unwrapScalarRMValue(sample.Value)) + m.Collect(ch) + case *batchHistogram: + m.update(sample.Value.Float64Histogram(), c.exactSumFor(sample.Name)) + m.Collect(ch) + default: + panic("unexpected metric type") + } + } + + if c.msMetricsEnabled { + // ms is a dummy MemStats that we populate ourselves so that we can + // populate the old metrics from it if goMemStatsCollection is enabled. + var ms runtime.MemStats + memStatsFromRM(&ms, c.sampleMap) + for _, i := range c.msMetrics { + ch <- MustNewConstMetric(i.desc, i.valType, i.eval(&ms)) + } + } +} + +// unwrapScalarRMValue unwraps a runtime/metrics value that is assumed +// to be scalar and returns the equivalent float64 value. Panics if the +// value is not scalar. +func unwrapScalarRMValue(v metrics.Value) float64 { + switch v.Kind() { + case metrics.KindUint64: + return float64(v.Uint64()) + case metrics.KindFloat64: + return v.Float64() + case metrics.KindBad: + // Unsupported metric. + // + // This should never happen because we always populate our metric + // set from the runtime/metrics package. + panic("unexpected unsupported metric") + default: + // Unsupported metric kind. + // + // This should never happen because we check for this during initialization + // and flag and filter metrics whose kinds we don't understand. + panic("unexpected unsupported metric kind") + } +} + +// exactSumFor takes a runtime/metrics metric name (that is assumed to +// be of kind KindFloat64Histogram) and returns its exact sum and whether +// its exact sum exists. +// +// The runtime/metrics API for histograms doesn't currently expose exact +// sums, but some of the other metrics are in fact exact sums of histograms. +func (c *goCollector) exactSumFor(rmName string) float64 { + sumName, ok := c.rmExactSumMapForHist[rmName] + if !ok { + return 0 + } + s, ok := c.sampleMap[sumName] + if !ok { + return 0 + } + return unwrapScalarRMValue(s.Value) +} + +func memStatsFromRM(ms *runtime.MemStats, rm map[string]*metrics.Sample) { + lookupOrZero := func(name string) uint64 { + if s, ok := rm[name]; ok { + return s.Value.Uint64() + } + return 0 + } + + // Currently, MemStats adds tiny alloc count to both Mallocs AND Frees. + // The reason for this is because MemStats couldn't be extended at the time + // but there was a desire to have Mallocs at least be a little more representative, + // while having Mallocs - Frees still represent a live object count. + // Unfortunately, MemStats doesn't actually export a large allocation count, + // so it's impossible to pull this number out directly. + tinyAllocs := lookupOrZero(goGCHeapTinyAllocsObjects) + ms.Mallocs = lookupOrZero(goGCHeapAllocsObjects) + tinyAllocs + ms.Frees = lookupOrZero(goGCHeapFreesObjects) + tinyAllocs + + ms.TotalAlloc = lookupOrZero(goGCHeapAllocsBytes) + ms.Sys = lookupOrZero(goMemoryClassesTotalBytes) + ms.Lookups = 0 // Already always zero. + ms.HeapAlloc = lookupOrZero(goMemoryClassesHeapObjectsBytes) + ms.Alloc = ms.HeapAlloc + ms.HeapInuse = ms.HeapAlloc + lookupOrZero(goMemoryClassesHeapUnusedBytes) + ms.HeapReleased = lookupOrZero(goMemoryClassesHeapReleasedBytes) + ms.HeapIdle = ms.HeapReleased + lookupOrZero(goMemoryClassesHeapFreeBytes) + ms.HeapSys = ms.HeapInuse + ms.HeapIdle + ms.HeapObjects = lookupOrZero(goGCHeapObjects) + ms.StackInuse = lookupOrZero(goMemoryClassesHeapStacksBytes) + ms.StackSys = ms.StackInuse + lookupOrZero(goMemoryClassesOSStacksBytes) + ms.MSpanInuse = lookupOrZero(goMemoryClassesMetadataMSpanInuseBytes) + ms.MSpanSys = ms.MSpanInuse + lookupOrZero(goMemoryClassesMetadataMSPanFreeBytes) + ms.MCacheInuse = lookupOrZero(goMemoryClassesMetadataMCacheInuseBytes) + ms.MCacheSys = ms.MCacheInuse + lookupOrZero(goMemoryClassesMetadataMCacheFreeBytes) + ms.BuckHashSys = lookupOrZero(goMemoryClassesProfilingBucketsBytes) + ms.GCSys = lookupOrZero(goMemoryClassesMetadataOtherBytes) + ms.OtherSys = lookupOrZero(goMemoryClassesOtherBytes) + ms.NextGC = lookupOrZero(goGCHeapGoalBytes) + + // N.B. GCCPUFraction is intentionally omitted. This metric is not useful, + // and often misleading due to the fact that it's an average over the lifetime + // of the process. + // See https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 + // for more details. + ms.GCCPUFraction = 0 +} + +// batchHistogram is a mutable histogram that is updated +// in batches. +type batchHistogram struct { + selfCollector + + // Static fields updated only once. + desc *Desc + hasSum bool + + // Because this histogram operates in batches, it just uses a + // single mutex for everything. updates are always serialized + // but Write calls may operate concurrently with updates. + // Contention between these two sources should be rare. + mu sync.Mutex + buckets []float64 // Inclusive lower bounds, like runtime/metrics. + counts []uint64 + sum float64 // Used if hasSum is true. +} + +// newBatchHistogram creates a new batch histogram value with the given +// Desc, buckets, and whether or not it has an exact sum available. +// +// buckets must always be from the runtime/metrics package, following +// the same conventions. +func newBatchHistogram(desc *Desc, buckets []float64, hasSum bool) *batchHistogram { + // We need to remove -Inf values. runtime/metrics keeps them around. + // But -Inf bucket should not be allowed for prometheus histograms. + if buckets[0] == math.Inf(-1) { + buckets = buckets[1:] + } + h := &batchHistogram{ + desc: desc, + buckets: buckets, + // Because buckets follows runtime/metrics conventions, there's + // 1 more value in the buckets list than there are buckets represented, + // because in runtime/metrics, the bucket values represent *boundaries*, + // and non-Inf boundaries are inclusive lower bounds for that bucket. + counts: make([]uint64, len(buckets)-1), + hasSum: hasSum, + } + h.init(h) + return h +} + +// update updates the batchHistogram from a runtime/metrics histogram. +// +// sum must be provided if the batchHistogram was created to have an exact sum. +// h.buckets must be a strict subset of his.Buckets. +func (h *batchHistogram) update(his *metrics.Float64Histogram, sum float64) { + counts, buckets := his.Counts, his.Buckets + + h.mu.Lock() + defer h.mu.Unlock() + + // Clear buckets. + for i := range h.counts { + h.counts[i] = 0 + } + // Copy and reduce buckets. + var j int + for i, count := range counts { + h.counts[j] += count + if buckets[i+1] == h.buckets[j+1] { + j++ + } + } + if h.hasSum { + h.sum = sum + } +} + +func (h *batchHistogram) Desc() *Desc { + return h.desc +} + +func (h *batchHistogram) Write(out *dto.Metric) error { + h.mu.Lock() + defer h.mu.Unlock() + + sum := float64(0) + if h.hasSum { + sum = h.sum + } + dtoBuckets := make([]*dto.Bucket, 0, len(h.counts)) + totalCount := uint64(0) + for i, count := range h.counts { + totalCount += count + if !h.hasSum { + if count != 0 { + // N.B. This computed sum is an underestimate. + sum += h.buckets[i] * float64(count) + } + } + + // Skip the +Inf bucket, but only for the bucket list. + // It must still count for sum and totalCount. + if math.IsInf(h.buckets[i+1], 1) { + break + } + // Float64Histogram's upper bound is exclusive, so make it inclusive + // by obtaining the next float64 value down, in order. + upperBound := math.Nextafter(h.buckets[i+1], h.buckets[i]) + dtoBuckets = append(dtoBuckets, &dto.Bucket{ + CumulativeCount: proto.Uint64(totalCount), + UpperBound: proto.Float64(upperBound), + }) + } + out.Histogram = &dto.Histogram{ + Bucket: dtoBuckets, + SampleCount: proto.Uint64(totalCount), + SampleSum: proto.Float64(sum), + } + return nil +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index 8425640b3..b5c8bcb39 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go @@ -22,25 +22,222 @@ import ( "sync/atomic" "time" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" ) +// nativeHistogramBounds for the frac of observed values. Only relevant for +// schema > 0. The position in the slice is the schema. (0 is never used, just +// here for convenience of using the schema directly as the index.) +// +// TODO(beorn7): Currently, we do a binary search into these slices. There are +// ways to turn it into a small number of simple array lookups. It probably only +// matters for schema 5 and beyond, but should be investigated. See this comment +// as a starting point: +// https://github.com/open-telemetry/opentelemetry-specification/issues/1776#issuecomment-870164310 +var nativeHistogramBounds = [][]float64{ + // Schema "0": + {0.5}, + // Schema 1: + {0.5, 0.7071067811865475}, + // Schema 2: + {0.5, 0.5946035575013605, 0.7071067811865475, 0.8408964152537144}, + // Schema 3: + { + 0.5, 0.5452538663326288, 0.5946035575013605, 0.6484197773255048, + 0.7071067811865475, 0.7711054127039704, 0.8408964152537144, 0.9170040432046711, + }, + // Schema 4: + { + 0.5, 0.5221368912137069, 0.5452538663326288, 0.5693943173783458, + 0.5946035575013605, 0.620928906036742, 0.6484197773255048, 0.6771277734684463, + 0.7071067811865475, 0.7384130729697496, 0.7711054127039704, 0.805245165974627, + 0.8408964152537144, 0.8781260801866495, 0.9170040432046711, 0.9576032806985735, + }, + // Schema 5: + { + 0.5, 0.5109485743270583, 0.5221368912137069, 0.5335702003384117, + 0.5452538663326288, 0.5571933712979462, 0.5693943173783458, 0.5818624293887887, + 0.5946035575013605, 0.6076236799902344, 0.620928906036742, 0.6345254785958666, + 0.6484197773255048, 0.6626183215798706, 0.6771277734684463, 0.6919549409819159, + 0.7071067811865475, 0.7225904034885232, 0.7384130729697496, 0.7545822137967112, + 0.7711054127039704, 0.7879904225539431, 0.805245165974627, 0.8228777390769823, + 0.8408964152537144, 0.8593096490612387, 0.8781260801866495, 0.8973545375015533, + 0.9170040432046711, 0.9370838170551498, 0.9576032806985735, 0.9785720620876999, + }, + // Schema 6: + { + 0.5, 0.5054446430258502, 0.5109485743270583, 0.5165124395106142, + 0.5221368912137069, 0.5278225891802786, 0.5335702003384117, 0.5393803988785598, + 0.5452538663326288, 0.5511912916539204, 0.5571933712979462, 0.5632608093041209, + 0.5693943173783458, 0.5755946149764913, 0.5818624293887887, 0.5881984958251406, + 0.5946035575013605, 0.6010783657263515, 0.6076236799902344, 0.6142402680534349, + 0.620928906036742, 0.6276903785123455, 0.6345254785958666, 0.6414350080393891, + 0.6484197773255048, 0.6554806057623822, 0.6626183215798706, 0.6698337620266515, + 0.6771277734684463, 0.6845012114872953, 0.6919549409819159, 0.6994898362691555, + 0.7071067811865475, 0.7148066691959849, 0.7225904034885232, 0.7304588970903234, + 0.7384130729697496, 0.7464538641456323, 0.7545822137967112, 0.762799075372269, + 0.7711054127039704, 0.7795022001189185, 0.7879904225539431, 0.7965710756711334, + 0.805245165974627, 0.8140137109286738, 0.8228777390769823, 0.8318382901633681, + 0.8408964152537144, 0.8500531768592616, 0.8593096490612387, 0.8686669176368529, + 0.8781260801866495, 0.8876882462632604, 0.8973545375015533, 0.9071260877501991, + 0.9170040432046711, 0.9269895625416926, 0.9370838170551498, 0.9472879907934827, + 0.9576032806985735, 0.9680308967461471, 0.9785720620876999, 0.9892280131939752, + }, + // Schema 7: + { + 0.5, 0.5027149505564014, 0.5054446430258502, 0.5081891574554764, + 0.5109485743270583, 0.5137229745593818, 0.5165124395106142, 0.5193170509806894, + 0.5221368912137069, 0.5249720429003435, 0.5278225891802786, 0.5306886136446309, + 0.5335702003384117, 0.5364674337629877, 0.5393803988785598, 0.5423091811066545, + 0.5452538663326288, 0.5482145409081883, 0.5511912916539204, 0.5541842058618393, + 0.5571933712979462, 0.5602188762048033, 0.5632608093041209, 0.5663192597993595, + 0.5693943173783458, 0.572486072215902, 0.5755946149764913, 0.5787200368168754, + 0.5818624293887887, 0.585021884841625, 0.5881984958251406, 0.5913923554921704, + 0.5946035575013605, 0.5978321960199137, 0.6010783657263515, 0.6043421618132907, + 0.6076236799902344, 0.6109230164863786, 0.6142402680534349, 0.6175755319684665, + 0.620928906036742, 0.6243004885946023, 0.6276903785123455, 0.6310986751971253, + 0.6345254785958666, 0.637970889198196, 0.6414350080393891, 0.6449179367033329, + 0.6484197773255048, 0.6519406325959679, 0.6554806057623822, 0.659039800633032, + 0.6626183215798706, 0.6662162735415805, 0.6698337620266515, 0.6734708931164728, + 0.6771277734684463, 0.6808045103191123, 0.6845012114872953, 0.688217985377265, + 0.6919549409819159, 0.6957121878859629, 0.6994898362691555, 0.7032879969095076, + 0.7071067811865475, 0.7109463010845827, 0.7148066691959849, 0.718687998724491, + 0.7225904034885232, 0.7265139979245261, 0.7304588970903234, 0.7344252166684908, + 0.7384130729697496, 0.7424225829363761, 0.7464538641456323, 0.7505070348132126, + 0.7545822137967112, 0.7586795205991071, 0.762799075372269, 0.7669409989204777, + 0.7711054127039704, 0.7752924388424999, 0.7795022001189185, 0.7837348199827764, + 0.7879904225539431, 0.7922691326262467, 0.7965710756711334, 0.8008963778413465, + 0.805245165974627, 0.8096175675974316, 0.8140137109286738, 0.8184337248834821, + 0.8228777390769823, 0.8273458838280969, 0.8318382901633681, 0.8363550898207981, + 0.8408964152537144, 0.8454623996346523, 0.8500531768592616, 0.8546688815502312, + 0.8593096490612387, 0.8639756154809185, 0.8686669176368529, 0.8733836930995842, + 0.8781260801866495, 0.8828942179666361, 0.8876882462632604, 0.8925083056594671, + 0.8973545375015533, 0.9022270839033115, 0.9071260877501991, 0.9120516927035263, + 0.9170040432046711, 0.9219832844793128, 0.9269895625416926, 0.9320230241988943, + 0.9370838170551498, 0.9421720895161669, 0.9472879907934827, 0.9524316709088368, + 0.9576032806985735, 0.9628029718180622, 0.9680308967461471, 0.9732872087896164, + 0.9785720620876999, 0.9838856116165875, 0.9892280131939752, 0.9945994234836328, + }, + // Schema 8: + { + 0.5, 0.5013556375251013, 0.5027149505564014, 0.5040779490592088, + 0.5054446430258502, 0.5068150424757447, 0.5081891574554764, 0.509566998038869, + 0.5109485743270583, 0.5123338964485679, 0.5137229745593818, 0.5151158188430205, + 0.5165124395106142, 0.5179128468009786, 0.5193170509806894, 0.520725062344158, + 0.5221368912137069, 0.5235525479396449, 0.5249720429003435, 0.526395386502313, + 0.5278225891802786, 0.5292536613972564, 0.5306886136446309, 0.5321274564422321, + 0.5335702003384117, 0.5350168559101208, 0.5364674337629877, 0.5379219445313954, + 0.5393803988785598, 0.5408428074966075, 0.5423091811066545, 0.5437795304588847, + 0.5452538663326288, 0.5467321995364429, 0.5482145409081883, 0.549700901315111, + 0.5511912916539204, 0.5526857228508706, 0.5541842058618393, 0.5556867516724088, + 0.5571933712979462, 0.5587040757836845, 0.5602188762048033, 0.5617377836665098, + 0.5632608093041209, 0.564787964283144, 0.5663192597993595, 0.5678547070789026, + 0.5693943173783458, 0.5709381019847808, 0.572486072215902, 0.5740382394200894, + 0.5755946149764913, 0.5771552102951081, 0.5787200368168754, 0.5802891060137493, + 0.5818624293887887, 0.5834400184762408, 0.585021884841625, 0.5866080400818185, + 0.5881984958251406, 0.5897932637314379, 0.5913923554921704, 0.5929957828304968, + 0.5946035575013605, 0.5962156912915756, 0.5978321960199137, 0.5994530835371903, + 0.6010783657263515, 0.6027080545025619, 0.6043421618132907, 0.6059806996384005, + 0.6076236799902344, 0.6092711149137041, 0.6109230164863786, 0.6125793968185725, + 0.6142402680534349, 0.6159056423670379, 0.6175755319684665, 0.6192499490999082, + 0.620928906036742, 0.622612415087629, 0.6243004885946023, 0.6259931389331581, + 0.6276903785123455, 0.6293922197748583, 0.6310986751971253, 0.6328097572894031, + 0.6345254785958666, 0.6362458516947014, 0.637970889198196, 0.6397006037528346, + 0.6414350080393891, 0.6431741147730128, 0.6449179367033329, 0.6466664866145447, + 0.6484197773255048, 0.6501778216898253, 0.6519406325959679, 0.6537082229673385, + 0.6554806057623822, 0.6572577939746774, 0.659039800633032, 0.6608266388015788, + 0.6626183215798706, 0.6644148621029772, 0.6662162735415805, 0.6680225691020727, + 0.6698337620266515, 0.6716498655934177, 0.6734708931164728, 0.6752968579460171, + 0.6771277734684463, 0.6789636531064505, 0.6808045103191123, 0.6826503586020058, + 0.6845012114872953, 0.6863570825438342, 0.688217985377265, 0.690083933630119, + 0.6919549409819159, 0.6938310211492645, 0.6957121878859629, 0.6975984549830999, + 0.6994898362691555, 0.7013863456101023, 0.7032879969095076, 0.7051948041086352, + 0.7071067811865475, 0.7090239421602076, 0.7109463010845827, 0.7128738720527471, + 0.7148066691959849, 0.7167447066838943, 0.718687998724491, 0.7206365595643126, + 0.7225904034885232, 0.7245495448210174, 0.7265139979245261, 0.7284837772007218, + 0.7304588970903234, 0.7324393720732029, 0.7344252166684908, 0.7364164454346837, + 0.7384130729697496, 0.7404151139112358, 0.7424225829363761, 0.7444354947621984, + 0.7464538641456323, 0.7484777058836176, 0.7505070348132126, 0.7525418658117031, + 0.7545822137967112, 0.7566280937263048, 0.7586795205991071, 0.7607365094544071, + 0.762799075372269, 0.7648672334736434, 0.7669409989204777, 0.7690203869158282, + 0.7711054127039704, 0.7731960915705107, 0.7752924388424999, 0.7773944698885442, + 0.7795022001189185, 0.7816156449856788, 0.7837348199827764, 0.7858597406461707, + 0.7879904225539431, 0.7901268813264122, 0.7922691326262467, 0.7944171921585818, + 0.7965710756711334, 0.7987307989543135, 0.8008963778413465, 0.8030678282083853, + 0.805245165974627, 0.8074284071024302, 0.8096175675974316, 0.8118126635086642, + 0.8140137109286738, 0.8162207259936375, 0.8184337248834821, 0.820652723822003, + 0.8228777390769823, 0.8251087869603088, 0.8273458838280969, 0.8295890460808079, + 0.8318382901633681, 0.8340936325652911, 0.8363550898207981, 0.8386226785089391, + 0.8408964152537144, 0.8431763167241966, 0.8454623996346523, 0.8477546807446661, + 0.8500531768592616, 0.8523579048290255, 0.8546688815502312, 0.8569861239649629, + 0.8593096490612387, 0.8616394738731368, 0.8639756154809185, 0.8663180910111553, + 0.8686669176368529, 0.871022112577578, 0.8733836930995842, 0.8757516765159389, + 0.8781260801866495, 0.8805069215187917, 0.8828942179666361, 0.8852879870317771, + 0.8876882462632604, 0.890095013257712, 0.8925083056594671, 0.8949281411607002, + 0.8973545375015533, 0.8997875124702672, 0.9022270839033115, 0.9046732696855155, + 0.9071260877501991, 0.909585556079304, 0.9120516927035263, 0.9145245157024483, + 0.9170040432046711, 0.9194902933879467, 0.9219832844793128, 0.9244830347552253, + 0.9269895625416926, 0.92950288621441, 0.9320230241988943, 0.9345499949706191, + 0.9370838170551498, 0.93962450902828, 0.9421720895161669, 0.9447265771954693, + 0.9472879907934827, 0.9498563490882775, 0.9524316709088368, 0.9550139751351947, + 0.9576032806985735, 0.9601996065815236, 0.9628029718180622, 0.9654133954938133, + 0.9680308967461471, 0.9706554947643201, 0.9732872087896164, 0.9759260581154889, + 0.9785720620876999, 0.9812252401044634, 0.9838856116165875, 0.9865531961276168, + 0.9892280131939752, 0.9919100824251095, 0.9945994234836328, 0.9972960560854698, + }, +} + +// The nativeHistogramBounds above can be generated with the code below. +// +// TODO(beorn7): It's tempting to actually use `go generate` to generate the +// code above. However, this could lead to slightly different numbers on +// different architectures. We still need to come to terms if we are fine with +// that, or if we might prefer to specify precise numbers in the standard. +// +// var nativeHistogramBounds [][]float64 = make([][]float64, 9) +// +// func init() { +// // Populate nativeHistogramBounds. +// numBuckets := 1 +// for i := range nativeHistogramBounds { +// bounds := []float64{0.5} +// factor := math.Exp2(math.Exp2(float64(-i))) +// for j := 0; j < numBuckets-1; j++ { +// var bound float64 +// if (j+1)%2 == 0 { +// // Use previously calculated value for increased precision. +// bound = nativeHistogramBounds[i-1][j/2+1] +// } else { +// bound = bounds[j] * factor +// } +// bounds = append(bounds, bound) +// } +// numBuckets *= 2 +// nativeHistogramBounds[i] = bounds +// } +// } + // A Histogram counts individual observations from an event or sample stream in -// configurable buckets. Similar to a summary, it also provides a sum of -// observations and an observation count. +// configurable static buckets (or in dynamic sparse buckets as part of the +// experimental Native Histograms, see below for more details). Similar to a +// Summary, it also provides a sum of observations and an observation count. // // On the Prometheus server, quantiles can be calculated from a Histogram using -// the histogram_quantile function in the query language. +// the histogram_quantile PromQL function. // -// Note that Histograms, in contrast to Summaries, can be aggregated with the -// Prometheus query language (see the documentation for detailed -// procedures). However, Histograms require the user to pre-define suitable -// buckets, and they are in general less accurate. The Observe method of a -// Histogram has a very low performance overhead in comparison with the Observe -// method of a Summary. +// Note that Histograms, in contrast to Summaries, can be aggregated in PromQL +// (see the documentation for detailed procedures). However, Histograms require +// the user to pre-define suitable buckets, and they are in general less +// accurate. (Both problems are addressed by the experimental Native +// Histograms. To use them, configure a NativeHistogramBucketFactor in the +// HistogramOpts. They also require a Prometheus server v2.40+ with the +// corresponding feature flag enabled.) +// +// The Observe method of a Histogram has a very low performance overhead in +// comparison with the Observe method of a Summary. // // To create Histogram instances, use NewHistogram. type Histogram interface { @@ -50,7 +247,8 @@ type Histogram interface { // Observe adds a single observation to the histogram. Observations are // usually positive or zero. Negative observations are accepted but // prevent current versions of Prometheus from properly detecting - // counter resets in the sum of observations. See + // counter resets in the sum of observations. (The experimental Native + // Histograms handle negative observations properly.) See // https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations // for details. Observe(float64) @@ -64,18 +262,28 @@ const bucketLabel = "le" // tailored to broadly measure the response time (in seconds) of a network // service. Most likely, however, you will be required to define buckets // customized to your use case. -var ( - DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} +var DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} - errBucketLabelNotAllowed = fmt.Errorf( - "%q is not allowed as label name in histograms", bucketLabel, - ) +// DefNativeHistogramZeroThreshold is the default value for +// NativeHistogramZeroThreshold in the HistogramOpts. +// +// The value is 2^-128 (or 0.5*2^-127 in the actual IEEE 754 representation), +// which is a bucket boundary at all possible resolutions. +const DefNativeHistogramZeroThreshold = 2.938735877055719e-39 + +// NativeHistogramZeroThresholdZero can be used as NativeHistogramZeroThreshold +// in the HistogramOpts to create a zero bucket of width zero, i.e. a zero +// bucket that only receives observations of precisely zero. +const NativeHistogramZeroThresholdZero = -1 + +var errBucketLabelNotAllowed = fmt.Errorf( + "%q is not allowed as label name in histograms", bucketLabel, ) -// LinearBuckets creates 'count' buckets, each 'width' wide, where the lowest -// bucket has an upper bound of 'start'. The final +Inf bucket is not counted -// and not included in the returned slice. The returned slice is meant to be -// used for the Buckets field of HistogramOpts. +// LinearBuckets creates 'count' regular buckets, each 'width' wide, where the +// lowest bucket has an upper bound of 'start'. The final +Inf bucket is not +// counted and not included in the returned slice. The returned slice is meant +// to be used for the Buckets field of HistogramOpts. // // The function panics if 'count' is zero or negative. func LinearBuckets(start, width float64, count int) []float64 { @@ -90,11 +298,11 @@ func LinearBuckets(start, width float64, count int) []float64 { return buckets } -// ExponentialBuckets creates 'count' buckets, where the lowest bucket has an -// upper bound of 'start' and each following bucket's upper bound is 'factor' -// times the previous bucket's upper bound. The final +Inf bucket is not counted -// and not included in the returned slice. The returned slice is meant to be -// used for the Buckets field of HistogramOpts. +// ExponentialBuckets creates 'count' regular buckets, where the lowest bucket +// has an upper bound of 'start' and each following bucket's upper bound is +// 'factor' times the previous bucket's upper bound. The final +Inf bucket is +// not counted and not included in the returned slice. The returned slice is +// meant to be used for the Buckets field of HistogramOpts. // // The function panics if 'count' is 0 or negative, if 'start' is 0 or negative, // or if 'factor' is less than or equal 1. @@ -116,6 +324,34 @@ func ExponentialBuckets(start, factor float64, count int) []float64 { return buckets } +// ExponentialBucketsRange creates 'count' buckets, where the lowest bucket is +// 'min' and the highest bucket is 'max'. The final +Inf bucket is not counted +// and not included in the returned slice. The returned slice is meant to be +// used for the Buckets field of HistogramOpts. +// +// The function panics if 'count' is 0 or negative, if 'min' is 0 or negative. +func ExponentialBucketsRange(min, max float64, count int) []float64 { + if count < 1 { + panic("ExponentialBucketsRange count needs a positive count") + } + if min <= 0 { + panic("ExponentialBucketsRange min needs to be greater than 0") + } + + // Formula for exponential buckets. + // max = min*growthFactor^(bucketCount-1) + + // We know max/min and highest bucket. Solve for growthFactor. + growthFactor := math.Pow(max/min, 1.0/float64(count-1)) + + // Now that we know growthFactor, solve for each bucket. + buckets := make([]float64, count) + for i := 1; i <= count; i++ { + buckets[i-1] = min * math.Pow(growthFactor, float64(i-1)) + } + return buckets +} + // HistogramOpts bundles the options for creating a Histogram metric. It is // mandatory to set Name to a non-empty string. All other fields are optional // and can safely be left at their zero value, although it is strongly @@ -152,8 +388,108 @@ type HistogramOpts struct { // element in the slice is the upper inclusive bound of a bucket. The // values must be sorted in strictly increasing order. There is no need // to add a highest bucket with +Inf bound, it will be added - // implicitly. The default value is DefBuckets. + // implicitly. If Buckets is left as nil or set to a slice of length + // zero, it is replaced by default buckets. The default buckets are + // DefBuckets if no buckets for a native histogram (see below) are used, + // otherwise the default is no buckets. (In other words, if you want to + // use both regular buckets and buckets for a native histogram, you have + // to define the regular buckets here explicitly.) Buckets []float64 + + // If NativeHistogramBucketFactor is greater than one, so-called sparse + // buckets are used (in addition to the regular buckets, if defined + // above). A Histogram with sparse buckets will be ingested as a Native + // Histogram by a Prometheus server with that feature enabled (requires + // Prometheus v2.40+). Sparse buckets are exponential buckets covering + // the whole float64 range (with the exception of the “zero” bucket, see + // NativeHistogramZeroThreshold below). From any one bucket to the next, + // the width of the bucket grows by a constant + // factor. NativeHistogramBucketFactor provides an upper bound for this + // factor (exception see below). The smaller + // NativeHistogramBucketFactor, the more buckets will be used and thus + // the more costly the histogram will become. A generally good trade-off + // between cost and accuracy is a value of 1.1 (each bucket is at most + // 10% wider than the previous one), which will result in each power of + // two divided into 8 buckets (e.g. there will be 8 buckets between 1 + // and 2, same as between 2 and 4, and 4 and 8, etc.). + // + // Details about the actually used factor: The factor is calculated as + // 2^(2^-n), where n is an integer number between (and including) -4 and + // 8. n is chosen so that the resulting factor is the largest that is + // still smaller or equal to NativeHistogramBucketFactor. Note that the + // smallest possible factor is therefore approx. 1.00271 (i.e. 2^(2^-8) + // ). If NativeHistogramBucketFactor is greater than 1 but smaller than + // 2^(2^-8), then the actually used factor is still 2^(2^-8) even though + // it is larger than the provided NativeHistogramBucketFactor. + // + // NOTE: Native Histograms are still an experimental feature. Their + // behavior might still change without a major version + // bump. Subsequently, all NativeHistogram... options here might still + // change their behavior or name (or might completely disappear) without + // a major version bump. + NativeHistogramBucketFactor float64 + // All observations with an absolute value of less or equal + // NativeHistogramZeroThreshold are accumulated into a “zero” bucket. + // For best results, this should be close to a bucket boundary. This is + // usually the case if picking a power of two. If + // NativeHistogramZeroThreshold is left at zero, + // DefNativeHistogramZeroThreshold is used as the threshold. To + // configure a zero bucket with an actual threshold of zero (i.e. only + // observations of precisely zero will go into the zero bucket), set + // NativeHistogramZeroThreshold to the NativeHistogramZeroThresholdZero + // constant (or any negative float value). + NativeHistogramZeroThreshold float64 + + // The remaining fields define a strategy to limit the number of + // populated sparse buckets. If NativeHistogramMaxBucketNumber is left + // at zero, the number of buckets is not limited. (Note that this might + // lead to unbounded memory consumption if the values observed by the + // Histogram are sufficiently wide-spread. In particular, this could be + // used as a DoS attack vector. Where the observed values depend on + // external inputs, it is highly recommended to set a + // NativeHistogramMaxBucketNumber.) Once the set + // NativeHistogramMaxBucketNumber is exceeded, the following strategy is + // enacted: + // - First, if the last reset (or the creation) of the histogram is at + // least NativeHistogramMinResetDuration ago, then the whole + // histogram is reset to its initial state (including regular + // buckets). + // - If less time has passed, or if NativeHistogramMinResetDuration is + // zero, no reset is performed. Instead, the zero threshold is + // increased sufficiently to reduce the number of buckets to or below + // NativeHistogramMaxBucketNumber, but not to more than + // NativeHistogramMaxZeroThreshold. Thus, if + // NativeHistogramMaxZeroThreshold is already at or below the current + // zero threshold, nothing happens at this step. + // - After that, if the number of buckets still exceeds + // NativeHistogramMaxBucketNumber, the resolution of the histogram is + // reduced by doubling the width of the sparse buckets (up to a + // growth factor between one bucket to the next of 2^(2^4) = 65536, + // see above). + // - Any increased zero threshold or reduced resolution is reset back + // to their original values once NativeHistogramMinResetDuration has + // passed (since the last reset or the creation of the histogram). + NativeHistogramMaxBucketNumber uint32 + NativeHistogramMinResetDuration time.Duration + NativeHistogramMaxZeroThreshold float64 + + // now is for testing purposes, by default it's time.Now. + now func() time.Time + + // afterFunc is for testing purposes, by default it's time.AfterFunc. + afterFunc func(time.Duration, func()) *time.Timer +} + +// HistogramVecOpts bundles the options to create a HistogramVec metric. +// It is mandatory to set HistogramOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type HistogramVecOpts struct { + HistogramOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Constraint + // function, if provided. + VariableLabels ConstrainableLabels } // NewHistogram creates a new Histogram based on the provided HistogramOpts. It @@ -175,11 +511,11 @@ func NewHistogram(opts HistogramOpts) Histogram { } func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram { - if len(desc.variableLabels) != len(labelValues) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) + if len(desc.variableLabels.names) != len(labelValues) { + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, labelValues)) } - for _, n := range desc.variableLabels { + for _, n := range desc.variableLabels.names { if n == bucketLabel { panic(errBucketLabelNotAllowed) } @@ -190,16 +526,36 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr } } - if len(opts.Buckets) == 0 { - opts.Buckets = DefBuckets + if opts.now == nil { + opts.now = time.Now + } + if opts.afterFunc == nil { + opts.afterFunc = time.AfterFunc } - h := &histogram{ - desc: desc, - upperBounds: opts.Buckets, - labelPairs: MakeLabelPairs(desc, labelValues), - counts: [2]*histogramCounts{{}, {}}, - now: time.Now, + desc: desc, + upperBounds: opts.Buckets, + labelPairs: MakeLabelPairs(desc, labelValues), + nativeHistogramMaxBuckets: opts.NativeHistogramMaxBucketNumber, + nativeHistogramMaxZeroThreshold: opts.NativeHistogramMaxZeroThreshold, + nativeHistogramMinResetDuration: opts.NativeHistogramMinResetDuration, + lastResetTime: opts.now(), + now: opts.now, + afterFunc: opts.afterFunc, + } + if len(h.upperBounds) == 0 && opts.NativeHistogramBucketFactor <= 1 { + h.upperBounds = DefBuckets + } + if opts.NativeHistogramBucketFactor <= 1 { + h.nativeHistogramSchema = math.MinInt32 // To mark that there are no sparse buckets. + } else { + switch { + case opts.NativeHistogramZeroThreshold > 0: + h.nativeHistogramZeroThreshold = opts.NativeHistogramZeroThreshold + case opts.NativeHistogramZeroThreshold == 0: + h.nativeHistogramZeroThreshold = DefNativeHistogramZeroThreshold + } // Leave h.nativeHistogramZeroThreshold at 0 otherwise. + h.nativeHistogramSchema = pickSchema(opts.NativeHistogramBucketFactor) } for i, upperBound := range h.upperBounds { if i < len(h.upperBounds)-1 { @@ -218,8 +574,12 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr } // Finally we know the final length of h.upperBounds and can make buckets // for both counts as well as exemplars: - h.counts[0].buckets = make([]uint64, len(h.upperBounds)) - h.counts[1].buckets = make([]uint64, len(h.upperBounds)) + h.counts[0] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))} + atomic.StoreUint64(&h.counts[0].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) + atomic.StoreInt32(&h.counts[0].nativeHistogramSchema, h.nativeHistogramSchema) + h.counts[1] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))} + atomic.StoreUint64(&h.counts[1].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) + atomic.StoreInt32(&h.counts[1].nativeHistogramSchema, h.nativeHistogramSchema) h.exemplars = make([]atomic.Value, len(h.upperBounds)+1) h.init(h) // Init self-collection. @@ -227,13 +587,98 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr } type histogramCounts struct { + // Order in this struct matters for the alignment required by atomic + // operations, see http://golang.org/pkg/sync/atomic/#pkg-note-BUG + // sumBits contains the bits of the float64 representing the sum of all - // observations. sumBits and count have to go first in the struct to - // guarantee alignment for atomic operations. - // http://golang.org/pkg/sync/atomic/#pkg-note-BUG + // observations. sumBits uint64 count uint64 + + // nativeHistogramZeroBucket counts all (positive and negative) + // observations in the zero bucket (with an absolute value less or equal + // the current threshold, see next field. + nativeHistogramZeroBucket uint64 + // nativeHistogramZeroThresholdBits is the bit pattern of the current + // threshold for the zero bucket. It's initially equal to + // nativeHistogramZeroThreshold but may change according to the bucket + // count limitation strategy. + nativeHistogramZeroThresholdBits uint64 + // nativeHistogramSchema may change over time according to the bucket + // count limitation strategy and therefore has to be saved here. + nativeHistogramSchema int32 + // Number of (positive and negative) sparse buckets. + nativeHistogramBucketsNumber uint32 + + // Regular buckets. buckets []uint64 + + // The sparse buckets for native histograms are implemented with a + // sync.Map for now. A dedicated data structure will likely be more + // efficient. There are separate maps for negative and positive + // observations. The map's value is an *int64, counting observations in + // that bucket. (Note that we don't use uint64 as an int64 won't + // overflow in practice, and working with signed numbers from the + // beginning simplifies the handling of deltas.) The map's key is the + // index of the bucket according to the used + // nativeHistogramSchema. Index 0 is for an upper bound of 1. + nativeHistogramBucketsPositive, nativeHistogramBucketsNegative sync.Map +} + +// observe manages the parts of observe that only affects +// histogramCounts. doSparse is true if sparse buckets should be done, +// too. +func (hc *histogramCounts) observe(v float64, bucket int, doSparse bool) { + if bucket < len(hc.buckets) { + atomic.AddUint64(&hc.buckets[bucket], 1) + } + atomicAddFloat(&hc.sumBits, v) + if doSparse && !math.IsNaN(v) { + var ( + key int + schema = atomic.LoadInt32(&hc.nativeHistogramSchema) + zeroThreshold = math.Float64frombits(atomic.LoadUint64(&hc.nativeHistogramZeroThresholdBits)) + bucketCreated, isInf bool + ) + if math.IsInf(v, 0) { + // Pretend v is MaxFloat64 but later increment key by one. + if math.IsInf(v, +1) { + v = math.MaxFloat64 + } else { + v = -math.MaxFloat64 + } + isInf = true + } + frac, exp := math.Frexp(math.Abs(v)) + if schema > 0 { + bounds := nativeHistogramBounds[schema] + key = sort.SearchFloat64s(bounds, frac) + (exp-1)*len(bounds) + } else { + key = exp + if frac == 0.5 { + key-- + } + offset := (1 << -schema) - 1 + key = (key + offset) >> -schema + } + if isInf { + key++ + } + switch { + case v > zeroThreshold: + bucketCreated = addToBucket(&hc.nativeHistogramBucketsPositive, key, 1) + case v < -zeroThreshold: + bucketCreated = addToBucket(&hc.nativeHistogramBucketsNegative, key, 1) + default: + atomic.AddUint64(&hc.nativeHistogramZeroBucket, 1) + } + if bucketCreated { + atomic.AddUint32(&hc.nativeHistogramBucketsNumber, 1) + } + } + // Increment count last as we take it as a signal that the observation + // is complete. + atomic.AddUint64(&hc.count, 1) } type histogram struct { @@ -248,7 +693,7 @@ type histogram struct { // perspective of the histogram) swap the hot–cold under the writeMtx // lock. A cooldown is awaited (while locked) by comparing the number of // observations with the initiation count. Once they match, then the - // last observation on the now cool one has completed. All cool fields must + // last observation on the now cool one has completed. All cold fields must // be merged into the new hot before releasing writeMtx. // // Fields with atomic access first! See alignment constraint: @@ -256,8 +701,10 @@ type histogram struct { countAndHotIdx uint64 selfCollector - desc *Desc - writeMtx sync.Mutex // Only used in the Write method. + desc *Desc + + // Only used in the Write method and for sparse bucket management. + mtx sync.Mutex // Two counts, one is "hot" for lock-free observations, the other is // "cold" for writing out a dto.Metric. It has to be an array of @@ -265,11 +712,26 @@ type histogram struct { // http://golang.org/pkg/sync/atomic/#pkg-note-BUG. counts [2]*histogramCounts - upperBounds []float64 - labelPairs []*dto.LabelPair - exemplars []atomic.Value // One more than buckets (to include +Inf), each a *dto.Exemplar. + upperBounds []float64 + labelPairs []*dto.LabelPair + exemplars []atomic.Value // One more than buckets (to include +Inf), each a *dto.Exemplar. + nativeHistogramSchema int32 // The initial schema. Set to math.MinInt32 if no sparse buckets are used. + nativeHistogramZeroThreshold float64 // The initial zero threshold. + nativeHistogramMaxZeroThreshold float64 + nativeHistogramMaxBuckets uint32 + nativeHistogramMinResetDuration time.Duration + // lastResetTime is protected by mtx. It is also used as created timestamp. + lastResetTime time.Time + // resetScheduled is protected by mtx. It is true if a reset is + // scheduled for a later time (when nativeHistogramMinResetDuration has + // passed). + resetScheduled bool + + // now is for testing purposes, by default it's time.Now. + now func() time.Time - now func() time.Time // To mock out time.Now() for testing. + // afterFunc is for testing purposes, by default it's time.AfterFunc. + afterFunc func(time.Duration, func()) *time.Timer } func (h *histogram) Desc() *Desc { @@ -291,8 +753,8 @@ func (h *histogram) Write(out *dto.Metric) error { // the hot path, i.e. Observe is called much more often than Write. The // complication of making Write lock-free isn't worth it, if possible at // all. - h.writeMtx.Lock() - defer h.writeMtx.Unlock() + h.mtx.Lock() + defer h.mtx.Unlock() // Adding 1<<63 switches the hot index (from 0 to 1 or from 1 to 0) // without touching the count bits. See the struct comments for a full @@ -305,16 +767,17 @@ func (h *histogram) Write(out *dto.Metric) error { hotCounts := h.counts[n>>63] coldCounts := h.counts[(^n)>>63] - // Await cooldown. - for count != atomic.LoadUint64(&coldCounts.count) { - runtime.Gosched() // Let observations get work done. - } + waitForCooldown(count, coldCounts) his := &dto.Histogram{ - Bucket: make([]*dto.Bucket, len(h.upperBounds)), - SampleCount: proto.Uint64(count), - SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), + Bucket: make([]*dto.Bucket, len(h.upperBounds)), + SampleCount: proto.Uint64(count), + SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), + CreatedTimestamp: timestamppb.New(h.lastResetTime), } + out.Histogram = his + out.Label = h.labelPairs + var cumCount uint64 for i, upperBound := range h.upperBounds { cumCount += atomic.LoadUint64(&coldCounts.buckets[i]) @@ -335,25 +798,31 @@ func (h *histogram) Write(out *dto.Metric) error { } his.Bucket = append(his.Bucket, b) } + if h.nativeHistogramSchema > math.MinInt32 { + his.ZeroThreshold = proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.nativeHistogramZeroThresholdBits))) + his.Schema = proto.Int32(atomic.LoadInt32(&coldCounts.nativeHistogramSchema)) + zeroBucket := atomic.LoadUint64(&coldCounts.nativeHistogramZeroBucket) - out.Histogram = his - out.Label = h.labelPairs + defer func() { + coldCounts.nativeHistogramBucketsPositive.Range(addAndReset(&hotCounts.nativeHistogramBucketsPositive, &hotCounts.nativeHistogramBucketsNumber)) + coldCounts.nativeHistogramBucketsNegative.Range(addAndReset(&hotCounts.nativeHistogramBucketsNegative, &hotCounts.nativeHistogramBucketsNumber)) + }() - // Finally add all the cold counts to the new hot counts and reset the cold counts. - atomic.AddUint64(&hotCounts.count, count) - atomic.StoreUint64(&coldCounts.count, 0) - for { - oldBits := atomic.LoadUint64(&hotCounts.sumBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + his.GetSampleSum()) - if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { - atomic.StoreUint64(&coldCounts.sumBits, 0) - break + his.ZeroCount = proto.Uint64(zeroBucket) + his.NegativeSpan, his.NegativeDelta = makeBuckets(&coldCounts.nativeHistogramBucketsNegative) + his.PositiveSpan, his.PositiveDelta = makeBuckets(&coldCounts.nativeHistogramBucketsPositive) + + // Add a no-op span to a histogram without observations and with + // a zero threshold of zero. Otherwise, a native histogram would + // look like a classic histogram to scrapers. + if *his.ZeroThreshold == 0 && *his.ZeroCount == 0 && len(his.PositiveSpan) == 0 && len(his.NegativeSpan) == 0 { + his.PositiveSpan = []*dto.BucketSpan{{ + Offset: proto.Int32(0), + Length: proto.Uint32(0), + }} } } - for i := range h.upperBounds { - atomic.AddUint64(&hotCounts.buckets[i], atomic.LoadUint64(&coldCounts.buckets[i])) - atomic.StoreUint64(&coldCounts.buckets[i], 0) - } + addAndResetCounts(hotCounts, coldCounts) return nil } @@ -374,25 +843,252 @@ func (h *histogram) findBucket(v float64) int { // observe is the implementation for Observe without the findBucket part. func (h *histogram) observe(v float64, bucket int) { + // Do not add to sparse buckets for NaN observations. + doSparse := h.nativeHistogramSchema > math.MinInt32 && !math.IsNaN(v) // We increment h.countAndHotIdx so that the counter in the lower // 63 bits gets incremented. At the same time, we get the new value // back, which we can use to find the currently-hot counts. n := atomic.AddUint64(&h.countAndHotIdx, 1) hotCounts := h.counts[n>>63] + hotCounts.observe(v, bucket, doSparse) + if doSparse { + h.limitBuckets(hotCounts, v, bucket) + } +} - if bucket < len(h.upperBounds) { - atomic.AddUint64(&hotCounts.buckets[bucket], 1) +// limitBuckets applies a strategy to limit the number of populated sparse +// buckets. It's generally best effort, and there are situations where the +// number can go higher (if even the lowest resolution isn't enough to reduce +// the number sufficiently, or if the provided counts aren't fully updated yet +// by a concurrently happening Write call). +func (h *histogram) limitBuckets(counts *histogramCounts, value float64, bucket int) { + if h.nativeHistogramMaxBuckets == 0 { + return // No limit configured. } - for { - oldBits := atomic.LoadUint64(&hotCounts.sumBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + v) - if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { - break + if h.nativeHistogramMaxBuckets >= atomic.LoadUint32(&counts.nativeHistogramBucketsNumber) { + return // Bucket limit not exceeded yet. + } + + h.mtx.Lock() + defer h.mtx.Unlock() + + // The hot counts might have been swapped just before we acquired the + // lock. Re-fetch the hot counts first... + n := atomic.LoadUint64(&h.countAndHotIdx) + hotIdx := n >> 63 + coldIdx := (^n) >> 63 + hotCounts := h.counts[hotIdx] + coldCounts := h.counts[coldIdx] + // ...and then check again if we really have to reduce the bucket count. + if h.nativeHistogramMaxBuckets >= atomic.LoadUint32(&hotCounts.nativeHistogramBucketsNumber) { + return // Bucket limit not exceeded after all. + } + // Try the various strategies in order. + if h.maybeReset(hotCounts, coldCounts, coldIdx, value, bucket) { + return + } + // One of the other strategies will happen. To undo what they will do as + // soon as enough time has passed to satisfy + // h.nativeHistogramMinResetDuration, schedule a reset at the right time + // if we haven't done so already. + if h.nativeHistogramMinResetDuration > 0 && !h.resetScheduled { + h.resetScheduled = true + h.afterFunc(h.nativeHistogramMinResetDuration-h.now().Sub(h.lastResetTime), h.reset) + } + + if h.maybeWidenZeroBucket(hotCounts, coldCounts) { + return + } + h.doubleBucketWidth(hotCounts, coldCounts) +} + +// maybeReset resets the whole histogram if at least +// h.nativeHistogramMinResetDuration has been passed. It returns true if the +// histogram has been reset. The caller must have locked h.mtx. +func (h *histogram) maybeReset( + hot, cold *histogramCounts, coldIdx uint64, value float64, bucket int, +) bool { + // We are using the possibly mocked h.now() rather than + // time.Since(h.lastResetTime) to enable testing. + if h.nativeHistogramMinResetDuration == 0 || // No reset configured. + h.resetScheduled || // Do not interefere if a reset is already scheduled. + h.now().Sub(h.lastResetTime) < h.nativeHistogramMinResetDuration { + return false + } + // Completely reset coldCounts. + h.resetCounts(cold) + // Repeat the latest observation to not lose it completely. + cold.observe(value, bucket, true) + // Make coldCounts the new hot counts while resetting countAndHotIdx. + n := atomic.SwapUint64(&h.countAndHotIdx, (coldIdx<<63)+1) + count := n & ((1 << 63) - 1) + waitForCooldown(count, hot) + // Finally, reset the formerly hot counts, too. + h.resetCounts(hot) + h.lastResetTime = h.now() + return true +} + +// reset resets the whole histogram. It locks h.mtx itself, i.e. it has to be +// called without having locked h.mtx. +func (h *histogram) reset() { + h.mtx.Lock() + defer h.mtx.Unlock() + + n := atomic.LoadUint64(&h.countAndHotIdx) + hotIdx := n >> 63 + coldIdx := (^n) >> 63 + hot := h.counts[hotIdx] + cold := h.counts[coldIdx] + // Completely reset coldCounts. + h.resetCounts(cold) + // Make coldCounts the new hot counts while resetting countAndHotIdx. + n = atomic.SwapUint64(&h.countAndHotIdx, coldIdx<<63) + count := n & ((1 << 63) - 1) + waitForCooldown(count, hot) + // Finally, reset the formerly hot counts, too. + h.resetCounts(hot) + h.lastResetTime = h.now() + h.resetScheduled = false +} + +// maybeWidenZeroBucket widens the zero bucket until it includes the existing +// buckets closest to the zero bucket (which could be two, if an equidistant +// negative and a positive bucket exists, but usually it's only one bucket to be +// merged into the new wider zero bucket). h.nativeHistogramMaxZeroThreshold +// limits how far the zero bucket can be extended, and if that's not enough to +// include an existing bucket, the method returns false. The caller must have +// locked h.mtx. +func (h *histogram) maybeWidenZeroBucket(hot, cold *histogramCounts) bool { + currentZeroThreshold := math.Float64frombits(atomic.LoadUint64(&hot.nativeHistogramZeroThresholdBits)) + if currentZeroThreshold >= h.nativeHistogramMaxZeroThreshold { + return false + } + // Find the key of the bucket closest to zero. + smallestKey := findSmallestKey(&hot.nativeHistogramBucketsPositive) + smallestNegativeKey := findSmallestKey(&hot.nativeHistogramBucketsNegative) + if smallestNegativeKey < smallestKey { + smallestKey = smallestNegativeKey + } + if smallestKey == math.MaxInt32 { + return false + } + newZeroThreshold := getLe(smallestKey, atomic.LoadInt32(&hot.nativeHistogramSchema)) + if newZeroThreshold > h.nativeHistogramMaxZeroThreshold { + return false // New threshold would exceed the max threshold. + } + atomic.StoreUint64(&cold.nativeHistogramZeroThresholdBits, math.Float64bits(newZeroThreshold)) + // Remove applicable buckets. + if _, loaded := cold.nativeHistogramBucketsNegative.LoadAndDelete(smallestKey); loaded { + atomicDecUint32(&cold.nativeHistogramBucketsNumber) + } + if _, loaded := cold.nativeHistogramBucketsPositive.LoadAndDelete(smallestKey); loaded { + atomicDecUint32(&cold.nativeHistogramBucketsNumber) + } + // Make cold counts the new hot counts. + n := atomic.AddUint64(&h.countAndHotIdx, 1<<63) + count := n & ((1 << 63) - 1) + // Swap the pointer names to represent the new roles and make + // the rest less confusing. + hot, cold = cold, hot + waitForCooldown(count, cold) + // Add all the now cold counts to the new hot counts... + addAndResetCounts(hot, cold) + // ...adjust the new zero threshold in the cold counts, too... + atomic.StoreUint64(&cold.nativeHistogramZeroThresholdBits, math.Float64bits(newZeroThreshold)) + // ...and then merge the newly deleted buckets into the wider zero + // bucket. + mergeAndDeleteOrAddAndReset := func(hotBuckets, coldBuckets *sync.Map) func(k, v interface{}) bool { + return func(k, v interface{}) bool { + key := k.(int) + bucket := v.(*int64) + if key == smallestKey { + // Merge into hot zero bucket... + atomic.AddUint64(&hot.nativeHistogramZeroBucket, uint64(atomic.LoadInt64(bucket))) + // ...and delete from cold counts. + coldBuckets.Delete(key) + atomicDecUint32(&cold.nativeHistogramBucketsNumber) + } else { + // Add to corresponding hot bucket... + if addToBucket(hotBuckets, key, atomic.LoadInt64(bucket)) { + atomic.AddUint32(&hot.nativeHistogramBucketsNumber, 1) + } + // ...and reset cold bucket. + atomic.StoreInt64(bucket, 0) + } + return true } } - // Increment count last as we take it as a signal that the observation - // is complete. - atomic.AddUint64(&hotCounts.count, 1) + + cold.nativeHistogramBucketsPositive.Range(mergeAndDeleteOrAddAndReset(&hot.nativeHistogramBucketsPositive, &cold.nativeHistogramBucketsPositive)) + cold.nativeHistogramBucketsNegative.Range(mergeAndDeleteOrAddAndReset(&hot.nativeHistogramBucketsNegative, &cold.nativeHistogramBucketsNegative)) + return true +} + +// doubleBucketWidth doubles the bucket width (by decrementing the schema +// number). Note that very sparse buckets could lead to a low reduction of the +// bucket count (or even no reduction at all). The method does nothing if the +// schema is already -4. +func (h *histogram) doubleBucketWidth(hot, cold *histogramCounts) { + coldSchema := atomic.LoadInt32(&cold.nativeHistogramSchema) + if coldSchema == -4 { + return // Already at lowest resolution. + } + coldSchema-- + atomic.StoreInt32(&cold.nativeHistogramSchema, coldSchema) + // Play it simple and just delete all cold buckets. + atomic.StoreUint32(&cold.nativeHistogramBucketsNumber, 0) + deleteSyncMap(&cold.nativeHistogramBucketsNegative) + deleteSyncMap(&cold.nativeHistogramBucketsPositive) + // Make coldCounts the new hot counts. + n := atomic.AddUint64(&h.countAndHotIdx, 1<<63) + count := n & ((1 << 63) - 1) + // Swap the pointer names to represent the new roles and make + // the rest less confusing. + hot, cold = cold, hot + waitForCooldown(count, cold) + // Add all the now cold counts to the new hot counts... + addAndResetCounts(hot, cold) + // ...adjust the schema in the cold counts, too... + atomic.StoreInt32(&cold.nativeHistogramSchema, coldSchema) + // ...and then merge the cold buckets into the wider hot buckets. + merge := func(hotBuckets *sync.Map) func(k, v interface{}) bool { + return func(k, v interface{}) bool { + key := k.(int) + bucket := v.(*int64) + // Adjust key to match the bucket to merge into. + if key > 0 { + key++ + } + key /= 2 + // Add to corresponding hot bucket. + if addToBucket(hotBuckets, key, atomic.LoadInt64(bucket)) { + atomic.AddUint32(&hot.nativeHistogramBucketsNumber, 1) + } + return true + } + } + + cold.nativeHistogramBucketsPositive.Range(merge(&hot.nativeHistogramBucketsPositive)) + cold.nativeHistogramBucketsNegative.Range(merge(&hot.nativeHistogramBucketsNegative)) + // Play it simple again and just delete all cold buckets. + atomic.StoreUint32(&cold.nativeHistogramBucketsNumber, 0) + deleteSyncMap(&cold.nativeHistogramBucketsNegative) + deleteSyncMap(&cold.nativeHistogramBucketsPositive) +} + +func (h *histogram) resetCounts(counts *histogramCounts) { + atomic.StoreUint64(&counts.sumBits, 0) + atomic.StoreUint64(&counts.count, 0) + atomic.StoreUint64(&counts.nativeHistogramZeroBucket, 0) + atomic.StoreUint64(&counts.nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) + atomic.StoreInt32(&counts.nativeHistogramSchema, h.nativeHistogramSchema) + atomic.StoreUint32(&counts.nativeHistogramBucketsNumber, 0) + for i := range h.upperBounds { + atomic.StoreUint64(&counts.buckets[i], 0) + } + deleteSyncMap(&counts.nativeHistogramBucketsNegative) + deleteSyncMap(&counts.nativeHistogramBucketsPositive) } // updateExemplar replaces the exemplar for the provided bucket. With empty @@ -420,15 +1116,23 @@ type HistogramVec struct { // NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and // partitioned by the given label names. func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec { - desc := NewDesc( + return V2.NewHistogramVec(HistogramVecOpts{ + HistogramOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewHistogramVec creates a new HistogramVec based on the provided HistogramVecOpts. +func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec { + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) return &HistogramVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { - return newHistogram(desc, opts, lvs...) + return newHistogram(desc, opts.HistogramOpts, lvs...) }), } } @@ -488,7 +1192,8 @@ func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Observe(42.21) +// +// myVec.WithLabelValues("404", "GET").Observe(42.21) func (v *HistogramVec) WithLabelValues(lvs ...string) Observer { h, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -499,7 +1204,8 @@ func (v *HistogramVec) WithLabelValues(lvs ...string) Observer { // With works as GetMetricWith but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) func (v *HistogramVec) With(labels Labels) Observer { h, err := v.GetMetricWith(labels) if err != nil { @@ -545,6 +1251,7 @@ type constHistogram struct { sum float64 buckets map[float64]uint64 labelPairs []*dto.LabelPair + createdTs *timestamppb.Timestamp } func (h *constHistogram) Desc() *Desc { @@ -552,12 +1259,14 @@ func (h *constHistogram) Desc() *Desc { } func (h *constHistogram) Write(out *dto.Metric) error { - his := &dto.Histogram{} + his := &dto.Histogram{ + CreatedTimestamp: h.createdTs, + } + buckets := make([]*dto.Bucket, 0, len(h.buckets)) his.SampleCount = proto.Uint64(h.count) his.SampleSum = proto.Float64(h.sum) - for upperBound, count := range h.buckets { buckets = append(buckets, &dto.Bucket{ CumulativeCount: proto.Uint64(count), @@ -585,7 +1294,7 @@ func (h *constHistogram) Write(out *dto.Metric) error { // to send it to Prometheus in the Collect method. // // buckets is a map of upper bounds to cumulative counts, excluding the +Inf -// bucket. +// bucket. The +Inf bucket is implicit, and its value is equal to the provided count. // // NewConstHistogram returns an error if the length of labelValues is not // consistent with the variable labels in Desc or if Desc is invalid. @@ -599,7 +1308,7 @@ func NewConstHistogram( if desc.err != nil { return nil, desc.err } - if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { + if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil { return nil, err } return &constHistogram{ @@ -640,3 +1349,229 @@ func (s buckSort) Swap(i, j int) { func (s buckSort) Less(i, j int) bool { return s[i].GetUpperBound() < s[j].GetUpperBound() } + +// pickSchema returns the largest number n between -4 and 8 such that +// 2^(2^-n) is less or equal the provided bucketFactor. +// +// Special cases: +// - bucketFactor <= 1: panics. +// - bucketFactor < 2^(2^-8) (but > 1): still returns 8. +func pickSchema(bucketFactor float64) int32 { + if bucketFactor <= 1 { + panic(fmt.Errorf("bucketFactor %f is <=1", bucketFactor)) + } + floor := math.Floor(math.Log2(math.Log2(bucketFactor))) + switch { + case floor <= -8: + return 8 + case floor >= 4: + return -4 + default: + return -int32(floor) + } +} + +func makeBuckets(buckets *sync.Map) ([]*dto.BucketSpan, []int64) { + var ii []int + buckets.Range(func(k, v interface{}) bool { + ii = append(ii, k.(int)) + return true + }) + sort.Ints(ii) + + if len(ii) == 0 { + return nil, nil + } + + var ( + spans []*dto.BucketSpan + deltas []int64 + prevCount int64 + nextI int + ) + + appendDelta := func(count int64) { + *spans[len(spans)-1].Length++ + deltas = append(deltas, count-prevCount) + prevCount = count + } + + for n, i := range ii { + v, _ := buckets.Load(i) + count := atomic.LoadInt64(v.(*int64)) + // Multiple spans with only small gaps in between are probably + // encoded more efficiently as one larger span with a few empty + // buckets. Needs some research to find the sweet spot. For now, + // we assume that gaps of one or two buckets should not create + // a new span. + iDelta := int32(i - nextI) + if n == 0 || iDelta > 2 { + // We have to create a new span, either because we are + // at the very beginning, or because we have found a gap + // of more than two buckets. + spans = append(spans, &dto.BucketSpan{ + Offset: proto.Int32(iDelta), + Length: proto.Uint32(0), + }) + } else { + // We have found a small gap (or no gap at all). + // Insert empty buckets as needed. + for j := int32(0); j < iDelta; j++ { + appendDelta(0) + } + } + appendDelta(count) + nextI = i + 1 + } + return spans, deltas +} + +// addToBucket increments the sparse bucket at key by the provided amount. It +// returns true if a new sparse bucket had to be created for that. +func addToBucket(buckets *sync.Map, key int, increment int64) bool { + if existingBucket, ok := buckets.Load(key); ok { + // Fast path without allocation. + atomic.AddInt64(existingBucket.(*int64), increment) + return false + } + // Bucket doesn't exist yet. Slow path allocating new counter. + newBucket := increment // TODO(beorn7): Check if this is sufficient to not let increment escape. + if actualBucket, loaded := buckets.LoadOrStore(key, &newBucket); loaded { + // The bucket was created concurrently in another goroutine. + // Have to increment after all. + atomic.AddInt64(actualBucket.(*int64), increment) + return false + } + return true +} + +// addAndReset returns a function to be used with sync.Map.Range of spare +// buckets in coldCounts. It increments the buckets in the provided hotBuckets +// according to the buckets ranged through. It then resets all buckets ranged +// through to 0 (but leaves them in place so that they don't need to get +// recreated on the next scrape). +func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v interface{}) bool { + return func(k, v interface{}) bool { + bucket := v.(*int64) + if addToBucket(hotBuckets, k.(int), atomic.LoadInt64(bucket)) { + atomic.AddUint32(bucketNumber, 1) + } + atomic.StoreInt64(bucket, 0) + return true + } +} + +func deleteSyncMap(m *sync.Map) { + m.Range(func(k, v interface{}) bool { + m.Delete(k) + return true + }) +} + +func findSmallestKey(m *sync.Map) int { + result := math.MaxInt32 + m.Range(func(k, v interface{}) bool { + key := k.(int) + if key < result { + result = key + } + return true + }) + return result +} + +func getLe(key int, schema int32) float64 { + // Here a bit of context about the behavior for the last bucket counting + // regular numbers (called simply "last bucket" below) and the bucket + // counting observations of ±Inf (called "inf bucket" below, with a key + // one higher than that of the "last bucket"): + // + // If we apply the usual formula to the last bucket, its upper bound + // would be calculated as +Inf. The reason is that the max possible + // regular float64 number (math.MaxFloat64) doesn't coincide with one of + // the calculated bucket boundaries. So the calculated boundary has to + // be larger than math.MaxFloat64, and the only float64 larger than + // math.MaxFloat64 is +Inf. However, we want to count actual + // observations of ±Inf in the inf bucket. Therefore, we have to treat + // the upper bound of the last bucket specially and set it to + // math.MaxFloat64. (The upper bound of the inf bucket, with its key + // being one higher than that of the last bucket, naturally comes out as + // +Inf by the usual formula. So that's fine.) + // + // math.MaxFloat64 has a frac of 0.9999999999999999 and an exp of + // 1024. If there were a float64 number following math.MaxFloat64, it + // would have a frac of 1.0 and an exp of 1024, or equivalently a frac + // of 0.5 and an exp of 1025. However, since frac must be smaller than + // 1, and exp must be smaller than 1025, either representation overflows + // a float64. (Which, in turn, is the reason that math.MaxFloat64 is the + // largest possible float64. Q.E.D.) However, the formula for + // calculating the upper bound from the idx and schema of the last + // bucket results in precisely that. It is either frac=1.0 & exp=1024 + // (for schema < 0) or frac=0.5 & exp=1025 (for schema >=0). (This is, + // by the way, a power of two where the exponent itself is a power of + // two, 2¹⁰ in fact, which coinicides with a bucket boundary in all + // schemas.) So these are the special cases we have to catch below. + if schema < 0 { + exp := key << -schema + if exp == 1024 { + // This is the last bucket before the overflow bucket + // (for ±Inf observations). Return math.MaxFloat64 as + // explained above. + return math.MaxFloat64 + } + return math.Ldexp(1, exp) + } + + fracIdx := key & ((1 << schema) - 1) + frac := nativeHistogramBounds[schema][fracIdx] + exp := (key >> schema) + 1 + if frac == 0.5 && exp == 1025 { + // This is the last bucket before the overflow bucket (for ±Inf + // observations). Return math.MaxFloat64 as explained above. + return math.MaxFloat64 + } + return math.Ldexp(frac, exp) +} + +// waitForCooldown returns after the count field in the provided histogramCounts +// has reached the provided count value. +func waitForCooldown(count uint64, counts *histogramCounts) { + for count != atomic.LoadUint64(&counts.count) { + runtime.Gosched() // Let observations get work done. + } +} + +// atomicAddFloat adds the provided float atomically to another float +// represented by the bit pattern the bits pointer is pointing to. +func atomicAddFloat(bits *uint64, v float64) { + for { + loadedBits := atomic.LoadUint64(bits) + newBits := math.Float64bits(math.Float64frombits(loadedBits) + v) + if atomic.CompareAndSwapUint64(bits, loadedBits, newBits) { + break + } + } +} + +// atomicDecUint32 atomically decrements the uint32 p points to. See +// https://pkg.go.dev/sync/atomic#AddUint32 to understand how this is done. +func atomicDecUint32(p *uint32) { + atomic.AddUint32(p, ^uint32(0)) +} + +// addAndResetCounts adds certain fields (count, sum, conventional buckets, zero +// bucket) from the cold counts to the corresponding fields in the hot +// counts. Those fields are then reset to 0 in the cold counts. +func addAndResetCounts(hot, cold *histogramCounts) { + atomic.AddUint64(&hot.count, atomic.LoadUint64(&cold.count)) + atomic.StoreUint64(&cold.count, 0) + coldSum := math.Float64frombits(atomic.LoadUint64(&cold.sumBits)) + atomicAddFloat(&hot.sumBits, coldSum) + atomic.StoreUint64(&cold.sumBits, 0) + for i := range hot.buckets { + atomic.AddUint64(&hot.buckets[i], atomic.LoadUint64(&cold.buckets[i])) + atomic.StoreUint64(&cold.buckets[i], 0) + } + atomic.AddUint64(&hot.nativeHistogramZeroBucket, atomic.LoadUint64(&cold.nativeHistogramZeroBucket)) + atomic.StoreUint64(&cold.nativeHistogramZeroBucket, 0) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go new file mode 100644 index 000000000..1ed5abe74 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go @@ -0,0 +1,60 @@ +// Copyright (c) 2015 Björn Rabenstein +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// The code in this package is copy/paste to avoid a dependency. Hence this file +// carries the copyright of the original repo. +// https://github.com/beorn7/floats +package internal + +import ( + "math" +) + +// minNormalFloat64 is the smallest positive normal value of type float64. +var minNormalFloat64 = math.Float64frombits(0x0010000000000000) + +// AlmostEqualFloat64 returns true if a and b are equal within a relative error +// of epsilon. See http://floating-point-gui.de/errors/comparison/ for the +// details of the applied method. +func AlmostEqualFloat64(a, b, epsilon float64) bool { + if a == b { + return true + } + absA := math.Abs(a) + absB := math.Abs(b) + diff := math.Abs(a - b) + if a == 0 || b == 0 || absA+absB < minNormalFloat64 { + return diff < epsilon*minNormalFloat64 + } + return diff/math.Min(absA+absB, math.MaxFloat64) < epsilon +} + +// AlmostEqualFloat64s is the slice form of AlmostEqualFloat64. +func AlmostEqualFloat64s(a, b []float64, epsilon float64) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if !AlmostEqualFloat64(a[i], b[i], epsilon) { + return false + } + } + return true +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go new file mode 100644 index 000000000..a595a2036 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go @@ -0,0 +1,654 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// Maintaining `GetUnifiedDiffString` here because original repository +// (https://github.com/pmezard/go-difflib) is no longer maintained. +package internal + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool, +) *SequenceMatcher { + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// +// and for all (i',j',k') meeting those conditions, +// +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize++ + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize++ + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{ + c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n), + }) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s]++ + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches++ + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning-- // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + wf := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := ws(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := ws("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := ws("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return w.String(), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go new file mode 100644 index 000000000..723b45d64 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go @@ -0,0 +1,32 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package internal + +import "regexp" + +type GoCollectorRule struct { + Matcher *regexp.Regexp + Deny bool +} + +// GoCollectorOptions should not be used be directly by anything, except `collectors` package. +// Use it via collectors package instead. See issue +// https://github.com/prometheus/client_golang/issues/1030. +// +// This is internal, so external users only can use it via `collector.WithGoCollector*` methods +type GoCollectorOptions struct { + DisableMemStatsLikeMetrics bool + RuntimeMetricSumForHist map[string]string + RuntimeMetricRules []GoCollectorRule +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go new file mode 100644 index 000000000..97d17d6cb --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go @@ -0,0 +1,142 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build go1.17 +// +build go1.17 + +package internal + +import ( + "math" + "path" + "runtime/metrics" + "strings" + + "github.com/prometheus/common/model" +) + +// RuntimeMetricsToProm produces a Prometheus metric name from a runtime/metrics +// metric description and validates whether the metric is suitable for integration +// with Prometheus. +// +// Returns false if a name could not be produced, or if Prometheus does not understand +// the runtime/metrics Kind. +// +// Note that the main reason a name couldn't be produced is if the runtime/metrics +// package exports a name with characters outside the valid Prometheus metric name +// character set. This is theoretically possible, but should never happen in practice. +// Still, don't rely on it. +func RuntimeMetricsToProm(d *metrics.Description) (string, string, string, bool) { + namespace := "go" + + comp := strings.SplitN(d.Name, ":", 2) + key := comp[0] + unit := comp[1] + + // The last path element in the key is the name, + // the rest is the subsystem. + subsystem := path.Dir(key[1:] /* remove leading / */) + name := path.Base(key) + + // subsystem is translated by replacing all / and - with _. + subsystem = strings.ReplaceAll(subsystem, "/", "_") + subsystem = strings.ReplaceAll(subsystem, "-", "_") + + // unit is translated assuming that the unit contains no + // non-ASCII characters. + unit = strings.ReplaceAll(unit, "-", "_") + unit = strings.ReplaceAll(unit, "*", "_") + unit = strings.ReplaceAll(unit, "/", "_per_") + + // name has - replaced with _ and is concatenated with the unit and + // other data. + name = strings.ReplaceAll(name, "-", "_") + name += "_" + unit + if d.Cumulative && d.Kind != metrics.KindFloat64Histogram { + name += "_total" + } + + valid := model.IsValidMetricName(model.LabelValue(namespace + "_" + subsystem + "_" + name)) + switch d.Kind { + case metrics.KindUint64: + case metrics.KindFloat64: + case metrics.KindFloat64Histogram: + default: + valid = false + } + return namespace, subsystem, name, valid +} + +// RuntimeMetricsBucketsForUnit takes a set of buckets obtained for a runtime/metrics histogram +// type (so, lower-bound inclusive) and a unit from a runtime/metrics name, and produces +// a reduced set of buckets. This function always removes any -Inf bucket as it's represented +// as the bottom-most upper-bound inclusive bucket in Prometheus. +func RuntimeMetricsBucketsForUnit(buckets []float64, unit string) []float64 { + switch unit { + case "bytes": + // Re-bucket as powers of 2. + return reBucketExp(buckets, 2) + case "seconds": + // Re-bucket as powers of 10 and then merge all buckets greater + // than 1 second into the +Inf bucket. + b := reBucketExp(buckets, 10) + for i := range b { + if b[i] <= 1 { + continue + } + b[i] = math.Inf(1) + b = b[:i+1] + break + } + return b + } + return buckets +} + +// reBucketExp takes a list of bucket boundaries (lower bound inclusive) and +// downsamples the buckets to those a multiple of base apart. The end result +// is a roughly exponential (in many cases, perfectly exponential) bucketing +// scheme. +func reBucketExp(buckets []float64, base float64) []float64 { + bucket := buckets[0] + var newBuckets []float64 + // We may see a -Inf here, in which case, add it and skip it + // since we risk producing NaNs otherwise. + // + // We need to preserve -Inf values to maintain runtime/metrics + // conventions. We'll strip it out later. + if bucket == math.Inf(-1) { + newBuckets = append(newBuckets, bucket) + buckets = buckets[1:] + bucket = buckets[0] + } + // From now on, bucket should always have a non-Inf value because + // Infs are only ever at the ends of the bucket lists, so + // arithmetic operations on it are non-NaN. + for i := 1; i < len(buckets); i++ { + if bucket >= 0 && buckets[i] < bucket*base { + // The next bucket we want to include is at least bucket*base. + continue + } else if bucket < 0 && buckets[i] < bucket/base { + // In this case the bucket we're targeting is negative, and since + // we're ascending through buckets here, we need to divide to get + // closer to zero exponentially. + continue + } + // The +Inf bucket will always be the last one, and we'll always + // end up including it here because bucket + newBuckets = append(newBuckets, bucket) + bucket = buckets[i] + } + return append(newBuckets, bucket) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go index 351c26e1a..6515c1148 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go @@ -19,18 +19,34 @@ import ( dto "github.com/prometheus/client_model/go" ) -// metricSorter is a sortable slice of *dto.Metric. -type metricSorter []*dto.Metric +// LabelPairSorter implements sort.Interface. It is used to sort a slice of +// dto.LabelPair pointers. +type LabelPairSorter []*dto.LabelPair -func (s metricSorter) Len() int { +func (s LabelPairSorter) Len() int { return len(s) } -func (s metricSorter) Swap(i, j int) { +func (s LabelPairSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s metricSorter) Less(i, j int) bool { +func (s LabelPairSorter) Less(i, j int) bool { + return s[i].GetName() < s[j].GetName() +} + +// MetricSorter is a sortable slice of *dto.Metric. +type MetricSorter []*dto.Metric + +func (s MetricSorter) Len() int { + return len(s) +} + +func (s MetricSorter) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s MetricSorter) Less(i, j int) bool { if len(s[i].Label) != len(s[j].Label) { // This should not happen. The metrics are // inconsistent. However, we have to deal with the fact, as @@ -68,7 +84,7 @@ func (s metricSorter) Less(i, j int) bool { // the slice, with the contained Metrics sorted within each MetricFamily. func NormalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily { for _, mf := range metricFamiliesByName { - sort.Sort(metricSorter(mf.Metric)) + sort.Sort(MetricSorter(mf.Metric)) } names := make([]string, 0, len(metricFamiliesByName)) for name, mf := range metricFamiliesByName { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/labels.go b/vendor/github.com/prometheus/client_golang/prometheus/labels.go index 2744443ac..c21911f29 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/labels.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/labels.go @@ -25,12 +25,111 @@ import ( // Labels represents a collection of label name -> value mappings. This type is // commonly used with the With(Labels) and GetMetricWith(Labels) methods of // metric vector Collectors, e.g.: -// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) +// +// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) // // The other use-case is the specification of constant label pairs in Opts or to // create a Desc. type Labels map[string]string +// LabelConstraint normalizes label values. +type LabelConstraint func(string) string + +// ConstrainedLabels represents a label name and its constrain function +// to normalize label values. This type is commonly used when constructing +// metric vector Collectors. +type ConstrainedLabel struct { + Name string + Constraint LabelConstraint +} + +// ConstrainableLabels is an interface that allows creating of labels that can +// be optionally constrained. +// +// prometheus.V2().NewCounterVec(CounterVecOpts{ +// CounterOpts: {...}, // Usual CounterOpts fields +// VariableLabels: []ConstrainedLabels{ +// {Name: "A"}, +// {Name: "B", Constraint: func(v string) string { ... }}, +// }, +// }) +type ConstrainableLabels interface { + compile() *compiledLabels + labelNames() []string +} + +// ConstrainedLabels represents a collection of label name -> constrain function +// to normalize label values. This type is commonly used when constructing +// metric vector Collectors. +type ConstrainedLabels []ConstrainedLabel + +func (cls ConstrainedLabels) compile() *compiledLabels { + compiled := &compiledLabels{ + names: make([]string, len(cls)), + labelConstraints: map[string]LabelConstraint{}, + } + + for i, label := range cls { + compiled.names[i] = label.Name + if label.Constraint != nil { + compiled.labelConstraints[label.Name] = label.Constraint + } + } + + return compiled +} + +func (cls ConstrainedLabels) labelNames() []string { + names := make([]string, len(cls)) + for i, label := range cls { + names[i] = label.Name + } + return names +} + +// UnconstrainedLabels represents collection of label without any constraint on +// their value. Thus, it is simply a collection of label names. +// +// UnconstrainedLabels([]string{ "A", "B" }) +// +// is equivalent to +// +// ConstrainedLabels { +// { Name: "A" }, +// { Name: "B" }, +// } +type UnconstrainedLabels []string + +func (uls UnconstrainedLabels) compile() *compiledLabels { + return &compiledLabels{ + names: uls, + } +} + +func (uls UnconstrainedLabels) labelNames() []string { + return uls +} + +type compiledLabels struct { + names []string + labelConstraints map[string]LabelConstraint +} + +func (cls *compiledLabels) compile() *compiledLabels { + return cls +} + +func (cls *compiledLabels) labelNames() []string { + return cls.names +} + +func (cls *compiledLabels) constrain(labelName, value string) string { + if fn, ok := cls.labelConstraints[labelName]; ok && fn != nil { + return fn(value) + } + return value +} + // reservedLabelPrefix is a prefix which is not legal in user-supplied // label names. const reservedLabelPrefix = "__" @@ -39,7 +138,7 @@ var errInconsistentCardinality = errors.New("inconsistent label cardinality") func makeInconsistentCardinalityError(fqName string, labels, labelValues []string) error { return fmt.Errorf( - "%s: %q has %d variable labels named %q but %d values %q were provided", + "%w: %q has %d variable labels named %q but %d values %q were provided", errInconsistentCardinality, fqName, len(labels), labels, len(labelValues), labelValues, @@ -49,7 +148,7 @@ func makeInconsistentCardinalityError(fqName string, labels, labelValues []strin func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { if len(labels) != expectedNumberOfValues { return fmt.Errorf( - "%s: expected %d label values but got %d in %#v", + "%w: expected %d label values but got %d in %#v", errInconsistentCardinality, expectedNumberOfValues, len(labels), labels, ) @@ -66,8 +165,10 @@ func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { func validateLabelValues(vals []string, expectedNumberOfValues int) error { if len(vals) != expectedNumberOfValues { + // The call below makes vals escape, copy them to avoid that. + vals := append([]string(nil), vals...) return fmt.Errorf( - "%s: expected %d label values but got %d in %#v", + "%w: expected %d label values but got %d in %#v", errInconsistentCardinality, expectedNumberOfValues, len(vals), vals, ) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go index dc121910a..f018e5723 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go @@ -14,14 +14,15 @@ package prometheus import ( + "errors" + "math" + "sort" "strings" "time" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/model" - dto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/model" + "google.golang.org/protobuf/proto" ) var separatorByteSlice = []byte{model.SeparatorByte} // For convenient use with xxhash. @@ -91,6 +92,9 @@ type Opts struct { // machine_role metric). See also // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels ConstLabels Labels + + // now is for testing purposes, by default it's time.Now. + now func() time.Time } // BuildFQName joins the given three name components by "_". Empty name @@ -115,22 +119,6 @@ func BuildFQName(namespace, subsystem, name string) string { return name } -// labelPairSorter implements sort.Interface. It is used to sort a slice of -// dto.LabelPair pointers. -type labelPairSorter []*dto.LabelPair - -func (s labelPairSorter) Len() int { - return len(s) -} - -func (s labelPairSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s labelPairSorter) Less(i, j int) bool { - return s[i].GetName() < s[j].GetName() -} - type invalidMetric struct { desc *Desc err error @@ -174,3 +162,96 @@ func (m timestampedMetric) Write(pb *dto.Metric) error { func NewMetricWithTimestamp(t time.Time, m Metric) Metric { return timestampedMetric{Metric: m, t: t} } + +type withExemplarsMetric struct { + Metric + + exemplars []*dto.Exemplar +} + +func (m *withExemplarsMetric) Write(pb *dto.Metric) error { + if err := m.Metric.Write(pb); err != nil { + return err + } + + switch { + case pb.Counter != nil: + pb.Counter.Exemplar = m.exemplars[len(m.exemplars)-1] + case pb.Histogram != nil: + for _, e := range m.exemplars { + // pb.Histogram.Bucket are sorted by UpperBound. + i := sort.Search(len(pb.Histogram.Bucket), func(i int) bool { + return pb.Histogram.Bucket[i].GetUpperBound() >= e.GetValue() + }) + if i < len(pb.Histogram.Bucket) { + pb.Histogram.Bucket[i].Exemplar = e + } else { + // The +Inf bucket should be explicitly added if there is an exemplar for it, similar to non-const histogram logic in https://github.com/prometheus/client_golang/blob/main/prometheus/histogram.go#L357-L365. + b := &dto.Bucket{ + CumulativeCount: proto.Uint64(pb.Histogram.GetSampleCount()), + UpperBound: proto.Float64(math.Inf(1)), + Exemplar: e, + } + pb.Histogram.Bucket = append(pb.Histogram.Bucket, b) + } + } + default: + // TODO(bwplotka): Implement Gauge? + return errors.New("cannot inject exemplar into Gauge, Summary or Untyped") + } + + return nil +} + +// Exemplar is easier to use, user-facing representation of *dto.Exemplar. +type Exemplar struct { + Value float64 + Labels Labels + // Optional. + // Default value (time.Time{}) indicates its empty, which should be + // understood as time.Now() time at the moment of creation of metric. + Timestamp time.Time +} + +// NewMetricWithExemplars returns a new Metric wrapping the provided Metric with given +// exemplars. Exemplars are validated. +// +// Only last applicable exemplar is injected from the list. +// For example for Counter it means last exemplar is injected. +// For Histogram, it means last applicable exemplar for each bucket is injected. +// +// NewMetricWithExemplars works best with MustNewConstMetric and +// MustNewConstHistogram, see example. +func NewMetricWithExemplars(m Metric, exemplars ...Exemplar) (Metric, error) { + if len(exemplars) == 0 { + return nil, errors.New("no exemplar was passed for NewMetricWithExemplars") + } + + var ( + now = time.Now() + exs = make([]*dto.Exemplar, len(exemplars)) + err error + ) + for i, e := range exemplars { + ts := e.Timestamp + if ts == (time.Time{}) { + ts = now + } + exs[i], err = newExemplar(e.Value, ts, e.Labels) + if err != nil { + return nil, err + } + } + + return &withExemplarsMetric{Metric: m, exemplars: exs}, nil +} + +// MustNewMetricWithExemplars is a version of NewMetricWithExemplars that panics where +// NewMetricWithExemplars would have returned an error. +func MustNewMetricWithExemplars(m Metric, exemplars ...Exemplar) Metric { + ret, err := NewMetricWithExemplars(m, exemplars...) + if err != nil { + panic(err) + } + return ret +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/num_threads.go b/vendor/github.com/prometheus/client_golang/prometheus/num_threads.go new file mode 100644 index 000000000..7c12b2108 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/num_threads.go @@ -0,0 +1,25 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !js || wasm +// +build !js wasm + +package prometheus + +import "runtime" + +// getRuntimeNumThreads returns the number of open OS threads. +func getRuntimeNumThreads() float64 { + n, _ := runtime.ThreadCreateProfile(nil) + return float64(n) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go b/vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go new file mode 100644 index 000000000..7348df01d --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go @@ -0,0 +1,22 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build js && !wasm +// +build js,!wasm + +package prometheus + +// getRuntimeNumThreads returns the number of open OS threads. +func getRuntimeNumThreads() float64 { + return 1 +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/observer.go b/vendor/github.com/prometheus/client_golang/prometheus/observer.go index 44128016f..03773b21f 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/observer.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/observer.go @@ -58,7 +58,7 @@ type ObserverVec interface { // current time as timestamp, and the provided Labels. Empty Labels will lead to // a valid (label-less) exemplar. But if Labels is nil, the current exemplar is // left in place. ObserveWithExemplar panics if any of the provided labels are -// invalid or if the provided labels contain more than 64 runes in total. +// invalid or if the provided labels contain more than 128 runes in total. type ExemplarObserver interface { ObserveWithExemplar(value float64, exemplar Labels) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go index 5bfe0ff5b..8548dd18e 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go @@ -16,7 +16,6 @@ package prometheus import ( "errors" "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -104,8 +103,7 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector { } if opts.PidFn == nil { - pid := os.Getpid() - c.pidFn = func() (int, error) { return pid, nil } + c.pidFn = getPIDFn() } else { c.pidFn = opts.PidFn } @@ -152,13 +150,13 @@ func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) // It is meant to be used for the PidFn field in ProcessCollectorOpts. func NewPidFileFn(pidFilePath string) func() (int, error) { return func() (int, error) { - content, err := ioutil.ReadFile(pidFilePath) + content, err := os.ReadFile(pidFilePath) if err != nil { - return 0, fmt.Errorf("can't read pid file %q: %+v", pidFilePath, err) + return 0, fmt.Errorf("can't read pid file %q: %w", pidFilePath, err) } pid, err := strconv.Atoi(strings.TrimSpace(string(content))) if err != nil { - return 0, fmt.Errorf("can't parse pid file %q: %+v", pidFilePath, err) + return 0, fmt.Errorf("can't parse pid file %q: %w", pidFilePath, err) } return pid, nil diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go new file mode 100644 index 000000000..b1e363d6c --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go @@ -0,0 +1,26 @@ +// Copyright 2019 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build js +// +build js + +package prometheus + +func canCollectProcess() bool { + return false +} + +func (c *processCollector) processCollect(ch chan<- Metric) { + // noop on this platform + return +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go index 3117461cd..8c1136cee 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go @@ -11,7 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +//go:build !windows && !js && !wasip1 +// +build !windows,!js,!wasip1 package prometheus diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go new file mode 100644 index 000000000..d8d9a6d7a --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_wasip1.go @@ -0,0 +1,26 @@ +// Copyright 2023 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build wasip1 +// +build wasip1 + +package prometheus + +func canCollectProcess() bool { + return false +} + +func (*processCollector) processCollect(chan<- Metric) { + // noop on this platform + return +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go index e7c0d0546..9819917b8 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go @@ -76,16 +76,19 @@ func (r *responseWriterDelegator) Write(b []byte) (int, error) { return n, err } -type closeNotifierDelegator struct{ *responseWriterDelegator } -type flusherDelegator struct{ *responseWriterDelegator } -type hijackerDelegator struct{ *responseWriterDelegator } -type readerFromDelegator struct{ *responseWriterDelegator } -type pusherDelegator struct{ *responseWriterDelegator } +type ( + closeNotifierDelegator struct{ *responseWriterDelegator } + flusherDelegator struct{ *responseWriterDelegator } + hijackerDelegator struct{ *responseWriterDelegator } + readerFromDelegator struct{ *responseWriterDelegator } + pusherDelegator struct{ *responseWriterDelegator } +) func (d closeNotifierDelegator) CloseNotify() <-chan bool { //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users. return d.ResponseWriter.(http.CloseNotifier).CloseNotify() } + func (d flusherDelegator) Flush() { // If applicable, call WriteHeader here so that observeWriteHeader is // handled appropriately. @@ -94,9 +97,11 @@ func (d flusherDelegator) Flush() { } d.ResponseWriter.(http.Flusher).Flush() } + func (d hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { return d.ResponseWriter.(http.Hijacker).Hijack() } + func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) { // If applicable, call WriteHeader here so that observeWriteHeader is // handled appropriately. @@ -107,6 +112,7 @@ func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) { d.written += n return n, err } + func (d pusherDelegator) Push(target string, opts *http.PushOptions) error { return d.ResponseWriter.(http.Pusher).Push(target, opts) } @@ -261,7 +267,7 @@ func init() { http.Flusher }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} } - pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23 + pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 23 return struct { *responseWriterDelegator http.Pusher diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index d86d0cf4b..09b8d2fbe 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -33,9 +33,11 @@ package promhttp import ( "compress/gzip" + "errors" "fmt" "io" "net/http" + "strconv" "strings" "sync" "time" @@ -46,9 +48,10 @@ import ( ) const ( - contentTypeHeader = "Content-Type" - contentEncodingHeader = "Content-Encoding" - acceptEncodingHeader = "Accept-Encoding" + contentTypeHeader = "Content-Type" + contentEncodingHeader = "Content-Encoding" + acceptEncodingHeader = "Accept-Encoding" + processStartTimeHeader = "Process-Start-Time-Unix" ) var gzipPool = sync.Pool{ @@ -84,6 +87,13 @@ func Handler() http.Handler { // instrumentation. Use the InstrumentMetricHandler function to apply the same // kind of instrumentation as it is used by the Handler function. func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { + return HandlerForTransactional(prometheus.ToTransactionalGatherer(reg), opts) +} + +// HandlerForTransactional is like HandlerFor, but it uses transactional gather, which +// can safely change in-place returned *dto.MetricFamily before call to `Gather` and after +// call to `done` of that `Gather`. +func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerOpts) http.Handler { var ( inFlightSem chan struct{} errCnt = prometheus.NewCounterVec( @@ -103,7 +113,8 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { errCnt.WithLabelValues("gathering") errCnt.WithLabelValues("encoding") if err := opts.Registry.Register(errCnt); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + are := &prometheus.AlreadyRegisteredError{} + if errors.As(err, are) { errCnt = are.ExistingCollector.(*prometheus.CounterVec) } else { panic(err) @@ -112,6 +123,9 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { } h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { + if !opts.ProcessStartTime.IsZero() { + rsp.Header().Set(processStartTimeHeader, strconv.FormatInt(opts.ProcessStartTime.Unix(), 10)) + } if inFlightSem != nil { select { case inFlightSem <- struct{}{}: // All good, carry on. @@ -123,7 +137,8 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { return } } - mfs, err := reg.Gather() + mfs, done, err := reg.Gather() + defer done() if err != nil { if opts.ErrorLog != nil { opts.ErrorLog.Println("error gathering metrics:", err) @@ -242,7 +257,8 @@ func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) ht cnt.WithLabelValues("500") cnt.WithLabelValues("503") if err := reg.Register(cnt); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + are := &prometheus.AlreadyRegisteredError{} + if errors.As(err, are) { cnt = are.ExistingCollector.(*prometheus.CounterVec) } else { panic(err) @@ -254,7 +270,8 @@ func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) ht Help: "Current number of scrapes being served.", }) if err := reg.Register(gge); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + are := &prometheus.AlreadyRegisteredError{} + if errors.As(err, are) { gge = are.ExistingCollector.(prometheus.Gauge) } else { panic(err) @@ -354,6 +371,14 @@ type HandlerOpts struct { // (which changes the identity of the resulting series on the Prometheus // server). EnableOpenMetrics bool + // ProcessStartTime allows setting process start timevalue that will be exposed + // with "Process-Start-Time-Unix" response header along with the metrics + // payload. This allow callers to have efficient transformations to cumulative + // counters (e.g. OpenTelemetry) or generally _created timestamp estimation per + // scrape target. + // NOTE: This feature is experimental and not covered by OpenMetrics or Prometheus + // exposition format. + ProcessStartTime time.Time } // gzipAccepted returns whether the client will accept gzip-encoded content. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go index 861b4d21c..d3482c40c 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go @@ -38,11 +38,11 @@ func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { // // See the example for ExampleInstrumentRoundTripperDuration for example usage. func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { gauge.Inc() defer gauge.Dec() return next.RoundTrip(r) - }) + } } // InstrumentRoundTripperCounter is a middleware that wraps the provided @@ -59,22 +59,29 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp // If the wrapped RoundTripper panics or returns a non-nil error, the Counter // is not incremented. // +// Use with WithExemplarFromContext to instrument the exemplars on the counter of requests. +// // See the example for ExampleInstrumentRoundTripperDuration for example usage. func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { - rtOpts := &option{} + rtOpts := defaultOptions() for _, o := range opts { - o(rtOpts) + o.apply(rtOpts) } - code, method := checkLabels(counter) + // Curry the counter with dynamic labels before checking the remaining labels. + code, method := checkLabels(counter.MustCurryWith(rtOpts.emptyDynamicLabels())) - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { resp, err := next.RoundTrip(r) if err == nil { - counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc() + l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) + for label, resolve := range rtOpts.extraLabelsFromCtx { + l[label] = resolve(resp.Request.Context()) + } + addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r.Context())) } return resp, err - }) + } } // InstrumentRoundTripperDuration is a middleware that wraps the provided @@ -94,24 +101,31 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou // If the wrapped RoundTripper panics or returns a non-nil error, no values are // reported. // +// Use with WithExemplarFromContext to instrument the exemplars on the duration histograms. +// // Note that this method is only guaranteed to never observe negative durations // if used with Go1.9+. func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { - rtOpts := &option{} + rtOpts := defaultOptions() for _, o := range opts { - o(rtOpts) + o.apply(rtOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(rtOpts.emptyDynamicLabels())) - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { start := time.Now() resp, err := next.RoundTrip(r) if err == nil { - obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds()) + l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) + for label, resolve := range rtOpts.extraLabelsFromCtx { + l[label] = resolve(resp.Request.Context()) + } + observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r.Context())) } return resp, err - }) + } } // InstrumentTrace is used to offer flexibility in instrumenting the available @@ -149,7 +163,7 @@ type InstrumentTrace struct { // // See the example for ExampleInstrumentRoundTripperDuration for example usage. func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { start := time.Now() trace := &httptrace.ClientTrace{ @@ -231,5 +245,5 @@ func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) Ro r = r.WithContext(httptrace.WithClientTrace(r.Context(), trace)) return next.RoundTrip(r) - }) + } } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go index a23f0edc6..356edb786 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go @@ -28,6 +28,26 @@ import ( // magicString is used for the hacky label test in checkLabels. Remove once fixed. const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa" +// observeWithExemplar is a wrapper for [prometheus.ExemplarAdder.ExemplarObserver], +// which falls back to [prometheus.Observer.Observe] if no labels are provided. +func observeWithExemplar(obs prometheus.Observer, val float64, labels map[string]string) { + if labels == nil { + obs.Observe(val) + return + } + obs.(prometheus.ExemplarObserver).ObserveWithExemplar(val, labels) +} + +// addWithExemplar is a wrapper for [prometheus.ExemplarAdder.AddWithExemplar], +// which falls back to [prometheus.Counter.Add] if no labels are provided. +func addWithExemplar(obs prometheus.Counter, val float64, labels map[string]string) { + if labels == nil { + obs.Add(val) + return + } + obs.(prometheus.ExemplarAdder).AddWithExemplar(val, labels) +} + // InstrumentHandlerInFlight is a middleware that wraps the provided // http.Handler. It sets the provided prometheus.Gauge to the number of // requests currently handled by the wrapped http.Handler. @@ -48,7 +68,7 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // names are "code" and "method". The function panics otherwise. For the "method" // label a predefined default label value set is used to filter given values. // Values besides predefined values will count as `unknown` method. -//`WithExtraMethods` can be used to add more methods to the set. The Observe +// `WithExtraMethods` can be used to add more methods to the set. The Observe // method of the Observer in the ObserverVec is called with the request duration // in seconds. Partitioning happens by HTTP status code and/or HTTP method if // the respective instance label names are present in the ObserverVec. For @@ -62,28 +82,37 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // Note that this method is only guaranteed to never observe negative durations // if used with Go1.9+. func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { now := time.Now() d := newDelegator(w, nil) next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) - }) + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) + } } - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { now := time.Now() next.ServeHTTP(w, r) - obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) - }) + l := labels(code, method, r.Method, 0, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) + } } // InstrumentHandlerCounter is a middleware that wraps the provided http.Handler @@ -104,25 +133,36 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(counter) + // Curry the counter with dynamic labels before checking the remaining labels. + code, method := checkLabels(counter.MustCurryWith(hOpts.emptyDynamicLabels())) if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) - counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc() - }) + + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) + } } - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { next.ServeHTTP(w, r) - counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc() - }) + + l := labels(code, method, r.Method, 0, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) + } } // InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided @@ -148,20 +188,25 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { now := time.Now() d := newDelegator(w, func(status int) { - obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) + l := labels(code, method, r.Method, status, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) }) next.ServeHTTP(d, r) - }) + } } // InstrumentHandlerRequestSize is a middleware that wraps the provided @@ -184,27 +229,38 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size)) - }) + + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) + } } - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { next.ServeHTTP(w, r) size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size)) - }) + + l := labels(code, method, r.Method, 0, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) + } } // InstrumentHandlerResponseSize is a middleware that wraps the provided @@ -227,17 +283,23 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written())) + + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r.Context())) }) } @@ -246,7 +308,7 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler // Collector does not have a Desc or has more than one Desc or its Desc is // invalid. It also panics if the Collector has any non-const, non-curried // labels that are not named "code" or "method". -func checkLabels(c prometheus.Collector) (code bool, method bool) { +func checkLabels(c prometheus.Collector) (code, method bool) { // TODO(beorn7): Remove this hacky way to check for instance labels // once Descriptors can have their dimensionality queried. var ( @@ -327,15 +389,12 @@ func isLabelCurried(c prometheus.Collector, label string) bool { return true } -// emptyLabels is a one-time allocation for non-partitioned metrics to avoid -// unnecessary allocations on each request. -var emptyLabels = prometheus.Labels{} - func labels(code, method bool, reqMethod string, status int, extraMethods ...string) prometheus.Labels { + labels := prometheus.Labels{} + if !(code || method) { - return emptyLabels + return labels } - labels := prometheus.Labels{} if code { labels["code"] = sanitizeCode(status) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go index 35e41bd1e..5d4383aa1 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go @@ -13,19 +13,72 @@ package promhttp -// Option are used to configure a middleware or round tripper.. -type Option func(*option) +import ( + "context" -type option struct { - extraMethods []string + "github.com/prometheus/client_golang/prometheus" +) + +// Option are used to configure both handler (middleware) or round tripper. +type Option interface { + apply(*options) +} + +// LabelValueFromCtx are used to compute the label value from request context. +// Context can be filled with values from request through middleware. +type LabelValueFromCtx func(ctx context.Context) string + +// options store options for both a handler or round tripper. +type options struct { + extraMethods []string + getExemplarFn func(requestCtx context.Context) prometheus.Labels + extraLabelsFromCtx map[string]LabelValueFromCtx +} + +func defaultOptions() *options { + return &options{ + getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil }, + extraLabelsFromCtx: map[string]LabelValueFromCtx{}, + } } +func (o *options) emptyDynamicLabels() prometheus.Labels { + labels := prometheus.Labels{} + + for label := range o.extraLabelsFromCtx { + labels[label] = "" + } + + return labels +} + +type optionApplyFunc func(*options) + +func (o optionApplyFunc) apply(opt *options) { o(opt) } + // WithExtraMethods adds additional HTTP methods to the list of allowed methods. // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list. // // See the example for ExampleInstrumentHandlerWithExtraMethods for example usage. func WithExtraMethods(methods ...string) Option { - return func(o *option) { + return optionApplyFunc(func(o *options) { o.extraMethods = methods - } + }) +} + +// WithExemplarFromContext allows to inject function that will get exemplar from context that will be put to counter and histogram metrics. +// If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but +// metric will continue to observe/increment. +func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prometheus.Labels) Option { + return optionApplyFunc(func(o *options) { + o.getExemplarFn = getExemplarFn + }) +} + +// WithLabelFromCtx registers a label for dynamic resolution with access to context. +// See the example for ExampleInstrumentHandlerWithLabelResolver for example usage +func WithLabelFromCtx(name string, valueFn LabelValueFromCtx) Option { + return optionApplyFunc(func(o *options) { + o.extraLabelsFromCtx[name] = valueFn + }) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go index 383a7f594..5e2ced25a 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go @@ -15,24 +15,23 @@ package prometheus import ( "bytes" + "errors" "fmt" - "io/ioutil" "os" "path/filepath" "runtime" "sort" + "strconv" "strings" "sync" "unicode/utf8" - "github.com/cespare/xxhash/v2" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/expfmt" + "github.com/prometheus/client_golang/prometheus/internal" + "github.com/cespare/xxhash/v2" dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus/internal" + "github.com/prometheus/common/expfmt" + "google.golang.org/protobuf/proto" ) const ( @@ -252,9 +251,12 @@ func (errs MultiError) MaybeUnwrap() error { } // Registry registers Prometheus collectors, collects their metrics, and gathers -// them into MetricFamilies for exposition. It implements both Registerer and -// Gatherer. The zero value is not usable. Create instances with NewRegistry or -// NewPedanticRegistry. +// them into MetricFamilies for exposition. It implements Registerer, Gatherer, +// and Collector. The zero value is not usable. Create instances with +// NewRegistry or NewPedanticRegistry. +// +// Registry implements Collector to allow it to be used for creating groups of +// metrics. See the Grouping example for how this can be done. type Registry struct { mtx sync.RWMutex collectorsByID map[uint64]Collector // ID is a hash of the descIDs. @@ -289,7 +291,7 @@ func (r *Registry) Register(c Collector) error { // Is the descriptor valid at all? if desc.err != nil { - return fmt.Errorf("descriptor %s is invalid: %s", desc, desc.err) + return fmt.Errorf("descriptor %s is invalid: %w", desc, desc.err) } // Is the descID unique? @@ -407,6 +409,14 @@ func (r *Registry) MustRegister(cs ...Collector) { // Gather implements Gatherer. func (r *Registry) Gather() ([]*dto.MetricFamily, error) { + r.mtx.RLock() + + if len(r.collectorsByID) == 0 && len(r.uncheckedCollectors) == 0 { + // Fast path. + r.mtx.RUnlock() + return nil, nil + } + var ( checkedMetricChan = make(chan Metric, capMetricChan) uncheckedMetricChan = make(chan Metric, capMetricChan) @@ -416,7 +426,6 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { registeredDescIDs map[uint64]struct{} // Only used for pedantic checks ) - r.mtx.RLock() goroutineBudget := len(r.collectorsByID) + len(r.uncheckedCollectors) metricFamiliesByName := make(map[string]*dto.MetricFamily, len(r.dimHashesByName)) checkedCollectors := make(chan Collector, len(r.collectorsByID)) @@ -539,7 +548,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { goroutineBudget-- runtime.Gosched() } - // Once both checkedMetricChan and uncheckdMetricChan are closed + // Once both checkedMetricChan and uncheckedMetricChan are closed // and drained, the contraption above will nil out cmc and umc, // and then we can leave the collect loop here. if cmc == nil && umc == nil { @@ -549,6 +558,31 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() } +// Describe implements Collector. +func (r *Registry) Describe(ch chan<- *Desc) { + r.mtx.RLock() + defer r.mtx.RUnlock() + + // Only report the checked Collectors; unchecked collectors don't report any + // Desc. + for _, c := range r.collectorsByID { + c.Describe(ch) + } +} + +// Collect implements Collector. +func (r *Registry) Collect(ch chan<- Metric) { + r.mtx.RLock() + defer r.mtx.RUnlock() + + for _, c := range r.collectorsByID { + c.Collect(ch) + } + for _, c := range r.uncheckedCollectors { + c.Collect(ch) + } +} + // WriteToTextfile calls Gather on the provided Gatherer, encodes the result in the // Prometheus text format, and writes it to a temporary file. Upon success, the // temporary file is renamed to the provided filename. @@ -556,7 +590,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { // This is intended for use with the textfile collector of the node exporter. // Note that the node exporter expects the filename to be suffixed with ".prom". func WriteToTextfile(filename string, g Gatherer) error { - tmp, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)) + tmp, err := os.CreateTemp(filepath.Dir(filename), filepath.Base(filename)) if err != nil { return err } @@ -575,7 +609,7 @@ func WriteToTextfile(filename string, g Gatherer) error { return err } - if err := os.Chmod(tmp.Name(), 0644); err != nil { + if err := os.Chmod(tmp.Name(), 0o644); err != nil { return err } return os.Rename(tmp.Name(), filename) @@ -596,7 +630,7 @@ func processMetric( } dtoMetric := &dto.Metric{} if err := metric.Write(dtoMetric); err != nil { - return fmt.Errorf("error collecting metric %v: %s", desc, err) + return fmt.Errorf("error collecting metric %v: %w", desc, err) } metricFamily, ok := metricFamiliesByName[desc.fqName] if ok { // Existing name. @@ -718,12 +752,13 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) { for i, g := range gs { mfs, err := g.Gather() if err != nil { - if multiErr, ok := err.(MultiError); ok { + multiErr := MultiError{} + if errors.As(err, &multiErr) { for _, err := range multiErr { - errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err)) + errs = append(errs, fmt.Errorf("[from Gatherer #%d] %w", i+1, err)) } } else { - errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err)) + errs = append(errs, fmt.Errorf("[from Gatherer #%d] %w", i+1, err)) } } for _, mf := range mfs { @@ -884,11 +919,11 @@ func checkMetricConsistency( h.Write(separatorByteSlice) // Make sure label pairs are sorted. We depend on it for the consistency // check. - if !sort.IsSorted(labelPairSorter(dtoMetric.Label)) { + if !sort.IsSorted(internal.LabelPairSorter(dtoMetric.Label)) { // We cannot sort dtoMetric.Label in place as it is immutable by contract. copiedLabels := make([]*dto.LabelPair, len(dtoMetric.Label)) copy(copiedLabels, dtoMetric.Label) - sort.Sort(labelPairSorter(copiedLabels)) + sort.Sort(internal.LabelPairSorter(copiedLabels)) dtoMetric.Label = copiedLabels } for _, lp := range dtoMetric.Label { @@ -897,6 +932,10 @@ func checkMetricConsistency( h.WriteString(lp.GetValue()) h.Write(separatorByteSlice) } + if dtoMetric.TimestampMs != nil { + h.WriteString(strconv.FormatInt(*(dtoMetric.TimestampMs), 10)) + h.Write(separatorByteSlice) + } hSum := h.Sum64() if _, exists := metricHashes[hSum]; exists { return fmt.Errorf( @@ -924,7 +963,7 @@ func checkDescConsistency( // Is the desc consistent with the content of the metric? lpsFromDesc := make([]*dto.LabelPair, len(desc.constLabelPairs), len(dtoMetric.Label)) copy(lpsFromDesc, desc.constLabelPairs) - for _, l := range desc.variableLabels { + for _, l := range desc.variableLabels.names { lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{ Name: proto.String(l), }) @@ -935,7 +974,7 @@ func checkDescConsistency( metricFamily.GetName(), dtoMetric, desc, ) } - sort.Sort(labelPairSorter(lpsFromDesc)) + sort.Sort(internal.LabelPairSorter(lpsFromDesc)) for i, lpFromDesc := range lpsFromDesc { lpFromMetric := dtoMetric.Label[i] if lpFromDesc.GetName() != lpFromMetric.GetName() || @@ -948,3 +987,89 @@ func checkDescConsistency( } return nil } + +var _ TransactionalGatherer = &MultiTRegistry{} + +// MultiTRegistry is a TransactionalGatherer that joins gathered metrics from multiple +// transactional gatherers. +// +// It is caller responsibility to ensure two registries have mutually exclusive metric families, +// no deduplication will happen. +type MultiTRegistry struct { + tGatherers []TransactionalGatherer +} + +// NewMultiTRegistry creates MultiTRegistry. +func NewMultiTRegistry(tGatherers ...TransactionalGatherer) *MultiTRegistry { + return &MultiTRegistry{ + tGatherers: tGatherers, + } +} + +// Gather implements TransactionalGatherer interface. +func (r *MultiTRegistry) Gather() (mfs []*dto.MetricFamily, done func(), err error) { + errs := MultiError{} + + dFns := make([]func(), 0, len(r.tGatherers)) + // TODO(bwplotka): Implement concurrency for those? + for _, g := range r.tGatherers { + // TODO(bwplotka): Check for duplicates? + m, d, err := g.Gather() + errs.Append(err) + + mfs = append(mfs, m...) + dFns = append(dFns, d) + } + + // TODO(bwplotka): Consider sort in place, given metric family in gather is sorted already. + sort.Slice(mfs, func(i, j int) bool { + return *mfs[i].Name < *mfs[j].Name + }) + return mfs, func() { + for _, d := range dFns { + d() + } + }, errs.MaybeUnwrap() +} + +// TransactionalGatherer represents transactional gatherer that can be triggered to notify gatherer that memory +// used by metric family is no longer used by a caller. This allows implementations with cache. +type TransactionalGatherer interface { + // Gather returns metrics in a lexicographically sorted slice + // of uniquely named MetricFamily protobufs. Gather ensures that the + // returned slice is valid and self-consistent so that it can be used + // for valid exposition. As an exception to the strict consistency + // requirements described for metric.Desc, Gather will tolerate + // different sets of label names for metrics of the same metric family. + // + // Even if an error occurs, Gather attempts to gather as many metrics as + // possible. Hence, if a non-nil error is returned, the returned + // MetricFamily slice could be nil (in case of a fatal error that + // prevented any meaningful metric collection) or contain a number of + // MetricFamily protobufs, some of which might be incomplete, and some + // might be missing altogether. The returned error (which might be a + // MultiError) explains the details. Note that this is mostly useful for + // debugging purposes. If the gathered protobufs are to be used for + // exposition in actual monitoring, it is almost always better to not + // expose an incomplete result and instead disregard the returned + // MetricFamily protobufs in case the returned error is non-nil. + // + // Important: done is expected to be triggered (even if the error occurs!) + // once caller does not need returned slice of dto.MetricFamily. + Gather() (_ []*dto.MetricFamily, done func(), err error) +} + +// ToTransactionalGatherer transforms Gatherer to transactional one with noop as done function. +func ToTransactionalGatherer(g Gatherer) TransactionalGatherer { + return &noTransactionGatherer{g: g} +} + +type noTransactionGatherer struct { + g Gatherer +} + +// Gather implements TransactionalGatherer interface. +func (g *noTransactionGatherer) Gather() (_ []*dto.MetricFamily, done func(), err error) { + mfs, err := g.g.Gather() + return mfs, func() {}, err +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index c5fa8ed7c..146270444 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go @@ -22,11 +22,11 @@ import ( "sync/atomic" "time" - "github.com/beorn7/perks/quantile" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" + + "github.com/beorn7/perks/quantile" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" ) // quantileLabel is used for the label that defines the quantile in a @@ -146,6 +146,21 @@ type SummaryOpts struct { // is the internal buffer size of the underlying package // "github.com/bmizerany/perks/quantile"). BufCap uint32 + + // now is for testing purposes, by default it's time.Now. + now func() time.Time +} + +// SummaryVecOpts bundles the options to create a SummaryVec metric. +// It is mandatory to set SummaryOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type SummaryVecOpts struct { + SummaryOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Constraint + // function, if provided. + VariableLabels ConstrainableLabels } // Problem with the sliding-window decay algorithm... The Merge method of @@ -177,11 +192,11 @@ func NewSummary(opts SummaryOpts) Summary { } func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { - if len(desc.variableLabels) != len(labelValues) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) + if len(desc.variableLabels.names) != len(labelValues) { + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.names, labelValues)) } - for _, n := range desc.variableLabels { + for _, n := range desc.variableLabels.names { if n == quantileLabel { panic(errQuantileLabelNotAllowed) } @@ -211,6 +226,9 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { opts.BufCap = DefBufCap } + if opts.now == nil { + opts.now = time.Now + } if len(opts.Objectives) == 0 { // Use the lock-free implementation of a Summary without objectives. s := &noObjectivesSummary{ @@ -219,6 +237,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { counts: [2]*summaryCounts{{}, {}}, } s.init(s) // Init self-collection. + s.createdTs = timestamppb.New(opts.now()) return s } @@ -234,7 +253,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { coldBuf: make([]float64, 0, opts.BufCap), streamDuration: opts.MaxAge / time.Duration(opts.AgeBuckets), } - s.headStreamExpTime = time.Now().Add(s.streamDuration) + s.headStreamExpTime = opts.now().Add(s.streamDuration) s.hotBufExpTime = s.headStreamExpTime for i := uint32(0); i < opts.AgeBuckets; i++ { @@ -248,6 +267,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { sort.Float64s(s.sortedObjectives) s.init(s) // Init self-collection. + s.createdTs = timestamppb.New(opts.now()) return s } @@ -275,6 +295,8 @@ type summary struct { headStream *quantile.Stream headStreamIdx int headStreamExpTime, hotBufExpTime time.Time + + createdTs *timestamppb.Timestamp } func (s *summary) Desc() *Desc { @@ -296,7 +318,9 @@ func (s *summary) Observe(v float64) { } func (s *summary) Write(out *dto.Metric) error { - sum := &dto.Summary{} + sum := &dto.Summary{ + CreatedTimestamp: s.createdTs, + } qs := make([]*dto.Quantile, 0, len(s.objectives)) s.bufMtx.Lock() @@ -429,6 +453,8 @@ type noObjectivesSummary struct { counts [2]*summaryCounts labelPairs []*dto.LabelPair + + createdTs *timestamppb.Timestamp } func (s *noObjectivesSummary) Desc() *Desc { @@ -479,8 +505,9 @@ func (s *noObjectivesSummary) Write(out *dto.Metric) error { } sum := &dto.Summary{ - SampleCount: proto.Uint64(count), - SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), + SampleCount: proto.Uint64(count), + SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), + CreatedTimestamp: s.createdTs, } out.Summary = sum @@ -530,20 +557,28 @@ type SummaryVec struct { // it is handled by the Prometheus server internally, “quantile” is an illegal // label name. NewSummaryVec will panic if this label name is used. func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec { - for _, ln := range labelNames { + return V2.NewSummaryVec(SummaryVecOpts{ + SummaryOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewSummaryVec creates a new SummaryVec based on the provided SummaryVecOpts. +func (v2) NewSummaryVec(opts SummaryVecOpts) *SummaryVec { + for _, ln := range opts.VariableLabels.labelNames() { if ln == quantileLabel { panic(errQuantileLabelNotAllowed) } } - desc := NewDesc( + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) return &SummaryVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { - return newSummary(desc, opts, lvs...) + return newSummary(desc, opts.SummaryOpts, lvs...) }), } } @@ -603,7 +638,8 @@ func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Observe(42.21) +// +// myVec.WithLabelValues("404", "GET").Observe(42.21) func (v *SummaryVec) WithLabelValues(lvs ...string) Observer { s, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -614,7 +650,8 @@ func (v *SummaryVec) WithLabelValues(lvs ...string) Observer { // With works as GetMetricWith, but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) func (v *SummaryVec) With(labels Labels) Observer { s, err := v.GetMetricWith(labels) if err != nil { @@ -660,6 +697,7 @@ type constSummary struct { sum float64 quantiles map[float64]float64 labelPairs []*dto.LabelPair + createdTs *timestamppb.Timestamp } func (s *constSummary) Desc() *Desc { @@ -667,7 +705,9 @@ func (s *constSummary) Desc() *Desc { } func (s *constSummary) Write(out *dto.Metric) error { - sum := &dto.Summary{} + sum := &dto.Summary{ + CreatedTimestamp: s.createdTs, + } qs := make([]*dto.Quantile, 0, len(s.quantiles)) sum.SampleCount = proto.Uint64(s.count) @@ -701,7 +741,8 @@ func (s *constSummary) Write(out *dto.Metric) error { // // quantiles maps ranks to quantile values. For example, a median latency of // 0.23s and a 99th percentile latency of 0.56s would be expressed as: -// map[float64]float64{0.5: 0.23, 0.99: 0.56} +// +// map[float64]float64{0.5: 0.23, 0.99: 0.56} // // NewConstSummary returns an error if the length of labelValues is not // consistent with the variable labels in Desc or if Desc is invalid. @@ -715,7 +756,7 @@ func NewConstSummary( if desc.err != nil { return nil, desc.err } - if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { + if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil { return nil, err } return &constSummary{ diff --git a/vendor/github.com/prometheus/client_golang/prometheus/timer.go b/vendor/github.com/prometheus/client_golang/prometheus/timer.go index 8d5f10523..52344fef5 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/timer.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/timer.go @@ -23,13 +23,24 @@ type Timer struct { } // NewTimer creates a new Timer. The provided Observer is used to observe a -// duration in seconds. Timer is usually used to time a function call in the +// duration in seconds. If the Observer implements ExemplarObserver, passing exemplar +// later on will be also supported. +// Timer is usually used to time a function call in the // following way: -// func TimeMe() { -// timer := NewTimer(myHistogram) -// defer timer.ObserveDuration() -// // Do actual work. -// } +// +// func TimeMe() { +// timer := NewTimer(myHistogram) +// defer timer.ObserveDuration() +// // Do actual work. +// } +// +// or +// +// func TimeMeWithExemplar() { +// timer := NewTimer(myHistogram) +// defer timer.ObserveDurationWithExemplar(exemplar) +// // Do actual work. +// } func NewTimer(o Observer) *Timer { return &Timer{ begin: time.Now(), @@ -52,3 +63,19 @@ func (t *Timer) ObserveDuration() time.Duration { } return d } + +// ObserveDurationWithExemplar is like ObserveDuration, but it will also +// observe exemplar with the duration unless exemplar is nil or provided Observer can't +// be casted to ExemplarObserver. +func (t *Timer) ObserveDurationWithExemplar(exemplar Labels) time.Duration { + d := time.Since(t.begin) + eo, ok := t.observer.(ExemplarObserver) + if ok && exemplar != nil { + eo.ObserveWithExemplar(d.Seconds(), exemplar) + return d + } + if t.observer != nil { + t.observer.Observe(d.Seconds()) + } + return d +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/value.go b/vendor/github.com/prometheus/client_golang/prometheus/value.go index c778711b8..cc23011fa 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/value.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/value.go @@ -14,16 +14,17 @@ package prometheus import ( + "errors" "fmt" "sort" "time" "unicode/utf8" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes" + "github.com/prometheus/client_golang/prometheus/internal" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" ) // ValueType is an enumeration of metric types that represent a simple value. @@ -38,6 +39,23 @@ const ( UntypedValue ) +var ( + CounterMetricTypePtr = func() *dto.MetricType { d := dto.MetricType_COUNTER; return &d }() + GaugeMetricTypePtr = func() *dto.MetricType { d := dto.MetricType_GAUGE; return &d }() + UntypedMetricTypePtr = func() *dto.MetricType { d := dto.MetricType_UNTYPED; return &d }() +) + +func (v ValueType) ToDTO() *dto.MetricType { + switch v { + case CounterValue: + return CounterMetricTypePtr + case GaugeValue: + return GaugeMetricTypePtr + default: + return UntypedMetricTypePtr + } +} + // valueFunc is a generic metric for simple values retrieved on collect time // from a function. It implements Metric and Collector. Its effective type is // determined by ValueType. This is a low-level building block used by the @@ -74,7 +92,7 @@ func (v *valueFunc) Desc() *Desc { } func (v *valueFunc) Write(out *dto.Metric) error { - return populateMetric(v.valType, v.function(), v.labelPairs, nil, out) + return populateMetric(v.valType, v.function(), v.labelPairs, nil, out, nil) } // NewConstMetric returns a metric with one fixed value that cannot be @@ -88,14 +106,18 @@ func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues if desc.err != nil { return nil, desc.err } - if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { + if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil { + return nil, err + } + + metric := &dto.Metric{} + if err := populateMetric(valueType, value, MakeLabelPairs(desc, labelValues), nil, metric, nil); err != nil { return nil, err } + return &constMetric{ - desc: desc, - valType: valueType, - val: value, - labelPairs: MakeLabelPairs(desc, labelValues), + desc: desc, + metric: metric, }, nil } @@ -109,11 +131,46 @@ func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelVal return m } +// NewConstMetricWithCreatedTimestamp does the same thing as NewConstMetric, but generates Counters +// with created timestamp set and returns an error for other metric types. +func NewConstMetricWithCreatedTimestamp(desc *Desc, valueType ValueType, value float64, ct time.Time, labelValues ...string) (Metric, error) { + if desc.err != nil { + return nil, desc.err + } + if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil { + return nil, err + } + switch valueType { + case CounterValue: + break + default: + return nil, errors.New("created timestamps are only supported for counters") + } + + metric := &dto.Metric{} + if err := populateMetric(valueType, value, MakeLabelPairs(desc, labelValues), nil, metric, timestamppb.New(ct)); err != nil { + return nil, err + } + + return &constMetric{ + desc: desc, + metric: metric, + }, nil +} + +// MustNewConstMetricWithCreatedTimestamp is a version of NewConstMetricWithCreatedTimestamp that panics where +// NewConstMetricWithCreatedTimestamp would have returned an error. +func MustNewConstMetricWithCreatedTimestamp(desc *Desc, valueType ValueType, value float64, ct time.Time, labelValues ...string) Metric { + m, err := NewConstMetricWithCreatedTimestamp(desc, valueType, value, ct, labelValues...) + if err != nil { + panic(err) + } + return m +} + type constMetric struct { - desc *Desc - valType ValueType - val float64 - labelPairs []*dto.LabelPair + desc *Desc + metric *dto.Metric } func (m *constMetric) Desc() *Desc { @@ -121,7 +178,11 @@ func (m *constMetric) Desc() *Desc { } func (m *constMetric) Write(out *dto.Metric) error { - return populateMetric(m.valType, m.val, m.labelPairs, nil, out) + out.Label = m.metric.Label + out.Counter = m.metric.Counter + out.Gauge = m.metric.Gauge + out.Untyped = m.metric.Untyped + return nil } func populateMetric( @@ -130,11 +191,12 @@ func populateMetric( labelPairs []*dto.LabelPair, e *dto.Exemplar, m *dto.Metric, + ct *timestamppb.Timestamp, ) error { m.Label = labelPairs switch t { case CounterValue: - m.Counter = &dto.Counter{Value: proto.Float64(v), Exemplar: e} + m.Counter = &dto.Counter{Value: proto.Float64(v), Exemplar: e, CreatedTimestamp: ct} case GaugeValue: m.Gauge = &dto.Gauge{Value: proto.Float64(v)} case UntypedValue: @@ -153,29 +215,29 @@ func populateMetric( // This function is only needed for custom Metric implementations. See MetricVec // example. func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair { - totalLen := len(desc.variableLabels) + len(desc.constLabelPairs) + totalLen := len(desc.variableLabels.names) + len(desc.constLabelPairs) if totalLen == 0 { // Super fast path. return nil } - if len(desc.variableLabels) == 0 { + if len(desc.variableLabels.names) == 0 { // Moderately fast path. return desc.constLabelPairs } labelPairs := make([]*dto.LabelPair, 0, totalLen) - for i, n := range desc.variableLabels { + for i, l := range desc.variableLabels.names { labelPairs = append(labelPairs, &dto.LabelPair{ - Name: proto.String(n), + Name: proto.String(l), Value: proto.String(labelValues[i]), }) } labelPairs = append(labelPairs, desc.constLabelPairs...) - sort.Sort(labelPairSorter(labelPairs)) + sort.Sort(internal.LabelPairSorter(labelPairs)) return labelPairs } // ExemplarMaxRunes is the max total number of runes allowed in exemplar labels. -const ExemplarMaxRunes = 64 +const ExemplarMaxRunes = 128 // newExemplar creates a new dto.Exemplar from the provided values. An error is // returned if any of the label names or values are invalid or if the total @@ -183,8 +245,8 @@ const ExemplarMaxRunes = 64 func newExemplar(value float64, ts time.Time, l Labels) (*dto.Exemplar, error) { e := &dto.Exemplar{} e.Value = proto.Float64(value) - tsProto, err := ptypes.TimestampProto(ts) - if err != nil { + tsProto := timestamppb.New(ts) + if err := tsProto.CheckValid(); err != nil { return nil, err } e.Timestamp = tsProto diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go index 4ababe6c9..955cfd59f 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go @@ -72,6 +72,8 @@ func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec { // with a performance overhead (for creating and processing the Labels map). // See also the CounterVec example. func (m *MetricVec) DeleteLabelValues(lvs ...string) bool { + lvs = constrainLabelValues(m.desc, lvs, m.curry) + h, err := m.hashLabelValues(lvs) if err != nil { return false @@ -91,6 +93,9 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool { // This method is used for the same purpose as DeleteLabelValues(...string). See // there for pros and cons of the two methods. func (m *MetricVec) Delete(labels Labels) bool { + labels, closer := constrainLabels(m.desc, labels) + defer closer() + h, err := m.hashLabels(labels) if err != nil { return false @@ -99,6 +104,19 @@ func (m *MetricVec) Delete(labels Labels) bool { return m.metricMap.deleteByHashWithLabels(h, labels, m.curry) } +// DeletePartialMatch deletes all metrics where the variable labels contain all of those +// passed in as labels. The order of the labels does not matter. +// It returns the number of metrics deleted. +// +// Note that curried labels will never be matched if deleting from the curried vector. +// To match curried labels with DeletePartialMatch, it must be called on the base vector. +func (m *MetricVec) DeletePartialMatch(labels Labels) int { + labels, closer := constrainLabels(m.desc, labels) + defer closer() + + return m.metricMap.deleteByLabels(labels, m.curry) +} + // Without explicit forwarding of Describe, Collect, Reset, those methods won't // show up in GoDoc. @@ -134,11 +152,11 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) { oldCurry = m.curry iCurry int ) - for i, label := range m.desc.variableLabels { - val, ok := labels[label] + for i, labelName := range m.desc.variableLabels.names { + val, ok := labels[labelName] if iCurry < len(oldCurry) && oldCurry[iCurry].index == i { if ok { - return nil, fmt.Errorf("label name %q is already curried", label) + return nil, fmt.Errorf("label name %q is already curried", labelName) } newCurry = append(newCurry, oldCurry[iCurry]) iCurry++ @@ -146,7 +164,10 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) { if !ok { continue // Label stays uncurried. } - newCurry = append(newCurry, curriedLabelValue{i, val}) + newCurry = append(newCurry, curriedLabelValue{ + i, + m.desc.variableLabels.constrain(labelName, val), + }) } } if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 { @@ -189,6 +210,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) { // a wrapper around MetricVec, implementing a vector for a specific Metric // implementation, for example GaugeVec. func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) { + lvs = constrainLabelValues(m.desc, lvs, m.curry) h, err := m.hashLabelValues(lvs) if err != nil { return nil, err @@ -214,6 +236,9 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) { // around MetricVec, implementing a vector for a specific Metric implementation, // for example GaugeVec. func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) { + labels, closer := constrainLabels(m.desc, labels) + defer closer() + h, err := m.hashLabels(labels) if err != nil { return nil, err @@ -223,7 +248,7 @@ func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) { } func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) { - if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil { + if err := validateLabelValues(vals, len(m.desc.variableLabels.names)-len(m.curry)); err != nil { return 0, err } @@ -232,7 +257,7 @@ func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) { curry = m.curry iVals, iCurry int ) - for i := 0; i < len(m.desc.variableLabels); i++ { + for i := 0; i < len(m.desc.variableLabels.names); i++ { if iCurry < len(curry) && curry[iCurry].index == i { h = m.hashAdd(h, curry[iCurry].value) iCurry++ @@ -246,7 +271,7 @@ func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) { } func (m *MetricVec) hashLabels(labels Labels) (uint64, error) { - if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil { + if err := validateValuesInLabels(labels, len(m.desc.variableLabels.names)-len(m.curry)); err != nil { return 0, err } @@ -255,17 +280,17 @@ func (m *MetricVec) hashLabels(labels Labels) (uint64, error) { curry = m.curry iCurry int ) - for i, label := range m.desc.variableLabels { - val, ok := labels[label] + for i, labelName := range m.desc.variableLabels.names { + val, ok := labels[labelName] if iCurry < len(curry) && curry[iCurry].index == i { if ok { - return 0, fmt.Errorf("label name %q is already curried", label) + return 0, fmt.Errorf("label name %q is already curried", labelName) } h = m.hashAdd(h, curry[iCurry].value) iCurry++ } else { if !ok { - return 0, fmt.Errorf("label name %q missing in label map", label) + return 0, fmt.Errorf("label name %q missing in label map", labelName) } h = m.hashAdd(h, val) } @@ -381,6 +406,82 @@ func (m *metricMap) deleteByHashWithLabels( return true } +// deleteByLabels deletes a metric if the given labels are present in the metric. +func (m *metricMap) deleteByLabels(labels Labels, curry []curriedLabelValue) int { + m.mtx.Lock() + defer m.mtx.Unlock() + + var numDeleted int + + for h, metrics := range m.metrics { + i := findMetricWithPartialLabels(m.desc, metrics, labels, curry) + if i >= len(metrics) { + // Didn't find matching labels in this metric slice. + continue + } + delete(m.metrics, h) + numDeleted++ + } + + return numDeleted +} + +// findMetricWithPartialLabel returns the index of the matching metric or +// len(metrics) if not found. +func findMetricWithPartialLabels( + desc *Desc, metrics []metricWithLabelValues, labels Labels, curry []curriedLabelValue, +) int { + for i, metric := range metrics { + if matchPartialLabels(desc, metric.values, labels, curry) { + return i + } + } + return len(metrics) +} + +// indexOf searches the given slice of strings for the target string and returns +// the index or len(items) as well as a boolean whether the search succeeded. +func indexOf(target string, items []string) (int, bool) { + for i, l := range items { + if l == target { + return i, true + } + } + return len(items), false +} + +// valueMatchesVariableOrCurriedValue determines if a value was previously curried, +// and returns whether it matches either the "base" value or the curried value accordingly. +// It also indicates whether the match is against a curried or uncurried value. +func valueMatchesVariableOrCurriedValue(targetValue string, index int, values []string, curry []curriedLabelValue) (bool, bool) { + for _, curriedValue := range curry { + if curriedValue.index == index { + // This label was curried. See if the curried value matches our target. + return curriedValue.value == targetValue, true + } + } + // This label was not curried. See if the current value matches our target label. + return values[index] == targetValue, false +} + +// matchPartialLabels searches the current metric and returns whether all of the target label:value pairs are present. +func matchPartialLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool { + for l, v := range labels { + // Check if the target label exists in our metrics and get the index. + varLabelIndex, validLabel := indexOf(l, desc.variableLabels.names) + if validLabel { + // Check the value of that label against the target value. + // We don't consider curried values in partial matches. + matches, curried := valueMatchesVariableOrCurriedValue(v, varLabelIndex, values, curry) + if matches && !curried { + continue + } + } + return false + } + return true +} + // getOrCreateMetricWithLabelValues retrieves the metric by hash and label value // or creates it and returns the new one. // @@ -485,7 +586,7 @@ func findMetricWithLabels( return len(metrics) } -func matchLabelValues(values []string, lvs []string, curry []curriedLabelValue) bool { +func matchLabelValues(values, lvs []string, curry []curriedLabelValue) bool { if len(values) != len(lvs)+len(curry) { return false } @@ -511,7 +612,7 @@ func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabe return false } iCurry := 0 - for i, k := range desc.variableLabels { + for i, k := range desc.variableLabels.names { if iCurry < len(curry) && curry[iCurry].index == i { if values[i] != curry[iCurry].value { return false @@ -529,7 +630,7 @@ func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabe func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) []string { labelValues := make([]string, len(labels)+len(curry)) iCurry := 0 - for i, k := range desc.variableLabels { + for i, k := range desc.variableLabels.names { if iCurry < len(curry) && curry[iCurry].index == i { labelValues[i] = curry[iCurry].value iCurry++ @@ -554,3 +655,55 @@ func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string { } return labelValues } + +var labelsPool = &sync.Pool{ + New: func() interface{} { + return make(Labels) + }, +} + +func constrainLabels(desc *Desc, labels Labels) (Labels, func()) { + if len(desc.variableLabels.labelConstraints) == 0 { + // Fast path when there's no constraints + return labels, func() {} + } + + constrainedLabels := labelsPool.Get().(Labels) + for l, v := range labels { + constrainedLabels[l] = desc.variableLabels.constrain(l, v) + } + + return constrainedLabels, func() { + for k := range constrainedLabels { + delete(constrainedLabels, k) + } + labelsPool.Put(constrainedLabels) + } +} + +func constrainLabelValues(desc *Desc, lvs []string, curry []curriedLabelValue) []string { + if len(desc.variableLabels.labelConstraints) == 0 { + // Fast path when there's no constraints + return lvs + } + + constrainedValues := make([]string, len(lvs)) + var iCurry, iLVs int + for i := 0; i < len(lvs)+len(curry); i++ { + if iCurry < len(curry) && curry[iCurry].index == i { + iCurry++ + continue + } + + if i < len(desc.variableLabels.names) { + constrainedValues[iLVs] = desc.variableLabels.constrain( + desc.variableLabels.names[i], + lvs[iLVs], + ) + } else { + constrainedValues[iLVs] = lvs[iLVs] + } + iLVs++ + } + return constrainedValues +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vnext.go b/vendor/github.com/prometheus/client_golang/prometheus/vnext.go new file mode 100644 index 000000000..42bc3a8f0 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/vnext.go @@ -0,0 +1,23 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prometheus + +type v2 struct{} + +// V2 is a struct that can be referenced to access experimental API that might +// be present in v2 of client golang someday. It offers extended functionality +// of v1 with slightly changed API. It is acceptable to use some pieces from v1 +// and e.g `prometheus.NewGauge` and some from v2 e.g. `prometheus.V2.NewDesc` +// in the same codebase. +var V2 = v2{} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go index 74ee93280..25da157f1 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go @@ -17,10 +17,10 @@ import ( "fmt" "sort" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" + "github.com/prometheus/client_golang/prometheus/internal" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" ) // WrapRegistererWith returns a Registerer wrapping the provided @@ -182,7 +182,7 @@ func (m *wrappingMetric) Write(out *dto.Metric) error { Value: proto.String(lv), }) } - sort.Sort(labelPairSorter(out.Label)) + sort.Sort(internal.LabelPairSorter(out.Label)) return nil } @@ -204,7 +204,7 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc { constLabels[ln] = lv } // NewDesc will do remaining validations. - newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) + newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) // Propagate errors if there was any. This will override any errer // created by NewDesc above, i.e. earlier errors get precedence. if desc.err != nil { diff --git a/vendor/github.com/prometheus/client_model/go/metrics.pb.go b/vendor/github.com/prometheus/client_model/go/metrics.pb.go index 2f4930d9d..cee360db7 100644 --- a/vendor/github.com/prometheus/client_model/go/metrics.pb.go +++ b/vendor/github.com/prometheus/client_model/go/metrics.pb.go @@ -1,51 +1,75 @@ +// Copyright 2013 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by protoc-gen-go. DO NOT EDIT. -// source: metrics.proto +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.20.3 +// source: io/prometheus/client/metrics.proto package io_prometheus_client import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - timestamp "github.com/golang/protobuf/ptypes/timestamp" - math "math" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) type MetricType int32 const ( - MetricType_COUNTER MetricType = 0 - MetricType_GAUGE MetricType = 1 - MetricType_SUMMARY MetricType = 2 - MetricType_UNTYPED MetricType = 3 + // COUNTER must use the Metric field "counter". + MetricType_COUNTER MetricType = 0 + // GAUGE must use the Metric field "gauge". + MetricType_GAUGE MetricType = 1 + // SUMMARY must use the Metric field "summary". + MetricType_SUMMARY MetricType = 2 + // UNTYPED must use the Metric field "untyped". + MetricType_UNTYPED MetricType = 3 + // HISTOGRAM must use the Metric field "histogram". MetricType_HISTOGRAM MetricType = 4 + // GAUGE_HISTOGRAM must use the Metric field "histogram". + MetricType_GAUGE_HISTOGRAM MetricType = 5 ) -var MetricType_name = map[int32]string{ - 0: "COUNTER", - 1: "GAUGE", - 2: "SUMMARY", - 3: "UNTYPED", - 4: "HISTOGRAM", -} - -var MetricType_value = map[string]int32{ - "COUNTER": 0, - "GAUGE": 1, - "SUMMARY": 2, - "UNTYPED": 3, - "HISTOGRAM": 4, -} +// Enum value maps for MetricType. +var ( + MetricType_name = map[int32]string{ + 0: "COUNTER", + 1: "GAUGE", + 2: "SUMMARY", + 3: "UNTYPED", + 4: "HISTOGRAM", + 5: "GAUGE_HISTOGRAM", + } + MetricType_value = map[string]int32{ + "COUNTER": 0, + "GAUGE": 1, + "SUMMARY": 2, + "UNTYPED": 3, + "HISTOGRAM": 4, + "GAUGE_HISTOGRAM": 5, + } +) func (x MetricType) Enum() *MetricType { p := new(MetricType) @@ -54,670 +78,1299 @@ func (x MetricType) Enum() *MetricType { } func (x MetricType) String() string { - return proto.EnumName(MetricType_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MetricType) Descriptor() protoreflect.EnumDescriptor { + return file_io_prometheus_client_metrics_proto_enumTypes[0].Descriptor() +} + +func (MetricType) Type() protoreflect.EnumType { + return &file_io_prometheus_client_metrics_proto_enumTypes[0] +} + +func (x MetricType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) } -func (x *MetricType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MetricType_value, data, "MetricType") +// Deprecated: Do not use. +func (x *MetricType) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } - *x = MetricType(value) + *x = MetricType(num) return nil } +// Deprecated: Use MetricType.Descriptor instead. func (MetricType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{0} + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{0} } type LabelPair struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *LabelPair) Reset() { *m = LabelPair{} } -func (m *LabelPair) String() string { return proto.CompactTextString(m) } -func (*LabelPair) ProtoMessage() {} -func (*LabelPair) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{0} + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` } -func (m *LabelPair) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LabelPair.Unmarshal(m, b) -} -func (m *LabelPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LabelPair.Marshal(b, m, deterministic) -} -func (m *LabelPair) XXX_Merge(src proto.Message) { - xxx_messageInfo_LabelPair.Merge(m, src) +func (x *LabelPair) Reset() { + *x = LabelPair{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *LabelPair) XXX_Size() int { - return xxx_messageInfo_LabelPair.Size(m) + +func (x *LabelPair) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *LabelPair) XXX_DiscardUnknown() { - xxx_messageInfo_LabelPair.DiscardUnknown(m) + +func (*LabelPair) ProtoMessage() {} + +func (x *LabelPair) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_LabelPair proto.InternalMessageInfo +// Deprecated: Use LabelPair.ProtoReflect.Descriptor instead. +func (*LabelPair) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{0} +} -func (m *LabelPair) GetName() string { - if m != nil && m.Name != nil { - return *m.Name +func (x *LabelPair) GetName() string { + if x != nil && x.Name != nil { + return *x.Name } return "" } -func (m *LabelPair) GetValue() string { - if m != nil && m.Value != nil { - return *m.Value +func (x *LabelPair) GetValue() string { + if x != nil && x.Value != nil { + return *x.Value } return "" } type Gauge struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Gauge) Reset() { *m = Gauge{} } -func (m *Gauge) String() string { return proto.CompactTextString(m) } -func (*Gauge) ProtoMessage() {} -func (*Gauge) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{1} + Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` } -func (m *Gauge) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Gauge.Unmarshal(m, b) -} -func (m *Gauge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Gauge.Marshal(b, m, deterministic) -} -func (m *Gauge) XXX_Merge(src proto.Message) { - xxx_messageInfo_Gauge.Merge(m, src) +func (x *Gauge) Reset() { + *x = Gauge{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Gauge) XXX_Size() int { - return xxx_messageInfo_Gauge.Size(m) + +func (x *Gauge) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Gauge) XXX_DiscardUnknown() { - xxx_messageInfo_Gauge.DiscardUnknown(m) + +func (*Gauge) ProtoMessage() {} + +func (x *Gauge) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Gauge proto.InternalMessageInfo +// Deprecated: Use Gauge.ProtoReflect.Descriptor instead. +func (*Gauge) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{1} +} -func (m *Gauge) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Gauge) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } type Counter struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar" json:"exemplar,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Counter) Reset() { *m = Counter{} } -func (m *Counter) String() string { return proto.CompactTextString(m) } -func (*Counter) ProtoMessage() {} -func (*Counter) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{2} + Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` + Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar" json:"exemplar,omitempty"` + CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created_timestamp,json=createdTimestamp" json:"created_timestamp,omitempty"` } -func (m *Counter) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Counter.Unmarshal(m, b) -} -func (m *Counter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Counter.Marshal(b, m, deterministic) -} -func (m *Counter) XXX_Merge(src proto.Message) { - xxx_messageInfo_Counter.Merge(m, src) +func (x *Counter) Reset() { + *x = Counter{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Counter) XXX_Size() int { - return xxx_messageInfo_Counter.Size(m) + +func (x *Counter) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Counter) XXX_DiscardUnknown() { - xxx_messageInfo_Counter.DiscardUnknown(m) + +func (*Counter) ProtoMessage() {} + +func (x *Counter) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Counter proto.InternalMessageInfo +// Deprecated: Use Counter.ProtoReflect.Descriptor instead. +func (*Counter) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{2} +} -func (m *Counter) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Counter) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } -func (m *Counter) GetExemplar() *Exemplar { - if m != nil { - return m.Exemplar +func (x *Counter) GetExemplar() *Exemplar { + if x != nil { + return x.Exemplar } return nil } -type Quantile struct { - Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"` - Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +func (x *Counter) GetCreatedTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.CreatedTimestamp + } + return nil } -func (m *Quantile) Reset() { *m = Quantile{} } -func (m *Quantile) String() string { return proto.CompactTextString(m) } -func (*Quantile) ProtoMessage() {} -func (*Quantile) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{3} -} +type Quantile struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Quantile) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Quantile.Unmarshal(m, b) + Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"` + Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` } -func (m *Quantile) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Quantile.Marshal(b, m, deterministic) -} -func (m *Quantile) XXX_Merge(src proto.Message) { - xxx_messageInfo_Quantile.Merge(m, src) + +func (x *Quantile) Reset() { + *x = Quantile{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Quantile) XXX_Size() int { - return xxx_messageInfo_Quantile.Size(m) + +func (x *Quantile) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Quantile) XXX_DiscardUnknown() { - xxx_messageInfo_Quantile.DiscardUnknown(m) + +func (*Quantile) ProtoMessage() {} + +func (x *Quantile) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Quantile proto.InternalMessageInfo +// Deprecated: Use Quantile.ProtoReflect.Descriptor instead. +func (*Quantile) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{3} +} -func (m *Quantile) GetQuantile() float64 { - if m != nil && m.Quantile != nil { - return *m.Quantile +func (x *Quantile) GetQuantile() float64 { + if x != nil && x.Quantile != nil { + return *x.Quantile } return 0 } -func (m *Quantile) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Quantile) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } type Summary struct { - SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` - SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` - Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` + SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` + Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"` + CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_timestamp,json=createdTimestamp" json:"created_timestamp,omitempty"` +} + +func (x *Summary) Reset() { + *x = Summary{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Summary) Reset() { *m = Summary{} } -func (m *Summary) String() string { return proto.CompactTextString(m) } -func (*Summary) ProtoMessage() {} -func (*Summary) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{4} +func (x *Summary) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Summary) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Summary.Unmarshal(m, b) -} -func (m *Summary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Summary.Marshal(b, m, deterministic) -} -func (m *Summary) XXX_Merge(src proto.Message) { - xxx_messageInfo_Summary.Merge(m, src) -} -func (m *Summary) XXX_Size() int { - return xxx_messageInfo_Summary.Size(m) -} -func (m *Summary) XXX_DiscardUnknown() { - xxx_messageInfo_Summary.DiscardUnknown(m) +func (*Summary) ProtoMessage() {} + +func (x *Summary) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Summary proto.InternalMessageInfo +// Deprecated: Use Summary.ProtoReflect.Descriptor instead. +func (*Summary) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{4} +} -func (m *Summary) GetSampleCount() uint64 { - if m != nil && m.SampleCount != nil { - return *m.SampleCount +func (x *Summary) GetSampleCount() uint64 { + if x != nil && x.SampleCount != nil { + return *x.SampleCount } return 0 } -func (m *Summary) GetSampleSum() float64 { - if m != nil && m.SampleSum != nil { - return *m.SampleSum +func (x *Summary) GetSampleSum() float64 { + if x != nil && x.SampleSum != nil { + return *x.SampleSum } return 0 } -func (m *Summary) GetQuantile() []*Quantile { - if m != nil { - return m.Quantile +func (x *Summary) GetQuantile() []*Quantile { + if x != nil { + return x.Quantile } return nil } -type Untyped struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +func (x *Summary) GetCreatedTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.CreatedTimestamp + } + return nil } -func (m *Untyped) Reset() { *m = Untyped{} } -func (m *Untyped) String() string { return proto.CompactTextString(m) } -func (*Untyped) ProtoMessage() {} -func (*Untyped) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{5} -} +type Untyped struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Untyped) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Untyped.Unmarshal(m, b) -} -func (m *Untyped) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Untyped.Marshal(b, m, deterministic) + Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` } -func (m *Untyped) XXX_Merge(src proto.Message) { - xxx_messageInfo_Untyped.Merge(m, src) + +func (x *Untyped) Reset() { + *x = Untyped{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Untyped) XXX_Size() int { - return xxx_messageInfo_Untyped.Size(m) + +func (x *Untyped) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Untyped) XXX_DiscardUnknown() { - xxx_messageInfo_Untyped.DiscardUnknown(m) + +func (*Untyped) ProtoMessage() {} + +func (x *Untyped) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Untyped proto.InternalMessageInfo +// Deprecated: Use Untyped.ProtoReflect.Descriptor instead. +func (*Untyped) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{5} +} -func (m *Untyped) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Untyped) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } type Histogram struct { - SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` - SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` - Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` + SampleCountFloat *float64 `protobuf:"fixed64,4,opt,name=sample_count_float,json=sampleCountFloat" json:"sample_count_float,omitempty"` // Overrides sample_count if > 0. + SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` + // Buckets for the conventional histogram. + Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"` // Ordered in increasing order of upper_bound, +Inf bucket is optional. + CreatedTimestamp *timestamppb.Timestamp `protobuf:"bytes,15,opt,name=created_timestamp,json=createdTimestamp" json:"created_timestamp,omitempty"` + // schema defines the bucket schema. Currently, valid numbers are -4 <= n <= 8. + // They are all for base-2 bucket schemas, where 1 is a bucket boundary in each case, and + // then each power of two is divided into 2^n logarithmic buckets. + // Or in other words, each bucket boundary is the previous boundary times 2^(2^-n). + // In the future, more bucket schemas may be added using numbers < -4 or > 8. + Schema *int32 `protobuf:"zigzag32,5,opt,name=schema" json:"schema,omitempty"` + ZeroThreshold *float64 `protobuf:"fixed64,6,opt,name=zero_threshold,json=zeroThreshold" json:"zero_threshold,omitempty"` // Breadth of the zero bucket. + ZeroCount *uint64 `protobuf:"varint,7,opt,name=zero_count,json=zeroCount" json:"zero_count,omitempty"` // Count in zero bucket. + ZeroCountFloat *float64 `protobuf:"fixed64,8,opt,name=zero_count_float,json=zeroCountFloat" json:"zero_count_float,omitempty"` // Overrides sb_zero_count if > 0. + // Negative buckets for the native histogram. + NegativeSpan []*BucketSpan `protobuf:"bytes,9,rep,name=negative_span,json=negativeSpan" json:"negative_span,omitempty"` + // Use either "negative_delta" or "negative_count", the former for + // regular histograms with integer counts, the latter for float + // histograms. + NegativeDelta []int64 `protobuf:"zigzag64,10,rep,name=negative_delta,json=negativeDelta" json:"negative_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). + NegativeCount []float64 `protobuf:"fixed64,11,rep,name=negative_count,json=negativeCount" json:"negative_count,omitempty"` // Absolute count of each bucket. + // Positive buckets for the native histogram. + // Use a no-op span (offset 0, length 0) for a native histogram without any + // observations yet and with a zero_threshold of 0. Otherwise, it would be + // indistinguishable from a classic histogram. + PositiveSpan []*BucketSpan `protobuf:"bytes,12,rep,name=positive_span,json=positiveSpan" json:"positive_span,omitempty"` + // Use either "positive_delta" or "positive_count", the former for + // regular histograms with integer counts, the latter for float + // histograms. + PositiveDelta []int64 `protobuf:"zigzag64,13,rep,name=positive_delta,json=positiveDelta" json:"positive_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). + PositiveCount []float64 `protobuf:"fixed64,14,rep,name=positive_count,json=positiveCount" json:"positive_count,omitempty"` // Absolute count of each bucket. +} + +func (x *Histogram) Reset() { + *x = Histogram{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Histogram) Reset() { *m = Histogram{} } -func (m *Histogram) String() string { return proto.CompactTextString(m) } -func (*Histogram) ProtoMessage() {} +func (x *Histogram) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Histogram) ProtoMessage() {} + +func (x *Histogram) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Histogram.ProtoReflect.Descriptor instead. func (*Histogram) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{6} + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{6} } -func (m *Histogram) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Histogram.Unmarshal(m, b) +func (x *Histogram) GetSampleCount() uint64 { + if x != nil && x.SampleCount != nil { + return *x.SampleCount + } + return 0 } -func (m *Histogram) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Histogram.Marshal(b, m, deterministic) + +func (x *Histogram) GetSampleCountFloat() float64 { + if x != nil && x.SampleCountFloat != nil { + return *x.SampleCountFloat + } + return 0 } -func (m *Histogram) XXX_Merge(src proto.Message) { - xxx_messageInfo_Histogram.Merge(m, src) + +func (x *Histogram) GetSampleSum() float64 { + if x != nil && x.SampleSum != nil { + return *x.SampleSum + } + return 0 } -func (m *Histogram) XXX_Size() int { - return xxx_messageInfo_Histogram.Size(m) + +func (x *Histogram) GetBucket() []*Bucket { + if x != nil { + return x.Bucket + } + return nil } -func (m *Histogram) XXX_DiscardUnknown() { - xxx_messageInfo_Histogram.DiscardUnknown(m) + +func (x *Histogram) GetCreatedTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.CreatedTimestamp + } + return nil +} + +func (x *Histogram) GetSchema() int32 { + if x != nil && x.Schema != nil { + return *x.Schema + } + return 0 } -var xxx_messageInfo_Histogram proto.InternalMessageInfo +func (x *Histogram) GetZeroThreshold() float64 { + if x != nil && x.ZeroThreshold != nil { + return *x.ZeroThreshold + } + return 0 +} -func (m *Histogram) GetSampleCount() uint64 { - if m != nil && m.SampleCount != nil { - return *m.SampleCount +func (x *Histogram) GetZeroCount() uint64 { + if x != nil && x.ZeroCount != nil { + return *x.ZeroCount } return 0 } -func (m *Histogram) GetSampleSum() float64 { - if m != nil && m.SampleSum != nil { - return *m.SampleSum +func (x *Histogram) GetZeroCountFloat() float64 { + if x != nil && x.ZeroCountFloat != nil { + return *x.ZeroCountFloat } return 0 } -func (m *Histogram) GetBucket() []*Bucket { - if m != nil { - return m.Bucket +func (x *Histogram) GetNegativeSpan() []*BucketSpan { + if x != nil { + return x.NegativeSpan } return nil } -type Bucket struct { - CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"` - UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"` - Exemplar *Exemplar `protobuf:"bytes,3,opt,name=exemplar" json:"exemplar,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +func (x *Histogram) GetNegativeDelta() []int64 { + if x != nil { + return x.NegativeDelta + } + return nil } -func (m *Bucket) Reset() { *m = Bucket{} } -func (m *Bucket) String() string { return proto.CompactTextString(m) } -func (*Bucket) ProtoMessage() {} -func (*Bucket) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{7} +func (x *Histogram) GetNegativeCount() []float64 { + if x != nil { + return x.NegativeCount + } + return nil } -func (m *Bucket) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Bucket.Unmarshal(m, b) +func (x *Histogram) GetPositiveSpan() []*BucketSpan { + if x != nil { + return x.PositiveSpan + } + return nil } -func (m *Bucket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Bucket.Marshal(b, m, deterministic) + +func (x *Histogram) GetPositiveDelta() []int64 { + if x != nil { + return x.PositiveDelta + } + return nil } -func (m *Bucket) XXX_Merge(src proto.Message) { - xxx_messageInfo_Bucket.Merge(m, src) + +func (x *Histogram) GetPositiveCount() []float64 { + if x != nil { + return x.PositiveCount + } + return nil } -func (m *Bucket) XXX_Size() int { - return xxx_messageInfo_Bucket.Size(m) + +// A Bucket of a conventional histogram, each of which is treated as +// an individual counter-like time series by Prometheus. +type Bucket struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"` // Cumulative in increasing order. + CumulativeCountFloat *float64 `protobuf:"fixed64,4,opt,name=cumulative_count_float,json=cumulativeCountFloat" json:"cumulative_count_float,omitempty"` // Overrides cumulative_count if > 0. + UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"` // Inclusive. + Exemplar *Exemplar `protobuf:"bytes,3,opt,name=exemplar" json:"exemplar,omitempty"` +} + +func (x *Bucket) Reset() { + *x = Bucket{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Bucket) XXX_DiscardUnknown() { - xxx_messageInfo_Bucket.DiscardUnknown(m) + +func (x *Bucket) String() string { + return protoimpl.X.MessageStringOf(x) } -var xxx_messageInfo_Bucket proto.InternalMessageInfo +func (*Bucket) ProtoMessage() {} -func (m *Bucket) GetCumulativeCount() uint64 { - if m != nil && m.CumulativeCount != nil { - return *m.CumulativeCount +func (x *Bucket) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Bucket.ProtoReflect.Descriptor instead. +func (*Bucket) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{7} +} + +func (x *Bucket) GetCumulativeCount() uint64 { + if x != nil && x.CumulativeCount != nil { + return *x.CumulativeCount + } + return 0 +} + +func (x *Bucket) GetCumulativeCountFloat() float64 { + if x != nil && x.CumulativeCountFloat != nil { + return *x.CumulativeCountFloat } return 0 } -func (m *Bucket) GetUpperBound() float64 { - if m != nil && m.UpperBound != nil { - return *m.UpperBound +func (x *Bucket) GetUpperBound() float64 { + if x != nil && x.UpperBound != nil { + return *x.UpperBound } return 0 } -func (m *Bucket) GetExemplar() *Exemplar { - if m != nil { - return m.Exemplar +func (x *Bucket) GetExemplar() *Exemplar { + if x != nil { + return x.Exemplar } return nil } -type Exemplar struct { - Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` - Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` - Timestamp *timestamp.Timestamp `protobuf:"bytes,3,opt,name=timestamp" json:"timestamp,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +// A BucketSpan defines a number of consecutive buckets in a native +// histogram with their offset. Logically, it would be more +// straightforward to include the bucket counts in the Span. However, +// the protobuf representation is more compact in the way the data is +// structured here (with all the buckets in a single array separate +// from the Spans). +type BucketSpan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Offset *int32 `protobuf:"zigzag32,1,opt,name=offset" json:"offset,omitempty"` // Gap to previous span, or starting point for 1st span (which can be negative). + Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` // Length of consecutive buckets. } -func (m *Exemplar) Reset() { *m = Exemplar{} } -func (m *Exemplar) String() string { return proto.CompactTextString(m) } -func (*Exemplar) ProtoMessage() {} -func (*Exemplar) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{8} +func (x *BucketSpan) Reset() { + *x = BucketSpan{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Exemplar) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Exemplar.Unmarshal(m, b) +func (x *BucketSpan) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Exemplar) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Exemplar.Marshal(b, m, deterministic) + +func (*BucketSpan) ProtoMessage() {} + +func (x *BucketSpan) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *Exemplar) XXX_Merge(src proto.Message) { - xxx_messageInfo_Exemplar.Merge(m, src) + +// Deprecated: Use BucketSpan.ProtoReflect.Descriptor instead. +func (*BucketSpan) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{8} } -func (m *Exemplar) XXX_Size() int { - return xxx_messageInfo_Exemplar.Size(m) + +func (x *BucketSpan) GetOffset() int32 { + if x != nil && x.Offset != nil { + return *x.Offset + } + return 0 } -func (m *Exemplar) XXX_DiscardUnknown() { - xxx_messageInfo_Exemplar.DiscardUnknown(m) + +func (x *BucketSpan) GetLength() uint32 { + if x != nil && x.Length != nil { + return *x.Length + } + return 0 } -var xxx_messageInfo_Exemplar proto.InternalMessageInfo +type Exemplar struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` + Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp" json:"timestamp,omitempty"` // OpenMetrics-style. +} + +func (x *Exemplar) Reset() { + *x = Exemplar{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Exemplar) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Exemplar) ProtoMessage() {} + +func (x *Exemplar) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Exemplar.ProtoReflect.Descriptor instead. +func (*Exemplar) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{9} +} -func (m *Exemplar) GetLabel() []*LabelPair { - if m != nil { - return m.Label +func (x *Exemplar) GetLabel() []*LabelPair { + if x != nil { + return x.Label } return nil } -func (m *Exemplar) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Exemplar) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } -func (m *Exemplar) GetTimestamp() *timestamp.Timestamp { - if m != nil { - return m.Timestamp +func (x *Exemplar) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp } return nil } type Metric struct { - Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` - Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"` - Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"` - Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"` - Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"` - Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"` - TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Metric) Reset() { *m = Metric{} } -func (m *Metric) String() string { return proto.CompactTextString(m) } -func (*Metric) ProtoMessage() {} -func (*Metric) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{9} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` + Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"` + Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"` + Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"` + Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"` + Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"` + TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"` +} + +func (x *Metric) Reset() { + *x = Metric{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Metric) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Metric.Unmarshal(m, b) -} -func (m *Metric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Metric.Marshal(b, m, deterministic) +func (x *Metric) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Metric) XXX_Merge(src proto.Message) { - xxx_messageInfo_Metric.Merge(m, src) -} -func (m *Metric) XXX_Size() int { - return xxx_messageInfo_Metric.Size(m) -} -func (m *Metric) XXX_DiscardUnknown() { - xxx_messageInfo_Metric.DiscardUnknown(m) + +func (*Metric) ProtoMessage() {} + +func (x *Metric) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Metric proto.InternalMessageInfo +// Deprecated: Use Metric.ProtoReflect.Descriptor instead. +func (*Metric) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{10} +} -func (m *Metric) GetLabel() []*LabelPair { - if m != nil { - return m.Label +func (x *Metric) GetLabel() []*LabelPair { + if x != nil { + return x.Label } return nil } -func (m *Metric) GetGauge() *Gauge { - if m != nil { - return m.Gauge +func (x *Metric) GetGauge() *Gauge { + if x != nil { + return x.Gauge } return nil } -func (m *Metric) GetCounter() *Counter { - if m != nil { - return m.Counter +func (x *Metric) GetCounter() *Counter { + if x != nil { + return x.Counter } return nil } -func (m *Metric) GetSummary() *Summary { - if m != nil { - return m.Summary +func (x *Metric) GetSummary() *Summary { + if x != nil { + return x.Summary } return nil } -func (m *Metric) GetUntyped() *Untyped { - if m != nil { - return m.Untyped +func (x *Metric) GetUntyped() *Untyped { + if x != nil { + return x.Untyped } return nil } -func (m *Metric) GetHistogram() *Histogram { - if m != nil { - return m.Histogram +func (x *Metric) GetHistogram() *Histogram { + if x != nil { + return x.Histogram } return nil } -func (m *Metric) GetTimestampMs() int64 { - if m != nil && m.TimestampMs != nil { - return *m.TimestampMs +func (x *Metric) GetTimestampMs() int64 { + if x != nil && x.TimestampMs != nil { + return *x.TimestampMs } return 0 } type MetricFamily struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` - Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` - Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *MetricFamily) Reset() { *m = MetricFamily{} } -func (m *MetricFamily) String() string { return proto.CompactTextString(m) } -func (*MetricFamily) ProtoMessage() {} -func (*MetricFamily) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{10} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` + Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` + Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` +} + +func (x *MetricFamily) Reset() { + *x = MetricFamily{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *MetricFamily) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MetricFamily.Unmarshal(m, b) +func (x *MetricFamily) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *MetricFamily) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MetricFamily.Marshal(b, m, deterministic) -} -func (m *MetricFamily) XXX_Merge(src proto.Message) { - xxx_messageInfo_MetricFamily.Merge(m, src) -} -func (m *MetricFamily) XXX_Size() int { - return xxx_messageInfo_MetricFamily.Size(m) -} -func (m *MetricFamily) XXX_DiscardUnknown() { - xxx_messageInfo_MetricFamily.DiscardUnknown(m) + +func (*MetricFamily) ProtoMessage() {} + +func (x *MetricFamily) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_MetricFamily proto.InternalMessageInfo +// Deprecated: Use MetricFamily.ProtoReflect.Descriptor instead. +func (*MetricFamily) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{11} +} -func (m *MetricFamily) GetName() string { - if m != nil && m.Name != nil { - return *m.Name +func (x *MetricFamily) GetName() string { + if x != nil && x.Name != nil { + return *x.Name } return "" } -func (m *MetricFamily) GetHelp() string { - if m != nil && m.Help != nil { - return *m.Help +func (x *MetricFamily) GetHelp() string { + if x != nil && x.Help != nil { + return *x.Help } return "" } -func (m *MetricFamily) GetType() MetricType { - if m != nil && m.Type != nil { - return *m.Type +func (x *MetricFamily) GetType() MetricType { + if x != nil && x.Type != nil { + return *x.Type } return MetricType_COUNTER } -func (m *MetricFamily) GetMetric() []*Metric { - if m != nil { - return m.Metric +func (x *MetricFamily) GetMetric() []*Metric { + if x != nil { + return x.Metric } return nil } -func init() { - proto.RegisterEnum("io.prometheus.client.MetricType", MetricType_name, MetricType_value) - proto.RegisterType((*LabelPair)(nil), "io.prometheus.client.LabelPair") - proto.RegisterType((*Gauge)(nil), "io.prometheus.client.Gauge") - proto.RegisterType((*Counter)(nil), "io.prometheus.client.Counter") - proto.RegisterType((*Quantile)(nil), "io.prometheus.client.Quantile") - proto.RegisterType((*Summary)(nil), "io.prometheus.client.Summary") - proto.RegisterType((*Untyped)(nil), "io.prometheus.client.Untyped") - proto.RegisterType((*Histogram)(nil), "io.prometheus.client.Histogram") - proto.RegisterType((*Bucket)(nil), "io.prometheus.client.Bucket") - proto.RegisterType((*Exemplar)(nil), "io.prometheus.client.Exemplar") - proto.RegisterType((*Metric)(nil), "io.prometheus.client.Metric") - proto.RegisterType((*MetricFamily)(nil), "io.prometheus.client.MetricFamily") -} - -func init() { proto.RegisterFile("metrics.proto", fileDescriptor_6039342a2ba47b72) } - -var fileDescriptor_6039342a2ba47b72 = []byte{ - // 665 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0xfd, 0xdc, 0x38, 0x3f, 0xbe, 0x69, 0x3f, 0xa2, 0x51, 0x17, 0x56, 0xa1, 0x24, 0x78, 0x55, - 0x58, 0x38, 0xa2, 0x6a, 0x05, 0x2a, 0xb0, 0x68, 0x4b, 0x48, 0x91, 0x48, 0x5b, 0x26, 0xc9, 0xa2, - 0xb0, 0x88, 0x1c, 0x77, 0x70, 0x2c, 0x3c, 0xb1, 0xb1, 0x67, 0x2a, 0xb2, 0x66, 0xc1, 0x16, 0x5e, - 0x81, 0x17, 0x05, 0xcd, 0x8f, 0x6d, 0x2a, 0xb9, 0x95, 0x40, 0xec, 0x66, 0xee, 0x3d, 0xe7, 0xfa, - 0xcc, 0xf8, 0x9c, 0x81, 0x0d, 0x4a, 0x58, 0x1a, 0xfa, 0x99, 0x9b, 0xa4, 0x31, 0x8b, 0xd1, 0x66, - 0x18, 0x8b, 0x15, 0x25, 0x6c, 0x41, 0x78, 0xe6, 0xfa, 0x51, 0x48, 0x96, 0x6c, 0xab, 0x1b, 0xc4, - 0x71, 0x10, 0x91, 0xbe, 0xc4, 0xcc, 0xf9, 0x87, 0x3e, 0x0b, 0x29, 0xc9, 0x98, 0x47, 0x13, 0x45, - 0x73, 0xf6, 0xc1, 0x7a, 0xe3, 0xcd, 0x49, 0x74, 0xee, 0x85, 0x29, 0x42, 0x60, 0x2e, 0x3d, 0x4a, - 0x6c, 0xa3, 0x67, 0xec, 0x58, 0x58, 0xae, 0xd1, 0x26, 0xd4, 0xaf, 0xbc, 0x88, 0x13, 0x7b, 0x4d, - 0x16, 0xd5, 0xc6, 0xd9, 0x86, 0xfa, 0xd0, 0xe3, 0xc1, 0x6f, 0x6d, 0xc1, 0x31, 0xf2, 0xf6, 0x7b, - 0x68, 0x1e, 0xc7, 0x7c, 0xc9, 0x48, 0x5a, 0x0d, 0x40, 0x07, 0xd0, 0x22, 0x9f, 0x09, 0x4d, 0x22, - 0x2f, 0x95, 0x83, 0xdb, 0xbb, 0xf7, 0xdd, 0xaa, 0x03, 0xb8, 0x03, 0x8d, 0xc2, 0x05, 0xde, 0x79, - 0x0e, 0xad, 0xb7, 0xdc, 0x5b, 0xb2, 0x30, 0x22, 0x68, 0x0b, 0x5a, 0x9f, 0xf4, 0x5a, 0x7f, 0xa0, - 0xd8, 0x5f, 0x57, 0x5e, 0x48, 0xfb, 0x6a, 0x40, 0x73, 0xcc, 0x29, 0xf5, 0xd2, 0x15, 0x7a, 0x00, - 0xeb, 0x99, 0x47, 0x93, 0x88, 0xcc, 0x7c, 0xa1, 0x56, 0x4e, 0x30, 0x71, 0x5b, 0xd5, 0xe4, 0x01, - 0xd0, 0x36, 0x80, 0x86, 0x64, 0x9c, 0xea, 0x49, 0x96, 0xaa, 0x8c, 0x39, 0x15, 0xe7, 0x28, 0xbe, - 0x5f, 0xeb, 0xd5, 0x6e, 0x3e, 0x47, 0xae, 0xb8, 0xd4, 0xe7, 0x74, 0xa1, 0x39, 0x5d, 0xb2, 0x55, - 0x42, 0x2e, 0x6f, 0xb8, 0xc5, 0x2f, 0x06, 0x58, 0x27, 0x61, 0xc6, 0xe2, 0x20, 0xf5, 0xe8, 0x3f, - 0x10, 0xbb, 0x07, 0x8d, 0x39, 0xf7, 0x3f, 0x12, 0xa6, 0xa5, 0xde, 0xab, 0x96, 0x7a, 0x24, 0x31, - 0x58, 0x63, 0x9d, 0x6f, 0x06, 0x34, 0x54, 0x09, 0x3d, 0x84, 0x8e, 0xcf, 0x29, 0x8f, 0x3c, 0x16, - 0x5e, 0x5d, 0x97, 0x71, 0xa7, 0xac, 0x2b, 0x29, 0x5d, 0x68, 0xf3, 0x24, 0x21, 0xe9, 0x6c, 0x1e, - 0xf3, 0xe5, 0xa5, 0xd6, 0x02, 0xb2, 0x74, 0x24, 0x2a, 0xd7, 0x1c, 0x50, 0xfb, 0x43, 0x07, 0x7c, - 0x37, 0xa0, 0x95, 0x97, 0xd1, 0x3e, 0xd4, 0x23, 0xe1, 0x60, 0xdb, 0x90, 0x87, 0xea, 0x56, 0x4f, - 0x29, 0x4c, 0x8e, 0x15, 0xba, 0xda, 0x1d, 0xe8, 0x29, 0x58, 0x45, 0x42, 0xb4, 0xac, 0x2d, 0x57, - 0x65, 0xc8, 0xcd, 0x33, 0xe4, 0x4e, 0x72, 0x04, 0x2e, 0xc1, 0xce, 0xcf, 0x35, 0x68, 0x8c, 0x64, - 0x22, 0xff, 0x56, 0xd1, 0x63, 0xa8, 0x07, 0x22, 0x53, 0x3a, 0x10, 0x77, 0xab, 0x69, 0x32, 0x76, - 0x58, 0x21, 0xd1, 0x13, 0x68, 0xfa, 0x2a, 0x67, 0x5a, 0xec, 0x76, 0x35, 0x49, 0x87, 0x11, 0xe7, - 0x68, 0x41, 0xcc, 0x54, 0x08, 0x6c, 0xf3, 0x36, 0xa2, 0x4e, 0x0a, 0xce, 0xd1, 0x82, 0xc8, 0x95, - 0x69, 0xed, 0xfa, 0x6d, 0x44, 0xed, 0x6c, 0x9c, 0xa3, 0xd1, 0x0b, 0xb0, 0x16, 0xb9, 0x97, 0xed, - 0xa6, 0xa4, 0xde, 0x70, 0x31, 0x85, 0xe5, 0x71, 0xc9, 0x10, 0xee, 0x2f, 0xee, 0x7a, 0x46, 0x33, - 0xbb, 0xd1, 0x33, 0x76, 0x6a, 0xb8, 0x5d, 0xd4, 0x46, 0x99, 0xf3, 0xc3, 0x80, 0x75, 0xf5, 0x07, - 0x5e, 0x79, 0x34, 0x8c, 0x56, 0x95, 0xcf, 0x19, 0x02, 0x73, 0x41, 0xa2, 0x44, 0xbf, 0x66, 0x72, - 0x8d, 0xf6, 0xc0, 0x14, 0x1a, 0xe5, 0x15, 0xfe, 0xbf, 0xdb, 0xab, 0x56, 0xa5, 0x26, 0x4f, 0x56, - 0x09, 0xc1, 0x12, 0x2d, 0xd2, 0xa4, 0x5e, 0x60, 0xdb, 0xbc, 0x2d, 0x4d, 0x8a, 0x87, 0x35, 0xf6, - 0xd1, 0x08, 0xa0, 0x9c, 0x84, 0xda, 0xd0, 0x3c, 0x3e, 0x9b, 0x9e, 0x4e, 0x06, 0xb8, 0xf3, 0x1f, - 0xb2, 0xa0, 0x3e, 0x3c, 0x9c, 0x0e, 0x07, 0x1d, 0x43, 0xd4, 0xc7, 0xd3, 0xd1, 0xe8, 0x10, 0x5f, - 0x74, 0xd6, 0xc4, 0x66, 0x7a, 0x3a, 0xb9, 0x38, 0x1f, 0xbc, 0xec, 0xd4, 0xd0, 0x06, 0x58, 0x27, - 0xaf, 0xc7, 0x93, 0xb3, 0x21, 0x3e, 0x1c, 0x75, 0xcc, 0x23, 0x0c, 0x95, 0xef, 0xfe, 0xbb, 0x83, - 0x20, 0x64, 0x0b, 0x3e, 0x77, 0xfd, 0x98, 0xf6, 0xcb, 0x6e, 0x5f, 0x75, 0x67, 0x34, 0xbe, 0x24, - 0x51, 0x3f, 0x88, 0x9f, 0x85, 0xf1, 0xac, 0xec, 0xce, 0x54, 0xf7, 0x57, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xd0, 0x84, 0x91, 0x73, 0x59, 0x06, 0x00, 0x00, +var File_io_prometheus_client_metrics_proto protoreflect.FileDescriptor + +var file_io_prometheus_client_metrics_proto_rawDesc = []byte{ + 0x0a, 0x22, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, + 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x35, 0x0a, 0x09, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x47, 0x61, 0x75, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0xa4, 0x01, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, + 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, + 0x47, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3c, 0x0a, 0x08, 0x51, 0x75, 0x61, 0x6e, + 0x74, 0x69, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x07, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, + 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x53, 0x75, 0x6d, 0x12, 0x3a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, + 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x51, 0x75, + 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, + 0x12, 0x47, 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x1f, 0x0a, 0x07, 0x55, 0x6e, 0x74, + 0x79, 0x70, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xac, 0x05, 0x0a, 0x09, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, + 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x73, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x12, 0x34, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, + 0x65, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, + 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, + 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x47, + 0x0a, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, + 0x25, 0x0a, 0x0e, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, + 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x7a, 0x65, 0x72, 0x6f, 0x54, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x7a, 0x65, 0x72, 0x6f, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, + 0x0e, 0x7a, 0x65, 0x72, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, + 0x45, 0x0a, 0x0d, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x6e, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, + 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x42, 0x75, + 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x52, 0x0c, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x76, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, + 0x76, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x12, 0x52, 0x0d, + 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x25, 0x0a, + 0x0e, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x0b, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x69, 0x6f, + 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x52, 0x0c, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x0d, 0x20, + 0x03, 0x28, 0x12, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c, + 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc6, 0x01, 0x0a, 0x06, 0x42, 0x75, + 0x63, 0x6b, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, + 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, + 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x34, 0x0a, 0x16, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, + 0x14, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x75, 0x70, 0x70, 0x65, + 0x72, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, + 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, + 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x72, 0x22, 0x3c, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, + 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, + 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x22, 0x91, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, 0x35, 0x0a, + 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x22, 0xff, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, + 0x35, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, + 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, + 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x61, 0x75, + 0x67, 0x65, 0x52, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, + 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, + 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x75, + 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x52, 0x07, 0x75, 0x6e, 0x74, + 0x79, 0x70, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, + 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, + 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, + 0x65, 0x6c, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x12, + 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, + 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, + 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2a, 0x62, 0x0a, 0x0a, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x55, + 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47, 0x45, 0x10, + 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x02, 0x12, 0x0b, + 0x0a, 0x07, 0x55, 0x4e, 0x54, 0x59, 0x50, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x48, + 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x41, + 0x55, 0x47, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x05, 0x42, + 0x52, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, + 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x67, 0x6f, 0x3b, 0x69, + 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, +} + +var ( + file_io_prometheus_client_metrics_proto_rawDescOnce sync.Once + file_io_prometheus_client_metrics_proto_rawDescData = file_io_prometheus_client_metrics_proto_rawDesc +) + +func file_io_prometheus_client_metrics_proto_rawDescGZIP() []byte { + file_io_prometheus_client_metrics_proto_rawDescOnce.Do(func() { + file_io_prometheus_client_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_io_prometheus_client_metrics_proto_rawDescData) + }) + return file_io_prometheus_client_metrics_proto_rawDescData +} + +var file_io_prometheus_client_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_io_prometheus_client_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_io_prometheus_client_metrics_proto_goTypes = []interface{}{ + (MetricType)(0), // 0: io.prometheus.client.MetricType + (*LabelPair)(nil), // 1: io.prometheus.client.LabelPair + (*Gauge)(nil), // 2: io.prometheus.client.Gauge + (*Counter)(nil), // 3: io.prometheus.client.Counter + (*Quantile)(nil), // 4: io.prometheus.client.Quantile + (*Summary)(nil), // 5: io.prometheus.client.Summary + (*Untyped)(nil), // 6: io.prometheus.client.Untyped + (*Histogram)(nil), // 7: io.prometheus.client.Histogram + (*Bucket)(nil), // 8: io.prometheus.client.Bucket + (*BucketSpan)(nil), // 9: io.prometheus.client.BucketSpan + (*Exemplar)(nil), // 10: io.prometheus.client.Exemplar + (*Metric)(nil), // 11: io.prometheus.client.Metric + (*MetricFamily)(nil), // 12: io.prometheus.client.MetricFamily + (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp +} +var file_io_prometheus_client_metrics_proto_depIdxs = []int32{ + 10, // 0: io.prometheus.client.Counter.exemplar:type_name -> io.prometheus.client.Exemplar + 13, // 1: io.prometheus.client.Counter.created_timestamp:type_name -> google.protobuf.Timestamp + 4, // 2: io.prometheus.client.Summary.quantile:type_name -> io.prometheus.client.Quantile + 13, // 3: io.prometheus.client.Summary.created_timestamp:type_name -> google.protobuf.Timestamp + 8, // 4: io.prometheus.client.Histogram.bucket:type_name -> io.prometheus.client.Bucket + 13, // 5: io.prometheus.client.Histogram.created_timestamp:type_name -> google.protobuf.Timestamp + 9, // 6: io.prometheus.client.Histogram.negative_span:type_name -> io.prometheus.client.BucketSpan + 9, // 7: io.prometheus.client.Histogram.positive_span:type_name -> io.prometheus.client.BucketSpan + 10, // 8: io.prometheus.client.Bucket.exemplar:type_name -> io.prometheus.client.Exemplar + 1, // 9: io.prometheus.client.Exemplar.label:type_name -> io.prometheus.client.LabelPair + 13, // 10: io.prometheus.client.Exemplar.timestamp:type_name -> google.protobuf.Timestamp + 1, // 11: io.prometheus.client.Metric.label:type_name -> io.prometheus.client.LabelPair + 2, // 12: io.prometheus.client.Metric.gauge:type_name -> io.prometheus.client.Gauge + 3, // 13: io.prometheus.client.Metric.counter:type_name -> io.prometheus.client.Counter + 5, // 14: io.prometheus.client.Metric.summary:type_name -> io.prometheus.client.Summary + 6, // 15: io.prometheus.client.Metric.untyped:type_name -> io.prometheus.client.Untyped + 7, // 16: io.prometheus.client.Metric.histogram:type_name -> io.prometheus.client.Histogram + 0, // 17: io.prometheus.client.MetricFamily.type:type_name -> io.prometheus.client.MetricType + 11, // 18: io.prometheus.client.MetricFamily.metric:type_name -> io.prometheus.client.Metric + 19, // [19:19] is the sub-list for method output_type + 19, // [19:19] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name +} + +func init() { file_io_prometheus_client_metrics_proto_init() } +func file_io_prometheus_client_metrics_proto_init() { + if File_io_prometheus_client_metrics_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_io_prometheus_client_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LabelPair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Gauge); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Counter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Quantile); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Summary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Untyped); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Histogram); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Bucket); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BucketSpan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Exemplar); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Metric); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricFamily); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_io_prometheus_client_metrics_proto_rawDesc, + NumEnums: 1, + NumMessages: 12, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_io_prometheus_client_metrics_proto_goTypes, + DependencyIndexes: file_io_prometheus_client_metrics_proto_depIdxs, + EnumInfos: file_io_prometheus_client_metrics_proto_enumTypes, + MessageInfos: file_io_prometheus_client_metrics_proto_msgTypes, + }.Build() + File_io_prometheus_client_metrics_proto = out.File + file_io_prometheus_client_metrics_proto_rawDesc = nil + file_io_prometheus_client_metrics_proto_goTypes = nil + file_io_prometheus_client_metrics_proto_depIdxs = nil } diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go index 7657f841d..b2b89b017 100644 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ b/vendor/github.com/prometheus/common/expfmt/decode.go @@ -14,6 +14,7 @@ package expfmt import ( + "bufio" "fmt" "io" "math" @@ -21,8 +22,8 @@ import ( "net/http" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/encoding/protodelim" - "github.com/matttproud/golang_protobuf_extensions/pbutil" "github.com/prometheus/common/model" ) @@ -44,7 +45,7 @@ func ResponseFormat(h http.Header) Format { mediatype, params, err := mime.ParseMediaType(ct) if err != nil { - return FmtUnknown + return fmtUnknown } const textType = "text/plain" @@ -52,28 +53,28 @@ func ResponseFormat(h http.Header) Format { switch mediatype { case ProtoType: if p, ok := params["proto"]; ok && p != ProtoProtocol { - return FmtUnknown + return fmtUnknown } if e, ok := params["encoding"]; ok && e != "delimited" { - return FmtUnknown + return fmtUnknown } - return FmtProtoDelim + return fmtProtoDelim case textType: if v, ok := params["version"]; ok && v != TextVersion { - return FmtUnknown + return fmtUnknown } - return FmtText + return fmtText } - return FmtUnknown + return fmtUnknown } // NewDecoder returns a new decoder based on the given input format. // If the input format does not imply otherwise, a text format decoder is returned. func NewDecoder(r io.Reader, format Format) Decoder { - switch format { - case FmtProtoDelim: + switch format.FormatType() { + case TypeProtoDelim: return &protoDecoder{r: r} } return &textDecoder{r: r} @@ -86,8 +87,10 @@ type protoDecoder struct { // Decode implements the Decoder interface. func (d *protoDecoder) Decode(v *dto.MetricFamily) error { - _, err := pbutil.ReadDelimited(d.r, v) - if err != nil { + opts := protodelim.UnmarshalOptions{ + MaxSize: -1, + } + if err := opts.UnmarshalFrom(bufio.NewReader(d.r), v); err != nil { return err } if !model.IsValidMetricName(model.LabelValue(v.GetName())) { @@ -115,32 +118,31 @@ func (d *protoDecoder) Decode(v *dto.MetricFamily) error { // textDecoder implements the Decoder interface for the text protocol. type textDecoder struct { r io.Reader - p TextParser - fams []*dto.MetricFamily + fams map[string]*dto.MetricFamily + err error } // Decode implements the Decoder interface. func (d *textDecoder) Decode(v *dto.MetricFamily) error { - // TODO(fabxc): Wrap this as a line reader to make streaming safer. - if len(d.fams) == 0 { - // No cached metric families, read everything and parse metrics. - fams, err := d.p.TextToMetricFamilies(d.r) - if err != nil { - return err - } - if len(fams) == 0 { - return io.EOF - } - d.fams = make([]*dto.MetricFamily, 0, len(fams)) - for _, f := range fams { - d.fams = append(d.fams, f) + if d.err == nil { + // Read all metrics in one shot. + var p TextParser + d.fams, d.err = p.TextToMetricFamilies(d.r) + // If we don't get an error, store io.EOF for the end. + if d.err == nil { + d.err = io.EOF } } - - *v = *d.fams[0] - d.fams = d.fams[1:] - - return nil + // Pick off one MetricFamily per Decode until there's nothing left. + for key, fam := range d.fams { + v.Name = fam.Name + v.Help = fam.Help + v.Type = fam.Type + v.Metric = fam.Metric + delete(d.fams, key) + return nil + } + return d.err } // SampleDecoder wraps a Decoder to extract samples from the metric families diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go index bd4e34745..8fd806184 100644 --- a/vendor/github.com/prometheus/common/expfmt/encode.go +++ b/vendor/github.com/prometheus/common/expfmt/encode.go @@ -18,9 +18,11 @@ import ( "io" "net/http" - "github.com/golang/protobuf/proto" - "github.com/matttproud/golang_protobuf_extensions/pbutil" + "google.golang.org/protobuf/encoding/protodelim" + "google.golang.org/protobuf/encoding/prototext" + "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" + "github.com/prometheus/common/model" dto "github.com/prometheus/client_model/go" ) @@ -60,23 +62,32 @@ func (ec encoderCloser) Close() error { // as the support is still experimental. To include the option to negotiate // FmtOpenMetrics, use NegotiateOpenMetrics. func Negotiate(h http.Header) Format { + escapingScheme := Format(fmt.Sprintf("; escaping=%s", Format(model.NameEscapingScheme.String()))) for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { + if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" { + switch Format(escapeParam) { + case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues: + escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam)) + default: + // If the escaping parameter is unknown, ignore it. + } + } ver := ac.Params["version"] if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return FmtProtoDelim + return fmtProtoDelim + escapingScheme case "text": - return FmtProtoText + return fmtProtoText + escapingScheme case "compact-text": - return FmtProtoCompact + return fmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return FmtText + return fmtText + escapingScheme } } - return FmtText + return fmtText + escapingScheme } // NegotiateIncludingOpenMetrics works like Negotiate but includes @@ -84,26 +95,40 @@ func Negotiate(h http.Header) Format { // temporary and will disappear once FmtOpenMetrics is fully supported and as // such may be negotiated by the normal Negotiate function. func NegotiateIncludingOpenMetrics(h http.Header) Format { + escapingScheme := Format(fmt.Sprintf("; escaping=%s", Format(model.NameEscapingScheme.String()))) for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { + if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" { + switch Format(escapeParam) { + case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues: + escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam)) + default: + // If the escaping parameter is unknown, ignore it. + } + } ver := ac.Params["version"] if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return FmtProtoDelim + return fmtProtoDelim + escapingScheme case "text": - return FmtProtoText + return fmtProtoText + escapingScheme case "compact-text": - return FmtProtoCompact + return fmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return FmtText + return fmtText + escapingScheme } - if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion || ver == "") { - return FmtOpenMetrics + if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") { + switch ver { + case OpenMetricsVersion_1_0_0: + return fmtOpenMetrics_1_0_0 + escapingScheme + default: + return fmtOpenMetrics_0_0_1 + escapingScheme + } } } - return FmtText + return fmtText + escapingScheme } // NewEncoder returns a new encoder based on content type negotiation. All @@ -112,44 +137,48 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format { // for FmtOpenMetrics, but a future (breaking) release will add the Close method // to the Encoder interface directly. The current version of the Encoder // interface is kept for backwards compatibility. +// In cases where the Format does not allow for UTF-8 names, the global +// NameEscapingScheme will be applied. func NewEncoder(w io.Writer, format Format) Encoder { - switch format { - case FmtProtoDelim: + escapingScheme := format.ToEscapingScheme() + + switch format.FormatType() { + case TypeProtoDelim: return encoderCloser{ encode: func(v *dto.MetricFamily) error { - _, err := pbutil.WriteDelimited(w, v) + _, err := protodelim.MarshalTo(w, v) return err }, close: func() error { return nil }, } - case FmtProtoCompact: + case TypeProtoCompact: return encoderCloser{ encode: func(v *dto.MetricFamily) error { - _, err := fmt.Fprintln(w, v.String()) + _, err := fmt.Fprintln(w, model.EscapeMetricFamily(v, escapingScheme).String()) return err }, close: func() error { return nil }, } - case FmtProtoText: + case TypeProtoText: return encoderCloser{ encode: func(v *dto.MetricFamily) error { - _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) + _, err := fmt.Fprintln(w, prototext.Format(model.EscapeMetricFamily(v, escapingScheme))) return err }, close: func() error { return nil }, } - case FmtText: + case TypeTextPlain: return encoderCloser{ encode: func(v *dto.MetricFamily) error { - _, err := MetricFamilyToText(w, v) + _, err := MetricFamilyToText(w, model.EscapeMetricFamily(v, escapingScheme)) return err }, close: func() error { return nil }, } - case FmtOpenMetrics: + case TypeOpenMetrics: return encoderCloser{ encode: func(v *dto.MetricFamily) error { - _, err := MetricFamilyToOpenMetrics(w, v) + _, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme)) return err }, close: func() error { diff --git a/vendor/github.com/prometheus/common/expfmt/expfmt.go b/vendor/github.com/prometheus/common/expfmt/expfmt.go index 0f176fa64..6fc9555e3 100644 --- a/vendor/github.com/prometheus/common/expfmt/expfmt.go +++ b/vendor/github.com/prometheus/common/expfmt/expfmt.go @@ -14,28 +14,154 @@ // Package expfmt contains tools for reading and writing Prometheus metrics. package expfmt +import ( + "strings" + + "github.com/prometheus/common/model" +) + // Format specifies the HTTP content type of the different wire protocols. type Format string -// Constants to assemble the Content-Type values for the different wire protocols. +// Constants to assemble the Content-Type values for the different wire +// protocols. The Content-Type strings here are all for the legacy exposition +// formats, where valid characters for metric names and label names are limited. +// Support for arbitrary UTF-8 characters in those names is already partially +// implemented in this module (see model.ValidationScheme), but to actually use +// it on the wire, new content-type strings will have to be agreed upon and +// added here. const ( - TextVersion = "0.0.4" - ProtoType = `application/vnd.google.protobuf` - ProtoProtocol = `io.prometheus.client.MetricFamily` - ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" - OpenMetricsType = `application/openmetrics-text` - OpenMetricsVersion = "0.0.1" - - // The Content-Type values for the different wire protocols. - FmtUnknown Format = `` - FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` - FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` - FmtProtoText Format = ProtoFmt + ` encoding=text` - FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` - FmtOpenMetrics Format = OpenMetricsType + `; version=` + OpenMetricsVersion + `; charset=utf-8` + TextVersion = "0.0.4" + ProtoType = `application/vnd.google.protobuf` + ProtoProtocol = `io.prometheus.client.MetricFamily` + protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" + OpenMetricsType = `application/openmetrics-text` + OpenMetricsVersion_0_0_1 = "0.0.1" + OpenMetricsVersion_1_0_0 = "1.0.0" + + // The Content-Type values for the different wire protocols. Note that these + // values are now unexported. If code was relying on comparisons to these + // constants, instead use FormatType(). + fmtUnknown Format = `` + fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` + fmtProtoDelim Format = protoFmt + ` encoding=delimited` + fmtProtoText Format = protoFmt + ` encoding=text` + fmtProtoCompact Format = protoFmt + ` encoding=compact-text` + fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` + fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` ) const ( hdrContentType = "Content-Type" hdrAccept = "Accept" ) + +// FormatType is a Go enum representing the overall category for the given +// Format. As the number of Format permutations increases, doing basic string +// comparisons are not feasible, so this enum captures the most useful +// high-level attribute of the Format string. +type FormatType int + +const ( + TypeUnknown = iota + TypeProtoCompact + TypeProtoDelim + TypeProtoText + TypeTextPlain + TypeOpenMetrics +) + +// NewFormat generates a new Format from the type provided. Mostly used for +// tests, most Formats should be generated as part of content negotiation in +// encode.go. +func NewFormat(t FormatType) Format { + switch t { + case TypeProtoCompact: + return fmtProtoCompact + case TypeProtoDelim: + return fmtProtoDelim + case TypeProtoText: + return fmtProtoText + case TypeTextPlain: + return fmtText + case TypeOpenMetrics: + return fmtOpenMetrics_1_0_0 + default: + return fmtUnknown + } +} + +// FormatType deduces an overall FormatType for the given format. +func (f Format) FormatType() FormatType { + toks := strings.Split(string(f), ";") + if len(toks) < 2 { + return TypeUnknown + } + + params := make(map[string]string) + for i, t := range toks { + if i == 0 { + continue + } + args := strings.Split(t, "=") + if len(args) != 2 { + continue + } + params[strings.TrimSpace(args[0])] = strings.TrimSpace(args[1]) + } + + switch strings.TrimSpace(toks[0]) { + case ProtoType: + if params["proto"] != ProtoProtocol { + return TypeUnknown + } + switch params["encoding"] { + case "delimited": + return TypeProtoDelim + case "text": + return TypeProtoText + case "compact-text": + return TypeProtoCompact + default: + return TypeUnknown + } + case OpenMetricsType: + if params["charset"] != "utf-8" { + return TypeUnknown + } + return TypeOpenMetrics + case "text/plain": + v, ok := params["version"] + if !ok { + return TypeTextPlain + } + if v == TextVersion { + return TypeTextPlain + } + return TypeUnknown + default: + return TypeUnknown + } +} + +// ToEscapingScheme returns an EscapingScheme depending on the Format. Iff the +// Format contains a escaping=allow-utf-8 term, it will select NoEscaping. If a valid +// "escaping" term exists, that will be used. Otherwise, the global default will +// be returned. +func (format Format) ToEscapingScheme() model.EscapingScheme { + for _, p := range strings.Split(string(format), ";") { + toks := strings.Split(p, "=") + if len(toks) != 2 { + continue + } + key, value := strings.TrimSpace(toks[0]), strings.TrimSpace(toks[1]) + if key == model.EscapingKey { + scheme, err := model.ToEscapingScheme(value) + if err != nil { + return model.NameEscapingScheme + } + return scheme + } + } + return model.NameEscapingScheme +} diff --git a/vendor/github.com/prometheus/common/expfmt/fuzz.go b/vendor/github.com/prometheus/common/expfmt/fuzz.go index dc2eedeef..dfac962a4 100644 --- a/vendor/github.com/prometheus/common/expfmt/fuzz.go +++ b/vendor/github.com/prometheus/common/expfmt/fuzz.go @@ -12,6 +12,7 @@ // limitations under the License. // Build only when actually fuzzing +//go:build gofuzz // +build gofuzz package expfmt @@ -20,8 +21,8 @@ import "bytes" // Fuzz text metric parser with with github.com/dvyukov/go-fuzz: // -// go-fuzz-build github.com/prometheus/common/expfmt -// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz +// go-fuzz-build github.com/prometheus/common/expfmt +// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz // // Further input samples should go in the folder fuzz/corpus. func Fuzz(in []byte) int { diff --git a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go index 8a9313a3b..5622578ed 100644 --- a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go +++ b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go @@ -22,7 +22,6 @@ import ( "strconv" "strings" - "github.com/golang/protobuf/ptypes" "github.com/prometheus/common/model" dto "github.com/prometheus/client_model/go" @@ -36,6 +35,18 @@ import ( // sanity checks. If the input contains duplicate metrics or invalid metric or // label names, the conversion will result in invalid text format output. // +// If metric names conform to the legacy validation pattern, they will be placed +// outside the brackets in the traditional way, like `foo{}`. If the metric name +// fails the legacy validation check, it will be placed quoted inside the +// brackets: `{"foo"}`. As stated above, the input is assumed to be santized and +// no error will be thrown in this case. +// +// Similar to metric names, if label names conform to the legacy validation +// pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label +// name fails the legacy validation check, it will be quoted: +// `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and +// no error will be thrown in this case. +// // This function fulfills the type 'expfmt.encoder'. // // Note that OpenMetrics requires a final `# EOF` line. Since this function acts @@ -47,20 +58,20 @@ import ( // missing features and peculiarities to avoid complications when switching from // Prometheus to OpenMetrics or vice versa: // -// - Counters are expected to have the `_total` suffix in their metric name. In -// the output, the suffix will be truncated from the `# TYPE` and `# HELP` -// line. A counter with a missing `_total` suffix is not an error. However, -// its type will be set to `unknown` in that case to avoid invalid OpenMetrics -// output. +// - Counters are expected to have the `_total` suffix in their metric name. In +// the output, the suffix will be truncated from the `# TYPE` and `# HELP` +// line. A counter with a missing `_total` suffix is not an error. However, +// its type will be set to `unknown` in that case to avoid invalid OpenMetrics +// output. // -// - No support for the following (optional) features: `# UNIT` line, `_created` -// line, info type, stateset type, gaugehistogram type. +// - No support for the following (optional) features: `# UNIT` line, `_created` +// line, info type, stateset type, gaugehistogram type. // -// - The size of exemplar labels is not checked (i.e. it's possible to create -// exemplars that are larger than allowed by the OpenMetrics specification). +// - The size of exemplar labels is not checked (i.e. it's possible to create +// exemplars that are larger than allowed by the OpenMetrics specification). // -// - The value of Counters is not checked. (OpenMetrics doesn't allow counters -// with a `NaN` value.) +// - The value of Counters is not checked. (OpenMetrics doesn't allow counters +// with a `NaN` value.) func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int, err error) { name := in.GetName() if name == "" { @@ -99,7 +110,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int if err != nil { return } - n, err = w.WriteString(shortName) + n, err = writeName(w, shortName) written += n if err != nil { return @@ -125,7 +136,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int if err != nil { return } - n, err = w.WriteString(shortName) + n, err = writeName(w, shortName) written += n if err != nil { return @@ -304,21 +315,9 @@ func writeOpenMetricsSample( floatValue float64, intValue uint64, useIntValue bool, exemplar *dto.Exemplar, ) (int, error) { - var written int - n, err := w.WriteString(name) - written += n - if err != nil { - return written, err - } - if suffix != "" { - n, err = w.WriteString(suffix) - written += n - if err != nil { - return written, err - } - } - n, err = writeOpenMetricsLabelPairs( - w, metric.Label, additionalLabelName, additionalLabelValue, + written := 0 + n, err := writeOpenMetricsNameAndLabelPairs( + w, name+suffix, metric.Label, additionalLabelName, additionalLabelValue, ) written += n if err != nil { @@ -366,27 +365,58 @@ func writeOpenMetricsSample( return written, nil } -// writeOpenMetricsLabelPairs works like writeOpenMetrics but formats the float -// in OpenMetrics style. -func writeOpenMetricsLabelPairs( +// writeOpenMetricsNameAndLabelPairs works like writeOpenMetricsSample but +// formats the float in OpenMetrics style. +func writeOpenMetricsNameAndLabelPairs( w enhancedWriter, + name string, in []*dto.LabelPair, additionalLabelName string, additionalLabelValue float64, ) (int, error) { - if len(in) == 0 && additionalLabelName == "" { - return 0, nil - } var ( - written int - separator byte = '{' + written int + separator byte = '{' + metricInsideBraces = false ) + + if name != "" { + // If the name does not pass the legacy validity check, we must put the + // metric name inside the braces, quoted. + if !model.IsValidLegacyMetricName(model.LabelValue(name)) { + metricInsideBraces = true + err := w.WriteByte(separator) + written++ + if err != nil { + return written, err + } + separator = ',' + } + + n, err := writeName(w, name) + written += n + if err != nil { + return written, err + } + } + + if len(in) == 0 && additionalLabelName == "" { + if metricInsideBraces { + err := w.WriteByte('}') + written++ + if err != nil { + return written, err + } + } + return written, nil + } + for _, lp := range in { err := w.WriteByte(separator) written++ if err != nil { return written, err } - n, err := w.WriteString(lp.GetName()) + n, err := writeName(w, lp.GetName()) written += n if err != nil { return written, err @@ -452,7 +482,7 @@ func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) { if err != nil { return written, err } - n, err = writeOpenMetricsLabelPairs(w, e.Label, "", 0) + n, err = writeOpenMetricsNameAndLabelPairs(w, "", e.Label, "", 0) written += n if err != nil { return written, err @@ -473,10 +503,11 @@ func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) { if err != nil { return written, err } - ts, err := ptypes.Timestamp((*e).Timestamp) + err = (*e).Timestamp.CheckValid() if err != nil { return written, err } + ts := (*e).Timestamp.AsTime() // TODO(beorn7): Format this directly from components of ts to // avoid overflow/underflow and precision issues of the float // conversion. diff --git a/vendor/github.com/prometheus/common/expfmt/text_create.go b/vendor/github.com/prometheus/common/expfmt/text_create.go index 5ba503b06..f9b8265a9 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_create.go +++ b/vendor/github.com/prometheus/common/expfmt/text_create.go @@ -17,7 +17,6 @@ import ( "bufio" "fmt" "io" - "io/ioutil" "math" "strconv" "strings" @@ -44,7 +43,7 @@ const ( var ( bufPool = sync.Pool{ New: func() interface{} { - return bufio.NewWriter(ioutil.Discard) + return bufio.NewWriter(io.Discard) }, } numBufPool = sync.Pool{ @@ -63,6 +62,18 @@ var ( // contains duplicate metrics or invalid metric or label names, the conversion // will result in invalid text format output. // +// If metric names conform to the legacy validation pattern, they will be placed +// outside the brackets in the traditional way, like `foo{}`. If the metric name +// fails the legacy validation check, it will be placed quoted inside the +// brackets: `{"foo"}`. As stated above, the input is assumed to be santized and +// no error will be thrown in this case. +// +// Similar to metric names, if label names conform to the legacy validation +// pattern, they will be unquoted as normal, like `foo{bar="baz"}`. If the label +// name fails the legacy validation check, it will be quoted: +// `foo{"bar"="baz"}`. As stated above, the input is assumed to be santized and +// no error will be thrown in this case. +// // This method fulfills the type 'prometheus.encoder'. func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err error) { // Fail-fast checks. @@ -99,7 +110,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e if err != nil { return } - n, err = w.WriteString(name) + n, err = writeName(w, name) written += n if err != nil { return @@ -125,7 +136,7 @@ func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (written int, err e if err != nil { return } - n, err = w.WriteString(name) + n, err = writeName(w, name) written += n if err != nil { return @@ -281,21 +292,9 @@ func writeSample( additionalLabelName string, additionalLabelValue float64, value float64, ) (int, error) { - var written int - n, err := w.WriteString(name) - written += n - if err != nil { - return written, err - } - if suffix != "" { - n, err = w.WriteString(suffix) - written += n - if err != nil { - return written, err - } - } - n, err = writeLabelPairs( - w, metric.Label, additionalLabelName, additionalLabelValue, + written := 0 + n, err := writeNameAndLabelPairs( + w, name+suffix, metric.Label, additionalLabelName, additionalLabelValue, ) written += n if err != nil { @@ -331,32 +330,64 @@ func writeSample( return written, nil } -// writeLabelPairs converts a slice of LabelPair proto messages plus the -// explicitly given additional label pair into text formatted as required by the -// text format and writes it to 'w'. An empty slice in combination with an empty -// string 'additionalLabelName' results in nothing being written. Otherwise, the -// label pairs are written, escaped as required by the text format, and enclosed -// in '{...}'. The function returns the number of bytes written and any error -// encountered. -func writeLabelPairs( +// writeNameAndLabelPairs converts a slice of LabelPair proto messages plus the +// explicitly given metric name and additional label pair into text formatted as +// required by the text format and writes it to 'w'. An empty slice in +// combination with an empty string 'additionalLabelName' results in nothing +// being written. Otherwise, the label pairs are written, escaped as required by +// the text format, and enclosed in '{...}'. The function returns the number of +// bytes written and any error encountered. If the metric name is not +// legacy-valid, it will be put inside the brackets as well. Legacy-invalid +// label names will also be quoted. +func writeNameAndLabelPairs( w enhancedWriter, + name string, in []*dto.LabelPair, additionalLabelName string, additionalLabelValue float64, ) (int, error) { - if len(in) == 0 && additionalLabelName == "" { - return 0, nil - } var ( - written int - separator byte = '{' + written int + separator byte = '{' + metricInsideBraces = false ) + + if name != "" { + // If the name does not pass the legacy validity check, we must put the + // metric name inside the braces. + if !model.IsValidLegacyMetricName(model.LabelValue(name)) { + metricInsideBraces = true + err := w.WriteByte(separator) + written++ + if err != nil { + return written, err + } + separator = ',' + } + n, err := writeName(w, name) + written += n + if err != nil { + return written, err + } + } + + if len(in) == 0 && additionalLabelName == "" { + if metricInsideBraces { + err := w.WriteByte('}') + written++ + if err != nil { + return written, err + } + } + return written, nil + } + for _, lp := range in { err := w.WriteByte(separator) written++ if err != nil { return written, err } - n, err := w.WriteString(lp.GetName()) + n, err := writeName(w, lp.GetName()) written += n if err != nil { return written, err @@ -463,3 +494,27 @@ func writeInt(w enhancedWriter, i int64) (int, error) { numBufPool.Put(bp) return written, err } + +// writeName writes a string as-is if it complies with the legacy naming +// scheme, or escapes it in double quotes if not. +func writeName(w enhancedWriter, name string) (int, error) { + if model.IsValidLegacyMetricName(model.LabelValue(name)) { + return w.WriteString(name) + } + var written int + var err error + err = w.WriteByte('"') + written++ + if err != nil { + return written, err + } + var n int + n, err = writeEscapedString(w, name, true) + written += n + if err != nil { + return written, err + } + err = w.WriteByte('"') + written++ + return written, err +} diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse.go b/vendor/github.com/prometheus/common/expfmt/text_parse.go index b6079b31e..26490211a 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_parse.go +++ b/vendor/github.com/prometheus/common/expfmt/text_parse.go @@ -16,6 +16,7 @@ package expfmt import ( "bufio" "bytes" + "errors" "fmt" "io" "math" @@ -24,7 +25,8 @@ import ( dto "github.com/prometheus/client_model/go" - "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/proto" + "github.com/prometheus/common/model" ) @@ -112,7 +114,7 @@ func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricF // stream. Turn this error into something nicer and more // meaningful. (io.EOF is often used as a signal for the legitimate end // of an input stream.) - if p.err == io.EOF { + if p.err != nil && errors.Is(p.err, io.EOF) { p.parseError("unexpected end of input stream") } return p.metricFamiliesByName, p.err @@ -142,9 +144,13 @@ func (p *TextParser) reset(in io.Reader) { func (p *TextParser) startOfLine() stateFn { p.lineCount++ if p.skipBlankTab(); p.err != nil { - // End of input reached. This is the only case where - // that is not an error but a signal that we are done. - p.err = nil + // This is the only place that we expect to see io.EOF, + // which is not an error but the signal that we are done. + // Any other error that happens to align with the start of + // a line is still an error. + if errors.Is(p.err, io.EOF) { + p.err = nil + } return nil } switch p.currentByte { diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go index 26e92288c..a21b9d15d 100644 --- a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go +++ b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go @@ -11,18 +11,18 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. - Neither the name of the Open Knowledge Foundation Ltd. nor the - names of its contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. + Neither the name of the Open Knowledge Foundation Ltd. nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,8 +35,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - */ package goautoneg diff --git a/vendor/github.com/prometheus/common/model/alert.go b/vendor/github.com/prometheus/common/model/alert.go index 35e739c7a..178fdbaf6 100644 --- a/vendor/github.com/prometheus/common/model/alert.go +++ b/vendor/github.com/prometheus/common/model/alert.go @@ -90,13 +90,13 @@ func (a *Alert) Validate() error { return fmt.Errorf("start time must be before end time") } if err := a.Labels.Validate(); err != nil { - return fmt.Errorf("invalid label set: %s", err) + return fmt.Errorf("invalid label set: %w", err) } if len(a.Labels) == 0 { return fmt.Errorf("at least one label pair required") } if err := a.Annotations.Validate(); err != nil { - return fmt.Errorf("invalid annotations: %s", err) + return fmt.Errorf("invalid annotations: %w", err) } return nil } diff --git a/vendor/github.com/prometheus/common/model/labels.go b/vendor/github.com/prometheus/common/model/labels.go index ef8956335..3317ce22f 100644 --- a/vendor/github.com/prometheus/common/model/labels.go +++ b/vendor/github.com/prometheus/common/model/labels.go @@ -97,17 +97,25 @@ var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") // therewith. type LabelName string -// IsValid is true iff the label name matches the pattern of LabelNameRE. This -// method, however, does not use LabelNameRE for the check but a much faster -// hardcoded implementation. +// IsValid returns true iff name matches the pattern of LabelNameRE for legacy +// names, and iff it's valid UTF-8 if NameValidationScheme is set to +// UTF8Validation. For the legacy matching, it does not use LabelNameRE for the +// check but a much faster hardcoded implementation. func (ln LabelName) IsValid() bool { if len(ln) == 0 { return false } - for i, b := range ln { - if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { - return false + switch NameValidationScheme { + case LegacyValidation: + for i, b := range ln { + if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { + return false + } } + case UTF8Validation: + return utf8.ValidString(string(ln)) + default: + panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme)) } return true } @@ -164,7 +172,7 @@ func (l LabelNames) String() string { // A LabelValue is an associated value for a LabelName. type LabelValue string -// IsValid returns true iff the string is a valid UTF8. +// IsValid returns true iff the string is a valid UTF-8. func (lv LabelValue) IsValid() bool { return utf8.ValidString(string(lv)) } diff --git a/vendor/github.com/prometheus/common/model/metadata.go b/vendor/github.com/prometheus/common/model/metadata.go new file mode 100644 index 000000000..447ab8ad6 --- /dev/null +++ b/vendor/github.com/prometheus/common/model/metadata.go @@ -0,0 +1,28 @@ +// Copyright 2023 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +// MetricType represents metric type values. +type MetricType string + +const ( + MetricTypeCounter = MetricType("counter") + MetricTypeGauge = MetricType("gauge") + MetricTypeHistogram = MetricType("histogram") + MetricTypeGaugeHistogram = MetricType("gaugehistogram") + MetricTypeSummary = MetricType("summary") + MetricTypeInfo = MetricType("info") + MetricTypeStateset = MetricType("stateset") + MetricTypeUnknown = MetricType("unknown") +) diff --git a/vendor/github.com/prometheus/common/model/metric.go b/vendor/github.com/prometheus/common/model/metric.go index 00804b7fe..0bd29b3a3 100644 --- a/vendor/github.com/prometheus/common/model/metric.go +++ b/vendor/github.com/prometheus/common/model/metric.go @@ -18,15 +18,84 @@ import ( "regexp" "sort" "strings" + "unicode/utf8" + + dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" ) var ( - // MetricNameRE is a regular expression matching valid metric - // names. Note that the IsValidMetricName function performs the same - // check but faster than a match with this regular expression. - MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`) + // NameValidationScheme determines the method of name validation to be used by + // all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 mode + // in isolation from other components that don't support UTF-8 may result in + // bugs or other undefined behavior. This value is intended to be set by + // UTF-8-aware binaries as part of their startup. To avoid need for locking, + // this value should be set once, ideally in an init(), before multiple + // goroutines are started. + NameValidationScheme = LegacyValidation + + // NameEscapingScheme defines the default way that names will be + // escaped when presented to systems that do not support UTF-8 names. If the + // Content-Type "escaping" term is specified, that will override this value. + NameEscapingScheme = ValueEncodingEscaping +) + +// ValidationScheme is a Go enum for determining how metric and label names will +// be validated by this library. +type ValidationScheme int + +const ( + // LegacyValidation is a setting that requirets that metric and label names + // conform to the original Prometheus character requirements described by + // MetricNameRE and LabelNameRE. + LegacyValidation ValidationScheme = iota + + // UTF8Validation only requires that metric and label names be valid UTF-8 + // strings. + UTF8Validation +) + +type EscapingScheme int + +const ( + // NoEscaping indicates that a name will not be escaped. Unescaped names that + // do not conform to the legacy validity check will use a new exposition + // format syntax that will be officially standardized in future versions. + NoEscaping EscapingScheme = iota + + // UnderscoreEscaping replaces all legacy-invalid characters with underscores. + UnderscoreEscaping + + // DotsEscaping is similar to UnderscoreEscaping, except that dots are + // converted to `_dot_` and pre-existing underscores are converted to `__`. + DotsEscaping + + // ValueEncodingEscaping prepends the name with `U__` and replaces all invalid + // characters with the unicode value, surrounded by underscores. Single + // underscores are replaced with double underscores. + ValueEncodingEscaping +) + +const ( + // EscapingKey is the key in an Accept or Content-Type header that defines how + // metric and label names that do not conform to the legacy character + // requirements should be escaped when being scraped by a legacy prometheus + // system. If a system does not explicitly pass an escaping parameter in the + // Accept header, the default NameEscapingScheme will be used. + EscapingKey = "escaping" + + // Possible values for Escaping Key: + AllowUTF8 = "allow-utf-8" // No escaping required. + EscapeUnderscores = "underscores" + EscapeDots = "dots" + EscapeValues = "values" ) +// MetricNameRE is a regular expression matching valid metric +// names. Note that the IsValidMetricName function performs the same +// check but faster than a match with this regular expression. +var MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`) + // A Metric is similar to a LabelSet, but the key difference is that a Metric is // a singleton and refers to one and only one stream of samples. type Metric LabelSet @@ -86,17 +155,302 @@ func (m Metric) FastFingerprint() Fingerprint { return LabelSet(m).FastFingerprint() } -// IsValidMetricName returns true iff name matches the pattern of MetricNameRE. +// IsValidMetricName returns true iff name matches the pattern of MetricNameRE +// for legacy names, and iff it's valid UTF-8 if the UTF8Validation scheme is +// selected. +func IsValidMetricName(n LabelValue) bool { + switch NameValidationScheme { + case LegacyValidation: + return IsValidLegacyMetricName(n) + case UTF8Validation: + if len(n) == 0 { + return false + } + return utf8.ValidString(string(n)) + default: + panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme)) + } +} + +// IsValidLegacyMetricName is similar to IsValidMetricName but always uses the +// legacy validation scheme regardless of the value of NameValidationScheme. // This function, however, does not use MetricNameRE for the check but a much // faster hardcoded implementation. -func IsValidMetricName(n LabelValue) bool { +func IsValidLegacyMetricName(n LabelValue) bool { if len(n) == 0 { return false } for i, b := range n { - if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) { + if !isValidLegacyRune(b, i) { return false } } return true } + +// EscapeMetricFamily escapes the given metric names and labels with the given +// escaping scheme. Returns a new object that uses the same pointers to fields +// when possible and creates new escaped versions so as not to mutate the +// input. +func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricFamily { + if v == nil { + return nil + } + + if scheme == NoEscaping { + return v + } + + out := &dto.MetricFamily{ + Help: v.Help, + Type: v.Type, + } + + // If the name is nil, copy as-is, don't try to escape. + if v.Name == nil || IsValidLegacyMetricName(LabelValue(v.GetName())) { + out.Name = v.Name + } else { + out.Name = proto.String(EscapeName(v.GetName(), scheme)) + } + for _, m := range v.Metric { + if !metricNeedsEscaping(m) { + out.Metric = append(out.Metric, m) + continue + } + + escaped := &dto.Metric{ + Gauge: m.Gauge, + Counter: m.Counter, + Summary: m.Summary, + Untyped: m.Untyped, + Histogram: m.Histogram, + TimestampMs: m.TimestampMs, + } + + for _, l := range m.Label { + if l.GetName() == MetricNameLabel { + if l.Value == nil || IsValidLegacyMetricName(LabelValue(l.GetValue())) { + escaped.Label = append(escaped.Label, l) + continue + } + escaped.Label = append(escaped.Label, &dto.LabelPair{ + Name: proto.String(MetricNameLabel), + Value: proto.String(EscapeName(l.GetValue(), scheme)), + }) + continue + } + if l.Name == nil || IsValidLegacyMetricName(LabelValue(l.GetName())) { + escaped.Label = append(escaped.Label, l) + continue + } + escaped.Label = append(escaped.Label, &dto.LabelPair{ + Name: proto.String(EscapeName(l.GetName(), scheme)), + Value: l.Value, + }) + } + out.Metric = append(out.Metric, escaped) + } + return out +} + +func metricNeedsEscaping(m *dto.Metric) bool { + for _, l := range m.Label { + if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(LabelValue(l.GetValue())) { + return true + } + if !IsValidLegacyMetricName(LabelValue(l.GetName())) { + return true + } + } + return false +} + +const ( + lowerhex = "0123456789abcdef" +) + +// EscapeName escapes the incoming name according to the provided escaping +// scheme. Depending on the rules of escaping, this may cause no change in the +// string that is returned. (Especially NoEscaping, which by definition is a +// noop). This function does not do any validation of the name. +func EscapeName(name string, scheme EscapingScheme) string { + if len(name) == 0 { + return name + } + var escaped strings.Builder + switch scheme { + case NoEscaping: + return name + case UnderscoreEscaping: + if IsValidLegacyMetricName(LabelValue(name)) { + return name + } + for i, b := range name { + if isValidLegacyRune(b, i) { + escaped.WriteRune(b) + } else { + escaped.WriteRune('_') + } + } + return escaped.String() + case DotsEscaping: + // Do not early return for legacy valid names, we still escape underscores. + for i, b := range name { + if b == '_' { + escaped.WriteString("__") + } else if b == '.' { + escaped.WriteString("_dot_") + } else if isValidLegacyRune(b, i) { + escaped.WriteRune(b) + } else { + escaped.WriteRune('_') + } + } + return escaped.String() + case ValueEncodingEscaping: + if IsValidLegacyMetricName(LabelValue(name)) { + return name + } + escaped.WriteString("U__") + for i, b := range name { + if isValidLegacyRune(b, i) { + escaped.WriteRune(b) + } else if !utf8.ValidRune(b) { + escaped.WriteString("_FFFD_") + } else if b < 0x100 { + escaped.WriteRune('_') + for s := 4; s >= 0; s -= 4 { + escaped.WriteByte(lowerhex[b>>uint(s)&0xF]) + } + escaped.WriteRune('_') + } else if b < 0x10000 { + escaped.WriteRune('_') + for s := 12; s >= 0; s -= 4 { + escaped.WriteByte(lowerhex[b>>uint(s)&0xF]) + } + escaped.WriteRune('_') + } + } + return escaped.String() + default: + panic(fmt.Sprintf("invalid escaping scheme %d", scheme)) + } +} + +// lower function taken from strconv.atoi +func lower(c byte) byte { + return c | ('x' - 'X') +} + +// UnescapeName unescapes the incoming name according to the provided escaping +// scheme if possible. Some schemes are partially or totally non-roundtripable. +// If any error is enountered, returns the original input. +func UnescapeName(name string, scheme EscapingScheme) string { + if len(name) == 0 { + return name + } + switch scheme { + case NoEscaping: + return name + case UnderscoreEscaping: + // It is not possible to unescape from underscore replacement. + return name + case DotsEscaping: + name = strings.ReplaceAll(name, "_dot_", ".") + name = strings.ReplaceAll(name, "__", "_") + return name + case ValueEncodingEscaping: + escapedName, found := strings.CutPrefix(name, "U__") + if !found { + return name + } + + var unescaped strings.Builder + TOP: + for i := 0; i < len(escapedName); i++ { + // All non-underscores are treated normally. + if escapedName[i] != '_' { + unescaped.WriteByte(escapedName[i]) + continue + } + i++ + if i >= len(escapedName) { + return name + } + // A double underscore is a single underscore. + if escapedName[i] == '_' { + unescaped.WriteByte('_') + continue + } + // We think we are in a UTF-8 code, process it. + var utf8Val uint + for j := 0; i < len(escapedName); j++ { + // This is too many characters for a utf8 value. + if j > 4 { + return name + } + // Found a closing underscore, convert to a rune, check validity, and append. + if escapedName[i] == '_' { + utf8Rune := rune(utf8Val) + if !utf8.ValidRune(utf8Rune) { + return name + } + unescaped.WriteRune(utf8Rune) + continue TOP + } + r := lower(escapedName[i]) + utf8Val *= 16 + if r >= '0' && r <= '9' { + utf8Val += uint(r) - '0' + } else if r >= 'a' && r <= 'f' { + utf8Val += uint(r) - 'a' + 10 + } else { + return name + } + i++ + } + // Didn't find closing underscore, invalid. + return name + } + return unescaped.String() + default: + panic(fmt.Sprintf("invalid escaping scheme %d", scheme)) + } +} + +func isValidLegacyRune(b rune, i int) bool { + return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0) +} + +func (e EscapingScheme) String() string { + switch e { + case NoEscaping: + return AllowUTF8 + case UnderscoreEscaping: + return EscapeUnderscores + case DotsEscaping: + return EscapeDots + case ValueEncodingEscaping: + return EscapeValues + default: + panic(fmt.Sprintf("unknown format scheme %d", e)) + } +} + +func ToEscapingScheme(s string) (EscapingScheme, error) { + if s == "" { + return NoEscaping, fmt.Errorf("got empty string instead of escaping scheme") + } + switch s { + case AllowUTF8: + return NoEscaping, nil + case EscapeUnderscores: + return UnderscoreEscaping, nil + case EscapeDots: + return DotsEscaping, nil + case EscapeValues: + return ValueEncodingEscaping, nil + default: + return NoEscaping, fmt.Errorf("unknown format scheme " + s) + } +} diff --git a/vendor/github.com/prometheus/common/model/signature.go b/vendor/github.com/prometheus/common/model/signature.go index 8762b13c6..dc8a0026c 100644 --- a/vendor/github.com/prometheus/common/model/signature.go +++ b/vendor/github.com/prometheus/common/model/signature.go @@ -22,10 +22,8 @@ import ( // when calculating their combined hash value (aka signature aka fingerprint). const SeparatorByte byte = 255 -var ( - // cache the signature of an empty label set. - emptyLabelSignature = hashNew() -) +// cache the signature of an empty label set. +var emptyLabelSignature = hashNew() // LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a // given label set. (Collisions are possible but unlikely if the number of label diff --git a/vendor/github.com/prometheus/common/model/silence.go b/vendor/github.com/prometheus/common/model/silence.go index bb99889d2..910b0b71f 100644 --- a/vendor/github.com/prometheus/common/model/silence.go +++ b/vendor/github.com/prometheus/common/model/silence.go @@ -81,7 +81,7 @@ func (s *Silence) Validate() error { } for _, m := range s.Matchers { if err := m.Validate(); err != nil { - return fmt.Errorf("invalid matcher: %s", err) + return fmt.Errorf("invalid matcher: %w", err) } } if s.StartsAt.IsZero() { diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go index 7f67b16e4..5727452c1 100644 --- a/vendor/github.com/prometheus/common/model/time.go +++ b/vendor/github.com/prometheus/common/model/time.go @@ -18,7 +18,6 @@ import ( "errors" "fmt" "math" - "regexp" "strconv" "strings" "time" @@ -183,54 +182,78 @@ func (d *Duration) Type() string { return "duration" } -var durationRE = regexp.MustCompile("^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$") +func isdigit(c byte) bool { return c >= '0' && c <= '9' } + +// Units are required to go in order from biggest to smallest. +// This guards against confusion from "1m1d" being 1 minute + 1 day, not 1 month + 1 day. +var unitMap = map[string]struct { + pos int + mult uint64 +}{ + "ms": {7, uint64(time.Millisecond)}, + "s": {6, uint64(time.Second)}, + "m": {5, uint64(time.Minute)}, + "h": {4, uint64(time.Hour)}, + "d": {3, uint64(24 * time.Hour)}, + "w": {2, uint64(7 * 24 * time.Hour)}, + "y": {1, uint64(365 * 24 * time.Hour)}, +} // ParseDuration parses a string into a time.Duration, assuming that a year // always has 365d, a week always has 7d, and a day always has 24h. -func ParseDuration(durationStr string) (Duration, error) { - switch durationStr { +func ParseDuration(s string) (Duration, error) { + switch s { case "0": // Allow 0 without a unit. return 0, nil case "": - return 0, fmt.Errorf("empty duration string") - } - matches := durationRE.FindStringSubmatch(durationStr) - if matches == nil { - return 0, fmt.Errorf("not a valid duration string: %q", durationStr) + return 0, errors.New("empty duration string") } - var dur time.Duration - // Parse the match at pos `pos` in the regex and use `mult` to turn that - // into ms, then add that value to the total parsed duration. - var overflowErr error - m := func(pos int, mult time.Duration) { - if matches[pos] == "" { - return + orig := s + var dur uint64 + lastUnitPos := 0 + + for s != "" { + if !isdigit(s[0]) { + return 0, fmt.Errorf("not a valid duration string: %q", orig) + } + // Consume [0-9]* + i := 0 + for ; i < len(s) && isdigit(s[i]); i++ { + } + v, err := strconv.ParseUint(s[:i], 10, 0) + if err != nil { + return 0, fmt.Errorf("not a valid duration string: %q", orig) } - n, _ := strconv.Atoi(matches[pos]) + s = s[i:] + // Consume unit. + for i = 0; i < len(s) && !isdigit(s[i]); i++ { + } + if i == 0 { + return 0, fmt.Errorf("not a valid duration string: %q", orig) + } + u := s[:i] + s = s[i:] + unit, ok := unitMap[u] + if !ok { + return 0, fmt.Errorf("unknown unit %q in duration %q", u, orig) + } + if unit.pos <= lastUnitPos { // Units must go in order from biggest to smallest. + return 0, fmt.Errorf("not a valid duration string: %q", orig) + } + lastUnitPos = unit.pos // Check if the provided duration overflows time.Duration (> ~ 290years). - if n > int((1<<63-1)/mult/time.Millisecond) { - overflowErr = errors.New("duration out of range") + if v > 1<<63/unit.mult { + return 0, errors.New("duration out of range") } - d := time.Duration(n) * time.Millisecond - dur += d * mult - - if dur < 0 { - overflowErr = errors.New("duration out of range") + dur += v * unit.mult + if dur > 1<<63-1 { + return 0, errors.New("duration out of range") } } - - m(2, 1000*60*60*24*365) // y - m(4, 1000*60*60*24*7) // w - m(6, 1000*60*60*24) // d - m(8, 1000*60*60) // h - m(10, 1000*60) // m - m(12, 1000) // s - m(14, 1) // ms - - return Duration(dur), overflowErr + return Duration(dur), nil } func (d Duration) String() string { diff --git a/vendor/github.com/prometheus/common/model/value.go b/vendor/github.com/prometheus/common/model/value.go index c9d8fb1a2..8050637d8 100644 --- a/vendor/github.com/prometheus/common/model/value.go +++ b/vendor/github.com/prometheus/common/model/value.go @@ -16,104 +16,26 @@ package model import ( "encoding/json" "fmt" - "math" "sort" "strconv" "strings" ) -var ( - // ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a - // non-existing sample pair. It is a SamplePair with timestamp Earliest and - // value 0.0. Note that the natural zero value of SamplePair has a timestamp - // of 0, which is possible to appear in a real SamplePair and thus not - // suitable to signal a non-existing SamplePair. - ZeroSamplePair = SamplePair{Timestamp: Earliest} - - // ZeroSample is the pseudo zero-value of Sample used to signal a - // non-existing sample. It is a Sample with timestamp Earliest, value 0.0, - // and metric nil. Note that the natural zero value of Sample has a timestamp - // of 0, which is possible to appear in a real Sample and thus not suitable - // to signal a non-existing Sample. - ZeroSample = Sample{Timestamp: Earliest} -) - -// A SampleValue is a representation of a value for a given sample at a given -// time. -type SampleValue float64 - -// MarshalJSON implements json.Marshaler. -func (v SampleValue) MarshalJSON() ([]byte, error) { - return json.Marshal(v.String()) -} - -// UnmarshalJSON implements json.Unmarshaler. -func (v *SampleValue) UnmarshalJSON(b []byte) error { - if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { - return fmt.Errorf("sample value must be a quoted string") - } - f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64) - if err != nil { - return err - } - *v = SampleValue(f) - return nil -} - -// Equal returns true if the value of v and o is equal or if both are NaN. Note -// that v==o is false if both are NaN. If you want the conventional float -// behavior, use == to compare two SampleValues. -func (v SampleValue) Equal(o SampleValue) bool { - if v == o { - return true - } - return math.IsNaN(float64(v)) && math.IsNaN(float64(o)) -} - -func (v SampleValue) String() string { - return strconv.FormatFloat(float64(v), 'f', -1, 64) -} - -// SamplePair pairs a SampleValue with a Timestamp. -type SamplePair struct { - Timestamp Time - Value SampleValue -} - -// MarshalJSON implements json.Marshaler. -func (s SamplePair) MarshalJSON() ([]byte, error) { - t, err := json.Marshal(s.Timestamp) - if err != nil { - return nil, err - } - v, err := json.Marshal(s.Value) - if err != nil { - return nil, err - } - return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (s *SamplePair) UnmarshalJSON(b []byte) error { - v := [...]json.Unmarshaler{&s.Timestamp, &s.Value} - return json.Unmarshal(b, &v) -} - -// Equal returns true if this SamplePair and o have equal Values and equal -// Timestamps. The semantics of Value equality is defined by SampleValue.Equal. -func (s *SamplePair) Equal(o *SamplePair) bool { - return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp)) -} - -func (s SamplePair) String() string { - return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp) -} +// ZeroSample is the pseudo zero-value of Sample used to signal a +// non-existing sample. It is a Sample with timestamp Earliest, value 0.0, +// and metric nil. Note that the natural zero value of Sample has a timestamp +// of 0, which is possible to appear in a real Sample and thus not suitable +// to signal a non-existing Sample. +var ZeroSample = Sample{Timestamp: Earliest} -// Sample is a sample pair associated with a metric. +// Sample is a sample pair associated with a metric. A single sample must either +// define Value or Histogram but not both. Histogram == nil implies the Value +// field is used, otherwise it should be ignored. type Sample struct { - Metric Metric `json:"metric"` - Value SampleValue `json:"value"` - Timestamp Time `json:"timestamp"` + Metric Metric `json:"metric"` + Value SampleValue `json:"value"` + Timestamp Time `json:"timestamp"` + Histogram *SampleHistogram `json:"histogram"` } // Equal compares first the metrics, then the timestamp, then the value. The @@ -129,11 +51,19 @@ func (s *Sample) Equal(o *Sample) bool { if !s.Timestamp.Equal(o.Timestamp) { return false } - + if s.Histogram != nil { + return s.Histogram.Equal(o.Histogram) + } return s.Value.Equal(o.Value) } func (s Sample) String() string { + if s.Histogram != nil { + return fmt.Sprintf("%s => %s", s.Metric, SampleHistogramPair{ + Timestamp: s.Timestamp, + Histogram: s.Histogram, + }) + } return fmt.Sprintf("%s => %s", s.Metric, SamplePair{ Timestamp: s.Timestamp, Value: s.Value, @@ -142,6 +72,19 @@ func (s Sample) String() string { // MarshalJSON implements json.Marshaler. func (s Sample) MarshalJSON() ([]byte, error) { + if s.Histogram != nil { + v := struct { + Metric Metric `json:"metric"` + Histogram SampleHistogramPair `json:"histogram"` + }{ + Metric: s.Metric, + Histogram: SampleHistogramPair{ + Timestamp: s.Timestamp, + Histogram: s.Histogram, + }, + } + return json.Marshal(&v) + } v := struct { Metric Metric `json:"metric"` Value SamplePair `json:"value"` @@ -152,21 +95,25 @@ func (s Sample) MarshalJSON() ([]byte, error) { Value: s.Value, }, } - return json.Marshal(&v) } // UnmarshalJSON implements json.Unmarshaler. func (s *Sample) UnmarshalJSON(b []byte) error { v := struct { - Metric Metric `json:"metric"` - Value SamplePair `json:"value"` + Metric Metric `json:"metric"` + Value SamplePair `json:"value"` + Histogram SampleHistogramPair `json:"histogram"` }{ Metric: s.Metric, Value: SamplePair{ Timestamp: s.Timestamp, Value: s.Value, }, + Histogram: SampleHistogramPair{ + Timestamp: s.Timestamp, + Histogram: s.Histogram, + }, } if err := json.Unmarshal(b, &v); err != nil { @@ -174,8 +121,13 @@ func (s *Sample) UnmarshalJSON(b []byte) error { } s.Metric = v.Metric - s.Timestamp = v.Value.Timestamp - s.Value = v.Value.Value + if v.Histogram.Histogram != nil { + s.Timestamp = v.Histogram.Timestamp + s.Histogram = v.Histogram.Histogram + } else { + s.Timestamp = v.Value.Timestamp + s.Value = v.Value.Value + } return nil } @@ -221,80 +173,76 @@ func (s Samples) Equal(o Samples) bool { // SampleStream is a stream of Values belonging to an attached COWMetric. type SampleStream struct { - Metric Metric `json:"metric"` - Values []SamplePair `json:"values"` + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + Histograms []SampleHistogramPair `json:"histograms"` } func (ss SampleStream) String() string { - vals := make([]string, len(ss.Values)) + valuesLength := len(ss.Values) + vals := make([]string, valuesLength+len(ss.Histograms)) for i, v := range ss.Values { vals[i] = v.String() } + for i, v := range ss.Histograms { + vals[i+valuesLength] = v.String() + } return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n")) } -// Value is a generic interface for values resulting from a query evaluation. -type Value interface { - Type() ValueType - String() string +func (ss SampleStream) MarshalJSON() ([]byte, error) { + if len(ss.Histograms) > 0 && len(ss.Values) > 0 { + v := struct { + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + Histograms []SampleHistogramPair `json:"histograms"` + }{ + Metric: ss.Metric, + Values: ss.Values, + Histograms: ss.Histograms, + } + return json.Marshal(&v) + } else if len(ss.Histograms) > 0 { + v := struct { + Metric Metric `json:"metric"` + Histograms []SampleHistogramPair `json:"histograms"` + }{ + Metric: ss.Metric, + Histograms: ss.Histograms, + } + return json.Marshal(&v) + } else { + v := struct { + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + }{ + Metric: ss.Metric, + Values: ss.Values, + } + return json.Marshal(&v) + } } -func (Matrix) Type() ValueType { return ValMatrix } -func (Vector) Type() ValueType { return ValVector } -func (*Scalar) Type() ValueType { return ValScalar } -func (*String) Type() ValueType { return ValString } - -type ValueType int - -const ( - ValNone ValueType = iota - ValScalar - ValVector - ValMatrix - ValString -) - -// MarshalJSON implements json.Marshaler. -func (et ValueType) MarshalJSON() ([]byte, error) { - return json.Marshal(et.String()) -} +func (ss *SampleStream) UnmarshalJSON(b []byte) error { + v := struct { + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + Histograms []SampleHistogramPair `json:"histograms"` + }{ + Metric: ss.Metric, + Values: ss.Values, + Histograms: ss.Histograms, + } -func (et *ValueType) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err != nil { + if err := json.Unmarshal(b, &v); err != nil { return err } - switch s { - case "": - *et = ValNone - case "scalar": - *et = ValScalar - case "vector": - *et = ValVector - case "matrix": - *et = ValMatrix - case "string": - *et = ValString - default: - return fmt.Errorf("unknown value type %q", s) - } - return nil -} -func (e ValueType) String() string { - switch e { - case ValNone: - return "" - case ValScalar: - return "scalar" - case ValVector: - return "vector" - case ValMatrix: - return "matrix" - case ValString: - return "string" - } - panic("ValueType.String: unhandled value type") + ss.Metric = v.Metric + ss.Values = v.Values + ss.Histograms = v.Histograms + + return nil } // Scalar is a scalar value evaluated at the set timestamp. @@ -324,7 +272,7 @@ func (s *Scalar) UnmarshalJSON(b []byte) error { value, err := strconv.ParseFloat(f, 64) if err != nil { - return fmt.Errorf("error parsing sample value: %s", err) + return fmt.Errorf("error parsing sample value: %w", err) } s.Value = SampleValue(value) return nil diff --git a/vendor/github.com/prometheus/common/model/value_float.go b/vendor/github.com/prometheus/common/model/value_float.go new file mode 100644 index 000000000..ae35cc2ab --- /dev/null +++ b/vendor/github.com/prometheus/common/model/value_float.go @@ -0,0 +1,98 @@ +// Copyright 2013 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "fmt" + "math" + "strconv" +) + +// ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a +// non-existing sample pair. It is a SamplePair with timestamp Earliest and +// value 0.0. Note that the natural zero value of SamplePair has a timestamp +// of 0, which is possible to appear in a real SamplePair and thus not +// suitable to signal a non-existing SamplePair. +var ZeroSamplePair = SamplePair{Timestamp: Earliest} + +// A SampleValue is a representation of a value for a given sample at a given +// time. +type SampleValue float64 + +// MarshalJSON implements json.Marshaler. +func (v SampleValue) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +// UnmarshalJSON implements json.Unmarshaler. +func (v *SampleValue) UnmarshalJSON(b []byte) error { + if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { + return fmt.Errorf("sample value must be a quoted string") + } + f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64) + if err != nil { + return err + } + *v = SampleValue(f) + return nil +} + +// Equal returns true if the value of v and o is equal or if both are NaN. Note +// that v==o is false if both are NaN. If you want the conventional float +// behavior, use == to compare two SampleValues. +func (v SampleValue) Equal(o SampleValue) bool { + if v == o { + return true + } + return math.IsNaN(float64(v)) && math.IsNaN(float64(o)) +} + +func (v SampleValue) String() string { + return strconv.FormatFloat(float64(v), 'f', -1, 64) +} + +// SamplePair pairs a SampleValue with a Timestamp. +type SamplePair struct { + Timestamp Time + Value SampleValue +} + +func (s SamplePair) MarshalJSON() ([]byte, error) { + t, err := json.Marshal(s.Timestamp) + if err != nil { + return nil, err + } + v, err := json.Marshal(s.Value) + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (s *SamplePair) UnmarshalJSON(b []byte) error { + v := [...]json.Unmarshaler{&s.Timestamp, &s.Value} + return json.Unmarshal(b, &v) +} + +// Equal returns true if this SamplePair and o have equal Values and equal +// Timestamps. The semantics of Value equality is defined by SampleValue.Equal. +func (s *SamplePair) Equal(o *SamplePair) bool { + return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp)) +} + +func (s SamplePair) String() string { + return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp) +} diff --git a/vendor/github.com/prometheus/common/model/value_histogram.go b/vendor/github.com/prometheus/common/model/value_histogram.go new file mode 100644 index 000000000..54bb038cf --- /dev/null +++ b/vendor/github.com/prometheus/common/model/value_histogram.go @@ -0,0 +1,178 @@ +// Copyright 2013 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" +) + +type FloatString float64 + +func (v FloatString) String() string { + return strconv.FormatFloat(float64(v), 'f', -1, 64) +} + +func (v FloatString) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +func (v *FloatString) UnmarshalJSON(b []byte) error { + if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { + return fmt.Errorf("float value must be a quoted string") + } + f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64) + if err != nil { + return err + } + *v = FloatString(f) + return nil +} + +type HistogramBucket struct { + Boundaries int32 + Lower FloatString + Upper FloatString + Count FloatString +} + +func (s HistogramBucket) MarshalJSON() ([]byte, error) { + b, err := json.Marshal(s.Boundaries) + if err != nil { + return nil, err + } + l, err := json.Marshal(s.Lower) + if err != nil { + return nil, err + } + u, err := json.Marshal(s.Upper) + if err != nil { + return nil, err + } + c, err := json.Marshal(s.Count) + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("[%s,%s,%s,%s]", b, l, u, c)), nil +} + +func (s *HistogramBucket) UnmarshalJSON(buf []byte) error { + tmp := []interface{}{&s.Boundaries, &s.Lower, &s.Upper, &s.Count} + wantLen := len(tmp) + if err := json.Unmarshal(buf, &tmp); err != nil { + return err + } + if gotLen := len(tmp); gotLen != wantLen { + return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen) + } + return nil +} + +func (s *HistogramBucket) Equal(o *HistogramBucket) bool { + return s == o || (s.Boundaries == o.Boundaries && s.Lower == o.Lower && s.Upper == o.Upper && s.Count == o.Count) +} + +func (b HistogramBucket) String() string { + var sb strings.Builder + lowerInclusive := b.Boundaries == 1 || b.Boundaries == 3 + upperInclusive := b.Boundaries == 0 || b.Boundaries == 3 + if lowerInclusive { + sb.WriteRune('[') + } else { + sb.WriteRune('(') + } + fmt.Fprintf(&sb, "%g,%g", b.Lower, b.Upper) + if upperInclusive { + sb.WriteRune(']') + } else { + sb.WriteRune(')') + } + fmt.Fprintf(&sb, ":%v", b.Count) + return sb.String() +} + +type HistogramBuckets []*HistogramBucket + +func (s HistogramBuckets) Equal(o HistogramBuckets) bool { + if len(s) != len(o) { + return false + } + + for i, bucket := range s { + if !bucket.Equal(o[i]) { + return false + } + } + return true +} + +type SampleHistogram struct { + Count FloatString `json:"count"` + Sum FloatString `json:"sum"` + Buckets HistogramBuckets `json:"buckets"` +} + +func (s SampleHistogram) String() string { + return fmt.Sprintf("Count: %f, Sum: %f, Buckets: %v", s.Count, s.Sum, s.Buckets) +} + +func (s *SampleHistogram) Equal(o *SampleHistogram) bool { + return s == o || (s.Count == o.Count && s.Sum == o.Sum && s.Buckets.Equal(o.Buckets)) +} + +type SampleHistogramPair struct { + Timestamp Time + // Histogram should never be nil, it's only stored as pointer for efficiency. + Histogram *SampleHistogram +} + +func (s SampleHistogramPair) MarshalJSON() ([]byte, error) { + if s.Histogram == nil { + return nil, fmt.Errorf("histogram is nil") + } + t, err := json.Marshal(s.Timestamp) + if err != nil { + return nil, err + } + v, err := json.Marshal(s.Histogram) + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil +} + +func (s *SampleHistogramPair) UnmarshalJSON(buf []byte) error { + tmp := []interface{}{&s.Timestamp, &s.Histogram} + wantLen := len(tmp) + if err := json.Unmarshal(buf, &tmp); err != nil { + return err + } + if gotLen := len(tmp); gotLen != wantLen { + return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen) + } + if s.Histogram == nil { + return fmt.Errorf("histogram is null") + } + return nil +} + +func (s SampleHistogramPair) String() string { + return fmt.Sprintf("%s @[%s]", s.Histogram, s.Timestamp) +} + +func (s *SampleHistogramPair) Equal(o *SampleHistogramPair) bool { + return s == o || (s.Histogram.Equal(o.Histogram) && s.Timestamp.Equal(o.Timestamp)) +} diff --git a/vendor/github.com/prometheus/common/model/value_type.go b/vendor/github.com/prometheus/common/model/value_type.go new file mode 100644 index 000000000..726c50ee6 --- /dev/null +++ b/vendor/github.com/prometheus/common/model/value_type.go @@ -0,0 +1,83 @@ +// Copyright 2013 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "fmt" +) + +// Value is a generic interface for values resulting from a query evaluation. +type Value interface { + Type() ValueType + String() string +} + +func (Matrix) Type() ValueType { return ValMatrix } +func (Vector) Type() ValueType { return ValVector } +func (*Scalar) Type() ValueType { return ValScalar } +func (*String) Type() ValueType { return ValString } + +type ValueType int + +const ( + ValNone ValueType = iota + ValScalar + ValVector + ValMatrix + ValString +) + +// MarshalJSON implements json.Marshaler. +func (et ValueType) MarshalJSON() ([]byte, error) { + return json.Marshal(et.String()) +} + +func (et *ValueType) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + switch s { + case "": + *et = ValNone + case "scalar": + *et = ValScalar + case "vector": + *et = ValVector + case "matrix": + *et = ValMatrix + case "string": + *et = ValString + default: + return fmt.Errorf("unknown value type %q", s) + } + return nil +} + +func (e ValueType) String() string { + switch e { + case ValNone: + return "" + case ValScalar: + return "scalar" + case ValVector: + return "vector" + case ValMatrix: + return "matrix" + case ValString: + return "string" + } + panic("ValueType.String: unhandled value type") +} diff --git a/vendor/github.com/prometheus/procfs/.gitignore b/vendor/github.com/prometheus/procfs/.gitignore index 25e3659ab..7cc33ae4a 100644 --- a/vendor/github.com/prometheus/procfs/.gitignore +++ b/vendor/github.com/prometheus/procfs/.gitignore @@ -1 +1,2 @@ -/fixtures/ +/testdata/fixtures/ +/fixtures diff --git a/vendor/github.com/prometheus/procfs/.golangci.yml b/vendor/github.com/prometheus/procfs/.golangci.yml index 0aa09edac..c24864a92 100644 --- a/vendor/github.com/prometheus/procfs/.golangci.yml +++ b/vendor/github.com/prometheus/procfs/.golangci.yml @@ -1,4 +1,15 @@ --- linters: enable: - - golint + - godot + - misspell + - revive + +linter-settings: + godot: + capital: true + exclude: + # Ignore "See: URL" + - 'See:' + misspell: + locale: US diff --git a/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md b/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md index 9a1aff412..d325872bd 100644 --- a/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md +++ b/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ -## Prometheus Community Code of Conduct +# Prometheus Community Code of Conduct -Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). +Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). diff --git a/vendor/github.com/prometheus/procfs/CONTRIBUTING.md b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md index 943de7615..853eb9d49 100644 --- a/vendor/github.com/prometheus/procfs/CONTRIBUTING.md +++ b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md @@ -97,7 +97,7 @@ Many of the files are changing continuously and the data being read can in some reads in the same file. Also, most of the files are relatively small (less than a few KBs), and system calls to the `stat` function will often return the wrong size. Therefore, for most files it's recommended to read the full file in a single operation using an internal utility function called `util.ReadFileNoStat`. -This function is similar to `ioutil.ReadFile`, but it avoids the system call to `stat` to get the current size of +This function is similar to `os.ReadFile`, but it avoids the system call to `stat` to get the current size of the file. Note that parsing the file's contents can still be performed one line at a time. This is done by first reading @@ -113,7 +113,7 @@ the full file, and then using a scanner on the `[]byte` or `string` containing t ``` The `/sys` filesystem contains many very small files which contain only a single numeric or text value. These files -can be read using an internal function called `util.SysReadFile` which is similar to `ioutil.ReadFile` but does +can be read using an internal function called `util.SysReadFile` which is similar to `os.ReadFile` but does not bother to check the size of the file before reading. ``` data, err := util.SysReadFile("/sys/class/power_supply/BAT0/capacity") diff --git a/vendor/github.com/prometheus/procfs/Makefile b/vendor/github.com/prometheus/procfs/Makefile index 616a0d25e..7edfe4d09 100644 --- a/vendor/github.com/prometheus/procfs/Makefile +++ b/vendor/github.com/prometheus/procfs/Makefile @@ -14,16 +14,18 @@ include Makefile.common %/.unpacked: %.ttar - @echo ">> extracting fixtures" + @echo ">> extracting fixtures $*" ./ttar -C $(dir $*) -x -f $*.ttar touch $@ +fixtures: testdata/fixtures/.unpacked + update_fixtures: - rm -vf fixtures/.unpacked - ./ttar -c -f fixtures.ttar fixtures/ + rm -vf testdata/fixtures/.unpacked + ./ttar -c -f testdata/fixtures.ttar -C testdata/ fixtures/ .PHONY: build build: .PHONY: test -test: fixtures/.unpacked common-test +test: testdata/fixtures/.unpacked common-test diff --git a/vendor/github.com/prometheus/procfs/Makefile.common b/vendor/github.com/prometheus/procfs/Makefile.common index 3ac29c636..062a28185 100644 --- a/vendor/github.com/prometheus/procfs/Makefile.common +++ b/vendor/github.com/prometheus/procfs/Makefile.common @@ -36,29 +36,6 @@ GO_VERSION ?= $(shell $(GO) version) GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') -GOVENDOR := -GO111MODULE := -ifeq (, $(PRE_GO_111)) - ifneq (,$(wildcard go.mod)) - # Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI). - GO111MODULE := on - - ifneq (,$(wildcard vendor)) - # Always use the local vendor/ directory to satisfy the dependencies. - GOOPTS := $(GOOPTS) -mod=vendor - endif - endif -else - ifneq (,$(wildcard go.mod)) - ifneq (,$(wildcard vendor)) -$(warning This repository requires Go >= 1.11 because of Go modules) -$(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)') - endif - else - # This repository isn't using Go modules (yet). - GOVENDOR := $(FIRST_GOPATH)/bin/govendor - endif -endif PROMU := $(FIRST_GOPATH)/bin/promu pkgs = ./... @@ -72,23 +49,32 @@ endif GOTEST := $(GO) test GOTEST_DIR := ifneq ($(CIRCLE_JOB),) -ifneq ($(shell which gotestsum),) +ifneq ($(shell command -v gotestsum > /dev/null),) GOTEST_DIR := test-results GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml -- endif endif -PROMU_VERSION ?= 0.7.0 +PROMU_VERSION ?= 0.15.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz +SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.18.0 +GOLANGCI_LINT_VERSION ?= v1.54.2 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386)) - GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint + # If we're in CI and there is an Actions file, that means the linter + # is being run in Actions, so we don't need to run it here. + ifneq (,$(SKIP_GOLANGCI_LINT)) + GOLANGCI_LINT := + else ifeq (,$(CIRCLE_JOB)) + GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint + else ifeq (,$(wildcard .github/workflows/golangci-lint.yml)) + GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint + endif endif endif @@ -105,6 +91,8 @@ BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS)) PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS)) TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS)) +SANITIZED_DOCKER_IMAGE_TAG := $(subst +,-,$(DOCKER_IMAGE_TAG)) + ifeq ($(GOHOSTARCH),amd64) ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows)) # Only supported on amd64 @@ -118,7 +106,7 @@ endif %: common-% ; .PHONY: common-all -common-all: precheck style check_license lint unused build test +common-all: precheck style check_license lint yamllint unused build test .PHONY: common-style common-style: @@ -144,32 +132,25 @@ common-check_license: .PHONY: common-deps common-deps: @echo ">> getting dependencies" -ifdef GO111MODULE - GO111MODULE=$(GO111MODULE) $(GO) mod download -else - $(GO) get $(GOOPTS) -t ./... -endif + $(GO) mod download .PHONY: update-go-deps update-go-deps: @echo ">> updating Go dependencies" @for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ - $(GO) get $$m; \ + $(GO) get -d $$m; \ done - GO111MODULE=$(GO111MODULE) $(GO) mod tidy -ifneq (,$(wildcard vendor)) - GO111MODULE=$(GO111MODULE) $(GO) mod vendor -endif + $(GO) mod tidy .PHONY: common-test-short common-test-short: $(GOTEST_DIR) @echo ">> running short tests" - GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs) + $(GOTEST) -short $(GOOPTS) $(pkgs) .PHONY: common-test common-test: $(GOTEST_DIR) @echo ">> running all tests" - GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) + $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) $(GOTEST_DIR): @mkdir -p $@ @@ -177,25 +158,30 @@ $(GOTEST_DIR): .PHONY: common-format common-format: @echo ">> formatting code" - GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) + $(GO) fmt $(pkgs) .PHONY: common-vet common-vet: @echo ">> vetting code" - GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs) + $(GO) vet $(GOOPTS) $(pkgs) .PHONY: common-lint common-lint: $(GOLANGCI_LINT) ifdef GOLANGCI_LINT @echo ">> running golangci-lint" -ifdef GO111MODULE # 'go list' needs to be executed before staticcheck to prepopulate the modules cache. # Otherwise staticcheck might fail randomly for some reason not yet explained. - GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null - GO111MODULE=$(GO111MODULE) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) -else - $(GOLANGCI_LINT) run $(pkgs) + $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null + $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) endif + +.PHONY: common-yamllint +common-yamllint: + @echo ">> running yamllint on all YAML files in the repository" +ifeq (, $(shell command -v yamllint > /dev/null)) + @echo "yamllint not installed so skipping" +else + yamllint . endif # For backward-compatibility. @@ -203,28 +189,15 @@ endif common-staticcheck: lint .PHONY: common-unused -common-unused: $(GOVENDOR) -ifdef GOVENDOR - @echo ">> running check for unused packages" - @$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages' -else -ifdef GO111MODULE +common-unused: @echo ">> running check for unused/missing packages in go.mod" - GO111MODULE=$(GO111MODULE) $(GO) mod tidy -ifeq (,$(wildcard vendor)) + $(GO) mod tidy @git diff --exit-code -- go.sum go.mod -else - @echo ">> running check for unused packages in vendor/" - GO111MODULE=$(GO111MODULE) $(GO) mod vendor - @git diff --exit-code -- go.sum go.mod vendor/ -endif -endif -endif .PHONY: common-build common-build: promu @echo ">> building binaries" - GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) + $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) .PHONY: common-tarball common-tarball: promu @@ -234,7 +207,7 @@ common-tarball: promu .PHONY: common-docker $(BUILD_DOCKER_ARCHS) common-docker: $(BUILD_DOCKER_ARCHS) $(BUILD_DOCKER_ARCHS): common-docker-%: - docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \ + docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \ -f $(DOCKERFILE_PATH) \ --build-arg ARCH="$*" \ --build-arg OS="linux" \ @@ -243,19 +216,19 @@ $(BUILD_DOCKER_ARCHS): common-docker-%: .PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS) common-docker-publish: $(PUBLISH_DOCKER_ARCHS) $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%: - docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" + docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION))) .PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS) common-docker-tag-latest: $(TAG_DOCKER_ARCHS) $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%: - docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" - docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" .PHONY: common-docker-manifest common-docker-manifest: - DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(DOCKER_IMAGE_TAG)) - DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(SANITIZED_DOCKER_IMAGE_TAG)) + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" .PHONY: promu promu: $(PROMU) @@ -280,12 +253,6 @@ $(GOLANGCI_LINT): | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) endif -ifdef GOVENDOR -.PHONY: $(GOVENDOR) -$(GOVENDOR): - GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor -endif - .PHONY: precheck precheck:: diff --git a/vendor/github.com/prometheus/procfs/README.md b/vendor/github.com/prometheus/procfs/README.md index 55d1e3261..1224816c2 100644 --- a/vendor/github.com/prometheus/procfs/README.md +++ b/vendor/github.com/prometheus/procfs/README.md @@ -6,8 +6,8 @@ metrics from the pseudo-filesystems /proc and /sys. *WARNING*: This package is a work in progress. Its API may still break in backwards-incompatible ways without warnings. Use it at your own risk. -[![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs) -[![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs) +[![Go Reference](https://pkg.go.dev/badge/github.com/prometheus/procfs.svg)](https://pkg.go.dev/github.com/prometheus/procfs) +[![CircleCI](https://circleci.com/gh/prometheus/procfs/tree/master.svg?style=svg)](https://circleci.com/gh/prometheus/procfs/tree/master) [![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs) ## Usage @@ -51,11 +51,11 @@ ensure the `fixtures` directory is up to date by removing the existing directory extracting the ttar file using `make fixtures/.unpacked` or just `make test`. ```bash -rm -rf fixtures +rm -rf testdata/fixtures make test ``` Next, make the required changes to the extracted files in the `fixtures` directory. When the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file based on the updated `fixtures` directory. And finally, verify the changes using -`git diff fixtures.ttar`. +`git diff testdata/fixtures.ttar`. diff --git a/vendor/github.com/prometheus/procfs/SECURITY.md b/vendor/github.com/prometheus/procfs/SECURITY.md index 67741f015..fed02d85c 100644 --- a/vendor/github.com/prometheus/procfs/SECURITY.md +++ b/vendor/github.com/prometheus/procfs/SECURITY.md @@ -3,4 +3,4 @@ The Prometheus security policy, including how to report vulnerabilities, can be found here: -https://prometheus.io/docs/operating/security/ + diff --git a/vendor/github.com/prometheus/procfs/arp.go b/vendor/github.com/prometheus/procfs/arp.go index 4e47e6172..28783e2dd 100644 --- a/vendor/github.com/prometheus/procfs/arp.go +++ b/vendor/github.com/prometheus/procfs/arp.go @@ -15,11 +15,28 @@ package procfs import ( "fmt" - "io/ioutil" "net" + "os" + "strconv" "strings" ) +// Learned from include/uapi/linux/if_arp.h. +const ( + // completed entry (ha valid). + ATFComplete = 0x02 + // permanent entry. + ATFPermanent = 0x04 + // Publish entry. + ATFPublish = 0x08 + // Has requested trailers. + ATFUseTrailers = 0x10 + // Obsoleted: Want to use a netmask (only for proxy entries). + ATFNetmask = 0x20 + // Don't answer this addresses. + ATFDontPublish = 0x40 +) + // ARPEntry contains a single row of the columnar data represented in // /proc/net/arp. type ARPEntry struct { @@ -29,14 +46,16 @@ type ARPEntry struct { HWAddr net.HardwareAddr // Name of the device Device string + // Flags + Flags byte } // GatherARPEntries retrieves all the ARP entries, parse the relevant columns, // and then return a slice of ARPEntry's. func (fs FS) GatherARPEntries() ([]ARPEntry, error) { - data, err := ioutil.ReadFile(fs.proc.Path("net/arp")) + data, err := os.ReadFile(fs.proc.Path("net/arp")) if err != nil { - return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err) + return nil, fmt.Errorf("%s: error reading arp %s: %w", ErrFileRead, fs.proc.Path("net/arp"), err) } return parseARPEntries(data) @@ -59,11 +78,11 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) { } else if width == expectedDataWidth { entry, err := parseARPEntry(columns) if err != nil { - return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %w", err) + return []ARPEntry{}, fmt.Errorf("%s: Failed to parse ARP entry: %v: %w", ErrFileParse, entry, err) } entries = append(entries, entry) } else { - return []ARPEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedDataWidth) + return []ARPEntry{}, fmt.Errorf("%s: %d columns found, but expected %d: %w", ErrFileParse, width, expectedDataWidth, err) } } @@ -72,14 +91,26 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) { } func parseARPEntry(columns []string) (ARPEntry, error) { + entry := ARPEntry{Device: columns[5]} ip := net.ParseIP(columns[0]) - mac := net.HardwareAddr(columns[3]) + entry.IPAddr = ip + + if mac, err := net.ParseMAC(columns[3]); err == nil { + entry.HWAddr = mac + } else { + return ARPEntry{}, err + } - entry := ARPEntry{ - IPAddr: ip, - HWAddr: mac, - Device: columns[5], + if flags, err := strconv.ParseUint(columns[2], 0, 8); err == nil { + entry.Flags = byte(flags) + } else { + return ARPEntry{}, err } return entry, nil } + +// IsComplete returns true if ARP entry is marked with complete flag. +func (entry *ARPEntry) IsComplete() bool { + return entry.Flags&ATFComplete != 0 +} diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go index f5b7939b2..4a173636c 100644 --- a/vendor/github.com/prometheus/procfs/buddyinfo.go +++ b/vendor/github.com/prometheus/procfs/buddyinfo.go @@ -55,7 +55,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { parts := strings.Fields(line) if len(parts) < 4 { - return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo") + return nil, fmt.Errorf("%w: Invalid number of fields, found: %v", ErrFileParse, parts) } node := strings.TrimRight(parts[1], ",") @@ -66,7 +66,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { bucketCount = arraySize } else { if bucketCount != arraySize { - return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize) + return nil, fmt.Errorf("%w: mismatch in number of buddyinfo buckets, previous count %d, new count %d", ErrFileParse, bucketCount, arraySize) } } @@ -74,7 +74,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { for i := 0; i < arraySize; i++ { sizes[i], err = strconv.ParseFloat(parts[i+4], 64) if err != nil { - return nil, fmt.Errorf("invalid value in buddyinfo: %w", err) + return nil, fmt.Errorf("%s: Invalid valid in buddyinfo: %f: %w", ErrFileParse, sizes[i], err) } } diff --git a/vendor/github.com/prometheus/procfs/cmdline.go b/vendor/github.com/prometheus/procfs/cmdline.go new file mode 100644 index 000000000..bf4f3b48c --- /dev/null +++ b/vendor/github.com/prometheus/procfs/cmdline.go @@ -0,0 +1,30 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// CmdLine returns the command line of the kernel. +func (fs FS) CmdLine() ([]string, error) { + data, err := util.ReadFileNoStat(fs.proc.Path("cmdline")) + if err != nil { + return nil, err + } + + return strings.Fields(string(data)), nil +} diff --git a/vendor/github.com/prometheus/procfs/cpuinfo.go b/vendor/github.com/prometheus/procfs/cpuinfo.go index 5623b24a1..f4f5501c6 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux // +build linux package procfs @@ -27,7 +28,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// CPUInfo contains general information about a system CPU found in /proc/cpuinfo +// CPUInfo contains general information about a system CPU found in /proc/cpuinfo. type CPUInfo struct { Processor uint VendorID string @@ -78,7 +79,7 @@ func parseCPUInfoX86(info []byte) ([]CPUInfo, error) { // find the first "processor" line firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") { - return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine) + return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) v, err := strconv.ParseUint(field[1], 0, 32) @@ -191,9 +192,10 @@ func parseCPUInfoARM(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) firstLine := firstNonEmptyLine(scanner) - match, _ := regexp.MatchString("^[Pp]rocessor", firstLine) + match, err := regexp.MatchString("^[Pp]rocessor", firstLine) if !match || !strings.Contains(firstLine, ":") { - return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine) + return nil, fmt.Errorf("%s: Cannot parse line: %q: %w", ErrFileParse, firstLine, err) + } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} @@ -257,7 +259,7 @@ func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) { firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "vendor_id") || !strings.Contains(firstLine, ":") { - return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine) + return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} @@ -282,7 +284,7 @@ func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) { if strings.HasPrefix(line, "processor") { match := cpuinfoS390XProcessorRegexp.FindStringSubmatch(line) if len(match) < 2 { - return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine) + return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } cpu := commonCPUInfo v, err := strconv.ParseUint(match[1], 0, 32) @@ -342,7 +344,7 @@ func parseCPUInfoMips(info []byte) ([]CPUInfo, error) { // find the first "processor" line firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") { - return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine) + return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} @@ -379,12 +381,48 @@ func parseCPUInfoMips(info []byte) ([]CPUInfo, error) { return cpuinfo, nil } +func parseCPUInfoLoong(info []byte) ([]CPUInfo, error) { + scanner := bufio.NewScanner(bytes.NewReader(info)) + // find the first "processor" line + firstLine := firstNonEmptyLine(scanner) + if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") { + return nil, errors.New("invalid cpuinfo file: " + firstLine) + } + field := strings.SplitN(firstLine, ": ", 2) + cpuinfo := []CPUInfo{} + systemType := field[1] + i := 0 + for scanner.Scan() { + line := scanner.Text() + if !strings.Contains(line, ":") { + continue + } + field := strings.SplitN(line, ": ", 2) + switch strings.TrimSpace(field[0]) { + case "processor": + v, err := strconv.ParseUint(field[1], 0, 32) + if err != nil { + return nil, err + } + i = int(v) + cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor + cpuinfo[i].Processor = uint(v) + cpuinfo[i].VendorID = systemType + case "CPU Family": + cpuinfo[i].CPUFamily = field[1] + case "Model Name": + cpuinfo[i].ModelName = field[1] + } + } + return cpuinfo, nil +} + func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") { - return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine) + return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) v, err := strconv.ParseUint(field[1], 0, 32) @@ -429,7 +467,7 @@ func parseCPUInfoRISCV(info []byte) ([]CPUInfo, error) { firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") { - return nil, fmt.Errorf("invalid cpuinfo file: %q", firstLine) + return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) v, err := strconv.ParseUint(field[1], 0, 32) @@ -469,7 +507,7 @@ func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { // nolint:unused,deadcode } // firstNonEmptyLine advances the scanner to the first non-empty line -// and returns the contents of that line +// and returns the contents of that line. func firstNonEmptyLine(scanner *bufio.Scanner) string { for scanner.Scan() { line := scanner.Text() diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_armx.go b/vendor/github.com/prometheus/procfs/cpuinfo_armx.go index 44b590ed3..64cfd534c 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_armx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_armx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (arm || arm64) // +build linux // +build arm arm64 diff --git a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go b/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go similarity index 73% rename from vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go rename to vendor/github.com/prometheus/procfs/cpuinfo_loong64.go index c318385cb..d88442f0e 100644 --- a/vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go @@ -1,10 +1,9 @@ -// Copyright 2013 Matt T. Proud -// +// Copyright 2022 The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -12,5 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package pbutil provides record length-delimited Protocol Buffer streaming. -package pbutil +//go:build linux +// +build linux + +package procfs + +var parseCPUInfo = parseCPUInfoLoong diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go b/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go index 91e272573..c11207f3a 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (mips || mipsle || mips64 || mips64le) // +build linux // +build mips mipsle mips64 mips64le diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_others.go b/vendor/github.com/prometheus/procfs/cpuinfo_others.go index 95b5b4ec4..a6b2b3127 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_others.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_others.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux -// +build !386,!amd64,!arm,!arm64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x +//go:build linux && !386 && !amd64 && !arm && !arm64 && !loong64 && !mips && !mips64 && !mips64le && !mipsle && !ppc64 && !ppc64le && !riscv64 && !s390x +// +build linux,!386,!amd64,!arm,!arm64,!loong64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go b/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go index 6068bd571..003bc2ad4 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (ppc64 || ppc64le) // +build linux // +build ppc64 ppc64le diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go b/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go index e83c2e207..1c9b7313b 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (riscv || riscv64) // +build linux // +build riscv riscv64 diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go b/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go index 26814eeba..fa3686bc0 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux // +build linux package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_x86.go b/vendor/github.com/prometheus/procfs/cpuinfo_x86.go index d5bedf97f..a0ef55562 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_x86.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_x86.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (386 || amd64) // +build linux // +build 386 amd64 diff --git a/vendor/github.com/prometheus/procfs/crypto.go b/vendor/github.com/prometheus/procfs/crypto.go index 5048ad1f2..9a73e2639 100644 --- a/vendor/github.com/prometheus/procfs/crypto.go +++ b/vendor/github.com/prometheus/procfs/crypto.go @@ -55,12 +55,13 @@ func (fs FS) Crypto() ([]Crypto, error) { path := fs.proc.Path("crypto") b, err := util.ReadFileNoStat(path) if err != nil { - return nil, fmt.Errorf("error reading crypto %q: %w", path, err) + return nil, fmt.Errorf("%s: Cannot read file %v: %w", ErrFileRead, b, err) + } crypto, err := parseCrypto(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("error parsing crypto %q: %w", path, err) + return nil, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, crypto, err) } return crypto, nil @@ -83,7 +84,7 @@ func parseCrypto(r io.Reader) ([]Crypto, error) { kv := strings.Split(text, ":") if len(kv) != 2 { - return nil, fmt.Errorf("malformed crypto line: %q", text) + return nil, fmt.Errorf("%w: Cannot parae line: %q", ErrFileParse, text) } k := strings.TrimSpace(kv[0]) diff --git a/vendor/github.com/prometheus/procfs/doc.go b/vendor/github.com/prometheus/procfs/doc.go index e2acd6d40..f9d961e44 100644 --- a/vendor/github.com/prometheus/procfs/doc.go +++ b/vendor/github.com/prometheus/procfs/doc.go @@ -16,30 +16,29 @@ // // Example: // -// package main -// -// import ( -// "fmt" -// "log" -// -// "github.com/prometheus/procfs" -// ) -// -// func main() { -// p, err := procfs.Self() -// if err != nil { -// log.Fatalf("could not get process: %s", err) -// } -// -// stat, err := p.NewStat() -// if err != nil { -// log.Fatalf("could not get process stat: %s", err) -// } -// -// fmt.Printf("command: %s\n", stat.Comm) -// fmt.Printf("cpu time: %fs\n", stat.CPUTime()) -// fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) -// fmt.Printf("rss: %dB\n", stat.ResidentMemory()) -// } -// +// package main +// +// import ( +// "fmt" +// "log" +// +// "github.com/prometheus/procfs" +// ) +// +// func main() { +// p, err := procfs.Self() +// if err != nil { +// log.Fatalf("could not get process: %s", err) +// } +// +// stat, err := p.Stat() +// if err != nil { +// log.Fatalf("could not get process stat: %s", err) +// } +// +// fmt.Printf("command: %s\n", stat.Comm) +// fmt.Printf("cpu time: %fs\n", stat.CPUTime()) +// fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) +// fmt.Printf("rss: %dB\n", stat.ResidentMemory()) +// } package procfs diff --git a/vendor/github.com/prometheus/procfs/fixtures.ttar b/vendor/github.com/prometheus/procfs/fixtures.ttar deleted file mode 100644 index 1e76173da..000000000 --- a/vendor/github.com/prometheus/procfs/fixtures.ttar +++ /dev/null @@ -1,6553 +0,0 @@ -# Archive created by ttar -c -f fixtures.ttar fixtures/ -Directory: fixtures -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/cmdline -Lines: 1 -vimNULLBYTEtest.goNULLBYTE+10NULLBYTEEOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/comm -Lines: 1 -vim -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/cwd -SymlinkTo: /usr/bin -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/environ -Lines: 1 -PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNULLBYTEHOSTNAME=cd24e11f73a5NULLBYTETERM=xtermNULLBYTEGOLANG_VERSION=1.12.5NULLBYTEGOPATH=/goNULLBYTEHOME=/rootNULLBYTEEOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/exe -SymlinkTo: /usr/bin/vim -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/fd -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/0 -SymlinkTo: ../../symlinktargets/abc -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/1 -SymlinkTo: ../../symlinktargets/def -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/10 -SymlinkTo: ../../symlinktargets/xyz -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/2 -SymlinkTo: ../../symlinktargets/ghi -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/3 -SymlinkTo: ../../symlinktargets/uvw -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/fdinfo -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/0 -Lines: 6 -pos: 0 -flags: 02004000 -mnt_id: 13 -inotify wd:3 ino:1 sdev:34 mask:fce ignored_mask:0 fhandle-bytes:c fhandle-type:81 f_handle:000000000100000000000000 -inotify wd:2 ino:1300016 sdev:fd00002 mask:fce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:16003001ed3f022a -inotify wd:1 ino:2e0001 sdev:fd00000 mask:fce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:01002e00138e7c65 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/1 -Lines: 4 -pos: 0 -flags: 02004002 -mnt_id: 13 -eventfd-count: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/10 -Lines: 3 -pos: 0 -flags: 02004002 -mnt_id: 9 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/2 -Lines: 3 -pos: 0 -flags: 02004002 -mnt_id: 9 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/3 -Lines: 3 -pos: 0 -flags: 02004002 -mnt_id: 9 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/io -Lines: 7 -rchar: 750339 -wchar: 818609 -syscr: 7405 -syscw: 5245 -read_bytes: 1024 -write_bytes: 2048 -cancelled_write_bytes: -1024 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/limits -Lines: 17 -Limit Soft Limit Hard Limit Units -Max cpu time unlimited unlimited seconds -Max file size unlimited unlimited bytes -Max data size unlimited unlimited bytes -Max stack size 8388608 unlimited bytes -Max core file size 0 unlimited bytes -Max resident set unlimited unlimited bytes -Max processes 62898 62898 processes -Max open files 2048 4096 files -Max locked memory 18446744073708503040 18446744073708503040 bytes -Max address space 8589934592 unlimited bytes -Max file locks unlimited unlimited locks -Max pending signals 62898 62898 signals -Max msgqueue size 819200 819200 bytes -Max nice priority 0 0 -Max realtime priority 0 0 -Max realtime timeout unlimited unlimited us -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/mountstats -Lines: 20 -device rootfs mounted on / with fstype rootfs -device sysfs mounted on /sys with fstype sysfs -device proc mounted on /proc with fstype proc -device /dev/sda1 mounted on / with fstype ext4 -device 192.168.1.1:/srv/test mounted on /mnt/nfs/test with fstype nfs4 statvers=1.1 - opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,mountaddr=192.168.1.1,clientaddr=192.168.1.5,local_lock=none - age: 13968 - caps: caps=0xfff7,wtmult=512,dtsize=32768,bsize=0,namlen=255 - nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x0,acl=0x0,pnfs=not configured - sec: flavor=1,pseudoflavor=1 - events: 52 226 0 0 1 13 398 0 0 331 0 47 0 0 77 0 0 77 0 0 0 0 0 0 0 0 0 - bytes: 1207640230 0 0 0 1210214218 0 295483 0 - RPC iostats version: 1.0 p/v: 100003/4 (nfs) - xprt: tcp 832 0 1 0 11 6428 6428 0 12154 0 24 26 5726 - per-op statistics - NULL: 0 0 0 0 0 0 0 0 - READ: 1298 1298 0 207680 1210292152 6 79386 79407 - WRITE: 0 0 0 0 0 0 0 0 - ACCESS: 2927395007 2927394995 0 526931094212 362996810236 18446743919241604546 1667369447 1953587717 - -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/net -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/net/dev -Lines: 4 -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed - lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - eth0: 438 5 0 0 0 0 0 0 648 8 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/ns -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/ns/mnt -SymlinkTo: mnt:[4026531840] -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/ns/net -SymlinkTo: net:[4026531993] -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/root -SymlinkTo: / -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/schedstat -Lines: 1 -411605849 93680043 79 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/smaps -Lines: 252 -00400000-00cb1000 r-xp 00000000 fd:01 952273 /bin/alertmanager -Size: 8900 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 2952 kB -Pss: 2952 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 2952 kB -Private_Dirty: 0 kB -Referenced: 2864 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd ex mr mw me dw sd -00cb1000-016b0000 r--p 008b1000 fd:01 952273 /bin/alertmanager -Size: 10236 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 6152 kB -Pss: 6152 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 6152 kB -Private_Dirty: 0 kB -Referenced: 5308 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd mr mw me dw sd -016b0000-0171a000 rw-p 012b0000 fd:01 952273 /bin/alertmanager -Size: 424 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 176 kB -Pss: 176 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 84 kB -Private_Dirty: 92 kB -Referenced: 176 kB -Anonymous: 92 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 12 kB -SwapPss: 12 kB -Locked: 0 kB -VmFlags: rd wr mr mw me dw ac sd -0171a000-0173f000 rw-p 00000000 00:00 0 -Size: 148 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 76 kB -Pss: 76 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 76 kB -Referenced: 76 kB -Anonymous: 76 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -c000000000-c000400000 rw-p 00000000 00:00 0 -Size: 4096 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 2564 kB -Pss: 2564 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 20 kB -Private_Dirty: 2544 kB -Referenced: 2544 kB -Anonymous: 2564 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 1100 kB -SwapPss: 1100 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -c000400000-c001600000 rw-p 00000000 00:00 0 -Size: 18432 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 16024 kB -Pss: 16024 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 5864 kB -Private_Dirty: 10160 kB -Referenced: 11944 kB -Anonymous: 16024 kB -LazyFree: 5848 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 440 kB -SwapPss: 440 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd nh -c001600000-c004000000 rw-p 00000000 00:00 0 -Size: 43008 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 0 kB -Pss: 0 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 0 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -7f0ab95ca000-7f0abbb7b000 rw-p 00000000 00:00 0 -Size: 38596 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 1992 kB -Pss: 1992 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 476 kB -Private_Dirty: 1516 kB -Referenced: 1828 kB -Anonymous: 1992 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 384 kB -SwapPss: 384 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -7ffc07ecf000-7ffc07ef0000 rw-p 00000000 00:00 0 [stack] -Size: 132 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 8 kB -Pss: 8 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 8 kB -Referenced: 8 kB -Anonymous: 8 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 4 kB -SwapPss: 4 kB -Locked: 0 kB -VmFlags: rd wr mr mw me gd ac -7ffc07f9e000-7ffc07fa1000 r--p 00000000 00:00 0 [vvar] -Size: 12 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 0 kB -Pss: 0 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 0 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd mr pf io de dd sd -7ffc07fa1000-7ffc07fa3000 r-xp 00000000 00:00 0 [vdso] -Size: 8 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 4 kB -Pss: 0 kB -Shared_Clean: 4 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 4 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd ex mr mw me de sd -ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] -Size: 4 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 0 kB -Pss: 0 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 0 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd ex -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/smaps_rollup -Lines: 17 -00400000-ffffffffff601000 ---p 00000000 00:00 0 [rollup] -Rss: 29948 kB -Pss: 29944 kB -Shared_Clean: 4 kB -Shared_Dirty: 0 kB -Private_Clean: 15548 kB -Private_Dirty: 14396 kB -Referenced: 24752 kB -Anonymous: 20756 kB -LazyFree: 5848 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 1940 kB -SwapPss: 1940 kB -Locked: 0 kB -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/stat -Lines: 1 -26231 (vim) R 5392 7446 5392 34835 7446 4218880 32533 309516 26 82 1677 44 158 99 20 0 1 0 82375 56274944 1981 18446744073709551615 4194304 6294284 140736914091744 140736914087944 139965136429984 0 0 12288 1870679807 0 0 0 17 0 0 0 31 0 0 8391624 8481048 16420864 140736914093252 140736914093279 140736914093279 140736914096107 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/status -Lines: 53 - -Name: prometheus -Umask: 0022 -State: S (sleeping) -Tgid: 26231 -Ngid: 0 -Pid: 26231 -PPid: 1 -TracerPid: 0 -Uid: 1000 1000 1000 0 -Gid: 1001 1001 1001 0 -FDSize: 128 -Groups: -NStgid: 1 -NSpid: 1 -NSpgid: 1 -NSsid: 1 -VmPeak: 58472 kB -VmSize: 58440 kB -VmLck: 0 kB -VmPin: 0 kB -VmHWM: 8028 kB -VmRSS: 6716 kB -RssAnon: 2092 kB -RssFile: 4624 kB -RssShmem: 0 kB -VmData: 2580 kB -VmStk: 136 kB -VmExe: 948 kB -VmLib: 6816 kB -VmPTE: 128 kB -VmPMD: 12 kB -VmSwap: 660 kB -HugetlbPages: 0 kB -Threads: 1 -SigQ: 8/63965 -SigPnd: 0000000000000000 -ShdPnd: 0000000000000000 -SigBlk: 7be3c0fe28014a03 -SigIgn: 0000000000001000 -SigCgt: 00000001800004ec -CapInh: 0000000000000000 -CapPrm: 0000003fffffffff -CapEff: 0000003fffffffff -CapBnd: 0000003fffffffff -CapAmb: 0000000000000000 -Seccomp: 0 -Cpus_allowed: ff -Cpus_allowed_list: 0-7 -Mems_allowed: 00000000,00000001 -Mems_allowed_list: 0 -voluntary_ctxt_switches: 4742839 -nonvoluntary_ctxt_switches: 1727500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/wchan -Lines: 1 -poll_schedule_timeoutEOF -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26232 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/cmdline -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/comm -Lines: 1 -ata_sff -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/cwd -SymlinkTo: /does/not/exist -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26232/fd -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/0 -SymlinkTo: ../../symlinktargets/abc -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/1 -SymlinkTo: ../../symlinktargets/def -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/2 -SymlinkTo: ../../symlinktargets/ghi -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/3 -SymlinkTo: ../../symlinktargets/uvw -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/4 -SymlinkTo: ../../symlinktargets/xyz -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/limits -Lines: 17 -Limit Soft Limit Hard Limit Units -Max cpu time unlimited unlimited seconds -Max file size unlimited unlimited bytes -Max data size unlimited unlimited bytes -Max stack size 8388608 unlimited bytes -Max core file size 0 unlimited bytes -Max resident set unlimited unlimited bytes -Max processes 29436 29436 processes -Max open files 1024 4096 files -Max locked memory 65536 65536 bytes -Max address space unlimited unlimited bytes -Max file locks unlimited unlimited locks -Max pending signals 29436 29436 signals -Max msgqueue size 819200 819200 bytes -Max nice priority 0 0 -Max realtime priority 0 0 -Max realtime timeout unlimited unlimited us -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/maps -Lines: 9 -55680ae1e000-55680ae20000 r--p 00000000 fd:01 47316994 /bin/cat -55680ae29000-55680ae2a000 rwxs 0000a000 fd:01 47316994 /bin/cat -55680bed6000-55680bef7000 rw-p 00000000 00:00 0 [heap] -7fdf964fc000-7fdf973f2000 r--p 00000000 fd:01 17432624 /usr/lib/locale/locale-archive -7fdf973f2000-7fdf97417000 r--p 00000000 fd:01 60571062 /lib/x86_64-linux-gnu/libc-2.29.so -7ffe9215c000-7ffe9217f000 rw-p 00000000 00:00 0 [stack] -7ffe921da000-7ffe921dd000 r--p 00000000 00:00 0 [vvar] -7ffe921dd000-7ffe921de000 r-xp 00000000 00:00 0 [vdso] -ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall] -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/root -SymlinkTo: /does/not/exist -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/stat -Lines: 1 -33 (ata_sff) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 0 0 0 -20 1 0 5 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/wchan -Lines: 1 -0EOF -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26233 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26233/cmdline -Lines: 1 -com.github.uiautomatorNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEEOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26233/schedstat -Lines: 8 - ____________________________________ -< this is a malformed schedstat file > - ------------------------------------ - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26234 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26234/maps -Lines: 4 -08048000-08089000 r-xp 00000000 03:01 104219 /bin/tcsh -08089000-0808c000 rw-p 00041000 03:01 104219 /bin/tcsh -0808c000-08146000 rwxp 00000000 00:00 0 -40000000-40015000 r-xp 00000000 03:01 61874 /lib/ld-2.3.2.so -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/584 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/584/stat -Lines: 2 -1020 ((a b ) ( c d) ) R 28378 1020 28378 34842 1020 4218880 286 0 0 0 0 0 0 0 20 0 1 0 10839175 10395648 155 18446744073709551615 4194304 4238788 140736466511168 140736466511168 140609271124624 0 0 0 0 0 0 0 17 5 0 0 0 0 0 6336016 6337300 25579520 140736466515030 140736466515061 140736466515061 140736466518002 0 -#!/bin/cat /proc/self/stat -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/buddyinfo -Lines: 3 -Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 -Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 -Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/cpuinfo -Lines: 216 -processor : 0 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 799.998 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 0 -cpu cores : 4 -apicid : 0 -initial apicid : 0 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 1 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.037 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 1 -cpu cores : 4 -apicid : 2 -initial apicid : 2 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 2 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.010 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 2 -cpu cores : 4 -apicid : 4 -initial apicid : 4 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 3 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.028 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 3 -cpu cores : 4 -apicid : 6 -initial apicid : 6 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 4 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 799.989 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 0 -cpu cores : 4 -apicid : 1 -initial apicid : 1 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 5 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.083 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 1 -cpu cores : 4 -apicid : 3 -initial apicid : 3 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 6 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.017 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 2 -cpu cores : 4 -apicid : 5 -initial apicid : 5 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 7 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.030 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 3 -cpu cores : 4 -apicid : 7 -initial apicid : 7 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/crypto -Lines: 972 -name : ccm(aes) -driver : ccm_base(ctr(aes-aesni),cbcmac(aes-aesni)) -module : ccm -priority : 300 -refcnt : 4 -selftest : passed -internal : no -type : aead -async : no -blocksize : 1 -ivsize : 16 -maxauthsize : 16 -geniv : - -name : cbcmac(aes) -driver : cbcmac(aes-aesni) -module : ccm -priority : 300 -refcnt : 7 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 16 - -name : ecdh -driver : ecdh-generic -module : ecdh_generic -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : kpp -async : yes - -name : ecb(arc4) -driver : ecb(arc4)-generic -module : arc4 -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 1 -min keysize : 1 -max keysize : 256 -ivsize : 0 -chunksize : 1 -walksize : 1 - -name : arc4 -driver : arc4-generic -module : arc4 -priority : 0 -refcnt : 3 -selftest : passed -internal : no -type : cipher -blocksize : 1 -min keysize : 1 -max keysize : 256 - -name : crct10dif -driver : crct10dif-pclmul -module : crct10dif_pclmul -priority : 200 -refcnt : 2 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 2 - -name : crc32 -driver : crc32-pclmul -module : crc32_pclmul -priority : 200 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 4 - -name : __ghash -driver : cryptd(__ghash-pclmulqdqni) -module : kernel -priority : 50 -refcnt : 1 -selftest : passed -internal : yes -type : ahash -async : yes -blocksize : 16 -digestsize : 16 - -name : ghash -driver : ghash-clmulni -module : ghash_clmulni_intel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : ahash -async : yes -blocksize : 16 -digestsize : 16 - -name : __ghash -driver : __ghash-pclmulqdqni -module : ghash_clmulni_intel -priority : 0 -refcnt : 1 -selftest : passed -internal : yes -type : shash -blocksize : 16 -digestsize : 16 - -name : crc32c -driver : crc32c-intel -module : crc32c_intel -priority : 200 -refcnt : 5 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 4 - -name : cbc(aes) -driver : cbc(aes-aesni) -module : kernel -priority : 300 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : ctr(aes) -driver : ctr(aes-aesni) -module : kernel -priority : 300 -refcnt : 5 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 1 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : pkcs1pad(rsa,sha256) -driver : pkcs1pad(rsa-generic,sha256) -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : akcipher - -name : __xts(aes) -driver : cryptd(__xts-aes-aesni) -module : kernel -priority : 451 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 16 -min keysize : 32 -max keysize : 64 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : xts(aes) -driver : xts-aes-aesni -module : kernel -priority : 401 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 16 -min keysize : 32 -max keysize : 64 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ctr(aes) -driver : cryptd(__ctr-aes-aesni) -module : kernel -priority : 450 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 1 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : ctr(aes) -driver : ctr-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 1 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __cbc(aes) -driver : cryptd(__cbc-aes-aesni) -module : kernel -priority : 450 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : cbc(aes) -driver : cbc-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ecb(aes) -driver : cryptd(__ecb-aes-aesni) -module : kernel -priority : 450 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 0 -chunksize : 16 -walksize : 16 - -name : ecb(aes) -driver : ecb-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 0 -chunksize : 16 -walksize : 16 - -name : __generic-gcm-aes-aesni -driver : cryptd(__driver-generic-gcm-aes-aesni) -module : kernel -priority : 50 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : yes -blocksize : 1 -ivsize : 12 -maxauthsize : 16 -geniv : - -name : gcm(aes) -driver : generic-gcm-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : aead -async : yes -blocksize : 1 -ivsize : 12 -maxauthsize : 16 -geniv : - -name : __generic-gcm-aes-aesni -driver : __driver-generic-gcm-aes-aesni -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : no -blocksize : 1 -ivsize : 12 -maxauthsize : 16 -geniv : - -name : __gcm-aes-aesni -driver : cryptd(__driver-gcm-aes-aesni) -module : kernel -priority : 50 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : yes -blocksize : 1 -ivsize : 8 -maxauthsize : 16 -geniv : - -name : rfc4106(gcm(aes)) -driver : rfc4106-gcm-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : aead -async : yes -blocksize : 1 -ivsize : 8 -maxauthsize : 16 -geniv : - -name : __gcm-aes-aesni -driver : __driver-gcm-aes-aesni -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : no -blocksize : 1 -ivsize : 8 -maxauthsize : 16 -geniv : - -name : __xts(aes) -driver : __xts-aes-aesni -module : kernel -priority : 401 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 16 -min keysize : 32 -max keysize : 64 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ctr(aes) -driver : __ctr-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 1 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __cbc(aes) -driver : __cbc-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ecb(aes) -driver : __ecb-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 0 -chunksize : 16 -walksize : 16 - -name : __aes -driver : __aes-aesni -module : kernel -priority : 300 -refcnt : 1 -selftest : passed -internal : yes -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -name : aes -driver : aes-aesni -module : kernel -priority : 300 -refcnt : 8 -selftest : passed -internal : no -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -name : hmac(sha1) -driver : hmac(sha1-generic) -module : kernel -priority : 100 -refcnt : 9 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 20 - -name : ghash -driver : ghash-generic -module : kernel -priority : 100 -refcnt : 3 -selftest : passed -internal : no -type : shash -blocksize : 16 -digestsize : 16 - -name : jitterentropy_rng -driver : jitterentropy_rng -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha256 -module : kernel -priority : 221 -refcnt : 2 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha512 -module : kernel -priority : 220 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha384 -module : kernel -priority : 219 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha1 -module : kernel -priority : 218 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha256 -module : kernel -priority : 217 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha512 -module : kernel -priority : 216 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha384 -module : kernel -priority : 215 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha1 -module : kernel -priority : 214 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_ctr_aes256 -module : kernel -priority : 213 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_ctr_aes192 -module : kernel -priority : 212 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_ctr_aes128 -module : kernel -priority : 211 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : hmac(sha256) -driver : hmac(sha256-generic) -module : kernel -priority : 100 -refcnt : 10 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 32 - -name : stdrng -driver : drbg_pr_hmac_sha256 -module : kernel -priority : 210 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_hmac_sha512 -module : kernel -priority : 209 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_hmac_sha384 -module : kernel -priority : 208 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_hmac_sha1 -module : kernel -priority : 207 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha256 -module : kernel -priority : 206 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha512 -module : kernel -priority : 205 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha384 -module : kernel -priority : 204 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha1 -module : kernel -priority : 203 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_ctr_aes256 -module : kernel -priority : 202 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_ctr_aes192 -module : kernel -priority : 201 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_ctr_aes128 -module : kernel -priority : 200 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : 842 -driver : 842-scomp -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : 842 -driver : 842-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : lzo-rle -driver : lzo-rle-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : lzo-rle -driver : lzo-rle-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : lzo -driver : lzo-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : lzo -driver : lzo-generic -module : kernel -priority : 0 -refcnt : 9 -selftest : passed -internal : no -type : compression - -name : crct10dif -driver : crct10dif-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 2 - -name : crc32c -driver : crc32c-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 4 - -name : zlib-deflate -driver : zlib-deflate-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : deflate -driver : deflate-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : deflate -driver : deflate-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : aes -driver : aes-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -name : sha224 -driver : sha224-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 28 - -name : sha256 -driver : sha256-generic -module : kernel -priority : 100 -refcnt : 11 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 32 - -name : sha1 -driver : sha1-generic -module : kernel -priority : 100 -refcnt : 11 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 20 - -name : md5 -driver : md5-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 16 - -name : ecb(cipher_null) -driver : ecb-cipher_null -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 1 -min keysize : 0 -max keysize : 0 -ivsize : 0 -chunksize : 1 -walksize : 1 - -name : digest_null -driver : digest_null-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 0 - -name : compress_null -driver : compress_null-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : cipher_null -driver : cipher_null-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : cipher -blocksize : 1 -min keysize : 0 -max keysize : 0 - -name : rsa -driver : rsa-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : akcipher - -name : dh -driver : dh-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : kpp - -name : aes -driver : aes-asm -module : kernel -priority : 200 -refcnt : 1 -selftest : passed -internal : no -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -Mode: 444 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/diskstats -Lines: 52 - 1 0 ram0 0 0 0 0 0 0 0 0 0 0 0 - 1 1 ram1 0 0 0 0 0 0 0 0 0 0 0 - 1 2 ram2 0 0 0 0 0 0 0 0 0 0 0 - 1 3 ram3 0 0 0 0 0 0 0 0 0 0 0 - 1 4 ram4 0 0 0 0 0 0 0 0 0 0 0 - 1 5 ram5 0 0 0 0 0 0 0 0 0 0 0 - 1 6 ram6 0 0 0 0 0 0 0 0 0 0 0 - 1 7 ram7 0 0 0 0 0 0 0 0 0 0 0 - 1 8 ram8 0 0 0 0 0 0 0 0 0 0 0 - 1 9 ram9 0 0 0 0 0 0 0 0 0 0 0 - 1 10 ram10 0 0 0 0 0 0 0 0 0 0 0 - 1 11 ram11 0 0 0 0 0 0 0 0 0 0 0 - 1 12 ram12 0 0 0 0 0 0 0 0 0 0 0 - 1 13 ram13 0 0 0 0 0 0 0 0 0 0 0 - 1 14 ram14 0 0 0 0 0 0 0 0 0 0 0 - 1 15 ram15 0 0 0 0 0 0 0 0 0 0 0 - 7 0 loop0 0 0 0 0 0 0 0 0 0 0 0 - 7 1 loop1 0 0 0 0 0 0 0 0 0 0 0 - 7 2 loop2 0 0 0 0 0 0 0 0 0 0 0 - 7 3 loop3 0 0 0 0 0 0 0 0 0 0 0 - 7 4 loop4 0 0 0 0 0 0 0 0 0 0 0 - 7 5 loop5 0 0 0 0 0 0 0 0 0 0 0 - 7 6 loop6 0 0 0 0 0 0 0 0 0 0 0 - 7 7 loop7 0 0 0 0 0 0 0 0 0 0 0 - 8 0 sda 25354637 34367663 1003346126 18492372 28444756 11134226 505697032 63877960 0 9653880 82621804 - 8 1 sda1 250 0 2000 36 0 0 0 0 0 36 36 - 8 2 sda2 246 0 1968 32 0 0 0 0 0 32 32 - 8 3 sda3 340 13 2818 52 11 8 152 8 0 56 60 - 8 4 sda4 25353629 34367650 1003337964 18492232 27448755 11134218 505696880 61593380 0 7576432 80332428 - 252 0 dm-0 59910002 0 1003337218 46229572 39231014 0 505696880 1158557800 0 11325968 1206301256 - 252 1 dm-1 388 0 3104 84 74 0 592 0 0 76 84 - 252 2 dm-2 11571 0 308350 6536 153522 0 5093416 122884 0 65400 129416 - 252 3 dm-3 3870 0 3870 104 0 0 0 0 0 16 104 - 252 4 dm-4 392 0 1034 28 38 0 137 16 0 24 44 - 252 5 dm-5 3729 0 84279 924 98918 0 1151688 104684 0 58848 105632 - 179 0 mmcblk0 192 3 1560 156 0 0 0 0 0 136 156 - 179 1 mmcblk0p1 17 3 160 24 0 0 0 0 0 24 24 - 179 2 mmcblk0p2 95 0 760 68 0 0 0 0 0 68 68 - 2 0 fd0 2 0 16 80 0 0 0 0 0 80 80 - 254 0 vda 1775784 15386 32670882 8655768 6038856 20711856 213637440 2069221364 0 41614592 2077872228 - 254 1 vda1 668 85 5984 956 207 4266 35784 32772 0 8808 33720 - 254 2 vda2 1774936 15266 32663262 8654692 5991028 20707590 213601656 2069152216 0 41607628 2077801992 - 11 0 sr0 0 0 0 0 0 0 0 0 0 0 0 - 259 0 nvme0n1 47114 4 4643973 21650 1078320 43950 39451633 1011053 0 222766 1032546 - 259 1 nvme0n1p1 1140 0 9370 16 1 0 1 0 0 16 16 - 259 2 nvme0n1p2 45914 4 4631243 21626 1036885 43950 39451632 919480 0 131580 940970 - 8 0 sdb 326552 841 9657779 84 41822 2895 1972905 5007 0 60730 67070 68851 0 1925173784 11130 - 8 1 sdb1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0 - 8 2 sdb2 326310 838 9622281 67 40726 2872 1972799 4924 0 58250 64567 68851 0 1925173784 11130 - 8 0 sdc 14202 71 579164 21861 2995 1589 180500 40875 0 11628 55200 0 0 0 0 127 182 - 8 1 sdc1 1027 0 13795 5021 2 0 4096 3 0 690 4579 0 0 0 0 0 0 - 8 2 sdc2 13126 71 561749 16802 2830 1589 176404 40620 0 10931 50449 0 0 0 0 0 0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/fs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/fs/fscache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/fs/fscache/stats -Lines: 24 -FS-Cache statistics -Cookies: idx=3 dat=67877 spc=0 -Objects: alc=67473 nal=0 avl=67473 ded=388 -ChkAux : non=12 ok=33 upd=44 obs=55 -Pages : mrk=547164 unc=364577 -Acquire: n=67880 nul=98 noc=25 ok=67780 nbf=39 oom=26 -Lookups: n=67473 neg=67470 pos=58 crt=67473 tmo=85 -Invals : n=14 run=13 -Updates: n=7 nul=3 run=8 -Relinqs: n=394 nul=1 wcr=2 rtr=3 -AttrChg: n=6 ok=5 nbf=4 oom=3 run=2 -Allocs : n=20 ok=19 wt=18 nbf=17 int=16 -Allocs : ops=15 owt=14 abt=13 -Retrvls: n=151959 ok=82823 wt=23467 nod=69136 nbf=15 int=69 oom=43 -Retrvls: ops=151959 owt=42747 abt=44 -Stores : n=225565 ok=225565 agn=12 nbf=13 oom=14 -Stores : ops=69156 run=294721 pgs=225565 rxd=225565 olm=43 -VmScan : nos=364512 gon=2 bsy=43 can=12 wt=66 -Ops : pend=42753 run=221129 enq=628798 can=11 rej=88 -Ops : ini=377538 dfr=27 rel=377538 gc=37 -CacheOp: alo=1 luo=2 luc=3 gro=4 -CacheOp: inv=5 upo=6 dro=7 pto=8 atc=9 syn=10 -CacheOp: rap=11 ras=12 alp=13 als=14 wrp=15 ucp=16 dsp=17 -CacheEv: nsp=18 stl=19 rtr=20 cul=21EOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/fs/xfs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/fs/xfs/stat -Lines: 23 -extent_alloc 92447 97589 92448 93751 -abt 0 0 0 0 -blk_map 1767055 188820 184891 92447 92448 2140766 0 -bmbt 0 0 0 0 -dir 185039 92447 92444 136422 -trans 706 944304 0 -ig 185045 58807 0 126238 0 33637 22 -log 2883 113448 9 17360 739 -push_ail 945014 0 134260 15483 0 3940 464 159985 0 40 -xstrat 92447 0 -rw 107739 94045 -attr 4 0 0 0 -icluster 8677 7849 135802 -vnodes 92601 0 0 0 92444 92444 92444 0 -buf 2666287 7122 2659202 3599 2 7085 0 10297 7085 -abtb2 184941 1277345 13257 13278 0 0 0 0 0 0 0 0 0 0 2746147 -abtc2 345295 2416764 172637 172658 0 0 0 0 0 0 0 0 0 0 21406023 -bmbt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -ibt2 343004 1358467 0 0 0 0 0 0 0 0 0 0 0 0 0 -fibt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -qm 0 0 0 0 0 0 0 0 -xpc 399724544 92823103 86219234 -debug 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/loadavg -Lines: 1 -0.02 0.04 0.05 1/497 11947 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/mdstat -Lines: 60 -Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] - -md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] sdd1[10](S) sdd2[11](S) - 5853468288 blocks super 1.2 level 6, 64k chunk, algorithm 2 [8/8] [UUUUUUUU] - -md127 : active raid1 sdi2[0] sdj2[1] - 312319552 blocks [2/2] [UU] - -md0 : active raid1 sdi1[0] sdj1[1] - 248896 blocks [2/2] [UU] - -md4 : inactive raid1 sda3[0](F) sdb3[1](S) - 4883648 blocks [2/2] [UU] - -md6 : active raid1 sdb2[2](F) sdc[1](S) sda2[0] - 195310144 blocks [2/1] [U_] - [=>...................] recovery = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec - -md8 : active raid1 sdb1[1] sda1[0] sdc[2](S) sde[3](S) - 195310144 blocks [2/2] [UU] - [=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec - -md201 : active raid1 sda3[0] sdb3[1] - 1993728 blocks super 1.2 [2/2] [UU] - [=>...................] check = 5.7% (114176/1993728) finish=0.2min speed=114176K/sec - -md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1](F) - 7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU] - bitmap: 0/30 pages [0KB], 65536KB chunk - -md9 : active raid1 sdc2[2] sdd2[3] sdb2[1] sda2[0] sde[4](F) sdf[5](F) sdg[6](S) - 523968 blocks super 1.2 [4/4] [UUUU] - resync=DELAYED - -md10 : active raid0 sda1[0] sdb1[1] - 314159265 blocks 64k chunks - -md11 : active (auto-read-only) raid1 sdb2[0] sdc2[1] sdc3[2](F) hda[4](S) ssdc2[3](S) - 4190208 blocks super 1.2 [2/2] [UU] - resync=PENDING - -md12 : active raid0 sdc2[0] sdd2[1] - 3886394368 blocks super 1.2 512k chunks - -md126 : active raid0 sdb[1] sdc[0] - 1855870976 blocks super external:/md127/0 128k chunks - -md219 : inactive sdb[2](S) sdc[1](S) sda[0](S) - 7932 blocks super external:imsm - -md00 : active raid0 xvdb[0] - 4186624 blocks super 1.2 256k chunks - -md120 : active linear sda1[1] sdb1[0] - 2095104 blocks super 1.2 0k rounding - -md101 : active (read-only) raid0 sdb[2] sdd[1] sdc[0] - 322560 blocks super 1.2 512k chunks - -unused devices: -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/meminfo -Lines: 42 -MemTotal: 15666184 kB -MemFree: 440324 kB -Buffers: 1020128 kB -Cached: 12007640 kB -SwapCached: 0 kB -Active: 6761276 kB -Inactive: 6532708 kB -Active(anon): 267256 kB -Inactive(anon): 268 kB -Active(file): 6494020 kB -Inactive(file): 6532440 kB -Unevictable: 0 kB -Mlocked: 0 kB -SwapTotal: 0 kB -SwapFree: 0 kB -Dirty: 768 kB -Writeback: 0 kB -AnonPages: 266216 kB -Mapped: 44204 kB -Shmem: 1308 kB -Slab: 1807264 kB -SReclaimable: 1738124 kB -SUnreclaim: 69140 kB -KernelStack: 1616 kB -PageTables: 5288 kB -NFS_Unstable: 0 kB -Bounce: 0 kB -WritebackTmp: 0 kB -CommitLimit: 7833092 kB -Committed_AS: 530844 kB -VmallocTotal: 34359738367 kB -VmallocUsed: 36596 kB -VmallocChunk: 34359637840 kB -HardwareCorrupted: 0 kB -AnonHugePages: 12288 kB -HugePages_Total: 0 -HugePages_Free: 0 -HugePages_Rsvd: 0 -HugePages_Surp: 0 -Hugepagesize: 2048 kB -DirectMap4k: 91136 kB -DirectMap2M: 16039936 kB -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/net -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/arp -Lines: 2 -IP address HW type Flags HW address Mask Device -192.168.224.1 0x1 0x2 00:50:56:c0:00:08 * ens33 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/dev -Lines: 6 -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed -vethf345468: 648 8 0 0 0 0 0 0 438 5 0 0 0 0 0 0 - lo: 1664039048 1566805 0 0 0 0 0 0 1664039048 1566805 0 0 0 0 0 0 -docker0: 2568 38 0 0 0 0 0 0 438 5 0 0 0 0 0 0 - eth0: 874354587 1036395 0 0 0 0 0 0 563352563 732147 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/ip_vs -Lines: 21 -IP Virtual Server version 1.2.1 (size=4096) -Prot LocalAddress:Port Scheduler Flags - -> RemoteAddress:Port Forward Weight ActiveConn InActConn -TCP C0A80016:0CEA wlc - -> C0A85216:0CEA Tunnel 100 248 2 - -> C0A85318:0CEA Tunnel 100 248 2 - -> C0A85315:0CEA Tunnel 100 248 1 -TCP C0A80039:0CEA wlc - -> C0A85416:0CEA Tunnel 0 0 0 - -> C0A85215:0CEA Tunnel 100 1499 0 - -> C0A83215:0CEA Tunnel 100 1498 0 -TCP C0A80037:0CEA wlc - -> C0A8321A:0CEA Tunnel 0 0 0 - -> C0A83120:0CEA Tunnel 100 0 0 -TCP [2620:0000:0000:0000:0000:0000:0000:0001]:0050 sh - -> [2620:0000:0000:0000:0000:0000:0000:0002]:0050 Route 1 0 0 - -> [2620:0000:0000:0000:0000:0000:0000:0003]:0050 Route 1 0 0 - -> [2620:0000:0000:0000:0000:0000:0000:0004]:0050 Route 1 1 1 -FWM 10001000 wlc - -> C0A8321A:0CEA Route 0 0 1 - -> C0A83215:0CEA Route 0 0 2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/ip_vs_stats -Lines: 6 - Total Incoming Outgoing Incoming Outgoing - Conns Packets Packets Bytes Bytes - 16AA370 E33656E5 0 51D8C8883AB3 0 - - Conns/s Pkts/s Pkts/s Bytes/s Bytes/s - 4 1FB3C 0 1282A8F 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/protocols -Lines: 14 -protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em -PACKET 1344 2 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n -PINGv6 1112 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n -RAWv6 1112 1 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n -UDPLITEv6 1216 0 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n -UDPv6 1216 10 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n -TCPv6 2144 1937 1225378 no 320 yes kernel y y y y y y y y y y y y y n y y y y y -UNIX 1024 120 -1 NI 0 yes kernel n n n n n n n n n n n n n n n n n n n -UDP-Lite 1024 0 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n -PING 904 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n -RAW 912 0 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n -UDP 1024 73 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n -TCP 1984 93064 1225378 yes 320 yes kernel y y y y y y y y y y y y y n y y y y y -NETLINK 1040 16 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/net/rpc -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/rpc/nfs -Lines: 5 -net 18628 0 18628 6 -rpc 4329785 0 4338291 -proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 -proc3 22 1 4084749 29200 94754 32580 186 47747 7981 8639 0 6356 0 6962 0 7958 0 0 241 4 4 2 39 -proc4 61 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/rpc/nfsd -Lines: 11 -rc 0 6 18622 -fh 0 0 0 0 0 -io 157286400 0 -th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 -ra 32 0 0 0 0 0 0 0 0 0 0 0 -net 18628 0 18628 6 -rpc 18628 0 0 0 0 -proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 -proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 -proc4 2 2 10853 -proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/sockstat -Lines: 6 -sockets: used 1602 -TCP: inuse 35 orphan 0 tw 4 alloc 59 mem 22 -UDP: inuse 12 mem 62 -UDPLITE: inuse 0 -RAW: inuse 0 -FRAG: inuse 0 memory 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/sockstat6 -Lines: 5 -TCP6: inuse 17 -UDP6: inuse 9 -UDPLITE6: inuse 0 -RAW6: inuse 1 -FRAG6: inuse 0 memory 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/softnet_stat -Lines: 2 -00015c73 00020e76 F0000769 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 -01663fb2 00000000 000109a4 00000000 00000000 00000000 00000000 00000000 00000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/softnet_stat.broken -Lines: 1 -00015c73 00020e76 F0000769 00000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/tcp -Lines: 4 - sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - 0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/tcp6 -Lines: 3 - sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops - 1315: 00000000000000000000000000000000:14EB 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 981 0 21040 2 0000000013726323 0 - 6073: 000080FE00000000FFADE15609667CFE:C781 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 11337031 2 00000000b9256fdd 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/udp -Lines: 4 - sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - 0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/udp6 -Lines: 3 - sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops - 1315: 00000000000000000000000000000000:14EB 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 981 0 21040 2 0000000013726323 0 - 6073: 000080FE00000000FFADE15609667CFE:C781 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 11337031 2 00000000b9256fdd 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/udp_broken -Lines: 2 - sl local_address rem_address st - 1: 00000000:0016 00000000:0000 0A -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/unix -Lines: 6 -Num RefCount Protocol Flags Type St Inode Path -0000000000000000: 00000002 00000000 00010000 0001 01 3442596 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 0000000a 00000000 00010000 0005 01 10061 /run/udev/control -0000000000000000: 00000007 00000000 00000000 0002 01 12392 /dev/log -0000000000000000: 00000003 00000000 00000000 0001 03 4787297 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 00000003 00000000 00000000 0001 03 5091797 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/unix_without_inode -Lines: 6 -Num RefCount Protocol Flags Type St Path -0000000000000000: 00000002 00000000 00010000 0001 01 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 0000000a 00000000 00010000 0005 01 /run/udev/control -0000000000000000: 00000007 00000000 00000000 0002 01 /dev/log -0000000000000000: 00000003 00000000 00000000 0001 03 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 00000003 00000000 00000000 0001 03 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/xfrm_stat -Lines: 28 -XfrmInError 1 -XfrmInBufferError 2 -XfrmInHdrError 4 -XfrmInNoStates 3 -XfrmInStateProtoError 40 -XfrmInStateModeError 100 -XfrmInStateSeqError 6000 -XfrmInStateExpired 4 -XfrmInStateMismatch 23451 -XfrmInStateInvalid 55555 -XfrmInTmplMismatch 51 -XfrmInNoPols 65432 -XfrmInPolBlock 100 -XfrmInPolError 10000 -XfrmOutError 1000000 -XfrmOutBundleGenError 43321 -XfrmOutBundleCheckError 555 -XfrmOutNoStates 869 -XfrmOutStateProtoError 4542 -XfrmOutStateModeError 4 -XfrmOutStateSeqError 543 -XfrmOutStateExpired 565 -XfrmOutPolBlock 43456 -XfrmOutPolDead 7656 -XfrmOutPolError 1454 -XfrmFwdHdrError 6654 -XfrmOutStateInvalid 28765 -XfrmAcquireError 24532 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/pressure -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/pressure/cpu -Lines: 1 -some avg10=0.10 avg60=2.00 avg300=3.85 total=15 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/pressure/io -Lines: 2 -some avg10=0.10 avg60=2.00 avg300=3.85 total=15 -full avg10=0.20 avg60=3.00 avg300=4.95 total=25 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/pressure/memory -Lines: 2 -some avg10=0.10 avg60=2.00 avg300=3.85 total=15 -full avg10=0.20 avg60=3.00 avg300=4.95 total=25 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/schedstat -Lines: 6 -version 15 -timestamp 15819019232 -cpu0 498494191 0 3533438552 2553969831 3853684107 2465731542 2045936778163039 343796328169361 4767485306 -domain0 00000000,00000003 212499247 210112015 1861015 1860405436 536440 369895 32599 210079416 25368550 24241256 384652 927363878 807233 6366 1647 24239609 2122447165 1886868564 121112060 2848625533 125678146 241025 1032026 1885836538 2545 12 2533 0 0 0 0 0 0 1387952561 21076581 0 -cpu1 518377256 0 4155211005 2778589869 10466382 2867629021 1904686152592476 364107263788241 5145567945 -domain0 00000000,00000003 217653037 215526982 1577949 1580427380 557469 393576 28538 215498444 28721913 27662819 371153 870843407 745912 5523 1639 27661180 2331056874 2107732788 111442342 652402556 123615235 196159 1045245 2106687543 2400 3 2397 0 0 0 0 0 0 1437804657 26220076 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/self -SymlinkTo: 26231 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/slabinfo -Lines: 302 -slabinfo - version: 2.1 -# name : tunables : slabdata -pid_3 375 532 576 28 4 : tunables 0 0 0 : slabdata 19 19 0 -pid_2 3 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -nvidia_p2p_page_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -nvidia_pte_cache 9022 9152 368 22 2 : tunables 0 0 0 : slabdata 416 416 0 -nvidia_stack_cache 321 326 12624 2 8 : tunables 0 0 0 : slabdata 163 163 0 -kvm_async_pf 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0 -kvm_vcpu 0 0 15552 2 8 : tunables 0 0 0 : slabdata 0 0 0 -kvm_mmu_page_header 0 0 504 32 4 : tunables 0 0 0 : slabdata 0 0 0 -pte_list_desc 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -x86_emulator 0 0 3024 10 8 : tunables 0 0 0 : slabdata 0 0 0 -x86_fpu 0 0 4608 7 8 : tunables 0 0 0 : slabdata 0 0 0 -iwl_cmd_pool:0000:04:00.0 0 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0 -ext4_groupinfo_4k 3719 3740 480 34 4 : tunables 0 0 0 : slabdata 110 110 0 -bio-6 32 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 -bio-5 16 48 1344 24 8 : tunables 0 0 0 : slabdata 2 2 0 -bio-4 17 92 1408 23 8 : tunables 0 0 0 : slabdata 4 4 0 -fat_inode_cache 0 0 1056 31 8 : tunables 0 0 0 : slabdata 0 0 0 -fat_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -ovl_aio_req 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -ovl_inode 0 0 1000 32 8 : tunables 0 0 0 : slabdata 0 0 0 -squashfs_inode_cache 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0 -fuse_request 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0 -fuse_inode 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_dqtrx 0 0 864 37 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_dquot 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_buf 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_bui_item 0 0 544 30 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_bud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_cui_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_cud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_rui_item 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_rud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_icr 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_ili 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_inode 0 0 1344 24 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_efi_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_efd_item 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_buf_item 0 0 608 26 4 : tunables 0 0 0 : slabdata 0 0 0 -xf_trans 0 0 568 28 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_ifork 0 0 376 21 2 : tunables 0 0 0 : slabdata 0 0 0 -xfs_da_state 0 0 816 20 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_btree_cur 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_bmap_free_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -xfs_log_ticket 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 -nfs_direct_cache 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0 -nfs_commit_data 4 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0 -nfs_write_data 32 50 1280 25 8 : tunables 0 0 0 : slabdata 2 2 0 -nfs_read_data 0 0 1280 25 8 : tunables 0 0 0 : slabdata 0 0 0 -nfs_inode_cache 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 -nfs_page 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -rpc_inode_cache 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -rpc_buffers 8 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 -rpc_tasks 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -fscache_cookie_jar 1 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0 -jfs_mp 32 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0 -jfs_ip 0 0 1592 20 8 : tunables 0 0 0 : slabdata 0 0 0 -reiser_inode_cache 0 0 1096 29 8 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_end_io_wq 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_prelim_ref 0 0 424 38 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_extent_op 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_data_ref 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_tree_ref 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_ref_head 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_inode_defrag 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_node 0 0 648 25 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_ordered_extent 0 0 752 21 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_extent_map 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_extent_state 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -bio-3 35 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0 -btrfs_extent_buffer 0 0 600 27 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_free_space_bitmap 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_free_space 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_path 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_trans_handle 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_inode 0 0 1496 21 8 : tunables 0 0 0 : slabdata 0 0 0 -ext4_inode_cache 84136 84755 1400 23 8 : tunables 0 0 0 : slabdata 3685 3685 0 -ext4_free_data 22 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 -ext4_allocation_context 0 70 464 35 4 : tunables 0 0 0 : slabdata 2 2 0 -ext4_prealloc_space 24 74 440 37 4 : tunables 0 0 0 : slabdata 2 2 0 -ext4_system_zone 267 273 376 21 2 : tunables 0 0 0 : slabdata 13 13 0 -ext4_io_end_vec 0 88 368 22 2 : tunables 0 0 0 : slabdata 4 4 0 -ext4_io_end 0 80 400 20 2 : tunables 0 0 0 : slabdata 4 4 0 -ext4_bio_post_read_ctx 128 147 384 21 2 : tunables 0 0 0 : slabdata 7 7 0 -ext4_pending_reservation 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -ext4_extent_status 79351 79422 376 21 2 : tunables 0 0 0 : slabdata 3782 3782 0 -jbd2_transaction_s 44 100 640 25 4 : tunables 0 0 0 : slabdata 4 4 0 -jbd2_inode 6785 6840 400 20 2 : tunables 0 0 0 : slabdata 342 342 0 -jbd2_journal_handle 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 -jbd2_journal_head 824 1944 448 36 4 : tunables 0 0 0 : slabdata 54 54 0 -jbd2_revoke_table_s 4 23 352 23 2 : tunables 0 0 0 : slabdata 1 1 0 -jbd2_revoke_record_s 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0 -ext2_inode_cache 0 0 1144 28 8 : tunables 0 0 0 : slabdata 0 0 0 -mbcache 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -dm_thin_new_mapping 0 152 424 38 4 : tunables 0 0 0 : slabdata 4 4 0 -dm_snap_pending_exception 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0 -dm_exception 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dm_dirty_log_flush_entry 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dm_bio_prison_cell_v2 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0 -dm_bio_prison_cell 0 148 432 37 4 : tunables 0 0 0 : slabdata 4 4 0 -kcopyd_job 0 8 3648 8 8 : tunables 0 0 0 : slabdata 1 1 0 -io 0 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 -dm_uevent 0 0 3224 10 8 : tunables 0 0 0 : slabdata 0 0 0 -dax_cache 1 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0 -aic94xx_ascb 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -aic94xx_dma_token 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -asd_sas_event 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -sas_task 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0 -qla2xxx_srbs 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0 -sd_ext_cdb 2 22 368 22 2 : tunables 0 0 0 : slabdata 1 1 0 -scsi_sense_cache 258 288 512 32 4 : tunables 0 0 0 : slabdata 9 9 0 -virtio_scsi_cmd 64 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 -L2TP/IPv6 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -L2TP/IP 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 -ip6-frags 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 -fib6_nodes 5 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 -ip6_dst_cache 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -ip6_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -PINGv6 0 0 1600 20 8 : tunables 0 0 0 : slabdata 0 0 0 -RAWv6 25 40 1600 20 8 : tunables 0 0 0 : slabdata 2 2 0 -UDPLITEv6 0 0 1728 18 8 : tunables 0 0 0 : slabdata 0 0 0 -UDPv6 3 54 1728 18 8 : tunables 0 0 0 : slabdata 3 3 0 -tw_sock_TCPv6 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -request_sock_TCPv6 0 0 632 25 4 : tunables 0 0 0 : slabdata 0 0 0 -TCPv6 0 33 2752 11 8 : tunables 0 0 0 : slabdata 3 3 0 -uhci_urb_priv 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -sgpool-128 2 14 4544 7 8 : tunables 0 0 0 : slabdata 2 2 0 -sgpool-64 2 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 -sgpool-32 2 44 1472 22 8 : tunables 0 0 0 : slabdata 2 2 0 -sgpool-16 2 68 960 34 8 : tunables 0 0 0 : slabdata 2 2 0 -sgpool-8 2 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 -btree_node 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -bfq_io_cq 0 0 488 33 4 : tunables 0 0 0 : slabdata 0 0 0 -bfq_queue 0 0 848 38 8 : tunables 0 0 0 : slabdata 0 0 0 -mqueue_inode_cache 1 24 1344 24 8 : tunables 0 0 0 : slabdata 1 1 0 -isofs_inode_cache 0 0 968 33 8 : tunables 0 0 0 : slabdata 0 0 0 -io_kiocb 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 -kioctx 0 30 1088 30 8 : tunables 0 0 0 : slabdata 1 1 0 -aio_kiocb 0 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -userfaultfd_ctx_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -fanotify_path_event 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -fanotify_fid_event 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -fsnotify_mark 0 0 408 20 2 : tunables 0 0 0 : slabdata 0 0 0 -dnotify_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -dnotify_struct 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dio 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0 -bio-2 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -fasync_cache 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -audit_tree_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -pid_namespace 30 34 480 34 4 : tunables 0 0 0 : slabdata 1 1 0 -posix_timers_cache 0 27 592 27 4 : tunables 0 0 0 : slabdata 1 1 0 -iommu_devinfo 24 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 -iommu_domain 10 10 3264 10 8 : tunables 0 0 0 : slabdata 1 1 0 -iommu_iova 8682 8748 448 36 4 : tunables 0 0 0 : slabdata 243 243 0 -UNIX 529 814 1472 22 8 : tunables 0 0 0 : slabdata 37 37 0 -ip4-frags 0 0 536 30 4 : tunables 0 0 0 : slabdata 0 0 0 -ip_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -UDP-Lite 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -tcp_bind_bucket 7 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0 -inet_peer_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -xfrm_dst_cache 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0 -xfrm_state 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0 -ip_fib_trie 7 21 384 21 2 : tunables 0 0 0 : slabdata 1 1 0 -ip_fib_alias 9 20 392 20 2 : tunables 0 0 0 : slabdata 1 1 0 -ip_dst_cache 27 84 576 28 4 : tunables 0 0 0 : slabdata 3 3 0 -PING 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 -RAW 32 46 1408 23 8 : tunables 0 0 0 : slabdata 2 2 0 -UDP 11 168 1536 21 8 : tunables 0 0 0 : slabdata 8 8 0 -tw_sock_TCP 1 56 576 28 4 : tunables 0 0 0 : slabdata 2 2 0 -request_sock_TCP 0 25 632 25 4 : tunables 0 0 0 : slabdata 1 1 0 -TCP 10 60 2624 12 8 : tunables 0 0 0 : slabdata 5 5 0 -hugetlbfs_inode_cache 2 35 928 35 8 : tunables 0 0 0 : slabdata 1 1 0 -dquot 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 -bio-1 32 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 -eventpoll_pwq 409 600 408 20 2 : tunables 0 0 0 : slabdata 30 30 0 -eventpoll_epi 408 672 576 28 4 : tunables 0 0 0 : slabdata 24 24 0 -inotify_inode_mark 58 195 416 39 4 : tunables 0 0 0 : slabdata 5 5 0 -scsi_data_buffer 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 -bio_crypt_ctx 128 147 376 21 2 : tunables 0 0 0 : slabdata 7 7 0 -request_queue 29 39 2408 13 8 : tunables 0 0 0 : slabdata 3 3 0 -blkdev_ioc 81 148 440 37 4 : tunables 0 0 0 : slabdata 4 4 0 -bio-0 125 200 640 25 4 : tunables 0 0 0 : slabdata 8 8 0 -biovec-max 166 196 4544 7 8 : tunables 0 0 0 : slabdata 28 28 0 -biovec-128 0 52 2496 13 8 : tunables 0 0 0 : slabdata 4 4 0 -biovec-64 0 88 1472 22 8 : tunables 0 0 0 : slabdata 4 4 0 -biovec-16 0 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0 -bio_integrity_payload 4 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -khugepaged_mm_slot 59 180 448 36 4 : tunables 0 0 0 : slabdata 5 5 0 -ksm_mm_slot 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -ksm_stable_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -ksm_rmap_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -user_namespace 2 37 864 37 8 : tunables 0 0 0 : slabdata 1 1 0 -uid_cache 5 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-256 1 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-128 1 22 1472 22 8 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-16 1 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-2 1 36 448 36 4 : tunables 0 0 0 : slabdata 1 1 0 -audit_buffer 0 22 360 22 2 : tunables 0 0 0 : slabdata 1 1 0 -sock_inode_cache 663 1170 1216 26 8 : tunables 0 0 0 : slabdata 45 45 0 -skbuff_ext_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -skbuff_fclone_cache 1 72 896 36 8 : tunables 0 0 0 : slabdata 2 2 0 -skbuff_head_cache 3 650 640 25 4 : tunables 0 0 0 : slabdata 26 26 0 -configfs_dir_cache 7 38 424 38 4 : tunables 0 0 0 : slabdata 1 1 0 -file_lock_cache 27 116 552 29 4 : tunables 0 0 0 : slabdata 4 4 0 -file_lock_ctx 106 120 392 20 2 : tunables 0 0 0 : slabdata 6 6 0 -fsnotify_mark_connector 52 66 368 22 2 : tunables 0 0 0 : slabdata 3 3 0 -net_namespace 1 6 5312 6 8 : tunables 0 0 0 : slabdata 1 1 0 -task_delay_info 784 1560 416 39 4 : tunables 0 0 0 : slabdata 40 40 0 -taskstats 45 92 688 23 4 : tunables 0 0 0 : slabdata 4 4 0 -proc_dir_entry 678 682 528 31 4 : tunables 0 0 0 : slabdata 22 22 0 -pde_opener 0 189 376 21 2 : tunables 0 0 0 : slabdata 9 9 0 -proc_inode_cache 7150 8250 992 33 8 : tunables 0 0 0 : slabdata 250 250 0 -seq_file 60 735 456 35 4 : tunables 0 0 0 : slabdata 21 21 0 -sigqueue 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0 -bdev_cache 36 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0 -shmem_inode_cache 1599 2208 1016 32 8 : tunables 0 0 0 : slabdata 69 69 0 -kernfs_iattrs_cache 1251 1254 424 38 4 : tunables 0 0 0 : slabdata 33 33 0 -kernfs_node_cache 52898 52920 464 35 4 : tunables 0 0 0 : slabdata 1512 1512 0 -mnt_cache 42 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 -filp 4314 6371 704 23 4 : tunables 0 0 0 : slabdata 277 277 0 -inode_cache 28695 29505 920 35 8 : tunables 0 0 0 : slabdata 843 843 0 -dentry 166069 169074 528 31 4 : tunables 0 0 0 : slabdata 5454 5454 0 -names_cache 0 35 4544 7 8 : tunables 0 0 0 : slabdata 5 5 0 -hashtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 -ebitmap_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -avtab_extended_perms 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -avtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_xperms_data 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_xperms_decision_node 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_xperms_node 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_node 37 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0 -iint_cache 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 -lsm_inode_cache 122284 122340 392 20 2 : tunables 0 0 0 : slabdata 6117 6117 0 -lsm_file_cache 4266 4485 352 23 2 : tunables 0 0 0 : slabdata 195 195 0 -key_jar 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -buffer_head 255622 257076 440 37 4 : tunables 0 0 0 : slabdata 6948 6948 0 -uts_namespace 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0 -nsproxy 31 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0 -vm_area_struct 39115 43214 528 31 4 : tunables 0 0 0 : slabdata 1394 1394 0 -mm_struct 96 529 1408 23 8 : tunables 0 0 0 : slabdata 23 23 0 -fs_cache 102 756 448 36 4 : tunables 0 0 0 : slabdata 21 21 0 -files_cache 102 588 1152 28 8 : tunables 0 0 0 : slabdata 21 21 0 -signal_cache 266 672 1536 21 8 : tunables 0 0 0 : slabdata 32 32 0 -sighand_cache 266 507 2496 13 8 : tunables 0 0 0 : slabdata 39 39 0 -task_struct 783 963 10240 3 8 : tunables 0 0 0 : slabdata 321 321 0 -cred_jar 364 952 576 28 4 : tunables 0 0 0 : slabdata 34 34 0 -anon_vma_chain 63907 67821 416 39 4 : tunables 0 0 0 : slabdata 1739 1739 0 -anon_vma 25891 28899 416 39 4 : tunables 0 0 0 : slabdata 741 741 0 -pid 408 992 512 32 4 : tunables 0 0 0 : slabdata 31 31 0 -Acpi-Operand 6682 6740 408 20 2 : tunables 0 0 0 : slabdata 337 337 0 -Acpi-ParseExt 0 39 416 39 4 : tunables 0 0 0 : slabdata 1 1 0 -Acpi-Parse 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 -Acpi-State 0 78 416 39 4 : tunables 0 0 0 : slabdata 2 2 0 -Acpi-Namespace 3911 3948 384 21 2 : tunables 0 0 0 : slabdata 188 188 0 -trace_event_file 2638 2660 424 38 4 : tunables 0 0 0 : slabdata 70 70 0 -ftrace_event_field 6592 6594 384 21 2 : tunables 0 0 0 : slabdata 314 314 0 -pool_workqueue 41 64 1024 32 8 : tunables 0 0 0 : slabdata 2 2 0 -radix_tree_node 21638 24045 912 35 8 : tunables 0 0 0 : slabdata 687 687 0 -task_group 48 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0 -vmap_area 4411 4680 400 20 2 : tunables 0 0 0 : slabdata 234 234 0 -dma-kmalloc-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-128 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-64 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-96 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-128 31 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 -kmalloc-rcl-96 3371 3626 432 37 4 : tunables 0 0 0 : slabdata 98 98 0 -kmalloc-rcl-64 2080 2272 512 32 4 : tunables 0 0 0 : slabdata 71 71 0 -kmalloc-rcl-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-8k 133 140 24576 1 8 : tunables 0 0 0 : slabdata 140 140 0 -kmalloc-4k 403 444 12288 2 8 : tunables 0 0 0 : slabdata 222 222 0 -kmalloc-2k 2391 2585 6144 5 8 : tunables 0 0 0 : slabdata 517 517 0 -kmalloc-1k 2163 2420 3072 10 8 : tunables 0 0 0 : slabdata 242 242 0 -kmalloc-512 2972 3633 1536 21 8 : tunables 0 0 0 : slabdata 173 173 0 -kmalloc-256 1841 1856 1024 32 8 : tunables 0 0 0 : slabdata 58 58 0 -kmalloc-192 2165 2914 528 31 4 : tunables 0 0 0 : slabdata 94 94 0 -kmalloc-128 1137 1175 640 25 4 : tunables 0 0 0 : slabdata 47 47 0 -kmalloc-96 1925 2590 432 37 4 : tunables 0 0 0 : slabdata 70 70 0 -kmalloc-64 9433 10688 512 32 4 : tunables 0 0 0 : slabdata 334 334 0 -kmalloc-32 9098 10062 416 39 4 : tunables 0 0 0 : slabdata 258 258 0 -kmalloc-16 10914 10956 368 22 2 : tunables 0 0 0 : slabdata 498 498 0 -kmalloc-8 7576 7705 344 23 2 : tunables 0 0 0 : slabdata 335 335 0 -kmem_cache_node 904 928 512 32 4 : tunables 0 0 0 : slabdata 29 29 0 -kmem_cache 904 936 832 39 8 : tunables 0 0 0 : slabdata 24 24 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/stat -Lines: 16 -cpu 301854 612 111922 8979004 3552 2 3944 0 0 0 -cpu0 44490 19 21045 1087069 220 1 3410 0 0 0 -cpu1 47869 23 16474 1110787 591 0 46 0 0 0 -cpu2 46504 36 15916 1112321 441 0 326 0 0 0 -cpu3 47054 102 15683 1113230 533 0 60 0 0 0 -cpu4 28413 25 10776 1140321 217 0 8 0 0 0 -cpu5 29271 101 11586 1136270 672 0 30 0 0 0 -cpu6 29152 36 10276 1139721 319 0 29 0 0 0 -cpu7 29098 268 10164 1139282 555 0 31 0 0 0 -intr 8885917 17 0 0 0 0 0 0 0 1 79281 0 0 0 0 0 0 0 231237 0 0 0 0 250586 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 223424 190745 13 906 1283803 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -ctxt 38014093 -btime 1418183276 -processes 26442 -procs_running 2 -procs_blocked 1 -softirq 5057579 250191 1481983 1647 211099 186066 0 1783454 622196 12499 508444 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/swaps -Lines: 2 -Filename Type Size Used Priority -/dev/dm-2 partition 131068 176 -2 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/symlinktargets -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/README -Lines: 2 -This directory contains some empty files that are the symlinks the files in the "fd" directory point to. -They are otherwise ignored by the tests -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/abc -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/def -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/ghi -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/uvw -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/xyz -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys/kernel -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys/kernel/random -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/entropy_avail -Lines: 1 -3943 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/poolsize -Lines: 1 -4096 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/urandom_min_reseed_secs -Lines: 1 -60 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/write_wakeup_threshold -Lines: 1 -3072 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys/vm -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/admin_reserve_kbytes -Lines: 1 -8192 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/block_dump -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/compact_unevictable_allowed -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_background_bytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_background_ratio -Lines: 1 -10 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_bytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_expire_centisecs -Lines: 1 -3000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_ratio -Lines: 1 -20 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_writeback_centisecs -Lines: 1 -500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirtytime_expire_seconds -Lines: 1 -43200 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/drop_caches -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/extfrag_threshold -Lines: 1 -500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/hugetlb_shm_group -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/laptop_mode -Lines: 1 -5 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/legacy_va_layout -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/lowmem_reserve_ratio -Lines: 1 -256 256 32 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/max_map_count -Lines: 1 -65530 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/memory_failure_early_kill -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/memory_failure_recovery -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/min_free_kbytes -Lines: 1 -67584 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/min_slab_ratio -Lines: 1 -5 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/min_unmapped_ratio -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/mmap_min_addr -Lines: 1 -65536 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/nr_hugepages -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/nr_hugepages_mempolicy -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/nr_overcommit_hugepages -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/numa_stat -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/numa_zonelist_order -Lines: 1 -Node -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/oom_dump_tasks -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/oom_kill_allocating_task -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/overcommit_kbytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/overcommit_memory -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/overcommit_ratio -Lines: 1 -50 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/page-cluster -Lines: 1 -3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/panic_on_oom -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/percpu_pagelist_fraction -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/stat_interval -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/swappiness -Lines: 1 -60 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/user_reserve_kbytes -Lines: 1 -131072 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/vfs_cache_pressure -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/watermark_boost_factor -Lines: 1 -15000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/watermark_scale_factor -Lines: 1 -10 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/zone_reclaim_mode -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/zoneinfo -Lines: 262 -Node 0, zone DMA - per-node stats - nr_inactive_anon 230981 - nr_active_anon 547580 - nr_inactive_file 316904 - nr_active_file 346282 - nr_unevictable 115467 - nr_slab_reclaimable 131220 - nr_slab_unreclaimable 47320 - nr_isolated_anon 0 - nr_isolated_file 0 - workingset_nodes 11627 - workingset_refault 466886 - workingset_activate 276925 - workingset_restore 84055 - workingset_nodereclaim 487 - nr_anon_pages 795576 - nr_mapped 215483 - nr_file_pages 761874 - nr_dirty 908 - nr_writeback 0 - nr_writeback_temp 0 - nr_shmem 224925 - nr_shmem_hugepages 0 - nr_shmem_pmdmapped 0 - nr_anon_transparent_hugepages 0 - nr_unstable 0 - nr_vmscan_write 12950 - nr_vmscan_immediate_reclaim 3033 - nr_dirtied 8007423 - nr_written 7752121 - nr_kernel_misc_reclaimable 0 - pages free 3952 - min 33 - low 41 - high 49 - spanned 4095 - present 3975 - managed 3956 - protection: (0, 2877, 7826, 7826, 7826) - nr_free_pages 3952 - nr_zone_inactive_anon 0 - nr_zone_active_anon 0 - nr_zone_inactive_file 0 - nr_zone_active_file 0 - nr_zone_unevictable 0 - nr_zone_write_pending 0 - nr_mlock 0 - nr_page_table_pages 0 - nr_kernel_stack 0 - nr_bounce 0 - nr_zspages 0 - nr_free_cma 0 - numa_hit 1 - numa_miss 0 - numa_foreign 0 - numa_interleave 0 - numa_local 1 - numa_other 0 - pagesets - cpu: 0 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 1 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 2 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 3 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 4 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 5 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 6 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 7 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - node_unreclaimable: 0 - start_pfn: 1 -Node 0, zone DMA32 - pages free 204252 - min 19510 - low 21059 - high 22608 - spanned 1044480 - present 759231 - managed 742806 - protection: (0, 0, 4949, 4949, 4949) - nr_free_pages 204252 - nr_zone_inactive_anon 118558 - nr_zone_active_anon 106598 - nr_zone_inactive_file 75475 - nr_zone_active_file 70293 - nr_zone_unevictable 66195 - nr_zone_write_pending 64 - nr_mlock 4 - nr_page_table_pages 1756 - nr_kernel_stack 2208 - nr_bounce 0 - nr_zspages 0 - nr_free_cma 0 - numa_hit 113952967 - numa_miss 0 - numa_foreign 0 - numa_interleave 0 - numa_local 113952967 - numa_other 0 - pagesets - cpu: 0 - count: 345 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 1 - count: 356 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 2 - count: 325 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 3 - count: 346 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 4 - count: 321 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 5 - count: 316 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 6 - count: 373 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 7 - count: 339 - high: 378 - batch: 63 - vm stats threshold: 48 - node_unreclaimable: 0 - start_pfn: 4096 -Node 0, zone Normal - pages free 18553 - min 11176 - low 13842 - high 16508 - spanned 1308160 - present 1308160 - managed 1268711 - protection: (0, 0, 0, 0, 0) - nr_free_pages 18553 - nr_zone_inactive_anon 112423 - nr_zone_active_anon 440982 - nr_zone_inactive_file 241429 - nr_zone_active_file 275989 - nr_zone_unevictable 49272 - nr_zone_write_pending 844 - nr_mlock 154 - nr_page_table_pages 9750 - nr_kernel_stack 15136 - nr_bounce 0 - nr_zspages 0 - nr_free_cma 0 - numa_hit 162718019 - numa_miss 0 - numa_foreign 0 - numa_interleave 26812 - numa_local 162718019 - numa_other 0 - pagesets - cpu: 0 - count: 316 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 1 - count: 366 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 2 - count: 60 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 3 - count: 256 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 4 - count: 253 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 5 - count: 159 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 6 - count: 311 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 7 - count: 264 - high: 378 - batch: 63 - vm stats threshold: 56 - node_unreclaimable: 0 - start_pfn: 1048576 -Node 0, zone Movable - pages free 0 - min 0 - low 0 - high 0 - spanned 0 - present 0 - managed 0 - protection: (0, 0, 0, 0, 0) -Node 0, zone Device - pages free 0 - min 0 - low 0 - high 0 - spanned 0 - present 0 - managed 0 - protection: (0, 0, 0, 0, 0) -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/dm-0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/dm-0/stat -Lines: 1 -6447303 0 710266738 1529043 953216 0 31201176 4557464 0 796160 6088971 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/sda -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/sda/queue -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/add_random -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/chunk_sectors -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/dax -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_granularity -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_max_bytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_max_hw_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_zeroes_data -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/fua -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/hw_sector_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/io_poll -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/io_poll_delay -Lines: 1 --1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/io_timeout -Lines: 1 -30000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/sda/queue/iosched -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/back_seek_max -Lines: 1 -16384 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/back_seek_penalty -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/fifo_expire_async -Lines: 1 -250 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/fifo_expire_sync -Lines: 1 -125 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/low_latency -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/max_budget -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/slice_idle -Lines: 1 -8 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/slice_idle_us -Lines: 1 -8000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/strict_guarantees -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/timeout_sync -Lines: 1 -125 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iostats -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/logical_block_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_discard_segments -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_hw_sectors_kb -Lines: 1 -32767 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_integrity_segments -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_sectors_kb -Lines: 1 -1280 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_segment_size -Lines: 1 -65536 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_segments -Lines: 1 -168 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/minimum_io_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/nomerges -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/nr_requests -Lines: 1 -64 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/nr_zones -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/optimal_io_size -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/physical_block_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/read_ahead_kb -Lines: 1 -128 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/rotational -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/rq_affinity -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/scheduler -Lines: 1 -mq-deadline kyber [bfq] none -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/wbt_lat_usec -Lines: 1 -75000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/write_cache -Lines: 1 -write back -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/write_same_max_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/write_zeroes_max_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/zoned -Lines: 1 -none -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/stat -Lines: 1 -9652963 396792 759304206 412943 8422549 6731723 286915323 13947418 0 5658367 19174573 1 2 3 12 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/fc_host -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/fc_host/host0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/dev_loss_tmo -Lines: 1 -30 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/fabric_name -Lines: 1 -0x0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/node_name -Lines: 1 -0x2000e0071bce95f2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_id -Lines: 1 -0x000002 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_name -Lines: 1 -0x1000e0071bce95f2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_state -Lines: 1 -Online -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_type -Lines: 1 -Point-To-Point (direct nport connection) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/speed -Lines: 1 -16 Gbit -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/fc_host/host0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/dumped_frames -Lines: 1 -0xffffffffffffffff -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/error_frames -Lines: 1 -0x0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/fcp_packet_aborts -Lines: 1 -0x13 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/invalid_crc_count -Lines: 1 -0x2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/invalid_tx_word_count -Lines: 1 -0x8 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/link_failure_count -Lines: 1 -0x9 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/loss_of_signal_count -Lines: 1 -0x11 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/loss_of_sync_count -Lines: 1 -0x10 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/nos_count -Lines: 1 -0x12 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/rx_frames -Lines: 1 -0x3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/rx_words -Lines: 1 -0x4 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/seconds_since_last_reset -Lines: 1 -0x7 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/tx_frames -Lines: 1 -0x5 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/tx_words -Lines: 1 -0x6 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/supported_classes -Lines: 1 -Class 3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/supported_speeds -Lines: 1 -4 Gbit, 8 Gbit, 16 Gbit -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/symbolic_name -Lines: 1 -Emulex SN1100E2P FV12.4.270.3 DV12.4.0.0. HN:gotest. OS:Linux -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/board_id -Lines: 1 -SM_1141000001000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/fw_ver -Lines: 1 -2.31.5050 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/hca_type -Lines: 1 -MT4099 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/VL15_dropped -Lines: 1 -0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/excessive_buffer_overrun_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/link_downed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/link_error_recovery -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/local_link_integrity_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_data -Lines: 1 -2221223609 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_packets -Lines: 1 -87169372 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_remote_physical_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_switch_relay_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_data -Lines: 1 -26509113295 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_discards -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_packets -Lines: 1 -85734114 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_wait -Lines: 1 -3599 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/symbol_error -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/phys_state -Lines: 1 -5: LinkUp -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/rate -Lines: 1 -40 Gb/sec (4X QDR) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/state -Lines: 1 -4: ACTIVE -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/2 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/VL15_dropped -Lines: 1 -0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/excessive_buffer_overrun_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/link_downed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/link_error_recovery -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/local_link_integrity_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_data -Lines: 1 -2460436784 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_packets -Lines: 1 -89332064 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_remote_physical_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_switch_relay_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_data -Lines: 1 -26540356890 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_discards -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_packets -Lines: 1 -88622850 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_wait -Lines: 1 -3846 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/symbol_error -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/phys_state -Lines: 1 -5: LinkUp -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/rate -Lines: 1 -40 Gb/sec (4X QDR) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/state -Lines: 1 -4: ACTIVE -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/net -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/net/eth0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/addr_assign_type -Lines: 1 -3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/addr_len -Lines: 1 -6 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/address -Lines: 1 -01:01:01:01:01:01 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/broadcast -Lines: 1 -ff:ff:ff:ff:ff:ff -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier_changes -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier_down_count -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier_up_count -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/dev_id -Lines: 1 -0x20 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/device -SymlinkTo: ../../../devices/pci0000:00/0000:00:1f.6/ -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/dormant -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/duplex -Lines: 1 -full -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/flags -Lines: 1 -0x1303 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/ifalias -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/ifindex -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/iflink -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/link_mode -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/mtu -Lines: 1 -1500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/name_assign_type -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/netdev_group -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/operstate -Lines: 1 -up -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/phys_port_id -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/phys_port_name -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/phys_switch_id -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/speed -Lines: 1 -1000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/tx_queue_len -Lines: 1 -1000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/type -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/power_supply -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/power_supply/AC -SymlinkTo: ../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/power_supply/BAT0 -SymlinkTo: ../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl/enabled -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_max_power_uw -Lines: 1 -95000000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_name -Lines: 1 -long_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_time_window_us -Lines: 1 -999424 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_max_power_uw -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_name -Lines: 1 -short_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_time_window_us -Lines: 1 -2440 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/enabled -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/energy_uj -Lines: 1 -240422366267 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/max_energy_range_uj -Lines: 1 -262143328850 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/name -Lines: 1 -package-0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_max_power_uw -Lines: 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_name -Lines: 1 -long_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_power_limit_uw -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_time_window_us -Lines: 1 -976 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/enabled -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/energy_uj -Lines: 1 -118821284256 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/max_energy_range_uj -Lines: 1 -262143328850 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/name -Lines: 1 -core -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl:a -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_max_power_uw -Lines: 1 -95000000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_name -Lines: 1 -long_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_time_window_us -Lines: 1 -999424 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_max_power_uw -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_name -Lines: 1 -short_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_time_window_us -Lines: 1 -2440 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/enabled -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/energy_uj -Lines: 1 -240422366267 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/max_energy_range_uj -Lines: 1 -262143328850 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/name -Lines: 1 -package-10 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/cooling_device0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device0/cur_state -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device0/max_state -Lines: 1 -50 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device0/type -Lines: 1 -Processor -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/cooling_device1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device1/cur_state -Lines: 1 --1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device1/max_state -Lines: 1 -27 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device1/type -Lines: 1 -intel_powerclamp -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/thermal_zone0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone0/policy -Lines: 1 -step_wise -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone0/temp -Lines: 1 -49925 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone0/type -Lines: 1 -bcm2835_thermal -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/thermal_zone1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/mode -Lines: 1 -enabled -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/passive -Lines: 1 -0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/policy -Lines: 1 -step_wise -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/temp -Lines: 1 --44000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/type -Lines: 1 -acpitz -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/device -SymlinkTo: ../../../ACPI0003:00 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/online -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/async -Lines: 1 -disabled -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/autosuspend_delay_ms -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/control -Lines: 1 -auto -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_active_kids -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_active_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_enabled -Lines: 1 -disabled -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_status -Lines: 1 -unsupported -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_suspended_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_usage -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup -Lines: 1 -enabled -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_abort_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_active -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_active_count -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_expire_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_last_time_ms -Lines: 1 -10598 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_max_time_ms -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_prevent_sleep_time_ms -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_total_time_ms -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/subsystem -SymlinkTo: ../../../../../../../../../class/power_supply -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/type -Lines: 1 -Mains -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/uevent -Lines: 2 -POWER_SUPPLY_NAME=AC -POWER_SUPPLY_ONLINE=0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/alarm -Lines: 1 -2369000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/capacity -Lines: 1 -98 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/capacity_level -Lines: 1 -Normal -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/charge_start_threshold -Lines: 1 -95 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/charge_stop_threshold -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/cycle_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/device -SymlinkTo: ../../../PNP0C0A:00 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full -Lines: 1 -50060000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full_design -Lines: 1 -47520000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_now -Lines: 1 -49450000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/manufacturer -Lines: 1 -LGC -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/model_name -Lines: 1 -LNV-45N1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/async -Lines: 1 -disabled -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/autosuspend_delay_ms -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/control -Lines: 1 -auto -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_active_kids -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_active_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_enabled -Lines: 1 -disabled -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_status -Lines: 1 -unsupported -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_suspended_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_usage -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power_now -Lines: 1 -4830000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/present -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/serial_number -Lines: 1 -38109 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/status -Lines: 1 -Discharging -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/subsystem -SymlinkTo: ../../../../../../../../../class/power_supply -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/technology -Lines: 1 -Li-ion -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/type -Lines: 1 -Battery -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/uevent -Lines: 16 -POWER_SUPPLY_NAME=BAT0 -POWER_SUPPLY_STATUS=Discharging -POWER_SUPPLY_PRESENT=1 -POWER_SUPPLY_TECHNOLOGY=Li-ion -POWER_SUPPLY_CYCLE_COUNT=0 -POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000 -POWER_SUPPLY_VOLTAGE_NOW=11750000 -POWER_SUPPLY_POWER_NOW=5064000 -POWER_SUPPLY_ENERGY_FULL_DESIGN=47520000 -POWER_SUPPLY_ENERGY_FULL=47390000 -POWER_SUPPLY_ENERGY_NOW=40730000 -POWER_SUPPLY_CAPACITY=85 -POWER_SUPPLY_CAPACITY_LEVEL=Normal -POWER_SUPPLY_MODEL_NAME=LNV-45N1 -POWER_SUPPLY_MANUFACTURER=LGC -POWER_SUPPLY_SERIAL_NUMBER=38109 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_min_design -Lines: 1 -10800000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_now -Lines: 1 -12229000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/dirty_data -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_hits -Lines: 1 -289 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_hits -Lines: 1 -546 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/io_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/metadata_written -Lines: 1 -512 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/priority_stats -Lines: 5 -Unused: 99% -Metadata: 0% -Average: 10473 -Sectors per Q: 64 -Quantiles: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946] -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/written -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:1f.6 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/ari_enabled -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/broken_parity_status -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/class -Lines: 1 -0x020000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/consistent_dma_mask_bits -Lines: 1 -64 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/d3cold_allowed -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/device -Lines: 1 -0x15d7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/dma_mask_bits -Lines: 1 -64 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/driver_override -Lines: 1 -(null) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/irq -Lines: 1 -140 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/local_cpulist -Lines: 1 -0-7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/local_cpus -Lines: 1 -ff -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/modalias -Lines: 1 -pci:v00008086d000015D7sv000017AAsd0000225Abc02sc00i00 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/msi_bus -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/numa_node -Lines: 1 --1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/resource -Lines: 13 -0x00000000ec200000 0x00000000ec21ffff 0x0000000000040200 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/revision -Lines: 1 -0x21 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/subsystem_device -Lines: 1 -0x225a -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/subsystem_vendor -Lines: 1 -0x17aa -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/uevent -Lines: 6 -DRIVER=e1000e -PCI_CLASS=20000 -PCI_ID=8086:15D7 -PCI_SUBSYS_ID=17AA:225A -PCI_SLOT_NAME=0000:00:1f.6 -MODALIAS=pci:v00008086d000015D7sv000017AAsd0000225Abc02sc00i00 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/vendor -Lines: 1 -0x8086 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/rbd -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/rbd/0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/0/name -Lines: 1 -demo -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/0/pool -Lines: 1 -iscsi-images -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/rbd/1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/1/name -Lines: 1 -wrong -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/1/pool -Lines: 1 -wrong-images -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/node -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/node/node1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/node/node1/vmstat -Lines: 6 -nr_free_pages 1 -nr_zone_inactive_anon 2 -nr_zone_active_anon 3 -nr_zone_inactive_file 4 -nr_zone_active_file 5 -nr_zone_unevictable 6 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/node/node2 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/node/node2/vmstat -Lines: 6 -nr_free_pages 7 -nr_zone_inactive_anon 8 -nr_zone_active_anon 9 -nr_zone_inactive_file 10 -nr_zone_active_file 11 -nr_zone_unevictable 12 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/clocksource -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/clocksource/clocksource0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/clocksource/clocksource0/available_clocksource -Lines: 1 -tsc hpet acpi_pm -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/clocksource/clocksource0/current_clocksource -Lines: 1 -tsc -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/cpufreq -SymlinkTo: ../cpufreq/policy0 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu0/thermal_throttle -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count -Lines: 1 -10084 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/thermal_throttle/package_throttle_count -Lines: 1 -34818 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu0/topology -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/core_id -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/core_siblings -Lines: 1 -ff -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/core_siblings_list -Lines: 1 -0-7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/physical_package_id -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/thread_siblings -Lines: 1 -11 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/thread_siblings_list -Lines: 1 -0,4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1/cpufreq -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq -Lines: 1 -1200195 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_max_freq -Lines: 1 -3300000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_min_freq -Lines: 1 -1200000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_transition_latency -Lines: 1 -4294967295 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/related_cpus -Lines: 1 -1 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_available_governors -Lines: 1 -performance powersave -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_driver -Lines: 1 -intel_pstate -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor -Lines: 1 -powersave -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq -Lines: 1 -3300000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq -Lines: 1 -1200000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_setspeed -Lines: 1 - -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1/thermal_throttle -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/thermal_throttle/core_throttle_count -Lines: 1 -523 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/thermal_throttle/package_throttle_count -Lines: 1 -34818 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1/topology -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/core_id -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/core_siblings -Lines: 1 -ff -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/core_siblings_list -Lines: 1 -0-7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/physical_package_id -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/thread_siblings -Lines: 1 -22 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/thread_siblings_list -Lines: 1 -1,5 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpufreq -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpufreq/policy0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/affected_cpus -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_max_freq -Lines: 1 -2400000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_min_freq -Lines: 1 -800000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_transition_latency -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/related_cpus -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_available_governors -Lines: 1 -performance powersave -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq -Lines: 1 -1219917 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_driver -Lines: 1 -intel_pstate -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_governor -Lines: 1 -powersave -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq -Lines: 1 -2400000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq -Lines: 1 -800000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed -Lines: 1 - -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpufreq/policy1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/average_key_size -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0 -Mode: 777 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/dirty_data -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_hits -Lines: 1 -289 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_hits -Lines: 1 -546 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/writeback_rate_debug -Lines: 7 -rate: 1.1M/sec -dirty: 20.4G -target: 20.4G -proportional: 427.5k -integral: 790.0k -change: 321.5k/sec -next io: 17ms -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/btree_cache_size -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0 -Mode: 777 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/io_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/metadata_written -Lines: 1 -512 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/priority_stats -Lines: 5 -Unused: 99% -Metadata: 0% -Average: 10473 -Sectors per Q: 64 -Quantiles: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946] -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/written -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache_available_percent -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/congested -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/active_journal_entries -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/btree_nodes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/btree_read_average_duration_us -Lines: 1 -1305 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/cache_read_races -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/root_usage_percent -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_hits -Lines: 1 -289 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_hits -Lines: 1 -546 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/tree_depth -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_used -Lines: 1 -808189952 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/disk_total -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/disk_used -Lines: 1 -808189952 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/flags -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/raid0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/raid0/total_bytes -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/raid0/used_bytes -Lines: 1 -808189952 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/total_bytes -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/global_rsv_reserved -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/global_rsv_size -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_may_use -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_readonly -Lines: 1 -131072 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_used -Lines: 1 -933888 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/disk_total -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/disk_used -Lines: 1 -1867776 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/flags -Lines: 1 -4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/raid1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/raid1/total_bytes -Lines: 1 -1073741824 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/raid1/used_bytes -Lines: 1 -933888 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/total_bytes -Lines: 1 -1073741824 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_used -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/disk_total -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/disk_used -Lines: 1 -32768 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/flags -Lines: 1 -2 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/raid1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/raid1/total_bytes -Lines: 1 -8388608 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/raid1/used_bytes -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/total_bytes -Lines: 1 -8388608 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/clone_alignment -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop25 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop25/size -Lines: 1 -20971520 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop26 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop26/size -Lines: 1 -20971520 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/big_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/extended_iref -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/mixed_backref -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/skinny_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/label -Lines: 1 -fixture -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/metadata_uuid -Lines: 1 -0abb23a9-579b-43e6-ad30-227ef47fcb9d -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/nodesize -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/quota_override -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/sectorsize -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_used -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/disk_total -Lines: 1 -644087808 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/disk_used -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/flags -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/raid5 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/raid5/total_bytes -Lines: 1 -644087808 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/raid5/used_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/total_bytes -Lines: 1 -644087808 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/global_rsv_reserved -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/global_rsv_size -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_may_use -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_readonly -Lines: 1 -262144 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_used -Lines: 1 -114688 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/disk_total -Lines: 1 -429391872 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/disk_used -Lines: 1 -114688 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/flags -Lines: 1 -4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/raid6 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/raid6/total_bytes -Lines: 1 -429391872 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/raid6/used_bytes -Lines: 1 -114688 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/total_bytes -Lines: 1 -429391872 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_used -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/disk_total -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/disk_used -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/flags -Lines: 1 -2 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/raid6 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/raid6/total_bytes -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/raid6/used_bytes -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/total_bytes -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/clone_alignment -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop22 -SymlinkTo: ../../../../devices/virtual/block/loop22 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop23 -SymlinkTo: ../../../../devices/virtual/block/loop23 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop24 -SymlinkTo: ../../../../devices/virtual/block/loop24 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop25 -SymlinkTo: ../../../../devices/virtual/block/loop25 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/big_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/extended_iref -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/mixed_backref -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/raid56 -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/skinny_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/label -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/metadata_uuid -Lines: 1 -7f07c59f-6136-449c-ab87-e1cf2328731b -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/nodesize -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/quota_override -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/sectorsize -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sda1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sda1/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/xfs/sda1/stats/stats -Lines: 1 -extent_alloc 1 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sdb1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sdb1/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/xfs/sdb1/stats/stats -Lines: 1 -extent_alloc 2 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/fileio_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/fileio_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/fileio_1/file_lio_1G -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/fileio_1/file_lio_1G/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/fileio_1/file_lio_1G/udev_path -Lines: 1 -/home/iscsi/file_back_1G -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/iblock_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/iblock_0/block_lio_rbd1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/iblock_0/block_lio_rbd1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/iblock_0/block_lio_rbd1/udev_path -Lines: 1 -/dev/rbd1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rbd_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rbd_0/iscsi-images-demo -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rbd_0/iscsi-images-demo/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rbd_0/iscsi-images-demo/udev_path -Lines: 1 -/dev/rbd/iscsi-images/demo -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rd_mcp_119 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rd_mcp_119/ramdisk_lio_1G -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rd_mcp_119/ramdisk_lio_1G/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rd_mcp_119/ramdisk_lio_1G/udev_path -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/7f4a4eb56d -SymlinkTo: ../../../../../../target/core/rd_mcp_119/ramdisk_lio_1G -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -204950 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -10325 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -40325 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/795b7c7026 -SymlinkTo: ../../../../../../target/core/iblock_0/block_lio_rbd1 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -104950 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -20095 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -71235 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/fff5e16686 -SymlinkTo: ../../../../../../target/core/fileio_1/file_lio_1G -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -301950 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -10195 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -30195 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/eba1edf893 -SymlinkTo: ../../../../../../target/core/rbd_0/iscsi-images-demo -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -1234 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -1504 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -4733 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go index 0102ab0fd..4980c875b 100644 --- a/vendor/github.com/prometheus/procfs/fs.go +++ b/vendor/github.com/prometheus/procfs/fs.go @@ -20,7 +20,8 @@ import ( // FS represents the pseudo-filesystem sys, which provides an interface to // kernel data structures. type FS struct { - proc fs.FS + proc fs.FS + isReal bool } // DefaultMountPoint is the common mount point of the proc filesystem. @@ -39,5 +40,11 @@ func NewFS(mountPoint string) (FS, error) { if err != nil { return FS{}, err } - return FS{fs}, nil + + isReal, err := isRealProc(mountPoint) + if err != nil { + return FS{}, err + } + + return FS{fs, isReal}, nil } diff --git a/vendor/github.com/prometheus/procfs/fs_statfs_notype.go b/vendor/github.com/prometheus/procfs/fs_statfs_notype.go new file mode 100644 index 000000000..134767d69 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/fs_statfs_notype.go @@ -0,0 +1,23 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !freebsd && !linux +// +build !freebsd,!linux + +package procfs + +// isRealProc returns true on architectures that don't have a Type argument +// in their Statfs_t struct +func isRealProc(mountPoint string) (bool, error) { + return true, nil +} diff --git a/vendor/github.com/prometheus/procfs/fs_statfs_type.go b/vendor/github.com/prometheus/procfs/fs_statfs_type.go new file mode 100644 index 000000000..80df79c31 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/fs_statfs_type.go @@ -0,0 +1,33 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build freebsd || linux +// +build freebsd linux + +package procfs + +import ( + "syscall" +) + +// isRealProc determines whether supplied mountpoint is really a proc filesystem. +func isRealProc(mountPoint string) (bool, error) { + stat := syscall.Statfs_t{} + err := syscall.Statfs(mountPoint, &stat) + if err != nil { + return false, err + } + + // 0x9fa0 is PROC_SUPER_MAGIC: https://elixir.bootlin.com/linux/v6.1/source/include/uapi/linux/magic.h#L87 + return stat.Type == 0x9fa0, nil +} diff --git a/vendor/github.com/prometheus/procfs/fscache.go b/vendor/github.com/prometheus/procfs/fscache.go index f8070e6e2..f560a8db3 100644 --- a/vendor/github.com/prometheus/procfs/fscache.go +++ b/vendor/github.com/prometheus/procfs/fscache.go @@ -236,7 +236,7 @@ func (fs FS) Fscacheinfo() (Fscacheinfo, error) { m, err := parseFscacheinfo(bytes.NewReader(b)) if err != nil { - return Fscacheinfo{}, fmt.Errorf("failed to parse Fscacheinfo: %w", err) + return Fscacheinfo{}, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, m, err) } return *m, nil @@ -245,7 +245,7 @@ func (fs FS) Fscacheinfo() (Fscacheinfo, error) { func setFSCacheFields(fields []string, setFields ...*uint64) error { var err error if len(fields) < len(setFields) { - return fmt.Errorf("Insufficient number of fields, expected %v, got %v", len(setFields), len(fields)) + return fmt.Errorf("%s: Expected %d, but got %d: %w", ErrFileParse, len(setFields), len(fields), err) } for i := range setFields { @@ -263,7 +263,7 @@ func parseFscacheinfo(r io.Reader) (*Fscacheinfo, error) { for s.Scan() { fields := strings.Fields(s.Text()) if len(fields) < 2 { - return nil, fmt.Errorf("malformed Fscacheinfo line: %q", s.Text()) + return nil, fmt.Errorf("%w: malformed Fscacheinfo line: %q", ErrFileParse, s.Text()) } switch fields[0] { diff --git a/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/vendor/github.com/prometheus/procfs/internal/fs/fs.go index 0040753b1..3c18c7610 100644 --- a/vendor/github.com/prometheus/procfs/internal/fs/fs.go +++ b/vendor/github.com/prometheus/procfs/internal/fs/fs.go @@ -26,7 +26,7 @@ const ( // DefaultSysMountPoint is the common mount point of the sys filesystem. DefaultSysMountPoint = "/sys" - // DefaultConfigfsMountPoint is the common mount point of the configfs + // DefaultConfigfsMountPoint is the common mount point of the configfs. DefaultConfigfsMountPoint = "/sys/kernel/config" ) diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go index 22cb07a6b..14272dc78 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/parse.go +++ b/vendor/github.com/prometheus/procfs/internal/util/parse.go @@ -14,7 +14,7 @@ package util import ( - "io/ioutil" + "os" "strconv" "strings" ) @@ -64,9 +64,24 @@ func ParsePInt64s(ss []string) ([]*int64, error) { return us, nil } +// Parses a uint64 from given hex in string. +func ParseHexUint64s(ss []string) ([]*uint64, error) { + us := make([]*uint64, 0, len(ss)) + for _, s := range ss { + u, err := strconv.ParseUint(s, 16, 64) + if err != nil { + return nil, err + } + + us = append(us, &u) + } + + return us, nil +} + // ReadUintFromFile reads a file and attempts to parse a uint64 from it. func ReadUintFromFile(path string) (uint64, error) { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return 0, err } @@ -75,7 +90,7 @@ func ReadUintFromFile(path string) (uint64, error) { // ReadIntFromFile reads a file and attempts to parse a int64 from it. func ReadIntFromFile(path string) (int64, error) { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return 0, err } diff --git a/vendor/github.com/prometheus/procfs/internal/util/readfile.go b/vendor/github.com/prometheus/procfs/internal/util/readfile.go index 8051161b2..71b7a70eb 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/readfile.go +++ b/vendor/github.com/prometheus/procfs/internal/util/readfile.go @@ -15,17 +15,16 @@ package util import ( "io" - "io/ioutil" "os" ) -// ReadFileNoStat uses ioutil.ReadAll to read contents of entire file. -// This is similar to ioutil.ReadFile but without the call to os.Stat, because +// ReadFileNoStat uses io.ReadAll to read contents of entire file. +// This is similar to os.ReadFile but without the call to os.Stat, because // many files in /proc and /sys report incorrect file sizes (either 0 or 4096). -// Reads a max file size of 512kB. For files larger than this, a scanner +// Reads a max file size of 1024kB. For files larger than this, a scanner // should be used. func ReadFileNoStat(filename string) ([]byte, error) { - const maxBufferSize = 1024 * 512 + const maxBufferSize = 1024 * 1024 f, err := os.Open(filename) if err != nil { @@ -34,5 +33,5 @@ func ReadFileNoStat(filename string) ([]byte, error) { defer f.Close() reader := io.LimitReader(f, maxBufferSize) - return ioutil.ReadAll(reader) + return io.ReadAll(reader) } diff --git a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go index c07de0b6c..1ab875cee 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go +++ b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go @@ -11,7 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux,!appengine +//go:build (linux || darwin) && !appengine +// +build linux darwin +// +build !appengine package util @@ -21,7 +23,7 @@ import ( "syscall" ) -// SysReadFile is a simplified ioutil.ReadFile that invokes syscall.Read directly. +// SysReadFile is a simplified os.ReadFile that invokes syscall.Read directly. // https://github.com/prometheus/node_exporter/pull/728/files // // Note that this function will not read files larger than 128 bytes. @@ -33,7 +35,7 @@ func SysReadFile(file string) (string, error) { defer f.Close() // On some machines, hwmon drivers are broken and return EAGAIN. This causes - // Go's ioutil.ReadFile implementation to poll forever. + // Go's os.ReadFile implementation to poll forever. // // Since we either want to read data or bail immediately, do the simplest // possible read using syscall directly. diff --git a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go index bd55b4537..1d86f5e63 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go +++ b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go @@ -11,7 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux,appengine !linux +//go:build (linux && appengine) || (!linux && !darwin) +// +build linux,appengine !linux,!darwin package util diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go index 89e447746..5a145bbfe 100644 --- a/vendor/github.com/prometheus/procfs/ipvs.go +++ b/vendor/github.com/prometheus/procfs/ipvs.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "strconv" @@ -84,7 +83,7 @@ func parseIPVSStats(r io.Reader) (IPVSStats, error) { stats IPVSStats ) - statContent, err := ioutil.ReadAll(r) + statContent, err := io.ReadAll(r) if err != nil { return IPVSStats{}, err } @@ -222,15 +221,16 @@ func parseIPPort(s string) (net.IP, uint16, error) { case 46: ip = net.ParseIP(s[1:40]) if ip == nil { - return nil, 0, fmt.Errorf("invalid IPv6 address: %s", s[1:40]) + return nil, 0, fmt.Errorf("%s: Invalid IPv6 addr %s: %w", ErrFileParse, s[1:40], err) } default: - return nil, 0, fmt.Errorf("unexpected IP:Port: %s", s) + return nil, 0, fmt.Errorf("%s: Unexpected IP:Port %s: %w", ErrFileParse, s, err) } portString := s[len(s)-4:] if len(portString) != 4 { - return nil, 0, fmt.Errorf("unexpected port string format: %s", portString) + return nil, 0, + fmt.Errorf("%s: Unexpected port string format %s: %w", ErrFileParse, portString, err) } port, err := strconv.ParseUint(portString, 16, 16) if err != nil { diff --git a/vendor/github.com/prometheus/procfs/kernel_random.go b/vendor/github.com/prometheus/procfs/kernel_random.go index da3a941d6..db88566bd 100644 --- a/vendor/github.com/prometheus/procfs/kernel_random.go +++ b/vendor/github.com/prometheus/procfs/kernel_random.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs diff --git a/vendor/github.com/prometheus/procfs/loadavg.go b/vendor/github.com/prometheus/procfs/loadavg.go index 0cce190ec..59465c5bb 100644 --- a/vendor/github.com/prometheus/procfs/loadavg.go +++ b/vendor/github.com/prometheus/procfs/loadavg.go @@ -21,7 +21,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// LoadAvg represents an entry in /proc/loadavg +// LoadAvg represents an entry in /proc/loadavg. type LoadAvg struct { Load1 float64 Load5 float64 @@ -44,14 +44,14 @@ func parseLoad(loadavgBytes []byte) (*LoadAvg, error) { loads := make([]float64, 3) parts := strings.Fields(string(loadavgBytes)) if len(parts) < 3 { - return nil, fmt.Errorf("malformed loadavg line: too few fields in loadavg string: %q", string(loadavgBytes)) + return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, string(loadavgBytes)) } var err error for i, load := range parts[0:3] { loads[i], err = strconv.ParseFloat(load, 64) if err != nil { - return nil, fmt.Errorf("could not parse load %q: %w", load, err) + return nil, fmt.Errorf("%s: Cannot parse load: %f: %w", ErrFileParse, loads[i], err) } } return &LoadAvg{ diff --git a/vendor/github.com/prometheus/procfs/mdstat.go b/vendor/github.com/prometheus/procfs/mdstat.go index 4c4493bfa..fdd4b9544 100644 --- a/vendor/github.com/prometheus/procfs/mdstat.go +++ b/vendor/github.com/prometheus/procfs/mdstat.go @@ -15,16 +15,19 @@ package procfs import ( "fmt" - "io/ioutil" + "os" "regexp" "strconv" "strings" ) var ( - statusLineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`) - recoveryLineRE = regexp.MustCompile(`\((\d+)/\d+\)`) - componentDeviceRE = regexp.MustCompile(`(.*)\[\d+\]`) + statusLineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[([U_]+)\]`) + recoveryLineBlocksRE = regexp.MustCompile(`\((\d+)/\d+\)`) + recoveryLinePctRE = regexp.MustCompile(`= (.+)%`) + recoveryLineFinishRE = regexp.MustCompile(`finish=(.+)min`) + recoveryLineSpeedRE = regexp.MustCompile(`speed=(.+)[A-Z]`) + componentDeviceRE = regexp.MustCompile(`(.*)\[\d+\]`) ) // MDStat holds info parsed from /proc/mdstat. @@ -39,12 +42,20 @@ type MDStat struct { DisksTotal int64 // Number of failed disks. DisksFailed int64 + // Number of "down" disks. (the _ indicator in the status line) + DisksDown int64 // Spare disks in the device. DisksSpare int64 // Number of blocks the device holds. BlocksTotal int64 // Number of blocks on the device that are in sync. BlocksSynced int64 + // progress percentage of current sync + BlocksSyncedPct float64 + // estimated finishing time for current sync (in minutes) + BlocksSyncedFinishTime float64 + // current sync speed (in Kilobytes/sec) + BlocksSyncedSpeed float64 // Name of md component devices Devices []string } @@ -53,13 +64,13 @@ type MDStat struct { // structs containing the relevant info. More information available here: // https://raid.wiki.kernel.org/index.php/Mdstat func (fs FS) MDStat() ([]MDStat, error) { - data, err := ioutil.ReadFile(fs.proc.Path("mdstat")) + data, err := os.ReadFile(fs.proc.Path("mdstat")) if err != nil { return nil, err } mdstat, err := parseMDStat(data) if err != nil { - return nil, fmt.Errorf("error parsing mdstat %q: %w", fs.proc.Path("mdstat"), err) + return nil, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, fs.proc.Path("mdstat"), err) } return mdstat, nil } @@ -79,22 +90,22 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { deviceFields := strings.Fields(line) if len(deviceFields) < 3 { - return nil, fmt.Errorf("not enough fields in mdline (expected at least 3): %s", line) + return nil, fmt.Errorf("%s: Expected 3+ lines, got %q", ErrFileParse, line) } mdName := deviceFields[0] // mdx state := deviceFields[2] // active or inactive if len(lines) <= i+3 { - return nil, fmt.Errorf("error parsing %q: too few lines for md device", mdName) + return nil, fmt.Errorf("%w: Too few lines for md device: %q", ErrFileParse, mdName) } // Failed disks have the suffix (F) & Spare disks have the suffix (S). fail := int64(strings.Count(line, "(F)")) spare := int64(strings.Count(line, "(S)")) - active, total, size, err := evalStatusLine(lines[i], lines[i+1]) + active, total, down, size, err := evalStatusLine(lines[i], lines[i+1]) if err != nil { - return nil, fmt.Errorf("error parsing md device lines: %w", err) + return nil, fmt.Errorf("%s: Cannot parse md device lines: %v: %w", ErrFileParse, active, err) } syncLineIdx := i + 2 @@ -105,6 +116,9 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { // If device is syncing at the moment, get the number of currently // synced bytes, otherwise that number equals the size of the device. syncedBlocks := size + speed := float64(0) + finish := float64(0) + pct := float64(0) recovering := strings.Contains(lines[syncLineIdx], "recovery") resyncing := strings.Contains(lines[syncLineIdx], "resync") checking := strings.Contains(lines[syncLineIdx], "check") @@ -124,77 +138,116 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { strings.Contains(lines[syncLineIdx], "DELAYED") { syncedBlocks = 0 } else { - syncedBlocks, err = evalRecoveryLine(lines[syncLineIdx]) + syncedBlocks, pct, finish, speed, err = evalRecoveryLine(lines[syncLineIdx]) if err != nil { - return nil, fmt.Errorf("error parsing sync line in md device %q: %w", mdName, err) + return nil, fmt.Errorf("%s: Cannot parse sync line in md device: %q: %w", ErrFileParse, mdName, err) } } } mdStats = append(mdStats, MDStat{ - Name: mdName, - ActivityState: state, - DisksActive: active, - DisksFailed: fail, - DisksSpare: spare, - DisksTotal: total, - BlocksTotal: size, - BlocksSynced: syncedBlocks, - Devices: evalComponentDevices(deviceFields), + Name: mdName, + ActivityState: state, + DisksActive: active, + DisksFailed: fail, + DisksDown: down, + DisksSpare: spare, + DisksTotal: total, + BlocksTotal: size, + BlocksSynced: syncedBlocks, + BlocksSyncedPct: pct, + BlocksSyncedFinishTime: finish, + BlocksSyncedSpeed: speed, + Devices: evalComponentDevices(deviceFields), }) } return mdStats, nil } -func evalStatusLine(deviceLine, statusLine string) (active, total, size int64, err error) { +func evalStatusLine(deviceLine, statusLine string) (active, total, down, size int64, err error) { + statusFields := strings.Fields(statusLine) + if len(statusFields) < 1 { + return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) + } - sizeStr := strings.Fields(statusLine)[0] + sizeStr := statusFields[0] size, err = strconv.ParseInt(sizeStr, 10, 64) if err != nil { - return 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err) + return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } if strings.Contains(deviceLine, "raid0") || strings.Contains(deviceLine, "linear") { // In the device deviceLine, only disks have a number associated with them in []. total = int64(strings.Count(deviceLine, "[")) - return total, total, size, nil + return total, total, 0, size, nil } if strings.Contains(deviceLine, "inactive") { - return 0, 0, size, nil + return 0, 0, 0, size, nil } matches := statusLineRE.FindStringSubmatch(statusLine) - if len(matches) != 4 { - return 0, 0, 0, fmt.Errorf("couldn't find all the substring matches: %s", statusLine) + if len(matches) != 5 { + return 0, 0, 0, 0, fmt.Errorf("%s: Could not fild all substring matches %s: %w", ErrFileParse, statusLine, err) } total, err = strconv.ParseInt(matches[2], 10, 64) if err != nil { - return 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err) + return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } active, err = strconv.ParseInt(matches[3], 10, 64) if err != nil { - return 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err) + return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected active %d: %w", ErrFileParse, active, err) } + down = int64(strings.Count(matches[4], "_")) - return active, total, size, nil + return active, total, down, size, nil } -func evalRecoveryLine(recoveryLine string) (syncedBlocks int64, err error) { - matches := recoveryLineRE.FindStringSubmatch(recoveryLine) +func evalRecoveryLine(recoveryLine string) (syncedBlocks int64, pct float64, finish float64, speed float64, err error) { + matches := recoveryLineBlocksRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { - return 0, fmt.Errorf("unexpected recoveryLine: %s", recoveryLine) + return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected recoveryLine %s: %w", ErrFileParse, recoveryLine, err) } syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) if err != nil { - return 0, fmt.Errorf("error parsing int from recoveryLine %q: %w", recoveryLine, err) + return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected parsing of recoveryLine %q: %w", ErrFileParse, recoveryLine, err) + } + + // Get percentage complete + matches = recoveryLinePctRE.FindStringSubmatch(recoveryLine) + if len(matches) != 2 { + return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching percentage %s", ErrFileParse, recoveryLine) + } + pct, err = strconv.ParseFloat(strings.TrimSpace(matches[1]), 64) + if err != nil { + return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Error parsing float from recoveryLine %q", ErrFileParse, recoveryLine) + } + + // Get time expected left to complete + matches = recoveryLineFinishRE.FindStringSubmatch(recoveryLine) + if len(matches) != 2 { + return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching est. finish time: %s", ErrFileParse, recoveryLine) + } + finish, err = strconv.ParseFloat(matches[1], 64) + if err != nil { + return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unable to parse float from recoveryLine: %q", ErrFileParse, recoveryLine) + } + + // Get recovery speed + matches = recoveryLineSpeedRE.FindStringSubmatch(recoveryLine) + if len(matches) != 2 { + return syncedBlocks, pct, finish, 0, fmt.Errorf("%w: Unexpected recoveryLine value: %s", ErrFileParse, recoveryLine) + } + speed, err = strconv.ParseFloat(matches[1], 64) + if err != nil { + return syncedBlocks, pct, finish, 0, fmt.Errorf("%s: Error parsing float from recoveryLine: %q: %w", ErrFileParse, recoveryLine, err) } - return syncedBlocks, nil + return syncedBlocks, pct, finish, speed, nil } func evalComponentDevices(deviceFields []string) []string { diff --git a/vendor/github.com/prometheus/procfs/meminfo.go b/vendor/github.com/prometheus/procfs/meminfo.go index f65e174e5..eaf00e224 100644 --- a/vendor/github.com/prometheus/procfs/meminfo.go +++ b/vendor/github.com/prometheus/procfs/meminfo.go @@ -152,7 +152,7 @@ func (fs FS) Meminfo() (Meminfo, error) { m, err := parseMemInfo(bytes.NewReader(b)) if err != nil { - return Meminfo{}, fmt.Errorf("failed to parse meminfo: %w", err) + return Meminfo{}, fmt.Errorf("%s: %w", ErrFileParse, err) } return *m, nil @@ -165,7 +165,7 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { // Each line has at least a name and value; we ignore the unit. fields := strings.Fields(s.Text()) if len(fields) < 2 { - return nil, fmt.Errorf("malformed meminfo line: %q", s.Text()) + return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, s.Text()) } v, err := strconv.ParseUint(fields[1], 0, 64) diff --git a/vendor/github.com/prometheus/procfs/mountinfo.go b/vendor/github.com/prometheus/procfs/mountinfo.go index 59f4d5055..388ebf396 100644 --- a/vendor/github.com/prometheus/procfs/mountinfo.go +++ b/vendor/github.com/prometheus/procfs/mountinfo.go @@ -78,11 +78,11 @@ func parseMountInfoString(mountString string) (*MountInfo, error) { mountInfo := strings.Split(mountString, " ") mountInfoLength := len(mountInfo) if mountInfoLength < 10 { - return nil, fmt.Errorf("couldn't find enough fields in mount string: %s", mountString) + return nil, fmt.Errorf("%w: Too few fields in mount string: %s", ErrFileParse, mountString) } if mountInfo[mountInfoLength-4] != "-" { - return nil, fmt.Errorf("couldn't find separator in expected field: %s", mountInfo[mountInfoLength-4]) + return nil, fmt.Errorf("%w: couldn't find separator in expected field: %s", ErrFileParse, mountInfo[mountInfoLength-4]) } mount := &MountInfo{ @@ -98,18 +98,18 @@ func parseMountInfoString(mountString string) (*MountInfo, error) { mount.MountID, err = strconv.Atoi(mountInfo[0]) if err != nil { - return nil, fmt.Errorf("failed to parse mount ID") + return nil, fmt.Errorf("%w: mount ID: %q", ErrFileParse, mount.MountID) } mount.ParentID, err = strconv.Atoi(mountInfo[1]) if err != nil { - return nil, fmt.Errorf("failed to parse parent ID") + return nil, fmt.Errorf("%w: parent ID: %q", ErrFileParse, mount.ParentID) } // Has optional fields, which is a space separated list of values. // Example: shared:2 master:7 if mountInfo[6] != "" { mount.OptionalFields, err = mountOptionsParseOptionalFields(mountInfo[6 : mountInfoLength-4]) if err != nil { - return nil, err + return nil, fmt.Errorf("%s: %w", ErrFileParse, err) } } return mount, nil diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go index f7a828bb1..9d8af6db7 100644 --- a/vendor/github.com/prometheus/procfs/mountstats.go +++ b/vendor/github.com/prometheus/procfs/mountstats.go @@ -44,6 +44,14 @@ const ( fieldTransport11TCPLen = 13 fieldTransport11UDPLen = 10 + + // kernel version >= 4.14 MaxLen + // See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393 + fieldTransport11RDMAMaxLen = 28 + + // kernel version <= 4.2 MinLen + // See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331 + fieldTransport11RDMAMinLen = 20 ) // A Mount is a device mount parsed from /proc/[pid]/mountstats. @@ -186,6 +194,8 @@ type NFSOperationStats struct { CumulativeTotalResponseMilliseconds uint64 // Duration from when a request was enqueued to when it was completely handled. CumulativeTotalRequestMilliseconds uint64 + // The average time from the point the client sends RPC requests until it receives the response. + AverageRTTMilliseconds float64 // The count of operations that complete with tk_status < 0. These statuses usually indicate error conditions. Errors uint64 } @@ -231,6 +241,33 @@ type NFSTransportStats struct { // A running counter, incremented on each request as the current size of the // pending queue. CumulativePendingQueue uint64 + + // Stats below only available with stat version 1.1. + // Transport over RDMA + + // accessed when sending a call + ReadChunkCount uint64 + WriteChunkCount uint64 + ReplyChunkCount uint64 + TotalRdmaRequest uint64 + + // rarely accessed error counters + PullupCopyCount uint64 + HardwayRegisterCount uint64 + FailedMarshalCount uint64 + BadReplyCount uint64 + MrsRecovered uint64 + MrsOrphaned uint64 + MrsAllocated uint64 + EmptySendctxQ uint64 + + // accessed when receiving a reply + TotalRdmaReply uint64 + FixupCopyCount uint64 + ReplyWaitsForSend uint64 + LocalInvNeeded uint64 + NomsgCallCount uint64 + BcallCount uint64 } // parseMountStats parses a /proc/[pid]/mountstats file and returns a slice @@ -264,7 +301,7 @@ func parseMountStats(r io.Reader) ([]*Mount, error) { if len(ss) > deviceEntryLen { // Only NFSv3 and v4 are supported for parsing statistics if m.Type != nfs3Type && m.Type != nfs4Type { - return nil, fmt.Errorf("cannot parse MountStats for fstype %q", m.Type) + return nil, fmt.Errorf("%w: Cannot parse MountStats for %q", ErrFileParse, m.Type) } statVersion := strings.TrimPrefix(ss[8], statVersionPrefix) @@ -284,10 +321,11 @@ func parseMountStats(r io.Reader) ([]*Mount, error) { } // parseMount parses an entry in /proc/[pid]/mountstats in the format: -// device [device] mounted on [mount] with fstype [type] +// +// device [device] mounted on [mount] with fstype [type] func parseMount(ss []string) (*Mount, error) { if len(ss) < deviceEntryLen { - return nil, fmt.Errorf("invalid device entry: %v", ss) + return nil, fmt.Errorf("%w: Invalid device %q", ErrFileParse, ss) } // Check for specific words appearing at specific indices to ensure @@ -305,7 +343,7 @@ func parseMount(ss []string) (*Mount, error) { for _, f := range format { if ss[f.i] != f.s { - return nil, fmt.Errorf("invalid device entry: %v", ss) + return nil, fmt.Errorf("%w: Invalid device %q", ErrFileParse, ss) } } @@ -342,7 +380,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e switch ss[0] { case fieldOpts: if len(ss) < 2 { - return nil, fmt.Errorf("not enough information for NFS stats: %v", ss) + return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss) } if stats.Opts == nil { stats.Opts = map[string]string{} @@ -357,7 +395,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e } case fieldAge: if len(ss) < 2 { - return nil, fmt.Errorf("not enough information for NFS stats: %v", ss) + return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss) } // Age integer is in seconds d, err := time.ParseDuration(ss[1] + "s") @@ -368,7 +406,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e stats.Age = d case fieldBytes: if len(ss) < 2 { - return nil, fmt.Errorf("not enough information for NFS stats: %v", ss) + return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss) } bstats, err := parseNFSBytesStats(ss[1:]) if err != nil { @@ -378,7 +416,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e stats.Bytes = *bstats case fieldEvents: if len(ss) < 2 { - return nil, fmt.Errorf("not enough information for NFS stats: %v", ss) + return nil, fmt.Errorf("%w: Incomplete information for NFS events: %v", ErrFileParse, ss) } estats, err := parseNFSEventsStats(ss[1:]) if err != nil { @@ -388,7 +426,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e stats.Events = *estats case fieldTransport: if len(ss) < 3 { - return nil, fmt.Errorf("not enough information for NFS transport stats: %v", ss) + return nil, fmt.Errorf("%w: Incomplete information for NFS transport stats: %v", ErrFileParse, ss) } tstats, err := parseNFSTransportStats(ss[1:], statVersion) @@ -427,7 +465,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e // integer fields. func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) { if len(ss) != fieldBytesLen { - return nil, fmt.Errorf("invalid NFS bytes stats: %v", ss) + return nil, fmt.Errorf("%w: Invalid NFS bytes stats: %v", ErrFileParse, ss) } ns := make([]uint64, 0, fieldBytesLen) @@ -456,7 +494,7 @@ func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) { // integer fields. func parseNFSEventsStats(ss []string) (*NFSEventsStats, error) { if len(ss) != fieldEventsLen { - return nil, fmt.Errorf("invalid NFS events stats: %v", ss) + return nil, fmt.Errorf("%w: invalid NFS events stats: %v", ErrFileParse, ss) } ns := make([]uint64, 0, fieldEventsLen) @@ -520,7 +558,7 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) { } if len(ss) < minFields { - return nil, fmt.Errorf("invalid NFS per-operations stats: %v", ss) + return nil, fmt.Errorf("%w: invalid NFS per-operations stats: %v", ErrFileParse, ss) } // Skip string operation name for integers @@ -533,7 +571,6 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) { ns = append(ns, n) } - opStats := NFSOperationStats{ Operation: strings.TrimSuffix(ss[0], ":"), Requests: ns[0], @@ -545,6 +582,9 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) { CumulativeTotalResponseMilliseconds: ns[6], CumulativeTotalRequestMilliseconds: ns[7], } + if ns[0] != 0 { + opStats.AverageRTTMilliseconds = float64(ns[6]) / float64(ns[0]) + } if len(ns) > 8 { opStats.Errors = ns[8] @@ -571,10 +611,10 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats } else if protocol == "udp" { expectedLength = fieldTransport10UDPLen } else { - return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.0 statement: %v", protocol, ss) + return nil, fmt.Errorf("%w: Invalid NFS protocol \"%s\" in stats 1.0 statement: %v", ErrFileParse, protocol, ss) } if len(ss) != expectedLength { - return nil, fmt.Errorf("invalid NFS transport stats 1.0 statement: %v", ss) + return nil, fmt.Errorf("%w: Invalid NFS transport stats 1.0 statement: %v", ErrFileParse, ss) } case statVersion11: var expectedLength int @@ -582,14 +622,17 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats expectedLength = fieldTransport11TCPLen } else if protocol == "udp" { expectedLength = fieldTransport11UDPLen + } else if protocol == "rdma" { + expectedLength = fieldTransport11RDMAMinLen } else { - return nil, fmt.Errorf("invalid NFS protocol \"%s\" in stats 1.1 statement: %v", protocol, ss) + return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss) } - if len(ss) != expectedLength { - return nil, fmt.Errorf("invalid NFS transport stats 1.1 statement: %v", ss) + if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) || + (protocol == "rdma" && len(ss) < expectedLength) { + return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v, protocol: %v", ErrFileParse, ss, protocol) } default: - return nil, fmt.Errorf("unrecognized NFS transport stats version: %q", statVersion) + return nil, fmt.Errorf("%s: Unrecognized NFS transport stats version: %q, protocol: %v", ErrFileParse, statVersion, protocol) } // Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay @@ -599,7 +642,9 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats // Note: slice length must be set to length of v1.1 stats to avoid a panic when // only v1.0 stats are present. // See: https://github.com/prometheus/node_exporter/issues/571. - ns := make([]uint64, fieldTransport11TCPLen) + // + // Note: NFS Over RDMA slice length is fieldTransport11RDMAMaxLen + ns := make([]uint64, fieldTransport11RDMAMaxLen+3) for i, s := range ss { n, err := strconv.ParseUint(s, 10, 64) if err != nil { @@ -617,9 +662,14 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats // we set them to 0 here. if protocol == "udp" { ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...) + } else if protocol == "tcp" { + ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...) + } else if protocol == "rdma" { + ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...) } return &NFSTransportStats{ + // NFS xprt over tcp or udp Protocol: protocol, Port: ns[0], Bind: ns[1], @@ -631,8 +681,32 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats BadTransactionIDs: ns[7], CumulativeActiveRequests: ns[8], CumulativeBacklog: ns[9], - MaximumRPCSlotsUsed: ns[10], - CumulativeSendingQueue: ns[11], - CumulativePendingQueue: ns[12], + + // NFS xprt over tcp or udp + // And statVersion 1.1 + MaximumRPCSlotsUsed: ns[10], + CumulativeSendingQueue: ns[11], + CumulativePendingQueue: ns[12], + + // NFS xprt over rdma + // And stat Version 1.1 + ReadChunkCount: ns[13], + WriteChunkCount: ns[14], + ReplyChunkCount: ns[15], + TotalRdmaRequest: ns[16], + PullupCopyCount: ns[17], + HardwayRegisterCount: ns[18], + FailedMarshalCount: ns[19], + BadReplyCount: ns[20], + MrsRecovered: ns[21], + MrsOrphaned: ns[22], + MrsAllocated: ns[23], + EmptySendctxQ: ns[24], + TotalRdmaReply: ns[25], + FixupCopyCount: ns[26], + ReplyWaitsForSend: ns[27], + LocalInvNeeded: ns[28], + NomsgCallCount: ns[29], + BcallCount: ns[30], }, nil } diff --git a/vendor/github.com/prometheus/procfs/net_conntrackstat.go b/vendor/github.com/prometheus/procfs/net_conntrackstat.go index 9964a3600..fdfa45611 100644 --- a/vendor/github.com/prometheus/procfs/net_conntrackstat.go +++ b/vendor/github.com/prometheus/procfs/net_conntrackstat.go @@ -18,19 +18,22 @@ import ( "bytes" "fmt" "io" - "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // A ConntrackStatEntry represents one line from net/stat/nf_conntrack -// and contains netfilter conntrack statistics at one CPU core +// and contains netfilter conntrack statistics at one CPU core. type ConntrackStatEntry struct { Entries uint64 + Searched uint64 Found uint64 + New uint64 Invalid uint64 Ignore uint64 + Delete uint64 + DeleteList uint64 Insert uint64 InsertFailed uint64 Drop uint64 @@ -38,12 +41,12 @@ type ConntrackStatEntry struct { SearchRestart uint64 } -// ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores +// ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores. func (fs FS) ConntrackStat() ([]ConntrackStatEntry, error) { return readConntrackStat(fs.proc.Path("net", "stat", "nf_conntrack")) } -// Parses a slice of ConntrackStatEntries from the given filepath +// Parses a slice of ConntrackStatEntries from the given filepath. func readConntrackStat(path string) ([]ConntrackStatEntry, error) { // This file is small and can be read with one syscall. b, err := util.ReadFileNoStat(path) @@ -55,13 +58,13 @@ func readConntrackStat(path string) ([]ConntrackStatEntry, error) { stat, err := parseConntrackStat(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("failed to read conntrack stats from %q: %w", path, err) + return nil, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, path, err) } return stat, nil } -// Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries +// Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries. func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { var entries []ConntrackStatEntry @@ -79,75 +82,37 @@ func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { return entries, nil } -// Parses a ConntrackStatEntry from given array of fields +// Parses a ConntrackStatEntry from given array of fields. func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) { - if len(fields) != 17 { - return nil, fmt.Errorf("invalid conntrackstat entry, missing fields") - } - entry := &ConntrackStatEntry{} - - entries, err := parseConntrackStatField(fields[0]) - if err != nil { - return nil, err - } - entry.Entries = entries - - found, err := parseConntrackStatField(fields[2]) - if err != nil { - return nil, err - } - entry.Found = found - - invalid, err := parseConntrackStatField(fields[4]) - if err != nil { - return nil, err - } - entry.Invalid = invalid - - ignore, err := parseConntrackStatField(fields[5]) - if err != nil { - return nil, err - } - entry.Ignore = ignore - - insert, err := parseConntrackStatField(fields[8]) + entries, err := util.ParseHexUint64s(fields) if err != nil { - return nil, err + return nil, fmt.Errorf("%s: Cannot parse entry: %d: %w", ErrFileParse, entries, err) } - entry.Insert = insert - - insertFailed, err := parseConntrackStatField(fields[9]) - if err != nil { - return nil, err + numEntries := len(entries) + if numEntries < 16 || numEntries > 17 { + return nil, + fmt.Errorf("%w: invalid conntrackstat entry, invalid number of fields: %d", ErrFileParse, numEntries) } - entry.InsertFailed = insertFailed - drop, err := parseConntrackStatField(fields[10]) - if err != nil { - return nil, err + stats := &ConntrackStatEntry{ + Entries: *entries[0], + Searched: *entries[1], + Found: *entries[2], + New: *entries[3], + Invalid: *entries[4], + Ignore: *entries[5], + Delete: *entries[6], + DeleteList: *entries[7], + Insert: *entries[8], + InsertFailed: *entries[9], + Drop: *entries[10], + EarlyDrop: *entries[11], } - entry.Drop = drop - earlyDrop, err := parseConntrackStatField(fields[11]) - if err != nil { - return nil, err + // Ignore missing search_restart on Linux < 2.6.35. + if numEntries == 17 { + stats.SearchRestart = *entries[16] } - entry.EarlyDrop = earlyDrop - searchRestart, err := parseConntrackStatField(fields[16]) - if err != nil { - return nil, err - } - entry.SearchRestart = searchRestart - - return entry, nil -} - -// Parses a uint64 from given hex in string -func parseConntrackStatField(field string) (uint64, error) { - val, err := strconv.ParseUint(field, 16, 64) - if err != nil { - return 0, fmt.Errorf("couldn't parse %q field: %w", field, err) - } - return val, err + return stats, nil } diff --git a/vendor/github.com/prometheus/procfs/net_dev.go b/vendor/github.com/prometheus/procfs/net_dev.go index 47a710bef..e66208aa0 100644 --- a/vendor/github.com/prometheus/procfs/net_dev.go +++ b/vendor/github.com/prometheus/procfs/net_dev.go @@ -87,17 +87,17 @@ func newNetDev(file string) (NetDev, error) { // parseLine parses a single line from the /proc/net/dev file. Header lines // must be filtered prior to calling this method. func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) { - parts := strings.SplitN(rawLine, ":", 2) - if len(parts) != 2 { + idx := strings.LastIndex(rawLine, ":") + if idx == -1 { return nil, errors.New("invalid net/dev line, missing colon") } - fields := strings.Fields(strings.TrimSpace(parts[1])) + fields := strings.Fields(strings.TrimSpace(rawLine[idx+1:])) var err error line := &NetDevLine{} // Interface Name - line.Name = strings.TrimSpace(parts[0]) + line.Name = strings.TrimSpace(rawLine[:idx]) if line.Name == "" { return nil, errors.New("invalid net/dev line, empty interface name") } diff --git a/vendor/github.com/prometheus/procfs/net_ip_socket.go b/vendor/github.com/prometheus/procfs/net_ip_socket.go index ac01dd847..4da81ea57 100644 --- a/vendor/github.com/prometheus/procfs/net_ip_socket.go +++ b/vendor/github.com/prometheus/procfs/net_ip_socket.go @@ -34,7 +34,7 @@ const ( readLimit = 4294967296 // Byte -> 4 GiB ) -// this contains generic data structures for both udp and tcp sockets +// This contains generic data structures for both udp and tcp sockets. type ( // NetIPSocket represents the contents of /proc/net/{t,u}dp{,6} file without the header. NetIPSocket []*netIPSocketLine @@ -65,6 +65,7 @@ type ( TxQueue uint64 RxQueue uint64 UID uint64 + Inode uint64 } ) @@ -129,7 +130,7 @@ func parseIP(hexIP string) (net.IP, error) { var byteIP []byte byteIP, err := hex.DecodeString(hexIP) if err != nil { - return nil, fmt.Errorf("cannot parse address field in socket line %q", hexIP) + return nil, fmt.Errorf("%s: Cannot parse socket field in %q: %w", ErrFileParse, hexIP, err) } switch len(byteIP) { case 4: @@ -143,16 +144,17 @@ func parseIP(hexIP string) (net.IP, error) { } return i, nil default: - return nil, fmt.Errorf("Unable to parse IP %s", hexIP) + return nil, fmt.Errorf("%s: Unable to parse IP %s: %w", ErrFileParse, hexIP, nil) } } // parseNetIPSocketLine parses a single line, represented by a list of fields. func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) { line := &netIPSocketLine{} - if len(fields) < 8 { + if len(fields) < 10 { return nil, fmt.Errorf( - "cannot parse net socket line as it has less then 8 columns %q", + "%w: Less than 10 columns found %q", + ErrFileParse, strings.Join(fields, " "), ) } @@ -161,59 +163,65 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) { // sl s := strings.Split(fields[0], ":") if len(s) != 2 { - return nil, fmt.Errorf("cannot parse sl field in socket line %q", fields[0]) + return nil, fmt.Errorf("%w: Unable to parse sl field in line %q", ErrFileParse, fields[0]) } if line.Sl, err = strconv.ParseUint(s[0], 0, 64); err != nil { - return nil, fmt.Errorf("cannot parse sl value in socket line: %w", err) + return nil, fmt.Errorf("%s: Unable to parse sl field in %q: %w", ErrFileParse, line.Sl, err) } // local_address l := strings.Split(fields[1], ":") if len(l) != 2 { - return nil, fmt.Errorf("cannot parse local_address field in socket line %q", fields[1]) + return nil, fmt.Errorf("%w: Unable to parse local_address field in %q", ErrFileParse, fields[1]) } if line.LocalAddr, err = parseIP(l[0]); err != nil { return nil, err } if line.LocalPort, err = strconv.ParseUint(l[1], 16, 64); err != nil { - return nil, fmt.Errorf("cannot parse local_address port value in socket line: %w", err) + return nil, fmt.Errorf("%s: Unable to parse local_address port value line %q: %w", ErrFileParse, line.LocalPort, err) } // remote_address r := strings.Split(fields[2], ":") if len(r) != 2 { - return nil, fmt.Errorf("cannot parse rem_address field in socket line %q", fields[1]) + return nil, fmt.Errorf("%w: Unable to parse rem_address field in %q", ErrFileParse, fields[1]) } if line.RemAddr, err = parseIP(r[0]); err != nil { return nil, err } if line.RemPort, err = strconv.ParseUint(r[1], 16, 64); err != nil { - return nil, fmt.Errorf("cannot parse rem_address port value in socket line: %w", err) + return nil, fmt.Errorf("%s: Cannot parse rem_address port value in %q: %w", ErrFileParse, line.RemPort, err) } // st if line.St, err = strconv.ParseUint(fields[3], 16, 64); err != nil { - return nil, fmt.Errorf("cannot parse st value in socket line: %w", err) + return nil, fmt.Errorf("%s: Cannot parse st value in %q: %w", ErrFileParse, line.St, err) } // tx_queue and rx_queue q := strings.Split(fields[4], ":") if len(q) != 2 { return nil, fmt.Errorf( - "cannot parse tx/rx queues in socket line as it has a missing colon %q", + "%w: Missing colon for tx/rx queues in socket line %q", + ErrFileParse, fields[4], ) } if line.TxQueue, err = strconv.ParseUint(q[0], 16, 64); err != nil { - return nil, fmt.Errorf("cannot parse tx_queue value in socket line: %w", err) + return nil, fmt.Errorf("%s: Cannot parse tx_queue value in %q: %w", ErrFileParse, line.TxQueue, err) } if line.RxQueue, err = strconv.ParseUint(q[1], 16, 64); err != nil { - return nil, fmt.Errorf("cannot parse rx_queue value in socket line: %w", err) + return nil, fmt.Errorf("%s: Cannot parse trx_queue value in %q: %w", ErrFileParse, line.RxQueue, err) } // uid if line.UID, err = strconv.ParseUint(fields[7], 0, 64); err != nil { - return nil, fmt.Errorf("cannot parse uid value in socket line: %w", err) + return nil, fmt.Errorf("%s: Cannot parse UID value in %q: %w", ErrFileParse, line.UID, err) + } + + // inode + if line.Inode, err = strconv.ParseUint(fields[9], 0, 64); err != nil { + return nil, fmt.Errorf("%s: Cannot parse inode value in %q: %w", ErrFileParse, line.Inode, err) } return line, nil diff --git a/vendor/github.com/prometheus/procfs/net_protocols.go b/vendor/github.com/prometheus/procfs/net_protocols.go index 8c6de3791..b6c77b709 100644 --- a/vendor/github.com/prometheus/procfs/net_protocols.go +++ b/vendor/github.com/prometheus/procfs/net_protocols.go @@ -23,7 +23,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// NetProtocolStats stores the contents from /proc/net/protocols +// NetProtocolStats stores the contents from /proc/net/protocols. type NetProtocolStats map[string]NetProtocolStatLine // NetProtocolStatLine contains a single line parsed from /proc/net/protocols. We @@ -41,7 +41,7 @@ type NetProtocolStatLine struct { Capabilities NetProtocolCapabilities } -// NetProtocolCapabilities contains a list of capabilities for each protocol +// NetProtocolCapabilities contains a list of capabilities for each protocol. type NetProtocolCapabilities struct { Close bool // 8 Connect bool // 9 @@ -131,7 +131,7 @@ func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, erro } else if fields[6] == disabled { line.Slab = false } else { - return nil, fmt.Errorf("unable to parse capability for protocol: %s", line.Name) + return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name) } line.ModuleName = fields[7] @@ -173,7 +173,7 @@ func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) erro } else if capabilities[i] == "n" { *capabilityFields[i] = false } else { - return fmt.Errorf("unable to parse capability block for protocol: position %d", i) + return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i) } } return nil diff --git a/vendor/github.com/prometheus/procfs/net_route.go b/vendor/github.com/prometheus/procfs/net_route.go new file mode 100644 index 000000000..deb7029fe --- /dev/null +++ b/vendor/github.com/prometheus/procfs/net_route.go @@ -0,0 +1,143 @@ +// Copyright 2023 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +const ( + blackholeRepresentation string = "*" + blackholeIfaceName string = "blackhole" + routeLineColumns int = 11 +) + +// A NetRouteLine represents one line from net/route. +type NetRouteLine struct { + Iface string + Destination uint32 + Gateway uint32 + Flags uint32 + RefCnt uint32 + Use uint32 + Metric uint32 + Mask uint32 + MTU uint32 + Window uint32 + IRTT uint32 +} + +func (fs FS) NetRoute() ([]NetRouteLine, error) { + return readNetRoute(fs.proc.Path("net", "route")) +} + +func readNetRoute(path string) ([]NetRouteLine, error) { + b, err := util.ReadFileNoStat(path) + if err != nil { + return nil, err + } + + routelines, err := parseNetRoute(bytes.NewReader(b)) + if err != nil { + return nil, fmt.Errorf("failed to read net route from %s: %w", path, err) + } + return routelines, nil +} + +func parseNetRoute(r io.Reader) ([]NetRouteLine, error) { + var routelines []NetRouteLine + + scanner := bufio.NewScanner(r) + scanner.Scan() + for scanner.Scan() { + fields := strings.Fields(scanner.Text()) + routeline, err := parseNetRouteLine(fields) + if err != nil { + return nil, err + } + routelines = append(routelines, *routeline) + } + return routelines, nil +} + +func parseNetRouteLine(fields []string) (*NetRouteLine, error) { + if len(fields) != routeLineColumns { + return nil, fmt.Errorf("invalid routeline, num of digits: %d", len(fields)) + } + iface := fields[0] + if iface == blackholeRepresentation { + iface = blackholeIfaceName + } + destination, err := strconv.ParseUint(fields[1], 16, 32) + if err != nil { + return nil, err + } + gateway, err := strconv.ParseUint(fields[2], 16, 32) + if err != nil { + return nil, err + } + flags, err := strconv.ParseUint(fields[3], 10, 32) + if err != nil { + return nil, err + } + refcnt, err := strconv.ParseUint(fields[4], 10, 32) + if err != nil { + return nil, err + } + use, err := strconv.ParseUint(fields[5], 10, 32) + if err != nil { + return nil, err + } + metric, err := strconv.ParseUint(fields[6], 10, 32) + if err != nil { + return nil, err + } + mask, err := strconv.ParseUint(fields[7], 16, 32) + if err != nil { + return nil, err + } + mtu, err := strconv.ParseUint(fields[8], 10, 32) + if err != nil { + return nil, err + } + window, err := strconv.ParseUint(fields[9], 10, 32) + if err != nil { + return nil, err + } + irtt, err := strconv.ParseUint(fields[10], 10, 32) + if err != nil { + return nil, err + } + routeline := &NetRouteLine{ + Iface: iface, + Destination: uint32(destination), + Gateway: uint32(gateway), + Flags: uint32(flags), + RefCnt: uint32(refcnt), + Use: uint32(use), + Metric: uint32(metric), + Mask: uint32(mask), + MTU: uint32(mtu), + Window: uint32(window), + IRTT: uint32(irtt), + } + return routeline, nil +} diff --git a/vendor/github.com/prometheus/procfs/net_sockstat.go b/vendor/github.com/prometheus/procfs/net_sockstat.go index e36f4872d..360e36af7 100644 --- a/vendor/github.com/prometheus/procfs/net_sockstat.go +++ b/vendor/github.com/prometheus/procfs/net_sockstat.go @@ -16,7 +16,6 @@ package procfs import ( "bufio" "bytes" - "errors" "fmt" "io" "strings" @@ -70,7 +69,7 @@ func readSockstat(name string) (*NetSockstat, error) { stat, err := parseSockstat(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("failed to read sockstats from %q: %w", name, err) + return nil, fmt.Errorf("%s: sockstats from %q: %w", ErrFileRead, name, err) } return stat, nil @@ -84,13 +83,13 @@ func parseSockstat(r io.Reader) (*NetSockstat, error) { // Expect a minimum of a protocol and one key/value pair. fields := strings.Split(s.Text(), " ") if len(fields) < 3 { - return nil, fmt.Errorf("malformed sockstat line: %q", s.Text()) + return nil, fmt.Errorf("%w: Malformed sockstat line: %q", ErrFileParse, s.Text()) } // The remaining fields are key/value pairs. kvs, err := parseSockstatKVs(fields[1:]) if err != nil { - return nil, fmt.Errorf("error parsing sockstat key/value pairs from %q: %w", s.Text(), err) + return nil, fmt.Errorf("%s: sockstat key/value pairs from %q: %w", ErrFileParse, s.Text(), err) } // The first field is the protocol. We must trim its colon suffix. @@ -119,7 +118,7 @@ func parseSockstat(r io.Reader) (*NetSockstat, error) { // parseSockstatKVs parses a string slice into a map of key/value pairs. func parseSockstatKVs(kvs []string) (map[string]int, error) { if len(kvs)%2 != 0 { - return nil, errors.New("odd number of fields in key/value pairs") + return nil, fmt.Errorf("%w:: Odd number of fields in key/value pairs %q", ErrFileParse, kvs) } // Iterate two values at a time to gather key/value pairs. diff --git a/vendor/github.com/prometheus/procfs/net_softnet.go b/vendor/github.com/prometheus/procfs/net_softnet.go index 46f12c61d..c77085291 100644 --- a/vendor/github.com/prometheus/procfs/net_softnet.go +++ b/vendor/github.com/prometheus/procfs/net_softnet.go @@ -27,17 +27,30 @@ import ( // For the proc file format details, // See: // * Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2343 -// * Linux 4.17 https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162 -// and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810. +// * Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 +// * Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 +// * Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 -// SoftnetStat contains a single row of data from /proc/net/softnet_stat +// SoftnetStat contains a single row of data from /proc/net/softnet_stat. type SoftnetStat struct { - // Number of processed packets + // Number of processed packets. Processed uint32 - // Number of dropped packets + // Number of dropped packets. Dropped uint32 - // Number of times processing packets ran out of quota + // Number of times processing packets ran out of quota. TimeSqueezed uint32 + // Number of collision occur while obtaining device lock while transmitting. + CPUCollision uint32 + // Number of times cpu woken up received_rps. + ReceivedRps uint32 + // number of times flow limit has been reached. + FlowLimitCount uint32 + // Softnet backlog status. + SoftnetBacklogLen uint32 + // CPU id owning this softnet_data. + Index uint32 + // softnet_data's Width. + Width int } var softNetProcFile = "net/softnet_stat" @@ -51,7 +64,7 @@ func (fs FS) NetSoftnetStat() ([]SoftnetStat, error) { entries, err := parseSoftnet(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("failed to parse /proc/net/softnet_stat: %w", err) + return nil, fmt.Errorf("%s: /proc/net/softnet_stat: %w", ErrFileParse, err) } return entries, nil @@ -63,25 +76,65 @@ func parseSoftnet(r io.Reader) ([]SoftnetStat, error) { s := bufio.NewScanner(r) var stats []SoftnetStat + cpuIndex := 0 for s.Scan() { columns := strings.Fields(s.Text()) width := len(columns) + softnetStat := SoftnetStat{} if width < minColumns { - return nil, fmt.Errorf("%d columns were detected, but at least %d were expected", width, minColumns) + return nil, fmt.Errorf("%w: detected %d columns, but expected at least %d", ErrFileParse, width, minColumns) } - // We only parse the first three columns at the moment. - us, err := parseHexUint32s(columns[0:3]) - if err != nil { - return nil, err + // Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2347 + if width >= minColumns { + us, err := parseHexUint32s(columns[0:9]) + if err != nil { + return nil, err + } + + softnetStat.Processed = us[0] + softnetStat.Dropped = us[1] + softnetStat.TimeSqueezed = us[2] + softnetStat.CPUCollision = us[8] + } + + // Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 + if width >= 10 { + us, err := parseHexUint32s(columns[9:10]) + if err != nil { + return nil, err + } + + softnetStat.ReceivedRps = us[0] } - stats = append(stats, SoftnetStat{ - Processed: us[0], - Dropped: us[1], - TimeSqueezed: us[2], - }) + // Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 + if width >= 11 { + us, err := parseHexUint32s(columns[10:11]) + if err != nil { + return nil, err + } + + softnetStat.FlowLimitCount = us[0] + } + + // Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 + if width >= 13 { + us, err := parseHexUint32s(columns[11:13]) + if err != nil { + return nil, err + } + + softnetStat.SoftnetBacklogLen = us[0] + softnetStat.Index = us[1] + } else { + // For older kernels, create the Index based on the scan line number. + softnetStat.Index = uint32(cpuIndex) + } + softnetStat.Width = width + stats = append(stats, softnetStat) + cpuIndex++ } return stats, nil diff --git a/vendor/github.com/prometheus/procfs/net_unix.go b/vendor/github.com/prometheus/procfs/net_unix.go index 98aa8e1c3..acbbc57ea 100644 --- a/vendor/github.com/prometheus/procfs/net_unix.go +++ b/vendor/github.com/prometheus/procfs/net_unix.go @@ -108,14 +108,14 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) { line := s.Text() item, err := nu.parseLine(line, hasInode, minFields) if err != nil { - return nil, fmt.Errorf("failed to parse /proc/net/unix data %q: %w", line, err) + return nil, fmt.Errorf("%s: /proc/net/unix encountered data %q: %w", ErrFileParse, line, err) } nu.Rows = append(nu.Rows, item) } if err := s.Err(); err != nil { - return nil, fmt.Errorf("failed to scan /proc/net/unix data: %w", err) + return nil, fmt.Errorf("%s: /proc/net/unix encountered data: %w", ErrFileParse, err) } return &nu, nil @@ -126,7 +126,7 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, l := len(fields) if l < min { - return nil, fmt.Errorf("expected at least %d fields but got %d", min, l) + return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l) } // Field offsets are as follows: @@ -136,29 +136,29 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, users, err := u.parseUsers(fields[1]) if err != nil { - return nil, fmt.Errorf("failed to parse ref count %q: %w", fields[1], err) + return nil, fmt.Errorf("%s: ref count %q: %w", ErrFileParse, fields[1], err) } flags, err := u.parseFlags(fields[3]) if err != nil { - return nil, fmt.Errorf("failed to parse flags %q: %w", fields[3], err) + return nil, fmt.Errorf("%s: Unable to parse flags %q: %w", ErrFileParse, fields[3], err) } typ, err := u.parseType(fields[4]) if err != nil { - return nil, fmt.Errorf("failed to parse type %q: %w", fields[4], err) + return nil, fmt.Errorf("%s: Failed to parse type %q: %w", ErrFileParse, fields[4], err) } state, err := u.parseState(fields[5]) if err != nil { - return nil, fmt.Errorf("failed to parse state %q: %w", fields[5], err) + return nil, fmt.Errorf("%s: Failed to parse state %q: %w", ErrFileParse, fields[5], err) } var inode uint64 if hasInode { inode, err = u.parseInode(fields[6]) if err != nil { - return nil, fmt.Errorf("failed to parse inode %q: %w", fields[6], err) + return nil, fmt.Errorf("%s failed to parse inode %q: %w", ErrFileParse, fields[6], err) } } diff --git a/vendor/github.com/prometheus/procfs/net_wireless.go b/vendor/github.com/prometheus/procfs/net_wireless.go new file mode 100644 index 000000000..7443edca9 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/net_wireless.go @@ -0,0 +1,182 @@ +// Copyright 2023 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// Wireless models the content of /proc/net/wireless. +type Wireless struct { + Name string + + // Status is the current 4-digit hex value status of the interface. + Status uint64 + + // QualityLink is the link quality. + QualityLink int + + // QualityLevel is the signal gain (dBm). + QualityLevel int + + // QualityNoise is the signal noise baseline (dBm). + QualityNoise int + + // DiscardedNwid is the number of discarded packets with wrong nwid/essid. + DiscardedNwid int + + // DiscardedCrypt is the number of discarded packets with wrong code/decode (WEP). + DiscardedCrypt int + + // DiscardedFrag is the number of discarded packets that can't perform MAC reassembly. + DiscardedFrag int + + // DiscardedRetry is the number of discarded packets that reached max MAC retries. + DiscardedRetry int + + // DiscardedMisc is the number of discarded packets for other reasons. + DiscardedMisc int + + // MissedBeacon is the number of missed beacons/superframe. + MissedBeacon int +} + +// Wireless returns kernel wireless statistics. +func (fs FS) Wireless() ([]*Wireless, error) { + b, err := util.ReadFileNoStat(fs.proc.Path("net/wireless")) + if err != nil { + return nil, err + } + + m, err := parseWireless(bytes.NewReader(b)) + if err != nil { + return nil, fmt.Errorf("%s: wireless: %w", ErrFileParse, err) + } + + return m, nil +} + +// parseWireless parses the contents of /proc/net/wireless. +/* +Inter-| sta-| Quality | Discarded packets | Missed | WE +face | tus | link level noise | nwid crypt frag retry misc | beacon | 22 + eth1: 0000 5. -256. -10. 0 1 0 3 0 0 + eth2: 0000 5. -256. -20. 0 2 0 4 0 0 +*/ +func parseWireless(r io.Reader) ([]*Wireless, error) { + var ( + interfaces []*Wireless + scanner = bufio.NewScanner(r) + ) + + for n := 0; scanner.Scan(); n++ { + // Skip the 2 header lines. + if n < 2 { + continue + } + + line := scanner.Text() + + parts := strings.Split(line, ":") + if len(parts) != 2 { + return nil, fmt.Errorf("%w: expected 2 parts after splitting line by ':', got %d for line %q", ErrFileParse, len(parts), line) + } + + name := strings.TrimSpace(parts[0]) + stats := strings.Fields(parts[1]) + + if len(stats) < 10 { + return nil, fmt.Errorf("%w: invalid number of fields in line %d, expected 10+, got %d: %q", ErrFileParse, n, len(stats), line) + } + + status, err := strconv.ParseUint(stats[0], 16, 16) + if err != nil { + return nil, fmt.Errorf("%w: invalid status in line %d: %q", ErrFileParse, n, line) + } + + qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], ".")) + if err != nil { + return nil, fmt.Errorf("%s: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err) + } + + qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], ".")) + if err != nil { + return nil, fmt.Errorf("%s: Quality:level as integer %q: %w", ErrFileParse, qlevel, err) + } + + qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], ".")) + if err != nil { + return nil, fmt.Errorf("%s: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err) + } + + dnwid, err := strconv.Atoi(stats[4]) + if err != nil { + return nil, fmt.Errorf("%s: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err) + } + + dcrypt, err := strconv.Atoi(stats[5]) + if err != nil { + return nil, fmt.Errorf("%s: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err) + } + + dfrag, err := strconv.Atoi(stats[6]) + if err != nil { + return nil, fmt.Errorf("%s: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err) + } + + dretry, err := strconv.Atoi(stats[7]) + if err != nil { + return nil, fmt.Errorf("%s: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err) + } + + dmisc, err := strconv.Atoi(stats[8]) + if err != nil { + return nil, fmt.Errorf("%s: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err) + } + + mbeacon, err := strconv.Atoi(stats[9]) + if err != nil { + return nil, fmt.Errorf("%s: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err) + } + + w := &Wireless{ + Name: name, + Status: status, + QualityLink: qlink, + QualityLevel: qlevel, + QualityNoise: qnoise, + DiscardedNwid: dnwid, + DiscardedCrypt: dcrypt, + DiscardedFrag: dfrag, + DiscardedRetry: dretry, + DiscardedMisc: dmisc, + MissedBeacon: mbeacon, + } + + interfaces = append(interfaces, w) + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("%s: Failed to scan /proc/net/wireless: %w", ErrFileRead, err) + } + + return interfaces, nil +} diff --git a/vendor/github.com/prometheus/procfs/xfrm.go b/vendor/github.com/prometheus/procfs/net_xfrm.go similarity index 94% rename from vendor/github.com/prometheus/procfs/xfrm.go rename to vendor/github.com/prometheus/procfs/net_xfrm.go index eed07c7d7..932ef2046 100644 --- a/vendor/github.com/prometheus/procfs/xfrm.go +++ b/vendor/github.com/prometheus/procfs/net_xfrm.go @@ -79,10 +79,13 @@ type XfrmStat struct { // Policy is dead XfrmOutPolDead int // Policy Error - XfrmOutPolError int - XfrmFwdHdrError int + XfrmOutPolError int + // Forward routing of a packet is not allowed + XfrmFwdHdrError int + // State is invalid, perhaps expired XfrmOutStateInvalid int - XfrmAcquireError int + // State hasn’t been fully acquired before use + XfrmAcquireError int } // NewXfrmStat reads the xfrm_stat statistics. @@ -112,7 +115,7 @@ func (fs FS) NewXfrmStat() (XfrmStat, error) { fields := strings.Fields(s.Text()) if len(fields) != 2 { - return XfrmStat{}, fmt.Errorf("couldn't parse %q line %q", file.Name(), s.Text()) + return XfrmStat{}, fmt.Errorf("%w: %q line %q", ErrFileParse, file.Name(), s.Text()) } name := fields[0] diff --git a/vendor/github.com/prometheus/procfs/netstat.go b/vendor/github.com/prometheus/procfs/netstat.go new file mode 100644 index 000000000..742dff453 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/netstat.go @@ -0,0 +1,82 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "os" + "path/filepath" + "strconv" + "strings" +) + +// NetStat contains statistics for all the counters from one file. +type NetStat struct { + Stats map[string][]uint64 + Filename string +} + +// NetStat retrieves stats from `/proc/net/stat/`. +func (fs FS) NetStat() ([]NetStat, error) { + statFiles, err := filepath.Glob(fs.proc.Path("net/stat/*")) + if err != nil { + return nil, err + } + + var netStatsTotal []NetStat + + for _, filePath := range statFiles { + procNetstat, err := parseNetstat(filePath) + if err != nil { + return nil, err + } + procNetstat.Filename = filepath.Base(filePath) + + netStatsTotal = append(netStatsTotal, procNetstat) + } + return netStatsTotal, nil +} + +// parseNetstat parses the metrics from `/proc/net/stat/` file +// and returns a NetStat structure. +func parseNetstat(filePath string) (NetStat, error) { + netStat := NetStat{ + Stats: make(map[string][]uint64), + } + file, err := os.Open(filePath) + if err != nil { + return netStat, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + scanner.Scan() + + // First string is always a header for stats + var headers []string + headers = append(headers, strings.Fields(scanner.Text())...) + + // Other strings represent per-CPU counters + for scanner.Scan() { + for num, counter := range strings.Fields(scanner.Text()) { + value, err := strconv.ParseUint(counter, 16, 64) + if err != nil { + return NetStat{}, err + } + netStat.Stats[headers[num]] = append(netStat.Stats[headers[num]], value) + } + } + + return netStat, nil +} diff --git a/vendor/github.com/prometheus/procfs/proc.go b/vendor/github.com/prometheus/procfs/proc.go index 28f696803..d1f71caa5 100644 --- a/vendor/github.com/prometheus/procfs/proc.go +++ b/vendor/github.com/prometheus/procfs/proc.go @@ -15,13 +15,13 @@ package procfs import ( "bytes" + "errors" "fmt" - "io/ioutil" + "io" "os" "strconv" "strings" - "github.com/prometheus/procfs/internal/fs" "github.com/prometheus/procfs/internal/util" ) @@ -30,12 +30,18 @@ type Proc struct { // The process ID. PID int - fs fs.FS + fs FS } // Procs represents a list of Proc structs. type Procs []Proc +var ( + ErrFileParse = errors.New("Error Parsing File") + ErrFileRead = errors.New("Error Reading File") + ErrMountPoint = errors.New("Error Accessing Mount point") +) + func (p Procs) Len() int { return len(p) } func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } @@ -43,7 +49,7 @@ func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } // Self returns a process for the current process read via /proc/self. func Self() (Proc, error) { fs, err := NewFS(DefaultMountPoint) - if err != nil { + if err != nil || errors.Unwrap(err) == ErrMountPoint { return Proc{}, err } return fs.Self() @@ -82,7 +88,7 @@ func (fs FS) Self() (Proc, error) { // NewProc returns a process for the given pid. // -// Deprecated: use fs.Proc() instead +// Deprecated: Use fs.Proc() instead. func (fs FS) NewProc(pid int) (Proc, error) { return fs.Proc(pid) } @@ -92,7 +98,7 @@ func (fs FS) Proc(pid int) (Proc, error) { if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil { return Proc{}, err } - return Proc{PID: pid, fs: fs.proc}, nil + return Proc{PID: pid, fs: fs}, nil } // AllProcs returns a list of all currently available processes. @@ -105,7 +111,7 @@ func (fs FS) AllProcs() (Procs, error) { names, err := d.Readdirnames(-1) if err != nil { - return Procs{}, fmt.Errorf("could not read %q: %w", d.Name(), err) + return Procs{}, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, names, err) } p := Procs{} @@ -114,7 +120,7 @@ func (fs FS) AllProcs() (Procs, error) { if err != nil { continue } - p = append(p, Proc{PID: int(pid), fs: fs.proc}) + p = append(p, Proc{PID: int(pid), fs: fs}) } return p, nil @@ -142,7 +148,7 @@ func (p Proc) Wchan() (string, error) { } defer f.Close() - data, err := ioutil.ReadAll(f) + data, err := io.ReadAll(f) if err != nil { return "", err } @@ -185,7 +191,7 @@ func (p Proc) Cwd() (string, error) { return wd, err } -// RootDir returns the absolute path to the process's root directory (as set by chroot) +// RootDir returns the absolute path to the process's root directory (as set by chroot). func (p Proc) RootDir() (string, error) { rdir, err := os.Readlink(p.path("root")) if os.IsNotExist(err) { @@ -206,7 +212,7 @@ func (p Proc) FileDescriptors() ([]uintptr, error) { for i, n := range names { fd, err := strconv.ParseInt(n, 10, 32) if err != nil { - return nil, fmt.Errorf("could not parse fd %q: %w", n, err) + return nil, fmt.Errorf("%s: Cannot parse line: %v: %w", ErrFileParse, i, err) } fds[i] = uintptr(fd) } @@ -237,6 +243,19 @@ func (p Proc) FileDescriptorTargets() ([]string, error) { // FileDescriptorsLen returns the number of currently open file descriptors of // a process. func (p Proc) FileDescriptorsLen() (int, error) { + // Use fast path if available (Linux v6.2): https://github.com/torvalds/linux/commit/f1f1f2569901 + if p.fs.isReal { + stat, err := os.Stat(p.path("fd")) + if err != nil { + return 0, err + } + + size := stat.Size() + if size > 0 { + return int(size), nil + } + } + fds, err := p.fileDescriptors() if err != nil { return 0, err @@ -278,14 +297,14 @@ func (p Proc) fileDescriptors() ([]string, error) { names, err := d.Readdirnames(-1) if err != nil { - return nil, fmt.Errorf("could not read %q: %w", d.Name(), err) + return nil, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, names, err) } return names, nil } func (p Proc) path(pa ...string) string { - return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...) + return p.fs.proc.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...) } // FileDescriptorsInfo retrieves information about all file descriptors of @@ -311,7 +330,7 @@ func (p Proc) FileDescriptorsInfo() (ProcFDInfos, error) { // Schedstat returns task scheduling information for the process. func (p Proc) Schedstat() (ProcSchedstat, error) { - contents, err := ioutil.ReadFile(p.path("schedstat")) + contents, err := os.ReadFile(p.path("schedstat")) if err != nil { return ProcSchedstat{}, err } diff --git a/vendor/github.com/prometheus/procfs/proc_cgroup.go b/vendor/github.com/prometheus/procfs/proc_cgroup.go index 0094a13c0..daeed7f57 100644 --- a/vendor/github.com/prometheus/procfs/proc_cgroup.go +++ b/vendor/github.com/prometheus/procfs/proc_cgroup.go @@ -23,7 +23,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the the placement of a PID inside a +// Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a // specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in @@ -45,13 +45,13 @@ type Cgroup struct { } // parseCgroupString parses each line of the /proc/[pid]/cgroup file -// Line format is hierarchyID:[controller1,controller2]:path +// Line format is hierarchyID:[controller1,controller2]:path. func parseCgroupString(cgroupStr string) (*Cgroup, error) { var err error fields := strings.SplitN(cgroupStr, ":", 3) if len(fields) < 3 { - return nil, fmt.Errorf("at least 3 fields required, found %d fields in cgroup string: %s", len(fields), cgroupStr) + return nil, fmt.Errorf("%w: 3+ fields required, found %d fields in cgroup string: %s", ErrFileParse, len(fields), cgroupStr) } cgroup := &Cgroup{ @@ -60,7 +60,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) { } cgroup.HierarchyID, err = strconv.Atoi(fields[0]) if err != nil { - return nil, fmt.Errorf("failed to parse hierarchy ID") + return nil, fmt.Errorf("%w: hierarchy ID: %q", ErrFileParse, cgroup.HierarchyID) } if fields[1] != "" { ssNames := strings.Split(fields[1], ",") @@ -69,7 +69,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) { return cgroup, nil } -// parseCgroups reads each line of the /proc/[pid]/cgroup file +// parseCgroups reads each line of the /proc/[pid]/cgroup file. func parseCgroups(data []byte) ([]Cgroup, error) { var cgroups []Cgroup scanner := bufio.NewScanner(bytes.NewReader(data)) @@ -88,9 +88,9 @@ func parseCgroups(data []byte) ([]Cgroup, error) { // Cgroups reads from /proc//cgroups and returns a []*Cgroup struct locating this PID in each process // control hierarchy running on this system. On every system (v1 and v2), all hierarchies contain all processes, -// so the len of the returned struct is equal to the number of active hierarchies on this system +// so the len of the returned struct is equal to the number of active hierarchies on this system. func (p Proc) Cgroups() ([]Cgroup, error) { - data, err := util.ReadFileNoStat(fmt.Sprintf("/proc/%d/cgroup", p.PID)) + data, err := util.ReadFileNoStat(p.path("cgroup")) if err != nil { return nil, err } diff --git a/vendor/github.com/prometheus/procfs/proc_cgroups.go b/vendor/github.com/prometheus/procfs/proc_cgroups.go new file mode 100644 index 000000000..5dd493899 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_cgroups.go @@ -0,0 +1,98 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// CgroupSummary models one line from /proc/cgroups. +// This file contains information about the controllers that are compiled into the kernel. +// +// Also see http://man7.org/linux/man-pages/man7/cgroups.7.html +type CgroupSummary struct { + // The name of the controller. controller is also known as subsystem. + SubsysName string + // The unique ID of the cgroup hierarchy on which this controller is mounted. + Hierarchy int + // The number of control groups in this hierarchy using this controller. + Cgroups int + // This field contains the value 1 if this controller is enabled, or 0 if it has been disabled + Enabled int +} + +// parseCgroupSummary parses each line of the /proc/cgroup file +// Line format is `subsys_name hierarchy num_cgroups enabled`. +func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) { + var err error + + fields := strings.Fields(CgroupSummaryStr) + // require at least 4 fields + if len(fields) < 4 { + return nil, fmt.Errorf("%w: 4+ fields required, found %d fields in cgroup info string: %s", ErrFileParse, len(fields), CgroupSummaryStr) + } + + CgroupSummary := &CgroupSummary{ + SubsysName: fields[0], + } + CgroupSummary.Hierarchy, err = strconv.Atoi(fields[1]) + if err != nil { + return nil, fmt.Errorf("%w: Unable to parse hierarchy ID from %q", ErrFileParse, fields[1]) + } + CgroupSummary.Cgroups, err = strconv.Atoi(fields[2]) + if err != nil { + return nil, fmt.Errorf("%w: Unable to parse Cgroup Num from %q", ErrFileParse, fields[2]) + } + CgroupSummary.Enabled, err = strconv.Atoi(fields[3]) + if err != nil { + return nil, fmt.Errorf("%w: Unable to parse Enabled from %q", ErrFileParse, fields[3]) + } + return CgroupSummary, nil +} + +// parseCgroupSummary reads each line of the /proc/cgroup file. +func parseCgroupSummary(data []byte) ([]CgroupSummary, error) { + var CgroupSummarys []CgroupSummary + scanner := bufio.NewScanner(bytes.NewReader(data)) + for scanner.Scan() { + CgroupSummaryString := scanner.Text() + // ignore comment lines + if strings.HasPrefix(CgroupSummaryString, "#") { + continue + } + CgroupSummary, err := parseCgroupSummaryString(CgroupSummaryString) + if err != nil { + return nil, err + } + CgroupSummarys = append(CgroupSummarys, *CgroupSummary) + } + + err := scanner.Err() + return CgroupSummarys, err +} + +// CgroupSummarys returns information about current /proc/cgroups. +func (fs FS) CgroupSummarys() ([]CgroupSummary, error) { + data, err := util.ReadFileNoStat(fs.proc.Path("cgroups")) + if err != nil { + return nil, err + } + return parseCgroupSummary(data) +} diff --git a/vendor/github.com/prometheus/procfs/proc_environ.go b/vendor/github.com/prometheus/procfs/proc_environ.go index 6134b3580..57a89895d 100644 --- a/vendor/github.com/prometheus/procfs/proc_environ.go +++ b/vendor/github.com/prometheus/procfs/proc_environ.go @@ -19,7 +19,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// Environ reads process environments from /proc//environ +// Environ reads process environments from `/proc//environ`. func (p Proc) Environ() ([]string, error) { environments := make([]string, 0) diff --git a/vendor/github.com/prometheus/procfs/proc_fdinfo.go b/vendor/github.com/prometheus/procfs/proc_fdinfo.go index cf63227f0..fa761b352 100644 --- a/vendor/github.com/prometheus/procfs/proc_fdinfo.go +++ b/vendor/github.com/prometheus/procfs/proc_fdinfo.go @@ -22,11 +22,11 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// Regexp variables var ( rPos = regexp.MustCompile(`^pos:\s+(\d+)$`) rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`) rMntID = regexp.MustCompile(`^mnt_id:\s+(\d+)$`) + rIno = regexp.MustCompile(`^ino:\s+(\d+)$`) rInotify = regexp.MustCompile(`^inotify`) rInotifyParts = regexp.MustCompile(`^inotify\s+wd:([0-9a-f]+)\s+ino:([0-9a-f]+)\s+sdev:([0-9a-f]+)(?:\s+mask:([0-9a-f]+))?`) ) @@ -41,6 +41,8 @@ type ProcFDInfo struct { Flags string // Mount point ID MntID string + // Inode number + Ino string // List of inotify lines (structured) in the fdinfo file (kernel 3.8+ only) InotifyInfos []InotifyInfo } @@ -52,7 +54,7 @@ func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) { return nil, err } - var text, pos, flags, mntid string + var text, pos, flags, mntid, ino string var inotify []InotifyInfo scanner := bufio.NewScanner(bytes.NewReader(data)) @@ -64,6 +66,8 @@ func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) { flags = rFlags.FindStringSubmatch(text)[1] } else if rMntID.MatchString(text) { mntid = rMntID.FindStringSubmatch(text)[1] + } else if rIno.MatchString(text) { + ino = rIno.FindStringSubmatch(text)[1] } else if rInotify.MatchString(text) { newInotify, err := parseInotifyInfo(text) if err != nil { @@ -78,6 +82,7 @@ func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) { Pos: pos, Flags: flags, MntID: mntid, + Ino: ino, InotifyInfos: inotify, } @@ -112,7 +117,7 @@ func parseInotifyInfo(line string) (*InotifyInfo, error) { } return i, nil } - return nil, fmt.Errorf("invalid inode entry: %q", line) + return nil, fmt.Errorf("%w: invalid inode entry: %q", ErrFileParse, line) } // ProcFDInfos represents a list of ProcFDInfo structs. @@ -122,7 +127,7 @@ func (p ProcFDInfos) Len() int { return len(p) } func (p ProcFDInfos) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p ProcFDInfos) Less(i, j int) bool { return p[i].FD < p[j].FD } -// InotifyWatchLen returns the total number of inotify watches +// InotifyWatchLen returns the total number of inotify watches. func (p ProcFDInfos) InotifyWatchLen() (int, error) { length := 0 for _, f := range p { diff --git a/vendor/github.com/prometheus/procfs/proc_interrupts.go b/vendor/github.com/prometheus/procfs/proc_interrupts.go new file mode 100644 index 000000000..86b4b4524 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_interrupts.go @@ -0,0 +1,98 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// Interrupt represents a single interrupt line. +type Interrupt struct { + // Info is the type of interrupt. + Info string + // Devices is the name of the device that is located at that IRQ + Devices string + // Values is the number of interrupts per CPU. + Values []string +} + +// Interrupts models the content of /proc/interrupts. Key is the IRQ number. +// - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-interrupts +// - https://raspberrypi.stackexchange.com/questions/105802/explanation-of-proc-interrupts-output +type Interrupts map[string]Interrupt + +// Interrupts creates a new instance from a given Proc instance. +func (p Proc) Interrupts() (Interrupts, error) { + data, err := util.ReadFileNoStat(p.path("interrupts")) + if err != nil { + return nil, err + } + return parseInterrupts(bytes.NewReader(data)) +} + +func parseInterrupts(r io.Reader) (Interrupts, error) { + var ( + interrupts = Interrupts{} + scanner = bufio.NewScanner(r) + ) + + if !scanner.Scan() { + return nil, errors.New("interrupts empty") + } + cpuNum := len(strings.Fields(scanner.Text())) // one header per cpu + + for scanner.Scan() { + parts := strings.Fields(scanner.Text()) + if len(parts) == 0 { // skip empty lines + continue + } + if len(parts) < 2 { + return nil, fmt.Errorf("%w: Not enough fields in interrupts (expected 2+ fields but got %d): %s", ErrFileParse, len(parts), parts) + } + intName := parts[0][:len(parts[0])-1] // remove trailing : + + if len(parts) == 2 { + interrupts[intName] = Interrupt{ + Info: "", + Devices: "", + Values: []string{ + parts[1], + }, + } + continue + } + + intr := Interrupt{ + Values: parts[1 : cpuNum+1], + } + + if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt + intr.Info = parts[cpuNum+1] + intr.Devices = strings.Join(parts[cpuNum+2:], " ") + } else { + intr.Info = strings.Join(parts[cpuNum+1:], " ") + } + interrupts[intName] = intr + } + + return interrupts, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_limits.go b/vendor/github.com/prometheus/procfs/proc_limits.go index dd20f198a..c86d815d7 100644 --- a/vendor/github.com/prometheus/procfs/proc_limits.go +++ b/vendor/github.com/prometheus/procfs/proc_limits.go @@ -79,7 +79,7 @@ var ( // NewLimits returns the current soft limits of the process. // -// Deprecated: use p.Limits() instead +// Deprecated: Use p.Limits() instead. func (p Proc) NewLimits() (ProcLimits, error) { return p.Limits() } @@ -103,7 +103,7 @@ func (p Proc) Limits() (ProcLimits, error) { //fields := limitsMatch.Split(s.Text(), limitsFields) fields := limitsMatch.FindStringSubmatch(s.Text()) if len(fields) != limitsFields { - return ProcLimits{}, fmt.Errorf("couldn't parse %q line %q", f.Name(), s.Text()) + return ProcLimits{}, fmt.Errorf("%w: couldn't parse %q line %q", ErrFileParse, f.Name(), s.Text()) } switch fields[1] { @@ -154,7 +154,7 @@ func parseUint(s string) (uint64, error) { } i, err := strconv.ParseUint(s, 10, 64) if err != nil { - return 0, fmt.Errorf("couldn't parse value %q: %w", s, err) + return 0, fmt.Errorf("%s: couldn't parse value %q: %w", ErrFileParse, s, err) } return i, nil } diff --git a/vendor/github.com/prometheus/procfs/proc_maps.go b/vendor/github.com/prometheus/procfs/proc_maps.go index 1d7772d51..7e75c286b 100644 --- a/vendor/github.com/prometheus/procfs/proc_maps.go +++ b/vendor/github.com/prometheus/procfs/proc_maps.go @@ -11,7 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && !js // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build !js package procfs @@ -25,7 +27,7 @@ import ( "golang.org/x/sys/unix" ) -// ProcMapPermissions contains permission settings read from /proc/[pid]/maps +// ProcMapPermissions contains permission settings read from `/proc/[pid]/maps`. type ProcMapPermissions struct { // mapping has the [R]ead flag set Read bool @@ -39,8 +41,8 @@ type ProcMapPermissions struct { Private bool } -// ProcMap contains the process memory-mappings of the process, -// read from /proc/[pid]/maps +// ProcMap contains the process memory-mappings of the process +// read from `/proc/[pid]/maps`. type ProcMap struct { // The start address of current mapping. StartAddr uintptr @@ -61,17 +63,17 @@ type ProcMap struct { // parseDevice parses the device token of a line and converts it to a dev_t // (mkdev) like structure. func parseDevice(s string) (uint64, error) { - toks := strings.Split(s, ":") - if len(toks) < 2 { - return 0, fmt.Errorf("unexpected number of fields") + i := strings.Index(s, ":") + if i == -1 { + return 0, fmt.Errorf("%w: expected separator `:` in %s", ErrFileParse, s) } - major, err := strconv.ParseUint(toks[0], 16, 0) + major, err := strconv.ParseUint(s[0:i], 16, 0) if err != nil { return 0, err } - minor, err := strconv.ParseUint(toks[1], 16, 0) + minor, err := strconv.ParseUint(s[i+1:], 16, 0) if err != nil { return 0, err } @@ -79,7 +81,7 @@ func parseDevice(s string) (uint64, error) { return unix.Mkdev(uint32(major), uint32(minor)), nil } -// parseAddress just converts a hex-string to a uintptr +// parseAddress converts a hex-string to a uintptr. func parseAddress(s string) (uintptr, error) { a, err := strconv.ParseUint(s, 16, 0) if err != nil { @@ -89,19 +91,19 @@ func parseAddress(s string) (uintptr, error) { return uintptr(a), nil } -// parseAddresses parses the start-end address +// parseAddresses parses the start-end address. func parseAddresses(s string) (uintptr, uintptr, error) { - toks := strings.Split(s, "-") - if len(toks) < 2 { - return 0, 0, fmt.Errorf("invalid address") + idx := strings.Index(s, "-") + if idx == -1 { + return 0, 0, fmt.Errorf("%w: expected separator `-` in %s", ErrFileParse, s) } - saddr, err := parseAddress(toks[0]) + saddr, err := parseAddress(s[0:idx]) if err != nil { return 0, 0, err } - eaddr, err := parseAddress(toks[1]) + eaddr, err := parseAddress(s[idx+1:]) if err != nil { return 0, 0, err } @@ -112,7 +114,7 @@ func parseAddresses(s string) (uintptr, uintptr, error) { // parsePermissions parses a token and returns any that are set. func parsePermissions(s string) (*ProcMapPermissions, error) { if len(s) < 4 { - return nil, fmt.Errorf("invalid permissions token") + return nil, fmt.Errorf("%w: invalid permissions token", ErrFileParse) } perms := ProcMapPermissions{} @@ -139,7 +141,7 @@ func parsePermissions(s string) (*ProcMapPermissions, error) { func parseProcMap(text string) (*ProcMap, error) { fields := strings.Fields(text) if len(fields) < 5 { - return nil, fmt.Errorf("truncated procmap entry") + return nil, fmt.Errorf("%w: truncated procmap entry", ErrFileParse) } saddr, eaddr, err := parseAddresses(fields[0]) diff --git a/vendor/github.com/prometheus/procfs/proc_netstat.go b/vendor/github.com/prometheus/procfs/proc_netstat.go new file mode 100644 index 000000000..8e3ff4d79 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_netstat.go @@ -0,0 +1,443 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ProcNetstat models the content of /proc//net/netstat. +type ProcNetstat struct { + // The process ID. + PID int + TcpExt + IpExt +} + +type TcpExt struct { // nolint:revive + SyncookiesSent *float64 + SyncookiesRecv *float64 + SyncookiesFailed *float64 + EmbryonicRsts *float64 + PruneCalled *float64 + RcvPruned *float64 + OfoPruned *float64 + OutOfWindowIcmps *float64 + LockDroppedIcmps *float64 + ArpFilter *float64 + TW *float64 + TWRecycled *float64 + TWKilled *float64 + PAWSActive *float64 + PAWSEstab *float64 + DelayedACKs *float64 + DelayedACKLocked *float64 + DelayedACKLost *float64 + ListenOverflows *float64 + ListenDrops *float64 + TCPHPHits *float64 + TCPPureAcks *float64 + TCPHPAcks *float64 + TCPRenoRecovery *float64 + TCPSackRecovery *float64 + TCPSACKReneging *float64 + TCPSACKReorder *float64 + TCPRenoReorder *float64 + TCPTSReorder *float64 + TCPFullUndo *float64 + TCPPartialUndo *float64 + TCPDSACKUndo *float64 + TCPLossUndo *float64 + TCPLostRetransmit *float64 + TCPRenoFailures *float64 + TCPSackFailures *float64 + TCPLossFailures *float64 + TCPFastRetrans *float64 + TCPSlowStartRetrans *float64 + TCPTimeouts *float64 + TCPLossProbes *float64 + TCPLossProbeRecovery *float64 + TCPRenoRecoveryFail *float64 + TCPSackRecoveryFail *float64 + TCPRcvCollapsed *float64 + TCPDSACKOldSent *float64 + TCPDSACKOfoSent *float64 + TCPDSACKRecv *float64 + TCPDSACKOfoRecv *float64 + TCPAbortOnData *float64 + TCPAbortOnClose *float64 + TCPAbortOnMemory *float64 + TCPAbortOnTimeout *float64 + TCPAbortOnLinger *float64 + TCPAbortFailed *float64 + TCPMemoryPressures *float64 + TCPMemoryPressuresChrono *float64 + TCPSACKDiscard *float64 + TCPDSACKIgnoredOld *float64 + TCPDSACKIgnoredNoUndo *float64 + TCPSpuriousRTOs *float64 + TCPMD5NotFound *float64 + TCPMD5Unexpected *float64 + TCPMD5Failure *float64 + TCPSackShifted *float64 + TCPSackMerged *float64 + TCPSackShiftFallback *float64 + TCPBacklogDrop *float64 + PFMemallocDrop *float64 + TCPMinTTLDrop *float64 + TCPDeferAcceptDrop *float64 + IPReversePathFilter *float64 + TCPTimeWaitOverflow *float64 + TCPReqQFullDoCookies *float64 + TCPReqQFullDrop *float64 + TCPRetransFail *float64 + TCPRcvCoalesce *float64 + TCPRcvQDrop *float64 + TCPOFOQueue *float64 + TCPOFODrop *float64 + TCPOFOMerge *float64 + TCPChallengeACK *float64 + TCPSYNChallenge *float64 + TCPFastOpenActive *float64 + TCPFastOpenActiveFail *float64 + TCPFastOpenPassive *float64 + TCPFastOpenPassiveFail *float64 + TCPFastOpenListenOverflow *float64 + TCPFastOpenCookieReqd *float64 + TCPFastOpenBlackhole *float64 + TCPSpuriousRtxHostQueues *float64 + BusyPollRxPackets *float64 + TCPAutoCorking *float64 + TCPFromZeroWindowAdv *float64 + TCPToZeroWindowAdv *float64 + TCPWantZeroWindowAdv *float64 + TCPSynRetrans *float64 + TCPOrigDataSent *float64 + TCPHystartTrainDetect *float64 + TCPHystartTrainCwnd *float64 + TCPHystartDelayDetect *float64 + TCPHystartDelayCwnd *float64 + TCPACKSkippedSynRecv *float64 + TCPACKSkippedPAWS *float64 + TCPACKSkippedSeq *float64 + TCPACKSkippedFinWait2 *float64 + TCPACKSkippedTimeWait *float64 + TCPACKSkippedChallenge *float64 + TCPWinProbe *float64 + TCPKeepAlive *float64 + TCPMTUPFail *float64 + TCPMTUPSuccess *float64 + TCPWqueueTooBig *float64 +} + +type IpExt struct { // nolint:revive + InNoRoutes *float64 + InTruncatedPkts *float64 + InMcastPkts *float64 + OutMcastPkts *float64 + InBcastPkts *float64 + OutBcastPkts *float64 + InOctets *float64 + OutOctets *float64 + InMcastOctets *float64 + OutMcastOctets *float64 + InBcastOctets *float64 + OutBcastOctets *float64 + InCsumErrors *float64 + InNoECTPkts *float64 + InECT1Pkts *float64 + InECT0Pkts *float64 + InCEPkts *float64 + ReasmOverlaps *float64 +} + +func (p Proc) Netstat() (ProcNetstat, error) { + filename := p.path("net/netstat") + data, err := util.ReadFileNoStat(filename) + if err != nil { + return ProcNetstat{PID: p.PID}, err + } + procNetstat, err := parseProcNetstat(bytes.NewReader(data), filename) + procNetstat.PID = p.PID + return procNetstat, err +} + +// parseProcNetstat parses the metrics from proc//net/netstat file +// and returns a ProcNetstat structure. +func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) { + var ( + scanner = bufio.NewScanner(r) + procNetstat = ProcNetstat{} + ) + + for scanner.Scan() { + nameParts := strings.Split(scanner.Text(), " ") + scanner.Scan() + valueParts := strings.Split(scanner.Text(), " ") + // Remove trailing :. + protocol := strings.TrimSuffix(nameParts[0], ":") + if len(nameParts) != len(valueParts) { + return procNetstat, fmt.Errorf("%w: mismatch field count mismatch in %s: %s", + ErrFileParse, fileName, protocol) + } + for i := 1; i < len(nameParts); i++ { + value, err := strconv.ParseFloat(valueParts[i], 64) + if err != nil { + return procNetstat, err + } + key := nameParts[i] + + switch protocol { + case "TcpExt": + switch key { + case "SyncookiesSent": + procNetstat.TcpExt.SyncookiesSent = &value + case "SyncookiesRecv": + procNetstat.TcpExt.SyncookiesRecv = &value + case "SyncookiesFailed": + procNetstat.TcpExt.SyncookiesFailed = &value + case "EmbryonicRsts": + procNetstat.TcpExt.EmbryonicRsts = &value + case "PruneCalled": + procNetstat.TcpExt.PruneCalled = &value + case "RcvPruned": + procNetstat.TcpExt.RcvPruned = &value + case "OfoPruned": + procNetstat.TcpExt.OfoPruned = &value + case "OutOfWindowIcmps": + procNetstat.TcpExt.OutOfWindowIcmps = &value + case "LockDroppedIcmps": + procNetstat.TcpExt.LockDroppedIcmps = &value + case "ArpFilter": + procNetstat.TcpExt.ArpFilter = &value + case "TW": + procNetstat.TcpExt.TW = &value + case "TWRecycled": + procNetstat.TcpExt.TWRecycled = &value + case "TWKilled": + procNetstat.TcpExt.TWKilled = &value + case "PAWSActive": + procNetstat.TcpExt.PAWSActive = &value + case "PAWSEstab": + procNetstat.TcpExt.PAWSEstab = &value + case "DelayedACKs": + procNetstat.TcpExt.DelayedACKs = &value + case "DelayedACKLocked": + procNetstat.TcpExt.DelayedACKLocked = &value + case "DelayedACKLost": + procNetstat.TcpExt.DelayedACKLost = &value + case "ListenOverflows": + procNetstat.TcpExt.ListenOverflows = &value + case "ListenDrops": + procNetstat.TcpExt.ListenDrops = &value + case "TCPHPHits": + procNetstat.TcpExt.TCPHPHits = &value + case "TCPPureAcks": + procNetstat.TcpExt.TCPPureAcks = &value + case "TCPHPAcks": + procNetstat.TcpExt.TCPHPAcks = &value + case "TCPRenoRecovery": + procNetstat.TcpExt.TCPRenoRecovery = &value + case "TCPSackRecovery": + procNetstat.TcpExt.TCPSackRecovery = &value + case "TCPSACKReneging": + procNetstat.TcpExt.TCPSACKReneging = &value + case "TCPSACKReorder": + procNetstat.TcpExt.TCPSACKReorder = &value + case "TCPRenoReorder": + procNetstat.TcpExt.TCPRenoReorder = &value + case "TCPTSReorder": + procNetstat.TcpExt.TCPTSReorder = &value + case "TCPFullUndo": + procNetstat.TcpExt.TCPFullUndo = &value + case "TCPPartialUndo": + procNetstat.TcpExt.TCPPartialUndo = &value + case "TCPDSACKUndo": + procNetstat.TcpExt.TCPDSACKUndo = &value + case "TCPLossUndo": + procNetstat.TcpExt.TCPLossUndo = &value + case "TCPLostRetransmit": + procNetstat.TcpExt.TCPLostRetransmit = &value + case "TCPRenoFailures": + procNetstat.TcpExt.TCPRenoFailures = &value + case "TCPSackFailures": + procNetstat.TcpExt.TCPSackFailures = &value + case "TCPLossFailures": + procNetstat.TcpExt.TCPLossFailures = &value + case "TCPFastRetrans": + procNetstat.TcpExt.TCPFastRetrans = &value + case "TCPSlowStartRetrans": + procNetstat.TcpExt.TCPSlowStartRetrans = &value + case "TCPTimeouts": + procNetstat.TcpExt.TCPTimeouts = &value + case "TCPLossProbes": + procNetstat.TcpExt.TCPLossProbes = &value + case "TCPLossProbeRecovery": + procNetstat.TcpExt.TCPLossProbeRecovery = &value + case "TCPRenoRecoveryFail": + procNetstat.TcpExt.TCPRenoRecoveryFail = &value + case "TCPSackRecoveryFail": + procNetstat.TcpExt.TCPSackRecoveryFail = &value + case "TCPRcvCollapsed": + procNetstat.TcpExt.TCPRcvCollapsed = &value + case "TCPDSACKOldSent": + procNetstat.TcpExt.TCPDSACKOldSent = &value + case "TCPDSACKOfoSent": + procNetstat.TcpExt.TCPDSACKOfoSent = &value + case "TCPDSACKRecv": + procNetstat.TcpExt.TCPDSACKRecv = &value + case "TCPDSACKOfoRecv": + procNetstat.TcpExt.TCPDSACKOfoRecv = &value + case "TCPAbortOnData": + procNetstat.TcpExt.TCPAbortOnData = &value + case "TCPAbortOnClose": + procNetstat.TcpExt.TCPAbortOnClose = &value + case "TCPDeferAcceptDrop": + procNetstat.TcpExt.TCPDeferAcceptDrop = &value + case "IPReversePathFilter": + procNetstat.TcpExt.IPReversePathFilter = &value + case "TCPTimeWaitOverflow": + procNetstat.TcpExt.TCPTimeWaitOverflow = &value + case "TCPReqQFullDoCookies": + procNetstat.TcpExt.TCPReqQFullDoCookies = &value + case "TCPReqQFullDrop": + procNetstat.TcpExt.TCPReqQFullDrop = &value + case "TCPRetransFail": + procNetstat.TcpExt.TCPRetransFail = &value + case "TCPRcvCoalesce": + procNetstat.TcpExt.TCPRcvCoalesce = &value + case "TCPRcvQDrop": + procNetstat.TcpExt.TCPRcvQDrop = &value + case "TCPOFOQueue": + procNetstat.TcpExt.TCPOFOQueue = &value + case "TCPOFODrop": + procNetstat.TcpExt.TCPOFODrop = &value + case "TCPOFOMerge": + procNetstat.TcpExt.TCPOFOMerge = &value + case "TCPChallengeACK": + procNetstat.TcpExt.TCPChallengeACK = &value + case "TCPSYNChallenge": + procNetstat.TcpExt.TCPSYNChallenge = &value + case "TCPFastOpenActive": + procNetstat.TcpExt.TCPFastOpenActive = &value + case "TCPFastOpenActiveFail": + procNetstat.TcpExt.TCPFastOpenActiveFail = &value + case "TCPFastOpenPassive": + procNetstat.TcpExt.TCPFastOpenPassive = &value + case "TCPFastOpenPassiveFail": + procNetstat.TcpExt.TCPFastOpenPassiveFail = &value + case "TCPFastOpenListenOverflow": + procNetstat.TcpExt.TCPFastOpenListenOverflow = &value + case "TCPFastOpenCookieReqd": + procNetstat.TcpExt.TCPFastOpenCookieReqd = &value + case "TCPFastOpenBlackhole": + procNetstat.TcpExt.TCPFastOpenBlackhole = &value + case "TCPSpuriousRtxHostQueues": + procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value + case "BusyPollRxPackets": + procNetstat.TcpExt.BusyPollRxPackets = &value + case "TCPAutoCorking": + procNetstat.TcpExt.TCPAutoCorking = &value + case "TCPFromZeroWindowAdv": + procNetstat.TcpExt.TCPFromZeroWindowAdv = &value + case "TCPToZeroWindowAdv": + procNetstat.TcpExt.TCPToZeroWindowAdv = &value + case "TCPWantZeroWindowAdv": + procNetstat.TcpExt.TCPWantZeroWindowAdv = &value + case "TCPSynRetrans": + procNetstat.TcpExt.TCPSynRetrans = &value + case "TCPOrigDataSent": + procNetstat.TcpExt.TCPOrigDataSent = &value + case "TCPHystartTrainDetect": + procNetstat.TcpExt.TCPHystartTrainDetect = &value + case "TCPHystartTrainCwnd": + procNetstat.TcpExt.TCPHystartTrainCwnd = &value + case "TCPHystartDelayDetect": + procNetstat.TcpExt.TCPHystartDelayDetect = &value + case "TCPHystartDelayCwnd": + procNetstat.TcpExt.TCPHystartDelayCwnd = &value + case "TCPACKSkippedSynRecv": + procNetstat.TcpExt.TCPACKSkippedSynRecv = &value + case "TCPACKSkippedPAWS": + procNetstat.TcpExt.TCPACKSkippedPAWS = &value + case "TCPACKSkippedSeq": + procNetstat.TcpExt.TCPACKSkippedSeq = &value + case "TCPACKSkippedFinWait2": + procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value + case "TCPACKSkippedTimeWait": + procNetstat.TcpExt.TCPACKSkippedTimeWait = &value + case "TCPACKSkippedChallenge": + procNetstat.TcpExt.TCPACKSkippedChallenge = &value + case "TCPWinProbe": + procNetstat.TcpExt.TCPWinProbe = &value + case "TCPKeepAlive": + procNetstat.TcpExt.TCPKeepAlive = &value + case "TCPMTUPFail": + procNetstat.TcpExt.TCPMTUPFail = &value + case "TCPMTUPSuccess": + procNetstat.TcpExt.TCPMTUPSuccess = &value + case "TCPWqueueTooBig": + procNetstat.TcpExt.TCPWqueueTooBig = &value + } + case "IpExt": + switch key { + case "InNoRoutes": + procNetstat.IpExt.InNoRoutes = &value + case "InTruncatedPkts": + procNetstat.IpExt.InTruncatedPkts = &value + case "InMcastPkts": + procNetstat.IpExt.InMcastPkts = &value + case "OutMcastPkts": + procNetstat.IpExt.OutMcastPkts = &value + case "InBcastPkts": + procNetstat.IpExt.InBcastPkts = &value + case "OutBcastPkts": + procNetstat.IpExt.OutBcastPkts = &value + case "InOctets": + procNetstat.IpExt.InOctets = &value + case "OutOctets": + procNetstat.IpExt.OutOctets = &value + case "InMcastOctets": + procNetstat.IpExt.InMcastOctets = &value + case "OutMcastOctets": + procNetstat.IpExt.OutMcastOctets = &value + case "InBcastOctets": + procNetstat.IpExt.InBcastOctets = &value + case "OutBcastOctets": + procNetstat.IpExt.OutBcastOctets = &value + case "InCsumErrors": + procNetstat.IpExt.InCsumErrors = &value + case "InNoECTPkts": + procNetstat.IpExt.InNoECTPkts = &value + case "InECT1Pkts": + procNetstat.IpExt.InECT1Pkts = &value + case "InECT0Pkts": + procNetstat.IpExt.InECT0Pkts = &value + case "InCEPkts": + procNetstat.IpExt.InCEPkts = &value + case "ReasmOverlaps": + procNetstat.IpExt.ReasmOverlaps = &value + } + } + } + } + return procNetstat, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_ns.go b/vendor/github.com/prometheus/procfs/proc_ns.go index 391b4cbd1..c22666750 100644 --- a/vendor/github.com/prometheus/procfs/proc_ns.go +++ b/vendor/github.com/prometheus/procfs/proc_ns.go @@ -40,7 +40,7 @@ func (p Proc) Namespaces() (Namespaces, error) { names, err := d.Readdirnames(-1) if err != nil { - return nil, fmt.Errorf("failed to read contents of ns dir: %w", err) + return nil, fmt.Errorf("%s: failed to read contents of ns dir: %w", ErrFileRead, err) } ns := make(Namespaces, len(names)) @@ -52,13 +52,13 @@ func (p Proc) Namespaces() (Namespaces, error) { fields := strings.SplitN(target, ":", 2) if len(fields) != 2 { - return nil, fmt.Errorf("failed to parse namespace type and inode from %q", target) + return nil, fmt.Errorf("%w: namespace type and inode from %q", ErrFileParse, target) } typ := fields[0] inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) if err != nil { - return nil, fmt.Errorf("failed to parse inode from %q: %w", fields[1], err) + return nil, fmt.Errorf("%s: inode from %q: %w", ErrFileParse, fields[1], err) } ns[name] = Namespace{typ, uint32(inode)} diff --git a/vendor/github.com/prometheus/procfs/proc_psi.go b/vendor/github.com/prometheus/procfs/proc_psi.go index dc6c14f0a..fe9dbb425 100644 --- a/vendor/github.com/prometheus/procfs/proc_psi.go +++ b/vendor/github.com/prometheus/procfs/proc_psi.go @@ -35,9 +35,10 @@ import ( const lineFormat = "avg10=%f avg60=%f avg300=%f total=%d" -// PSILine is a single line of values as returned by /proc/pressure/* -// The Avg entries are averages over n seconds, as a percentage -// The Total line is in microseconds +// PSILine is a single line of values as returned by `/proc/pressure/*`. +// +// The Avg entries are averages over n seconds, as a percentage. +// The Total line is in microseconds. type PSILine struct { Avg10 float64 Avg60 float64 @@ -46,8 +47,9 @@ type PSILine struct { } // PSIStats represent pressure stall information from /proc/pressure/* -// Some indicates the share of time in which at least some tasks are stalled -// Full indicates the share of time in which all non-idle tasks are stalled simultaneously +// +// "Some" indicates the share of time in which at least some tasks are stalled. +// "Full" indicates the share of time in which all non-idle tasks are stalled simultaneously. type PSIStats struct { Some *PSILine Full *PSILine @@ -59,14 +61,14 @@ type PSIStats struct { func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) { data, err := util.ReadFileNoStat(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource))) if err != nil { - return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %q: %w", resource, err) + return PSIStats{}, fmt.Errorf("%s: psi_stats: unavailable for %q: %w", ErrFileRead, resource, err) } - return parsePSIStats(resource, bytes.NewReader(data)) + return parsePSIStats(bytes.NewReader(data)) } -// parsePSIStats parses the specified file for pressure stall information -func parsePSIStats(resource string, r io.Reader) (PSIStats, error) { +// parsePSIStats parses the specified file for pressure stall information. +func parsePSIStats(r io.Reader) (PSIStats, error) { psiStats := PSIStats{} scanner := bufio.NewScanner(r) diff --git a/vendor/github.com/prometheus/procfs/proc_smaps.go b/vendor/github.com/prometheus/procfs/proc_smaps.go index a576a720a..ad8785a40 100644 --- a/vendor/github.com/prometheus/procfs/proc_smaps.go +++ b/vendor/github.com/prometheus/procfs/proc_smaps.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs @@ -28,30 +29,30 @@ import ( ) var ( - // match the header line before each mapped zone in /proc/pid/smaps + // match the header line before each mapped zone in `/proc/pid/smaps`. procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`) ) type ProcSMapsRollup struct { - // Amount of the mapping that is currently resident in RAM + // Amount of the mapping that is currently resident in RAM. Rss uint64 - // Process's proportional share of this mapping + // Process's proportional share of this mapping. Pss uint64 - // Size in bytes of clean shared pages + // Size in bytes of clean shared pages. SharedClean uint64 - // Size in bytes of dirty shared pages + // Size in bytes of dirty shared pages. SharedDirty uint64 - // Size in bytes of clean private pages + // Size in bytes of clean private pages. PrivateClean uint64 - // Size in bytes of dirty private pages + // Size in bytes of dirty private pages. PrivateDirty uint64 - // Amount of memory currently marked as referenced or accessed + // Amount of memory currently marked as referenced or accessed. Referenced uint64 - // Amount of memory that does not belong to any file + // Amount of memory that does not belong to any file. Anonymous uint64 - // Amount would-be-anonymous memory currently on swap + // Amount would-be-anonymous memory currently on swap. Swap uint64 - // Process's proportional memory on swap + // Process's proportional memory on swap. SwapPss uint64 } @@ -134,12 +135,12 @@ func (s *ProcSMapsRollup) parseLine(line string) error { } vBytes := vKBytes * 1024 - s.addValue(k, v, vKBytes, vBytes) + s.addValue(k, vBytes) return nil } -func (s *ProcSMapsRollup) addValue(k string, vString string, vUint uint64, vUintBytes uint64) { +func (s *ProcSMapsRollup) addValue(k string, vUintBytes uint64) { switch k { case "Rss": s.Rss += vUintBytes diff --git a/vendor/github.com/prometheus/procfs/proc_snmp.go b/vendor/github.com/prometheus/procfs/proc_snmp.go new file mode 100644 index 000000000..b9d2cf642 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_snmp.go @@ -0,0 +1,353 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ProcSnmp models the content of /proc//net/snmp. +type ProcSnmp struct { + // The process ID. + PID int + Ip + Icmp + IcmpMsg + Tcp + Udp + UdpLite +} + +type Ip struct { // nolint:revive + Forwarding *float64 + DefaultTTL *float64 + InReceives *float64 + InHdrErrors *float64 + InAddrErrors *float64 + ForwDatagrams *float64 + InUnknownProtos *float64 + InDiscards *float64 + InDelivers *float64 + OutRequests *float64 + OutDiscards *float64 + OutNoRoutes *float64 + ReasmTimeout *float64 + ReasmReqds *float64 + ReasmOKs *float64 + ReasmFails *float64 + FragOKs *float64 + FragFails *float64 + FragCreates *float64 +} + +type Icmp struct { // nolint:revive + InMsgs *float64 + InErrors *float64 + InCsumErrors *float64 + InDestUnreachs *float64 + InTimeExcds *float64 + InParmProbs *float64 + InSrcQuenchs *float64 + InRedirects *float64 + InEchos *float64 + InEchoReps *float64 + InTimestamps *float64 + InTimestampReps *float64 + InAddrMasks *float64 + InAddrMaskReps *float64 + OutMsgs *float64 + OutErrors *float64 + OutDestUnreachs *float64 + OutTimeExcds *float64 + OutParmProbs *float64 + OutSrcQuenchs *float64 + OutRedirects *float64 + OutEchos *float64 + OutEchoReps *float64 + OutTimestamps *float64 + OutTimestampReps *float64 + OutAddrMasks *float64 + OutAddrMaskReps *float64 +} + +type IcmpMsg struct { + InType3 *float64 + OutType3 *float64 +} + +type Tcp struct { // nolint:revive + RtoAlgorithm *float64 + RtoMin *float64 + RtoMax *float64 + MaxConn *float64 + ActiveOpens *float64 + PassiveOpens *float64 + AttemptFails *float64 + EstabResets *float64 + CurrEstab *float64 + InSegs *float64 + OutSegs *float64 + RetransSegs *float64 + InErrs *float64 + OutRsts *float64 + InCsumErrors *float64 +} + +type Udp struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 + IgnoredMulti *float64 +} + +type UdpLite struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 + IgnoredMulti *float64 +} + +func (p Proc) Snmp() (ProcSnmp, error) { + filename := p.path("net/snmp") + data, err := util.ReadFileNoStat(filename) + if err != nil { + return ProcSnmp{PID: p.PID}, err + } + procSnmp, err := parseSnmp(bytes.NewReader(data), filename) + procSnmp.PID = p.PID + return procSnmp, err +} + +// parseSnmp parses the metrics from proc//net/snmp file +// and returns a map contains those metrics (e.g. {"Ip": {"Forwarding": 2}}). +func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) { + var ( + scanner = bufio.NewScanner(r) + procSnmp = ProcSnmp{} + ) + + for scanner.Scan() { + nameParts := strings.Split(scanner.Text(), " ") + scanner.Scan() + valueParts := strings.Split(scanner.Text(), " ") + // Remove trailing :. + protocol := strings.TrimSuffix(nameParts[0], ":") + if len(nameParts) != len(valueParts) { + return procSnmp, fmt.Errorf("%w: mismatch field count mismatch in %s: %s", + ErrFileParse, fileName, protocol) + } + for i := 1; i < len(nameParts); i++ { + value, err := strconv.ParseFloat(valueParts[i], 64) + if err != nil { + return procSnmp, err + } + key := nameParts[i] + + switch protocol { + case "Ip": + switch key { + case "Forwarding": + procSnmp.Ip.Forwarding = &value + case "DefaultTTL": + procSnmp.Ip.DefaultTTL = &value + case "InReceives": + procSnmp.Ip.InReceives = &value + case "InHdrErrors": + procSnmp.Ip.InHdrErrors = &value + case "InAddrErrors": + procSnmp.Ip.InAddrErrors = &value + case "ForwDatagrams": + procSnmp.Ip.ForwDatagrams = &value + case "InUnknownProtos": + procSnmp.Ip.InUnknownProtos = &value + case "InDiscards": + procSnmp.Ip.InDiscards = &value + case "InDelivers": + procSnmp.Ip.InDelivers = &value + case "OutRequests": + procSnmp.Ip.OutRequests = &value + case "OutDiscards": + procSnmp.Ip.OutDiscards = &value + case "OutNoRoutes": + procSnmp.Ip.OutNoRoutes = &value + case "ReasmTimeout": + procSnmp.Ip.ReasmTimeout = &value + case "ReasmReqds": + procSnmp.Ip.ReasmReqds = &value + case "ReasmOKs": + procSnmp.Ip.ReasmOKs = &value + case "ReasmFails": + procSnmp.Ip.ReasmFails = &value + case "FragOKs": + procSnmp.Ip.FragOKs = &value + case "FragFails": + procSnmp.Ip.FragFails = &value + case "FragCreates": + procSnmp.Ip.FragCreates = &value + } + case "Icmp": + switch key { + case "InMsgs": + procSnmp.Icmp.InMsgs = &value + case "InErrors": + procSnmp.Icmp.InErrors = &value + case "InCsumErrors": + procSnmp.Icmp.InCsumErrors = &value + case "InDestUnreachs": + procSnmp.Icmp.InDestUnreachs = &value + case "InTimeExcds": + procSnmp.Icmp.InTimeExcds = &value + case "InParmProbs": + procSnmp.Icmp.InParmProbs = &value + case "InSrcQuenchs": + procSnmp.Icmp.InSrcQuenchs = &value + case "InRedirects": + procSnmp.Icmp.InRedirects = &value + case "InEchos": + procSnmp.Icmp.InEchos = &value + case "InEchoReps": + procSnmp.Icmp.InEchoReps = &value + case "InTimestamps": + procSnmp.Icmp.InTimestamps = &value + case "InTimestampReps": + procSnmp.Icmp.InTimestampReps = &value + case "InAddrMasks": + procSnmp.Icmp.InAddrMasks = &value + case "InAddrMaskReps": + procSnmp.Icmp.InAddrMaskReps = &value + case "OutMsgs": + procSnmp.Icmp.OutMsgs = &value + case "OutErrors": + procSnmp.Icmp.OutErrors = &value + case "OutDestUnreachs": + procSnmp.Icmp.OutDestUnreachs = &value + case "OutTimeExcds": + procSnmp.Icmp.OutTimeExcds = &value + case "OutParmProbs": + procSnmp.Icmp.OutParmProbs = &value + case "OutSrcQuenchs": + procSnmp.Icmp.OutSrcQuenchs = &value + case "OutRedirects": + procSnmp.Icmp.OutRedirects = &value + case "OutEchos": + procSnmp.Icmp.OutEchos = &value + case "OutEchoReps": + procSnmp.Icmp.OutEchoReps = &value + case "OutTimestamps": + procSnmp.Icmp.OutTimestamps = &value + case "OutTimestampReps": + procSnmp.Icmp.OutTimestampReps = &value + case "OutAddrMasks": + procSnmp.Icmp.OutAddrMasks = &value + case "OutAddrMaskReps": + procSnmp.Icmp.OutAddrMaskReps = &value + } + case "IcmpMsg": + switch key { + case "InType3": + procSnmp.IcmpMsg.InType3 = &value + case "OutType3": + procSnmp.IcmpMsg.OutType3 = &value + } + case "Tcp": + switch key { + case "RtoAlgorithm": + procSnmp.Tcp.RtoAlgorithm = &value + case "RtoMin": + procSnmp.Tcp.RtoMin = &value + case "RtoMax": + procSnmp.Tcp.RtoMax = &value + case "MaxConn": + procSnmp.Tcp.MaxConn = &value + case "ActiveOpens": + procSnmp.Tcp.ActiveOpens = &value + case "PassiveOpens": + procSnmp.Tcp.PassiveOpens = &value + case "AttemptFails": + procSnmp.Tcp.AttemptFails = &value + case "EstabResets": + procSnmp.Tcp.EstabResets = &value + case "CurrEstab": + procSnmp.Tcp.CurrEstab = &value + case "InSegs": + procSnmp.Tcp.InSegs = &value + case "OutSegs": + procSnmp.Tcp.OutSegs = &value + case "RetransSegs": + procSnmp.Tcp.RetransSegs = &value + case "InErrs": + procSnmp.Tcp.InErrs = &value + case "OutRsts": + procSnmp.Tcp.OutRsts = &value + case "InCsumErrors": + procSnmp.Tcp.InCsumErrors = &value + } + case "Udp": + switch key { + case "InDatagrams": + procSnmp.Udp.InDatagrams = &value + case "NoPorts": + procSnmp.Udp.NoPorts = &value + case "InErrors": + procSnmp.Udp.InErrors = &value + case "OutDatagrams": + procSnmp.Udp.OutDatagrams = &value + case "RcvbufErrors": + procSnmp.Udp.RcvbufErrors = &value + case "SndbufErrors": + procSnmp.Udp.SndbufErrors = &value + case "InCsumErrors": + procSnmp.Udp.InCsumErrors = &value + case "IgnoredMulti": + procSnmp.Udp.IgnoredMulti = &value + } + case "UdpLite": + switch key { + case "InDatagrams": + procSnmp.UdpLite.InDatagrams = &value + case "NoPorts": + procSnmp.UdpLite.NoPorts = &value + case "InErrors": + procSnmp.UdpLite.InErrors = &value + case "OutDatagrams": + procSnmp.UdpLite.OutDatagrams = &value + case "RcvbufErrors": + procSnmp.UdpLite.RcvbufErrors = &value + case "SndbufErrors": + procSnmp.UdpLite.SndbufErrors = &value + case "InCsumErrors": + procSnmp.UdpLite.InCsumErrors = &value + case "IgnoredMulti": + procSnmp.UdpLite.IgnoredMulti = &value + } + } + } + } + return procSnmp, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_snmp6.go b/vendor/github.com/prometheus/procfs/proc_snmp6.go new file mode 100644 index 000000000..3059cc6a1 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_snmp6.go @@ -0,0 +1,381 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "errors" + "io" + "os" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ProcSnmp6 models the content of /proc//net/snmp6. +type ProcSnmp6 struct { + // The process ID. + PID int + Ip6 + Icmp6 + Udp6 + UdpLite6 +} + +type Ip6 struct { // nolint:revive + InReceives *float64 + InHdrErrors *float64 + InTooBigErrors *float64 + InNoRoutes *float64 + InAddrErrors *float64 + InUnknownProtos *float64 + InTruncatedPkts *float64 + InDiscards *float64 + InDelivers *float64 + OutForwDatagrams *float64 + OutRequests *float64 + OutDiscards *float64 + OutNoRoutes *float64 + ReasmTimeout *float64 + ReasmReqds *float64 + ReasmOKs *float64 + ReasmFails *float64 + FragOKs *float64 + FragFails *float64 + FragCreates *float64 + InMcastPkts *float64 + OutMcastPkts *float64 + InOctets *float64 + OutOctets *float64 + InMcastOctets *float64 + OutMcastOctets *float64 + InBcastOctets *float64 + OutBcastOctets *float64 + InNoECTPkts *float64 + InECT1Pkts *float64 + InECT0Pkts *float64 + InCEPkts *float64 +} + +type Icmp6 struct { + InMsgs *float64 + InErrors *float64 + OutMsgs *float64 + OutErrors *float64 + InCsumErrors *float64 + InDestUnreachs *float64 + InPktTooBigs *float64 + InTimeExcds *float64 + InParmProblems *float64 + InEchos *float64 + InEchoReplies *float64 + InGroupMembQueries *float64 + InGroupMembResponses *float64 + InGroupMembReductions *float64 + InRouterSolicits *float64 + InRouterAdvertisements *float64 + InNeighborSolicits *float64 + InNeighborAdvertisements *float64 + InRedirects *float64 + InMLDv2Reports *float64 + OutDestUnreachs *float64 + OutPktTooBigs *float64 + OutTimeExcds *float64 + OutParmProblems *float64 + OutEchos *float64 + OutEchoReplies *float64 + OutGroupMembQueries *float64 + OutGroupMembResponses *float64 + OutGroupMembReductions *float64 + OutRouterSolicits *float64 + OutRouterAdvertisements *float64 + OutNeighborSolicits *float64 + OutNeighborAdvertisements *float64 + OutRedirects *float64 + OutMLDv2Reports *float64 + InType1 *float64 + InType134 *float64 + InType135 *float64 + InType136 *float64 + InType143 *float64 + OutType133 *float64 + OutType135 *float64 + OutType136 *float64 + OutType143 *float64 +} + +type Udp6 struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 + IgnoredMulti *float64 +} + +type UdpLite6 struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 +} + +func (p Proc) Snmp6() (ProcSnmp6, error) { + filename := p.path("net/snmp6") + data, err := util.ReadFileNoStat(filename) + if err != nil { + // On systems with IPv6 disabled, this file won't exist. + // Do nothing. + if errors.Is(err, os.ErrNotExist) { + return ProcSnmp6{PID: p.PID}, nil + } + + return ProcSnmp6{PID: p.PID}, err + } + + procSnmp6, err := parseSNMP6Stats(bytes.NewReader(data)) + procSnmp6.PID = p.PID + return procSnmp6, err +} + +// parseSnmp6 parses the metrics from proc//net/snmp6 file +// and returns a map contains those metrics. +func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) { + var ( + scanner = bufio.NewScanner(r) + procSnmp6 = ProcSnmp6{} + ) + + for scanner.Scan() { + stat := strings.Fields(scanner.Text()) + if len(stat) < 2 { + continue + } + // Expect to have "6" in metric name, skip line otherwise + if sixIndex := strings.Index(stat[0], "6"); sixIndex != -1 { + protocol := stat[0][:sixIndex+1] + key := stat[0][sixIndex+1:] + value, err := strconv.ParseFloat(stat[1], 64) + if err != nil { + return procSnmp6, err + } + + switch protocol { + case "Ip6": + switch key { + case "InReceives": + procSnmp6.Ip6.InReceives = &value + case "InHdrErrors": + procSnmp6.Ip6.InHdrErrors = &value + case "InTooBigErrors": + procSnmp6.Ip6.InTooBigErrors = &value + case "InNoRoutes": + procSnmp6.Ip6.InNoRoutes = &value + case "InAddrErrors": + procSnmp6.Ip6.InAddrErrors = &value + case "InUnknownProtos": + procSnmp6.Ip6.InUnknownProtos = &value + case "InTruncatedPkts": + procSnmp6.Ip6.InTruncatedPkts = &value + case "InDiscards": + procSnmp6.Ip6.InDiscards = &value + case "InDelivers": + procSnmp6.Ip6.InDelivers = &value + case "OutForwDatagrams": + procSnmp6.Ip6.OutForwDatagrams = &value + case "OutRequests": + procSnmp6.Ip6.OutRequests = &value + case "OutDiscards": + procSnmp6.Ip6.OutDiscards = &value + case "OutNoRoutes": + procSnmp6.Ip6.OutNoRoutes = &value + case "ReasmTimeout": + procSnmp6.Ip6.ReasmTimeout = &value + case "ReasmReqds": + procSnmp6.Ip6.ReasmReqds = &value + case "ReasmOKs": + procSnmp6.Ip6.ReasmOKs = &value + case "ReasmFails": + procSnmp6.Ip6.ReasmFails = &value + case "FragOKs": + procSnmp6.Ip6.FragOKs = &value + case "FragFails": + procSnmp6.Ip6.FragFails = &value + case "FragCreates": + procSnmp6.Ip6.FragCreates = &value + case "InMcastPkts": + procSnmp6.Ip6.InMcastPkts = &value + case "OutMcastPkts": + procSnmp6.Ip6.OutMcastPkts = &value + case "InOctets": + procSnmp6.Ip6.InOctets = &value + case "OutOctets": + procSnmp6.Ip6.OutOctets = &value + case "InMcastOctets": + procSnmp6.Ip6.InMcastOctets = &value + case "OutMcastOctets": + procSnmp6.Ip6.OutMcastOctets = &value + case "InBcastOctets": + procSnmp6.Ip6.InBcastOctets = &value + case "OutBcastOctets": + procSnmp6.Ip6.OutBcastOctets = &value + case "InNoECTPkts": + procSnmp6.Ip6.InNoECTPkts = &value + case "InECT1Pkts": + procSnmp6.Ip6.InECT1Pkts = &value + case "InECT0Pkts": + procSnmp6.Ip6.InECT0Pkts = &value + case "InCEPkts": + procSnmp6.Ip6.InCEPkts = &value + + } + case "Icmp6": + switch key { + case "InMsgs": + procSnmp6.Icmp6.InMsgs = &value + case "InErrors": + procSnmp6.Icmp6.InErrors = &value + case "OutMsgs": + procSnmp6.Icmp6.OutMsgs = &value + case "OutErrors": + procSnmp6.Icmp6.OutErrors = &value + case "InCsumErrors": + procSnmp6.Icmp6.InCsumErrors = &value + case "InDestUnreachs": + procSnmp6.Icmp6.InDestUnreachs = &value + case "InPktTooBigs": + procSnmp6.Icmp6.InPktTooBigs = &value + case "InTimeExcds": + procSnmp6.Icmp6.InTimeExcds = &value + case "InParmProblems": + procSnmp6.Icmp6.InParmProblems = &value + case "InEchos": + procSnmp6.Icmp6.InEchos = &value + case "InEchoReplies": + procSnmp6.Icmp6.InEchoReplies = &value + case "InGroupMembQueries": + procSnmp6.Icmp6.InGroupMembQueries = &value + case "InGroupMembResponses": + procSnmp6.Icmp6.InGroupMembResponses = &value + case "InGroupMembReductions": + procSnmp6.Icmp6.InGroupMembReductions = &value + case "InRouterSolicits": + procSnmp6.Icmp6.InRouterSolicits = &value + case "InRouterAdvertisements": + procSnmp6.Icmp6.InRouterAdvertisements = &value + case "InNeighborSolicits": + procSnmp6.Icmp6.InNeighborSolicits = &value + case "InNeighborAdvertisements": + procSnmp6.Icmp6.InNeighborAdvertisements = &value + case "InRedirects": + procSnmp6.Icmp6.InRedirects = &value + case "InMLDv2Reports": + procSnmp6.Icmp6.InMLDv2Reports = &value + case "OutDestUnreachs": + procSnmp6.Icmp6.OutDestUnreachs = &value + case "OutPktTooBigs": + procSnmp6.Icmp6.OutPktTooBigs = &value + case "OutTimeExcds": + procSnmp6.Icmp6.OutTimeExcds = &value + case "OutParmProblems": + procSnmp6.Icmp6.OutParmProblems = &value + case "OutEchos": + procSnmp6.Icmp6.OutEchos = &value + case "OutEchoReplies": + procSnmp6.Icmp6.OutEchoReplies = &value + case "OutGroupMembQueries": + procSnmp6.Icmp6.OutGroupMembQueries = &value + case "OutGroupMembResponses": + procSnmp6.Icmp6.OutGroupMembResponses = &value + case "OutGroupMembReductions": + procSnmp6.Icmp6.OutGroupMembReductions = &value + case "OutRouterSolicits": + procSnmp6.Icmp6.OutRouterSolicits = &value + case "OutRouterAdvertisements": + procSnmp6.Icmp6.OutRouterAdvertisements = &value + case "OutNeighborSolicits": + procSnmp6.Icmp6.OutNeighborSolicits = &value + case "OutNeighborAdvertisements": + procSnmp6.Icmp6.OutNeighborAdvertisements = &value + case "OutRedirects": + procSnmp6.Icmp6.OutRedirects = &value + case "OutMLDv2Reports": + procSnmp6.Icmp6.OutMLDv2Reports = &value + case "InType1": + procSnmp6.Icmp6.InType1 = &value + case "InType134": + procSnmp6.Icmp6.InType134 = &value + case "InType135": + procSnmp6.Icmp6.InType135 = &value + case "InType136": + procSnmp6.Icmp6.InType136 = &value + case "InType143": + procSnmp6.Icmp6.InType143 = &value + case "OutType133": + procSnmp6.Icmp6.OutType133 = &value + case "OutType135": + procSnmp6.Icmp6.OutType135 = &value + case "OutType136": + procSnmp6.Icmp6.OutType136 = &value + case "OutType143": + procSnmp6.Icmp6.OutType143 = &value + } + case "Udp6": + switch key { + case "InDatagrams": + procSnmp6.Udp6.InDatagrams = &value + case "NoPorts": + procSnmp6.Udp6.NoPorts = &value + case "InErrors": + procSnmp6.Udp6.InErrors = &value + case "OutDatagrams": + procSnmp6.Udp6.OutDatagrams = &value + case "RcvbufErrors": + procSnmp6.Udp6.RcvbufErrors = &value + case "SndbufErrors": + procSnmp6.Udp6.SndbufErrors = &value + case "InCsumErrors": + procSnmp6.Udp6.InCsumErrors = &value + case "IgnoredMulti": + procSnmp6.Udp6.IgnoredMulti = &value + } + case "UdpLite6": + switch key { + case "InDatagrams": + procSnmp6.UdpLite6.InDatagrams = &value + case "NoPorts": + procSnmp6.UdpLite6.NoPorts = &value + case "InErrors": + procSnmp6.UdpLite6.InErrors = &value + case "OutDatagrams": + procSnmp6.UdpLite6.OutDatagrams = &value + case "RcvbufErrors": + procSnmp6.UdpLite6.RcvbufErrors = &value + case "SndbufErrors": + procSnmp6.UdpLite6.SndbufErrors = &value + case "InCsumErrors": + procSnmp6.UdpLite6.InCsumErrors = &value + } + } + } + } + return procSnmp6, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_stat.go b/vendor/github.com/prometheus/procfs/proc_stat.go index 67ca0e9fb..923e55005 100644 --- a/vendor/github.com/prometheus/procfs/proc_stat.go +++ b/vendor/github.com/prometheus/procfs/proc_stat.go @@ -18,7 +18,6 @@ import ( "fmt" "os" - "github.com/prometheus/procfs/internal/fs" "github.com/prometheus/procfs/internal/util" ) @@ -81,10 +80,10 @@ type ProcStat struct { STime uint // Amount of time that this process's waited-for children have been // scheduled in user mode, measured in clock ticks. - CUTime uint + CUTime int // Amount of time that this process's waited-for children have been // scheduled in kernel mode, measured in clock ticks. - CSTime uint + CSTime int // For processes running a real-time scheduling policy, this is the negated // scheduling priority, minus one. Priority int @@ -100,13 +99,24 @@ type ProcStat struct { VSize uint // Resident set size in pages. RSS int - - proc fs.FS + // Soft limit in bytes on the rss of the process. + RSSLimit uint64 + // CPU number last executed on. + Processor uint + // Real-time scheduling priority, a number in the range 1 to 99 for processes + // scheduled under a real-time policy, or 0, for non-real-time processes. + RTPriority uint + // Scheduling policy. + Policy uint + // Aggregated block I/O delays, measured in clock ticks (centiseconds). + DelayAcctBlkIOTicks uint64 + + proc FS } // NewStat returns the current status information of the process. // -// Deprecated: use p.Stat() instead +// Deprecated: Use p.Stat() instead. func (p Proc) NewStat() (ProcStat, error) { return p.Stat() } @@ -119,7 +129,8 @@ func (p Proc) Stat() (ProcStat, error) { } var ( - ignore int + ignoreInt64 int64 + ignoreUint64 uint64 s = ProcStat{PID: p.PID, proc: p.fs} l = bytes.Index(data, []byte("(")) @@ -127,10 +138,15 @@ func (p Proc) Stat() (ProcStat, error) { ) if l < 0 || r < 0 { - return ProcStat{}, fmt.Errorf("unexpected format, couldn't extract comm %q", data) + return ProcStat{}, fmt.Errorf("%w: unexpected format, couldn't extract comm %q", ErrFileParse, data) } s.Comm = string(data[l+1 : r]) + + // Check the following resources for the details about the particular stat + // fields and their data types: + // * https://man7.org/linux/man-pages/man5/proc.5.html + // * https://man7.org/linux/man-pages/man3/scanf.3.html _, err = fmt.Fscan( bytes.NewBuffer(data[r+2:]), &s.State, @@ -151,10 +167,28 @@ func (p Proc) Stat() (ProcStat, error) { &s.Priority, &s.Nice, &s.NumThreads, - &ignore, + &ignoreInt64, &s.Starttime, &s.VSize, &s.RSS, + &s.RSSLimit, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreInt64, + &s.Processor, + &s.RTPriority, + &s.Policy, + &s.DelayAcctBlkIOTicks, ) if err != nil { return ProcStat{}, err @@ -175,8 +209,7 @@ func (s ProcStat) ResidentMemory() int { // StartTime returns the unix timestamp of the process in seconds. func (s ProcStat) StartTime() (float64, error) { - fs := FS{proc: s.proc} - stat, err := fs.Stat() + stat, err := s.proc.Stat() if err != nil { return 0, err } diff --git a/vendor/github.com/prometheus/procfs/proc_status.go b/vendor/github.com/prometheus/procfs/proc_status.go index 6edd8333b..46307f572 100644 --- a/vendor/github.com/prometheus/procfs/proc_status.go +++ b/vendor/github.com/prometheus/procfs/proc_status.go @@ -15,6 +15,7 @@ package procfs import ( "bytes" + "sort" "strconv" "strings" @@ -22,7 +23,7 @@ import ( ) // ProcStatus provides status information about the process, -// read from /proc/[pid]/stat. +// read from /proc/[pid]/status. type ProcStatus struct { // The process ID. PID int @@ -31,39 +32,41 @@ type ProcStatus struct { // Thread group ID. TGID int + // List of Pid namespace. + NSpids []uint64 // Peak virtual memory size. - VmPeak uint64 // nolint:golint + VmPeak uint64 // nolint:revive // Virtual memory size. - VmSize uint64 // nolint:golint + VmSize uint64 // nolint:revive // Locked memory size. - VmLck uint64 // nolint:golint + VmLck uint64 // nolint:revive // Pinned memory size. - VmPin uint64 // nolint:golint + VmPin uint64 // nolint:revive // Peak resident set size. - VmHWM uint64 // nolint:golint + VmHWM uint64 // nolint:revive // Resident set size (sum of RssAnnon RssFile and RssShmem). - VmRSS uint64 // nolint:golint + VmRSS uint64 // nolint:revive // Size of resident anonymous memory. - RssAnon uint64 // nolint:golint + RssAnon uint64 // nolint:revive // Size of resident file mappings. - RssFile uint64 // nolint:golint + RssFile uint64 // nolint:revive // Size of resident shared memory. - RssShmem uint64 // nolint:golint + RssShmem uint64 // nolint:revive // Size of data segments. - VmData uint64 // nolint:golint + VmData uint64 // nolint:revive // Size of stack segments. - VmStk uint64 // nolint:golint + VmStk uint64 // nolint:revive // Size of text segments. - VmExe uint64 // nolint:golint + VmExe uint64 // nolint:revive // Shared library code size. - VmLib uint64 // nolint:golint + VmLib uint64 // nolint:revive // Page table entries size. - VmPTE uint64 // nolint:golint + VmPTE uint64 // nolint:revive // Size of second-level page tables. - VmPMD uint64 // nolint:golint + VmPMD uint64 // nolint:revive // Swapped-out virtual memory size by anonymous private. - VmSwap uint64 // nolint:golint + VmSwap uint64 // nolint:revive // Size of hugetlb memory portions HugetlbPages uint64 @@ -76,6 +79,9 @@ type ProcStatus struct { UIDs [4]string // GIDs of the process (Real, effective, saved set, and filesystem GIDs) GIDs [4]string + + // CpusAllowedList: List of cpu cores processes are allowed to run on. + CpusAllowedList []uint64 } // NewStatus returns the current status information of the process. @@ -96,10 +102,10 @@ func (p Proc) NewStatus() (ProcStatus, error) { kv := strings.SplitN(line, ":", 2) // removes spaces - k := string(strings.TrimSpace(kv[0])) - v := string(strings.TrimSpace(kv[1])) + k := strings.TrimSpace(kv[0]) + v := strings.TrimSpace(kv[1]) // removes "kB" - v = string(bytes.Trim([]byte(v), " kB")) + v = strings.TrimSuffix(v, " kB") // value to int when possible // we can skip error check here, 'cause vKBytes is not used when value is a string @@ -123,6 +129,8 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt copy(s.UIDs[:], strings.Split(vString, "\t")) case "Gid": copy(s.GIDs[:], strings.Split(vString, "\t")) + case "NSpid": + s.NSpids = calcNSPidsList(vString) case "VmPeak": s.VmPeak = vUintBytes case "VmSize": @@ -161,10 +169,53 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt s.VoluntaryCtxtSwitches = vUint case "nonvoluntary_ctxt_switches": s.NonVoluntaryCtxtSwitches = vUint + case "Cpus_allowed_list": + s.CpusAllowedList = calcCpusAllowedList(vString) } + } // TotalCtxtSwitches returns the total context switch. func (s ProcStatus) TotalCtxtSwitches() uint64 { return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches } + +func calcCpusAllowedList(cpuString string) []uint64 { + s := strings.Split(cpuString, ",") + + var g []uint64 + + for _, cpu := range s { + // parse cpu ranges, example: 1-3=[1,2,3] + if l := strings.Split(strings.TrimSpace(cpu), "-"); len(l) > 1 { + startCPU, _ := strconv.ParseUint(l[0], 10, 64) + endCPU, _ := strconv.ParseUint(l[1], 10, 64) + + for i := startCPU; i <= endCPU; i++ { + g = append(g, i) + } + } else if len(l) == 1 { + cpu, _ := strconv.ParseUint(l[0], 10, 64) + g = append(g, cpu) + } + + } + + sort.Slice(g, func(i, j int) bool { return g[i] < g[j] }) + return g +} + +func calcNSPidsList(nspidsString string) []uint64 { + s := strings.Split(nspidsString, " ") + var nspids []uint64 + + for _, nspid := range s { + nspid, _ := strconv.ParseUint(nspid, 10, 64) + if nspid == 0 { + continue + } + nspids = append(nspids, nspid) + } + + return nspids +} diff --git a/vendor/github.com/prometheus/procfs/proc_sys.go b/vendor/github.com/prometheus/procfs/proc_sys.go new file mode 100644 index 000000000..12c5bf05b --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_sys.go @@ -0,0 +1,51 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "fmt" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +func sysctlToPath(sysctl string) string { + return strings.Replace(sysctl, ".", "/", -1) +} + +func (fs FS) SysctlStrings(sysctl string) ([]string, error) { + value, err := util.SysReadFile(fs.proc.Path("sys", sysctlToPath(sysctl))) + if err != nil { + return nil, err + } + return strings.Fields(value), nil + +} + +func (fs FS) SysctlInts(sysctl string) ([]int, error) { + fields, err := fs.SysctlStrings(sysctl) + if err != nil { + return nil, err + } + + values := make([]int, len(fields)) + for i, f := range fields { + vp := util.NewValueParser(f) + values[i] = vp.Int() + if err := vp.Err(); err != nil { + return nil, fmt.Errorf("%s: field %d in sysctl %s is not a valid int: %w", ErrFileParse, i, sysctl, err) + } + } + return values, nil +} diff --git a/vendor/github.com/prometheus/procfs/schedstat.go b/vendor/github.com/prometheus/procfs/schedstat.go index 28228164e..5f7f32dc8 100644 --- a/vendor/github.com/prometheus/procfs/schedstat.go +++ b/vendor/github.com/prometheus/procfs/schedstat.go @@ -40,7 +40,7 @@ type Schedstat struct { CPUs []*SchedstatCPU } -// SchedstatCPU contains the values from one "cpu" line +// SchedstatCPU contains the values from one "cpu" line. type SchedstatCPU struct { CPUNum string @@ -49,14 +49,14 @@ type SchedstatCPU struct { RunTimeslices uint64 } -// ProcSchedstat contains the values from /proc//schedstat +// ProcSchedstat contains the values from `/proc//schedstat`. type ProcSchedstat struct { RunningNanoseconds uint64 WaitingNanoseconds uint64 RunTimeslices uint64 } -// Schedstat reads data from /proc/schedstat +// Schedstat reads data from `/proc/schedstat`. func (fs FS) Schedstat() (*Schedstat, error) { file, err := os.Open(fs.proc.Path("schedstat")) if err != nil { diff --git a/vendor/github.com/prometheus/procfs/slab.go b/vendor/github.com/prometheus/procfs/slab.go index 7896fd724..8611c9017 100644 --- a/vendor/github.com/prometheus/procfs/slab.go +++ b/vendor/github.com/prometheus/procfs/slab.go @@ -68,7 +68,7 @@ func parseV21SlabEntry(line string) (*Slab, error) { l := slabSpace.ReplaceAllString(line, " ") s := strings.Split(l, " ") if len(s) != 16 { - return nil, fmt.Errorf("unable to parse: %q", line) + return nil, fmt.Errorf("%w: unable to parse: %q", ErrFileParse, line) } var err error i := &Slab{Name: s[0]} @@ -137,7 +137,7 @@ func parseSlabInfo21(r *bytes.Reader) (SlabInfo, error) { return s, nil } -// SlabInfo reads data from /proc/slabinfo +// SlabInfo reads data from `/proc/slabinfo`. func (fs FS) SlabInfo() (SlabInfo, error) { // TODO: Consider passing options to allow for parsing different // slabinfo versions. However, slabinfo 2.1 has been stable since diff --git a/vendor/github.com/prometheus/procfs/softirqs.go b/vendor/github.com/prometheus/procfs/softirqs.go new file mode 100644 index 000000000..b8fad677d --- /dev/null +++ b/vendor/github.com/prometheus/procfs/softirqs.go @@ -0,0 +1,160 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// Softirqs represents the softirq statistics. +type Softirqs struct { + Hi []uint64 + Timer []uint64 + NetTx []uint64 + NetRx []uint64 + Block []uint64 + IRQPoll []uint64 + Tasklet []uint64 + Sched []uint64 + HRTimer []uint64 + RCU []uint64 +} + +func (fs FS) Softirqs() (Softirqs, error) { + fileName := fs.proc.Path("softirqs") + data, err := util.ReadFileNoStat(fileName) + if err != nil { + return Softirqs{}, err + } + + reader := bytes.NewReader(data) + + return parseSoftirqs(reader) +} + +func parseSoftirqs(r io.Reader) (Softirqs, error) { + var ( + softirqs = Softirqs{} + scanner = bufio.NewScanner(r) + ) + + if !scanner.Scan() { + return Softirqs{}, fmt.Errorf("%w: softirqs empty", ErrFileRead) + } + + for scanner.Scan() { + parts := strings.Fields(scanner.Text()) + var err error + + // require at least one cpu + if len(parts) < 2 { + continue + } + switch { + case parts[0] == "HI:": + perCPU := parts[1:] + softirqs.Hi = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "TIMER:": + perCPU := parts[1:] + softirqs.Timer = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "NET_TX:": + perCPU := parts[1:] + softirqs.NetTx = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "NET_RX:": + perCPU := parts[1:] + softirqs.NetRx = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "BLOCK:": + perCPU := parts[1:] + softirqs.Block = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "IRQ_POLL:": + perCPU := parts[1:] + softirqs.IRQPoll = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "TASKLET:": + perCPU := parts[1:] + softirqs.Tasklet = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "SCHED:": + perCPU := parts[1:] + softirqs.Sched = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "HRTIMER:": + perCPU := parts[1:] + softirqs.HRTimer = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err) + } + } + case parts[0] == "RCU:": + perCPU := parts[1:] + softirqs.RCU = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (RCU%d): %w", ErrFileParse, count, i, err) + } + } + } + } + + if err := scanner.Err(); err != nil { + return Softirqs{}, fmt.Errorf("%s: couldn't parse softirqs: %w", ErrFileParse, err) + } + + return softirqs, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/stat.go b/vendor/github.com/prometheus/procfs/stat.go index 6d8727541..34fc3ee21 100644 --- a/vendor/github.com/prometheus/procfs/stat.go +++ b/vendor/github.com/prometheus/procfs/stat.go @@ -41,7 +41,7 @@ type CPUStat struct { // SoftIRQStat represent the softirq statistics as exported in the procfs stat file. // A nice introduction can be found at https://0xax.gitbooks.io/linux-insides/content/interrupts/interrupts-9.html -// It is possible to get per-cpu stats by reading /proc/softirqs +// It is possible to get per-cpu stats by reading `/proc/softirqs`. type SoftIRQStat struct { Hi uint64 Timer uint64 @@ -62,7 +62,7 @@ type Stat struct { // Summed up cpu statistics. CPUTotal CPUStat // Per-CPU statistics. - CPU []CPUStat + CPU map[int64]CPUStat // Number of times interrupts were handled, which contains numbered and unnumbered IRQs. IRQTotal uint64 // Number of times a numbered IRQ was triggered. @@ -93,10 +93,10 @@ func parseCPUStat(line string) (CPUStat, int64, error) { &cpuStat.Guest, &cpuStat.GuestNice) if err != nil && err != io.EOF { - return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu): %w", line, err) + return CPUStat{}, -1, fmt.Errorf("%s: couldn't parse %q (cpu): %w", ErrFileParse, line, err) } if count == 0 { - return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu): 0 elements parsed", line) + return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu): 0 elements parsed", ErrFileParse, line) } cpuStat.User /= userHZ @@ -116,7 +116,7 @@ func parseCPUStat(line string) (CPUStat, int64, error) { cpuID, err := strconv.ParseInt(cpu[3:], 10, 64) if err != nil { - return CPUStat{}, -1, fmt.Errorf("couldn't parse %q (cpu/cpuid): %w", line, err) + return CPUStat{}, -1, fmt.Errorf("%s: couldn't parse %q (cpu/cpuid): %w", ErrFileParse, line, err) } return cpuStat, cpuID, nil @@ -136,7 +136,7 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { &softIRQStat.Hrtimer, &softIRQStat.Rcu) if err != nil { - return SoftIRQStat{}, 0, fmt.Errorf("couldn't parse %q (softirq): %w", line, err) + return SoftIRQStat{}, 0, fmt.Errorf("%s: couldn't parse %q (softirq): %w", ErrFileParse, line, err) } return softIRQStat, total, nil @@ -145,7 +145,7 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { // NewStat returns information about current cpu/process statistics. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt // -// Deprecated: use fs.Stat() instead +// Deprecated: Use fs.Stat() instead. func NewStat() (Stat, error) { fs, err := NewFS(fs.DefaultProcMountPoint) if err != nil { @@ -155,25 +155,42 @@ func NewStat() (Stat, error) { } // NewStat returns information about current cpu/process statistics. -// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt +// See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt // -// Deprecated: use fs.Stat() instead +// Deprecated: Use fs.Stat() instead. func (fs FS) NewStat() (Stat, error) { return fs.Stat() } // Stat returns information about current cpu/process statistics. -// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt +// See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt func (fs FS) Stat() (Stat, error) { fileName := fs.proc.Path("stat") data, err := util.ReadFileNoStat(fileName) if err != nil { return Stat{}, err } + procStat, err := parseStat(bytes.NewReader(data), fileName) + if err != nil { + return Stat{}, err + } + return procStat, nil +} + +// parseStat parses the metrics from /proc/[pid]/stat. +func parseStat(r io.Reader, fileName string) (Stat, error) { + var ( + scanner = bufio.NewScanner(r) + stat = Stat{ + CPU: make(map[int64]CPUStat), + } + err error + ) - stat := Stat{} + // Increase default scanner buffer to handle very long `intr` lines. + buf := make([]byte, 0, 8*1024) + scanner.Buffer(buf, 1024*1024) - scanner := bufio.NewScanner(bytes.NewReader(data)) for scanner.Scan() { line := scanner.Text() parts := strings.Fields(scanner.Text()) @@ -184,34 +201,34 @@ func (fs FS) Stat() (Stat, error) { switch { case parts[0] == "btime": if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q (btime): %w", parts[1], err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q (btime): %w", ErrFileParse, parts[1], err) } case parts[0] == "intr": if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q (intr): %w", parts[1], err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q (intr): %w", ErrFileParse, parts[1], err) } numberedIRQs := parts[2:] stat.IRQ = make([]uint64, len(numberedIRQs)) for i, count := range numberedIRQs { if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q (intr%d): %w", count, i, err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q (intr%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "ctxt": if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q (ctxt): %w", parts[1], err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q (ctxt): %w", ErrFileParse, parts[1], err) } case parts[0] == "processes": if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q (processes): %w", parts[1], err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q (processes): %w", ErrFileParse, parts[1], err) } case parts[0] == "procs_running": if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q (procs_running): %w", parts[1], err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q (procs_running): %w", ErrFileParse, parts[1], err) } case parts[0] == "procs_blocked": if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q (procs_blocked): %w", parts[1], err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q (procs_blocked): %w", ErrFileParse, parts[1], err) } case parts[0] == "softirq": softIRQStats, total, err := parseSoftIRQStat(line) @@ -228,16 +245,13 @@ func (fs FS) Stat() (Stat, error) { if cpuID == -1 { stat.CPUTotal = cpuStat } else { - for int64(len(stat.CPU)) <= cpuID { - stat.CPU = append(stat.CPU, CPUStat{}) - } stat.CPU[cpuID] = cpuStat } } } if err := scanner.Err(); err != nil { - return Stat{}, fmt.Errorf("couldn't parse %q: %w", fileName, err) + return Stat{}, fmt.Errorf("%s: couldn't parse %q: %w", ErrFileParse, fileName, err) } return stat, nil diff --git a/vendor/github.com/prometheus/procfs/swaps.go b/vendor/github.com/prometheus/procfs/swaps.go index 15edc2212..fa00f555d 100644 --- a/vendor/github.com/prometheus/procfs/swaps.go +++ b/vendor/github.com/prometheus/procfs/swaps.go @@ -64,7 +64,7 @@ func parseSwapString(swapString string) (*Swap, error) { swapFields := strings.Fields(swapString) swapLength := len(swapFields) if swapLength < 5 { - return nil, fmt.Errorf("too few fields in swap string: %s", swapString) + return nil, fmt.Errorf("%w: too few fields in swap string: %s", ErrFileParse, swapString) } swap := &Swap{ @@ -74,15 +74,15 @@ func parseSwapString(swapString string) (*Swap, error) { swap.Size, err = strconv.Atoi(swapFields[2]) if err != nil { - return nil, fmt.Errorf("invalid swap size: %s", swapFields[2]) + return nil, fmt.Errorf("%s: invalid swap size: %s: %w", ErrFileParse, swapFields[2], err) } swap.Used, err = strconv.Atoi(swapFields[3]) if err != nil { - return nil, fmt.Errorf("invalid swap used: %s", swapFields[3]) + return nil, fmt.Errorf("%s: invalid swap used: %s: %w", ErrFileParse, swapFields[3], err) } swap.Priority, err = strconv.Atoi(swapFields[4]) if err != nil { - return nil, fmt.Errorf("invalid swap priority: %s", swapFields[4]) + return nil, fmt.Errorf("%s: invalid swap priority: %s: %w", ErrFileParse, swapFields[4], err) } return swap, nil diff --git a/vendor/github.com/prometheus/procfs/thread.go b/vendor/github.com/prometheus/procfs/thread.go new file mode 100644 index 000000000..df2215ece --- /dev/null +++ b/vendor/github.com/prometheus/procfs/thread.go @@ -0,0 +1,80 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "fmt" + "os" + "strconv" + + fsi "github.com/prometheus/procfs/internal/fs" +) + +// Provide access to /proc/PID/task/TID files, for thread specific values. Since +// such files have the same structure as /proc/PID/ ones, the data structures +// and the parsers for the latter may be reused. + +// AllThreads returns a list of all currently available threads under /proc/PID. +func AllThreads(pid int) (Procs, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return Procs{}, err + } + return fs.AllThreads(pid) +} + +// AllThreads returns a list of all currently available threads for PID. +func (fs FS) AllThreads(pid int) (Procs, error) { + taskPath := fs.proc.Path(strconv.Itoa(pid), "task") + d, err := os.Open(taskPath) + if err != nil { + return Procs{}, err + } + defer d.Close() + + names, err := d.Readdirnames(-1) + if err != nil { + return Procs{}, fmt.Errorf("%s: could not read %q: %w", ErrFileRead, d.Name(), err) + } + + t := Procs{} + for _, n := range names { + tid, err := strconv.ParseInt(n, 10, 64) + if err != nil { + continue + } + + t = append(t, Proc{PID: int(tid), fs: FS{fsi.FS(taskPath), fs.isReal}}) + } + + return t, nil +} + +// Thread returns a process for a given PID, TID. +func (fs FS) Thread(pid, tid int) (Proc, error) { + taskPath := fs.proc.Path(strconv.Itoa(pid), "task") + if _, err := os.Stat(taskPath); err != nil { + return Proc{}, err + } + return Proc{PID: tid, fs: FS{fsi.FS(taskPath), fs.isReal}}, nil +} + +// Thread returns a process for a given TID of Proc. +func (proc Proc) Thread(tid int) (Proc, error) { + tfs := FS{fsi.FS(proc.path("task")), proc.fs.isReal} + if _, err := os.Stat(tfs.proc.Path(strconv.Itoa(tid))); err != nil { + return Proc{}, err + } + return Proc{PID: tid, fs: tfs}, nil +} diff --git a/vendor/github.com/prometheus/procfs/vm.go b/vendor/github.com/prometheus/procfs/vm.go index cb1389141..51c49d89e 100644 --- a/vendor/github.com/prometheus/procfs/vm.go +++ b/vendor/github.com/prometheus/procfs/vm.go @@ -11,13 +11,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -26,10 +26,12 @@ import ( ) // The VM interface is described at -// https://www.kernel.org/doc/Documentation/sysctl/vm.txt +// +// https://www.kernel.org/doc/Documentation/sysctl/vm.txt +// // Each setting is exposed as a single file. // Each file contains one line with a single numerical value, except lowmem_reserve_ratio which holds an array -// and numa_zonelist_order (deprecated) which is a string +// and numa_zonelist_order (deprecated) which is a string. type VM struct { AdminReserveKbytes *int64 // /proc/sys/vm/admin_reserve_kbytes BlockDump *int64 // /proc/sys/vm/block_dump @@ -84,10 +86,10 @@ func (fs FS) VM() (*VM, error) { return nil, err } if !file.Mode().IsDir() { - return nil, fmt.Errorf("%s is not a directory", path) + return nil, fmt.Errorf("%w: %s is not a directory", ErrFileRead, path) } - files, err := ioutil.ReadDir(path) + files, err := os.ReadDir(path) if err != nil { return nil, err } diff --git a/vendor/github.com/prometheus/procfs/zoneinfo.go b/vendor/github.com/prometheus/procfs/zoneinfo.go index 0b9bb6796..ce5fefa5b 100644 --- a/vendor/github.com/prometheus/procfs/zoneinfo.go +++ b/vendor/github.com/prometheus/procfs/zoneinfo.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs @@ -18,7 +19,7 @@ package procfs import ( "bytes" "fmt" - "io/ioutil" + "os" "regexp" "strings" @@ -72,13 +73,13 @@ var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`) // structs containing the relevant info. More information available here: // https://www.kernel.org/doc/Documentation/sysctl/vm.txt func (fs FS) Zoneinfo() ([]Zoneinfo, error) { - data, err := ioutil.ReadFile(fs.proc.Path("zoneinfo")) + data, err := os.ReadFile(fs.proc.Path("zoneinfo")) if err != nil { - return nil, fmt.Errorf("error reading zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err) + return nil, fmt.Errorf("%s: error reading zoneinfo %q: %w", ErrFileRead, fs.proc.Path("zoneinfo"), err) } zoneinfo, err := parseZoneinfo(data) if err != nil { - return nil, fmt.Errorf("error parsing zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err) + return nil, fmt.Errorf("%s: error parsing zoneinfo %q: %w", ErrFileParse, fs.proc.Path("zoneinfo"), err) } return zoneinfo, nil } @@ -99,7 +100,6 @@ func parseZoneinfo(zoneinfoData []byte) ([]Zoneinfo, error) { continue } if strings.HasPrefix(strings.TrimSpace(line), "per-node stats") { - zoneinfoElement.Zone = "" continue } parts := strings.Fields(strings.TrimSpace(line)) diff --git a/vendor/golang.org/x/oauth2/google/default.go b/vendor/golang.org/x/oauth2/google/default.go index 12b12a30c..02ccd08a7 100644 --- a/vendor/golang.org/x/oauth2/google/default.go +++ b/vendor/golang.org/x/oauth2/google/default.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "runtime" + "sync" "time" "cloud.google.com/go/compute/metadata" @@ -41,12 +42,20 @@ type Credentials struct { // running on Google Cloud Platform. JSON []byte + udMu sync.Mutex // guards universeDomain // universeDomain is the default service domain for a given Cloud universe. universeDomain string } // UniverseDomain returns the default service domain for a given Cloud universe. +// // The default value is "googleapis.com". +// +// Deprecated: Use instead (*Credentials).GetUniverseDomain(), which supports +// obtaining the universe domain when authenticating via the GCE metadata server. +// Unlike GetUniverseDomain, this method, UniverseDomain, will always return the +// default value when authenticating via the GCE metadata server. +// See also [The attached service account](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa). func (c *Credentials) UniverseDomain() string { if c.universeDomain == "" { return universeDomainDefault @@ -54,6 +63,55 @@ func (c *Credentials) UniverseDomain() string { return c.universeDomain } +// GetUniverseDomain returns the default service domain for a given Cloud +// universe. +// +// The default value is "googleapis.com". +// +// It obtains the universe domain from the attached service account on GCE when +// authenticating via the GCE metadata server. See also [The attached service +// account](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa). +// If the GCE metadata server returns a 404 error, the default value is +// returned. If the GCE metadata server returns an error other than 404, the +// error is returned. +func (c *Credentials) GetUniverseDomain() (string, error) { + c.udMu.Lock() + defer c.udMu.Unlock() + if c.universeDomain == "" && metadata.OnGCE() { + // If we're on Google Compute Engine, an App Engine standard second + // generation runtime, or App Engine flexible, use the metadata server. + err := c.computeUniverseDomain() + if err != nil { + return "", err + } + } + // If not on Google Compute Engine, or in case of any non-error path in + // computeUniverseDomain that did not set universeDomain, set the default + // universe domain. + if c.universeDomain == "" { + c.universeDomain = universeDomainDefault + } + return c.universeDomain, nil +} + +// computeUniverseDomain fetches the default service domain for a given Cloud +// universe from Google Compute Engine (GCE)'s metadata server. It's only valid +// to use this method if your program is running on a GCE instance. +func (c *Credentials) computeUniverseDomain() error { + var err error + c.universeDomain, err = metadata.Get("universe/universe_domain") + if err != nil { + if _, ok := err.(metadata.NotDefinedError); ok { + // http.StatusNotFound (404) + c.universeDomain = universeDomainDefault + return nil + } else { + return err + } + } + return nil +} + // DefaultCredentials is the old name of Credentials. // // Deprecated: use Credentials instead. @@ -91,6 +149,12 @@ type CredentialsParams struct { // Note: This option is currently only respected when using credentials // fetched from the GCE metadata server. EarlyTokenRefresh time.Duration + + // UniverseDomain is the default service domain for a given Cloud universe. + // Only supported in authentication flows that support universe domains. + // This value takes precedence over a universe domain explicitly specified + // in a credentials config file or by the GCE metadata server. Optional. + UniverseDomain string } func (params CredentialsParams) deepCopy() CredentialsParams { @@ -175,8 +239,9 @@ func FindDefaultCredentialsWithParams(ctx context.Context, params CredentialsPar if metadata.OnGCE() { id, _ := metadata.ProjectID() return &Credentials{ - ProjectID: id, - TokenSource: computeTokenSource("", params.EarlyTokenRefresh, params.Scopes...), + ProjectID: id, + TokenSource: computeTokenSource("", params.EarlyTokenRefresh, params.Scopes...), + universeDomain: params.UniverseDomain, }, nil } @@ -217,6 +282,9 @@ func CredentialsFromJSONWithParams(ctx context.Context, jsonData []byte, params } universeDomain := f.UniverseDomain + if params.UniverseDomain != "" { + universeDomain = params.UniverseDomain + } // Authorized user credentials are only supported in the googleapis.com universe. if f.Type == userCredentialsKey { universeDomain = universeDomainDefault diff --git a/vendor/golang.org/x/sys/unix/mremap.go b/vendor/golang.org/x/sys/unix/mremap.go index fd45fe529..3a5e776f8 100644 --- a/vendor/golang.org/x/sys/unix/mremap.go +++ b/vendor/golang.org/x/sys/unix/mremap.go @@ -50,3 +50,8 @@ func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data [ func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) { return mapper.Mremap(oldData, newLength, flags) } + +func MremapPtr(oldAddr unsafe.Pointer, oldSize uintptr, newAddr unsafe.Pointer, newSize uintptr, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mremap(uintptr(oldAddr), oldSize, newSize, flags, uintptr(newAddr)) + return unsafe.Pointer(xaddr), err +} diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 59542a897..4cc7b0059 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -542,6 +542,18 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { } } +//sys pthread_chdir_np(path string) (err error) + +func PthreadChdir(path string) (err error) { + return pthread_chdir_np(path) +} + +//sys pthread_fchdir_np(fd int) (err error) + +func PthreadFchdir(fd int) (err error) { + return pthread_fchdir_np(fd) +} + //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_unix.go b/vendor/golang.org/x/sys/unix/syscall_unix.go index 77081de8c..4e92e5aa4 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -154,6 +154,15 @@ func Munmap(b []byte) (err error) { return mapper.Munmap(b) } +func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset) + return unsafe.Pointer(xaddr), err +} + +func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) { + return mapper.munmap(uintptr(addr), length) +} + func Read(fd int, p []byte) (n int, err error) { n, err = read(fd, p) if raceenabled { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index ccb02f240..07642c308 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -760,6 +760,39 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index 8b8bb2840..923e08cb7 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -228,6 +228,16 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 1b40b997b..7d73dda64 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -760,6 +760,39 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 08362c1ab..057700111 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -228,6 +228,16 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index 6f7d2ac70..97651b5bd 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -894,7 +894,7 @@ type ACL struct { aclRevision byte sbz1 byte aclSize uint16 - aceCount uint16 + AceCount uint16 sbz2 uint16 } @@ -1087,6 +1087,27 @@ type EXPLICIT_ACCESS struct { Trustee TRUSTEE } +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header +type ACE_HEADER struct { + AceType uint8 + AceFlags uint8 + AceSize uint16 +} + +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace +type ACCESS_ALLOWED_ACE struct { + Header ACE_HEADER + Mask ACCESS_MASK + SidStart uint32 +} + +const ( + // Constants for AceType + // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header + ACCESS_ALLOWED_ACE_TYPE = 0 + ACCESS_DENIED_ACE_TYPE = 1 +) + // This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions. type TrusteeValue uintptr @@ -1158,6 +1179,7 @@ type OBJECTS_AND_NAME struct { //sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD //sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW +//sys GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (ret error) = advapi32.GetAce // Control returns the security descriptor control bits. func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) { diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 9f73df75b..eba761018 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -91,6 +91,7 @@ var ( procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") procEqualSid = modadvapi32.NewProc("EqualSid") procFreeSid = modadvapi32.NewProc("FreeSid") + procGetAce = modadvapi32.NewProc("GetAce") procGetLengthSid = modadvapi32.NewProc("GetLengthSid") procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") @@ -1224,6 +1225,14 @@ func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCE return } +func GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (ret error) { + r0, _, _ := syscall.Syscall(procGetAce.Addr(), 3, uintptr(unsafe.Pointer(acl)), uintptr(aceIndex), uintptr(unsafe.Pointer(pAce))) + if r0 == 0 { + ret = GetLastError() + } + return +} + func SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) { r1, _, e1 := syscall.Syscall(procSetKernelObjectSecurity.Addr(), 3, uintptr(handle), uintptr(securityInformation), uintptr(unsafe.Pointer(securityDescriptor))) if r1 == 0 { diff --git a/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go b/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go new file mode 100644 index 000000000..2ef36bbcf --- /dev/null +++ b/vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go @@ -0,0 +1,160 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package protodelim marshals and unmarshals varint size-delimited messages. +package protodelim + +import ( + "bufio" + "encoding/binary" + "fmt" + "io" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/internal/errors" + "google.golang.org/protobuf/proto" +) + +// MarshalOptions is a configurable varint size-delimited marshaler. +type MarshalOptions struct{ proto.MarshalOptions } + +// MarshalTo writes a varint size-delimited wire-format message to w. +// If w returns an error, MarshalTo returns it unchanged. +func (o MarshalOptions) MarshalTo(w io.Writer, m proto.Message) (int, error) { + msgBytes, err := o.MarshalOptions.Marshal(m) + if err != nil { + return 0, err + } + + sizeBytes := protowire.AppendVarint(nil, uint64(len(msgBytes))) + sizeWritten, err := w.Write(sizeBytes) + if err != nil { + return sizeWritten, err + } + msgWritten, err := w.Write(msgBytes) + if err != nil { + return sizeWritten + msgWritten, err + } + return sizeWritten + msgWritten, nil +} + +// MarshalTo writes a varint size-delimited wire-format message to w +// with the default options. +// +// See the documentation for [MarshalOptions.MarshalTo]. +func MarshalTo(w io.Writer, m proto.Message) (int, error) { + return MarshalOptions{}.MarshalTo(w, m) +} + +// UnmarshalOptions is a configurable varint size-delimited unmarshaler. +type UnmarshalOptions struct { + proto.UnmarshalOptions + + // MaxSize is the maximum size in wire-format bytes of a single message. + // Unmarshaling a message larger than MaxSize will return an error. + // A zero MaxSize will default to 4 MiB. + // Setting MaxSize to -1 disables the limit. + MaxSize int64 +} + +const defaultMaxSize = 4 << 20 // 4 MiB, corresponds to the default gRPC max request/response size + +// SizeTooLargeError is an error that is returned when the unmarshaler encounters a message size +// that is larger than its configured [UnmarshalOptions.MaxSize]. +type SizeTooLargeError struct { + // Size is the varint size of the message encountered + // that was larger than the provided MaxSize. + Size uint64 + + // MaxSize is the MaxSize limit configured in UnmarshalOptions, which Size exceeded. + MaxSize uint64 +} + +func (e *SizeTooLargeError) Error() string { + return fmt.Sprintf("message size %d exceeded unmarshaler's maximum configured size %d", e.Size, e.MaxSize) +} + +// Reader is the interface expected by [UnmarshalFrom]. +// It is implemented by *[bufio.Reader]. +type Reader interface { + io.Reader + io.ByteReader +} + +// UnmarshalFrom parses and consumes a varint size-delimited wire-format message +// from r. +// The provided message must be mutable (e.g., a non-nil pointer to a message). +// +// The error is [io.EOF] error only if no bytes are read. +// If an EOF happens after reading some but not all the bytes, +// UnmarshalFrom returns a non-io.EOF error. +// In particular if r returns a non-io.EOF error, UnmarshalFrom returns it unchanged, +// and if only a size is read with no subsequent message, [io.ErrUnexpectedEOF] is returned. +func (o UnmarshalOptions) UnmarshalFrom(r Reader, m proto.Message) error { + var sizeArr [binary.MaxVarintLen64]byte + sizeBuf := sizeArr[:0] + for i := range sizeArr { + b, err := r.ReadByte() + if err != nil { + // Immediate EOF is unexpected. + if err == io.EOF && i != 0 { + break + } + return err + } + sizeBuf = append(sizeBuf, b) + if b < 0x80 { + break + } + } + size, n := protowire.ConsumeVarint(sizeBuf) + if n < 0 { + return protowire.ParseError(n) + } + + maxSize := o.MaxSize + if maxSize == 0 { + maxSize = defaultMaxSize + } + if maxSize != -1 && size > uint64(maxSize) { + return errors.Wrap(&SizeTooLargeError{Size: size, MaxSize: uint64(maxSize)}, "") + } + + var b []byte + var err error + if br, ok := r.(*bufio.Reader); ok { + // Use the []byte from the bufio.Reader instead of having to allocate one. + // This reduces CPU usage and allocated bytes. + b, err = br.Peek(int(size)) + if err == nil { + defer br.Discard(int(size)) + } else { + b = nil + } + } + if b == nil { + b = make([]byte, size) + _, err = io.ReadFull(r, b) + } + + if err == io.EOF { + return io.ErrUnexpectedEOF + } + if err != nil { + return err + } + if err := o.Unmarshal(b, m); err != nil { + return err + } + return nil +} + +// UnmarshalFrom parses and consumes a varint size-delimited wire-format message +// from r with the default options. +// The provided message must be mutable (e.g., a non-nil pointer to a message). +// +// See the documentation for [UnmarshalOptions.UnmarshalFrom]. +func UnmarshalFrom(r Reader, m proto.Message) error { + return UnmarshalOptions{}.UnmarshalFrom(r, m) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 4f74f9315..ae331caba 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -111,12 +111,23 @@ github.com/AzureAD/microsoft-authentication-library-for-go/apps/public # github.com/ajeddeloh/go-json v0.0.0-20200220154158-5ae607161559 ## explicit github.com/ajeddeloh/go-json -# github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 +# github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 ## explicit; go 1.15 github.com/alecthomas/units # github.com/anatol/tang.go v0.0.0-20230725175645-dcc6e9494f14 ## explicit; go 1.18 github.com/anatol/tang.go +# github.com/apricote/hcloud-upload-image/hcloudimages v0.3.0 +## explicit; go 1.22.2 +github.com/apricote/hcloud-upload-image/hcloudimages +github.com/apricote/hcloud-upload-image/hcloudimages/backoff +github.com/apricote/hcloud-upload-image/hcloudimages/contextlogger +github.com/apricote/hcloud-upload-image/hcloudimages/internal/actionutil +github.com/apricote/hcloud-upload-image/hcloudimages/internal/control +github.com/apricote/hcloud-upload-image/hcloudimages/internal/labelutil +github.com/apricote/hcloud-upload-image/hcloudimages/internal/randomid +github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshkey +github.com/apricote/hcloud-upload-image/hcloudimages/internal/sshsession # github.com/aws/aws-sdk-go v1.44.46 ## explicit; go 1.11 github.com/aws/aws-sdk-go/aws @@ -468,6 +479,11 @@ github.com/gophercloud/gophercloud/pagination # github.com/gophercloud/utils v0.0.0-20220704184730-55bdbbaec4ba ## explicit; go 1.15 github.com/gophercloud/utils/openstack/networking/v2/extensions/security/groups +# github.com/hetznercloud/hcloud-go/v2 v2.9.0 +## explicit; go 1.21 +github.com/hetznercloud/hcloud-go/v2/hcloud +github.com/hetznercloud/hcloud-go/v2/hcloud/internal/instrumentation +github.com/hetznercloud/hcloud-go/v2/hcloud/schema # github.com/inconshreveable/mousetrap v1.0.0 ## explicit github.com/inconshreveable/mousetrap @@ -477,7 +493,7 @@ github.com/jmespath/go-jmespath # github.com/jonboulle/clockwork v0.2.2 ## explicit; go 1.13 github.com/jonboulle/clockwork -# github.com/json-iterator/go v1.1.11 +# github.com/json-iterator/go v1.1.12 ## explicit; go 1.12 github.com/json-iterator/go # github.com/kballard/go-shellquote v0.0.0-20150810074751-d8ec1a69a250 @@ -515,14 +531,11 @@ github.com/lestrrat-go/jwx/x25519 # github.com/lestrrat-go/option v1.0.1 ## explicit; go 1.16 github.com/lestrrat-go/option -# github.com/matttproud/golang_protobuf_extensions v1.0.1 -## explicit -github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd ## explicit github.com/modern-go/concurrent -# github.com/modern-go/reflect2 v1.0.1 -## explicit +# github.com/modern-go/reflect2 v1.0.2 +## explicit; go 1.12 github.com/modern-go/reflect2 # github.com/packethost/packngo v0.21.0 ## explicit; go 1.16 @@ -543,21 +556,21 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/prometheus/client_golang v1.11.1 -## explicit; go 1.13 +# github.com/prometheus/client_golang v1.19.1 +## explicit; go 1.20 github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promhttp -# github.com/prometheus/client_model v0.2.0 -## explicit; go 1.9 +# github.com/prometheus/client_model v0.5.0 +## explicit; go 1.19 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.26.0 -## explicit; go 1.11 +# github.com/prometheus/common v0.48.0 +## explicit; go 1.20 github.com/prometheus/common/expfmt github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/model -# github.com/prometheus/procfs v0.6.0 -## explicit; go 1.13 +# github.com/prometheus/procfs v0.12.0 +## explicit; go 1.19 github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util @@ -805,7 +818,7 @@ golang.org/x/net/internal/socks golang.org/x/net/internal/timeseries golang.org/x/net/proxy golang.org/x/net/trace -# golang.org/x/oauth2 v0.14.0 +# golang.org/x/oauth2 v0.16.0 ## explicit; go 1.18 golang.org/x/oauth2 golang.org/x/oauth2/authhandler @@ -820,13 +833,13 @@ golang.org/x/oauth2/jwt # golang.org/x/sync v0.7.0 ## explicit; go 1.18 golang.org/x/sync/semaphore -# golang.org/x/sys v0.21.0 +# golang.org/x/sys v0.22.0 ## explicit; go 1.18 golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.21.0 +# golang.org/x/term v0.22.0 ## explicit; go 1.18 golang.org/x/term # golang.org/x/text v0.16.0 @@ -955,6 +968,7 @@ google.golang.org/grpc/status google.golang.org/grpc/tap # google.golang.org/protobuf v1.33.0 ## explicit; go 1.17 +google.golang.org/protobuf/encoding/protodelim google.golang.org/protobuf/encoding/protojson google.golang.org/protobuf/encoding/prototext google.golang.org/protobuf/encoding/protowire From 0f87509edcbaca00a6e4ec0c95d928e16b5e741e Mon Sep 17 00:00:00 2001 From: Mathieu Tortuyaux Date: Mon, 10 Jun 2024 15:20:35 +0200 Subject: [PATCH 3/6] platform/api: add Hetzner API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Tortuyaux Co-authored-by: Julian Tölle --- platform/api/hetzner/api.go | 391 ++++++++++++++++++++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 platform/api/hetzner/api.go diff --git a/platform/api/hetzner/api.go b/platform/api/hetzner/api.go new file mode 100644 index 000000000..d2eb3e9a8 --- /dev/null +++ b/platform/api/hetzner/api.go @@ -0,0 +1,391 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "context" + "fmt" + "net" + "net/url" + "os" + "sort" + "strings" + "time" + + "github.com/flatcar/mantle/platform" + "github.com/flatcar/mantle/version" + + "github.com/apricote/hcloud-upload-image/hcloudimages" + "github.com/hetznercloud/hcloud-go/v2/hcloud" +) + +var ( + DefaultLabels = map[string]string{ + "managed-by": "mantle", + } +) + +// Options hold the specific Hetzner options. +type Options struct { + *platform.Options + // Image is the ID of the Hetzner image to deploy. + Image string + // ServerType is the type of the instance (e.g. cx22). + ServerType string + // Location is used as "default" zone for all requests. + Location string + // Token is used to construct the Hetzner client + Token string +} + +// API is a wrapper around Hetzner instance API. +type API struct { + client *hcloud.Client + imagesclient *hcloudimages.Client + + serverType *hcloud.ServerType + image *hcloud.Image + location *hcloud.Location +} + +type Server struct{ *hcloud.Server } + +type SSHKey struct{ *hcloud.SSHKey } + +type Network struct{ *hcloud.Network } + +// New returns a Hetzner API instance. +func New(opts *Options) (*API, error) { + client := hcloud.NewClient( + hcloud.WithToken(opts.Token), + hcloud.WithApplication("flatcar-mantle", version.Version), + hcloud.WithPollBackoffFunc(hcloud.ExponentialBackoff(2, 500*time.Millisecond)), + ) + + imagesclient := hcloudimages.NewClient(client) + + ctx := context.Background() + + serverType, _, err := client.ServerType.Get(ctx, opts.ServerType) + if err != nil { + return nil, fmt.Errorf("verifying server type: %w", err) + } + + var image *hcloud.Image + if opts.Image != "" { + image, _, err = client.Image.GetForArchitecture(ctx, opts.Image, serverType.Architecture) + if err != nil { + return nil, fmt.Errorf("verifying image: %w", err) + } + } + + location, _, err := client.Location.Get(ctx, opts.Location) + if err != nil { + return nil, fmt.Errorf("verifying location: %w", err) + } + + return &API{ + client: client, + imagesclient: imagesclient, + + serverType: serverType, + image: image, + location: location, + }, nil +} + +// CreateServer using the Hetzner API. +func (a *API) CreateServer(ctx context.Context, name, userdata string, sshKey *SSHKey, network *Network) (*Server, error) { + opts := hcloud.ServerCreateOpts{ + Name: name, + ServerType: a.serverType, + Image: a.image, + Location: a.location, + UserData: userdata, + } + if sshKey != nil { + opts.SSHKeys = []*hcloud.SSHKey{sshKey.SSHKey} + } + if network != nil { + opts.Networks = []*hcloud.Network{network.Network} + } + + result, _, err := a.client.Server.Create(ctx, opts) + if err != nil { + return nil, fmt.Errorf("failed to request new server: %w", err) + } + + err = a.client.Action.WaitFor(ctx, append(result.NextActions, result.Action)...) + if err != nil { + return nil, fmt.Errorf("failed to create new server: %w", err) + } + + s := result.Server + + if network != nil && len(s.PrivateNet) == 0 { + // In some cases the private net might not be set on the server right after creation. + s, _, err = a.client.Server.GetByID(ctx, result.Server.ID) + if err != nil { + return nil, fmt.Errorf("failed to get updated server: %w", err) + } + } + + return &Server{s}, nil +} + +func (a *API) DeleteServer(ctx context.Context, id int64) error { + server, _, err := a.client.Server.GetByID(ctx, id) + if err != nil { + return fmt.Errorf("failed to find server: %w", err) + } + + if server == nil { + // No server with that ID exists in this project + return nil + } + + result, _, err := a.client.Server.DeleteWithResult(ctx, server) + if err != nil { + return fmt.Errorf("failed to request server delete: %w", err) + } + + err = a.client.Action.WaitFor(ctx, result.Action) + if err != nil { + return fmt.Errorf("failed to delete server: %w", err) + } + + return nil +} + +func (a *API) CreateSSHKey(ctx context.Context, name, publicKey string) (*SSHKey, error) { + sshKey, _, err := a.client.SSHKey.Create(ctx, hcloud.SSHKeyCreateOpts{ + Name: name, + PublicKey: publicKey, + Labels: DefaultLabels, + }) + if err != nil { + return nil, err + } + + return &SSHKey{sshKey}, nil +} + +func (a *API) DeleteSSHKey(ctx context.Context, key *SSHKey) error { + _, err := a.client.SSHKey.Delete(ctx, key.SSHKey) + return err +} + +func (a *API) CreateNetwork(ctx context.Context, name string) (*Network, error) { + _, ipnet, err := net.ParseCIDR("10.0.0.0/16") + if err != nil { + return nil, fmt.Errorf("parsing CIDR for network: %w", err) + } + + network, _, err := a.client.Network.Create(ctx, hcloud.NetworkCreateOpts{ + Name: name, + IPRange: ipnet, + Subnets: []hcloud.NetworkSubnet{{ + Type: hcloud.NetworkSubnetTypeCloud, + IPRange: ipnet, + NetworkZone: a.location.NetworkZone, + }}, + Labels: DefaultLabels, + }) + if err != nil { + return nil, fmt.Errorf("creating network: %w", err) + } + + return &Network{network}, nil +} + +func (a *API) DeleteNetwork(ctx context.Context, network *Network) error { + _, err := a.client.Network.Delete(ctx, network.Network) + if err != nil { + return fmt.Errorf("deleting network: %w", err) + } + + return nil +} + +func (a *API) UploadImage(ctx context.Context, name, path, board string) (int64, error) { + opts := hcloudimages.UploadOptions{ + ImageCompression: hcloudimages.CompressionBZ2, + Description: hcloud.Ptr(name), + Labels: DefaultLabels, + } + + parsedUrl, err := url.Parse(path) + if err != nil { + return 0, fmt.Errorf("parsing path: %w", err) + } + + if parsedUrl.Scheme != "" { + opts.ImageURL = parsedUrl + } else { + opts.ImageReader, err = os.Open(path) + if err != nil { + return 0, fmt.Errorf("opening local path: %w", err) + } + } + + switch board { + case "amd64-usr": + opts.Architecture = hcloud.ArchitectureX86 + case "arm64-usr": + opts.Architecture = hcloud.ArchitectureARM + } + + image, err := a.imagesclient.Upload(ctx, opts) + if err != nil { + return 0, fmt.Errorf("uploading the image: %w", err) + } + + return image.ID, nil +} + +// GC is the garbage collection (when we want to clear the project from resources created by Mantle (servers, images, etc.)) +func (a *API) GC(ctx context.Context, gracePeriod time.Duration) error { + createdCutoff := time.Now().Add(-gracePeriod) + + if err := a.gcServers(ctx, createdCutoff); err != nil { + return fmt.Errorf("failed to gc servers: %w", err) + } + + if err := a.gcImages(ctx, createdCutoff); err != nil { + return fmt.Errorf("failed to gc servers: %w", err) + } + + if err := a.gcSSHKeys(ctx, createdCutoff); err != nil { + return fmt.Errorf("failed to gc ssh keys: %w", err) + } + + if err := a.gcNetworks(ctx, createdCutoff); err != nil { + return fmt.Errorf("failed to gc networks: %w", err) + } + + return nil +} + +func (a *API) gcServers(ctx context.Context, createdCutoff time.Time) error { + servers, err := a.client.Server.AllWithOpts(ctx, hcloud.ServerListOpts{ + ListOpts: hcloud.ListOpts{ + LabelSelector: labelSelector(DefaultLabels), + }, + }) + if err != nil { + return fmt.Errorf("failed to list current servers: %w", err) + } + + for _, server := range servers { + if server.Created.After(createdCutoff) { + continue + } + + // Delete in series, could be made faster by triggering batches of deletes and then wait on the actions in parallel + result, _, err := a.client.Server.DeleteWithResult(ctx, server) + if err != nil { + return fmt.Errorf("failed to request server delete: %w", err) + } + + err = a.client.Action.WaitFor(ctx, result.Action) + if err != nil { + return fmt.Errorf("failed to delete server: %w", err) + } + } + + return nil +} + +func (a *API) gcImages(ctx context.Context, createdCutoff time.Time) error { + images, err := a.client.Image.AllWithOpts(ctx, hcloud.ImageListOpts{ + ListOpts: hcloud.ListOpts{ + LabelSelector: labelSelector(DefaultLabels), + }, + Type: []hcloud.ImageType{hcloud.ImageTypeSnapshot}, + }) + if err != nil { + return fmt.Errorf("failed to list current images: %w", err) + } + + for _, image := range images { + if image.Created.After(createdCutoff) { + continue + } + + _, err := a.client.Image.Delete(ctx, image) + if err != nil { + return fmt.Errorf("failed to delete image: %w", err) + } + } + + return nil +} + +func (a *API) gcSSHKeys(ctx context.Context, createdCutoff time.Time) error { + sshKeys, err := a.client.SSHKey.AllWithOpts(ctx, hcloud.SSHKeyListOpts{ + ListOpts: hcloud.ListOpts{ + LabelSelector: labelSelector(DefaultLabels), + }, + }) + if err != nil { + return fmt.Errorf("failed to list current ssh keys: %w", err) + } + + for _, sshKey := range sshKeys { + if sshKey.Created.After(createdCutoff) { + continue + } + + _, err := a.client.SSHKey.Delete(ctx, sshKey) + if err != nil { + return fmt.Errorf("failed to delete ssh key: %w", err) + } + } + + return nil +} + +func (a *API) gcNetworks(ctx context.Context, createdCutoff time.Time) error { + networks, err := a.client.Network.AllWithOpts(ctx, hcloud.NetworkListOpts{ + ListOpts: hcloud.ListOpts{ + LabelSelector: labelSelector(DefaultLabels), + }, + }) + if err != nil { + return fmt.Errorf("failed to list current networks: %w", err) + } + + for _, network := range networks { + if network.Created.After(createdCutoff) { + continue + } + + _, err := a.client.Network.Delete(ctx, network) + if err != nil { + return fmt.Errorf("failed to delete network: %w", err) + } + } + + return nil +} + +// GetConsoleOutput returns the console output using API calls or other. +func (a *API) GetConsoleOutput(id string) (string, error) { + // Hetzner Cloud API does not have an easy way to retrieve this. + // There is only the VNC console that could be used to get the last x lines of output. + return "", nil +} + +func labelSelector(labels map[string]string) string { + selectors := make([]string, 0, len(labels)) + + for k, v := range labels { + selectors = append(selectors, fmt.Sprintf("%s=%s", k, v)) + } + + // Reproducible result for tests + sort.Strings(selectors) + + return strings.Join(selectors, ",") +} From e1c2d45030c00092d14f6e55fbd93d0c4a95695a Mon Sep 17 00:00:00 2001 From: Mathieu Tortuyaux Date: Mon, 10 Jun 2024 15:21:02 +0200 Subject: [PATCH 4/6] platform: implement the kola elements for Hetzner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Tortuyaux Co-authored-by: Julian Tölle --- cmd/kola/options.go | 9 ++- kola/harness.go | 5 ++ platform/machine/hetzner/cluster.go | 102 ++++++++++++++++++++++++++++ platform/machine/hetzner/flight.go | 98 ++++++++++++++++++++++++++ platform/machine/hetzner/machine.go | 96 ++++++++++++++++++++++++++ 5 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 platform/machine/hetzner/cluster.go create mode 100644 platform/machine/hetzner/flight.go create mode 100644 platform/machine/hetzner/machine.go diff --git a/cmd/kola/options.go b/cmd/kola/options.go index 2d9781080..3894a6961 100644 --- a/cmd/kola/options.go +++ b/cmd/kola/options.go @@ -40,7 +40,7 @@ var ( kolaOffering string defaultTargetBoard = sdk.DefaultBoard() kolaArchitectures = []string{"amd64"} - kolaPlatforms = []string{"aws", "azure", "brightbox", "do", "esx", "external", "gce", "openstack", "equinixmetal", "qemu", "qemu-unpriv", "scaleway"} + kolaPlatforms = []string{"aws", "azure", "brightbox", "do", "esx", "external", "gce", "hetzner", "openstack", "equinixmetal", "qemu", "qemu-unpriv", "scaleway"} kolaDistros = []string{"cl", "fcos", "rhcos"} kolaChannels = []string{"alpha", "beta", "stable", "edge", "lts"} kolaOfferings = []string{"basic", "pro"} @@ -243,6 +243,12 @@ func init() { sv(&kola.ScalewayOptions.SecretKey, "scaleway-secret-key", "", "Scaleway credentials secret key") sv(&kola.ScalewayOptions.Image, "scaleway-image", "", "Scaleway image ID") sv(&kola.ScalewayOptions.InstanceType, "scaleway-instance-type", "DEV1-S", "Scaleway instance type") + + // Hetzner specific options + sv(&kola.HetznerOptions.Token, "hetzner-token", "", "Hetzner token for client authentication") + sv(&kola.HetznerOptions.Location, "hetzner-location", "fsn1", "Hetzner location name") + sv(&kola.HetznerOptions.Image, "hetzner-image", "", "Hetzner image ID") + sv(&kola.HetznerOptions.ServerType, "hetzner-server-type", "cx22", "Hetzner instance type") } // Sync up the command line options if there is dependency @@ -263,6 +269,7 @@ func syncOptions() error { kola.EquinixMetalOptions.GSOptions = &kola.GCEOptions kola.BrightboxOptions.Board = board kola.ScalewayOptions.Board = board + kola.HetznerOptions.Board = board validateOption := func(name, item string, valid []string) error { for _, v := range valid { diff --git a/kola/harness.go b/kola/harness.go index cb59f5f5d..6398b52d6 100644 --- a/kola/harness.go +++ b/kola/harness.go @@ -45,6 +45,7 @@ import ( equinixmetalapi "github.com/flatcar/mantle/platform/api/equinixmetal" esxapi "github.com/flatcar/mantle/platform/api/esx" gcloudapi "github.com/flatcar/mantle/platform/api/gcloud" + hetznerapi "github.com/flatcar/mantle/platform/api/hetzner" openstackapi "github.com/flatcar/mantle/platform/api/openstack" scalewayapi "github.com/flatcar/mantle/platform/api/scaleway" "github.com/flatcar/mantle/platform/conf" @@ -56,6 +57,7 @@ import ( "github.com/flatcar/mantle/platform/machine/esx" "github.com/flatcar/mantle/platform/machine/external" "github.com/flatcar/mantle/platform/machine/gcloud" + "github.com/flatcar/mantle/platform/machine/hetzner" "github.com/flatcar/mantle/platform/machine/openstack" "github.com/flatcar/mantle/platform/machine/qemu" "github.com/flatcar/mantle/platform/machine/scaleway" @@ -78,6 +80,7 @@ var ( EquinixMetalOptions = equinixmetalapi.Options{Options: &Options} // glue to set platform options from main QEMUOptions = qemu.Options{Options: &Options} // glue to set platform options from main ScalewayOptions = scalewayapi.Options{Options: &Options} // glue to set platform options from main + HetznerOptions = hetznerapi.Options{Options: &Options} // glue to set platform options from main TestParallelism int //glue var to set test parallelism from main TAPFile string // if not "", write TAP results here @@ -241,6 +244,8 @@ func NewFlight(pltfrm string) (flight platform.Flight, err error) { flight, err = external.NewFlight(&ExternalOptions) case "gce": flight, err = gcloud.NewFlight(&GCEOptions) + case "hetzner": + flight, err = hetzner.NewFlight(&HetznerOptions) case "openstack": flight, err = openstack.NewFlight(&OpenStackOptions) case "equinixmetal": diff --git a/platform/machine/hetzner/cluster.go b/platform/machine/hetzner/cluster.go new file mode 100644 index 000000000..6c3d3550c --- /dev/null +++ b/platform/machine/hetzner/cluster.go @@ -0,0 +1,102 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "context" + "crypto/rand" + "fmt" + "os" + "path/filepath" + + "github.com/flatcar/mantle/platform" + "github.com/flatcar/mantle/platform/api/hetzner" + "github.com/flatcar/mantle/platform/conf" +) + +type cluster struct { + *platform.BaseCluster + flight *flight + sshKey *hetzner.SSHKey + network *hetzner.Network +} + +func (bc *cluster) NewMachine(userdata *conf.UserData) (platform.Machine, error) { + conf, err := bc.RenderUserData(userdata, map[string]string{ + "$public_ipv4": "${COREOS_CUSTOM_PUBLIC_IPV4}", + "$private_ipv4": "${COREOS_CUSTOM_PRIVATE_IPV4}", + }) + if err != nil { + return nil, err + } + + // Hack to workaround CT inheritance. + // Can be dropped once we remove CT dependency. + // https://github.com/flatcar/Flatcar/issues/1386 + // Does this need a workaround for https://github.com/coreos/afterburn/pull/1083? + // The COREOS_COREOS line is a workaround for https://github.com/coreos/afterburn/pull/1083 + conf.AddSystemdUnitDropin("coreos-metadata.service", "00-custom-metadata.conf", `[Service] +ExecStartPost=/usr/bin/sed -i "s/HETZNER/CUSTOM/" /run/metadata/flatcar +ExecStartPost=/usr/bin/sed -i "s/COREOS_CUSTOM_PRIVATE_IPV4_0/COREOS_CUSTOM_PRIVATE_IPV4/" /run/metadata/flatcar +`) + + instance, err := bc.flight.api.CreateServer(context.TODO(), bc.vmname(), conf.String(), bc.sshKey, bc.network) + if err != nil { + return nil, err + } + + mach := &machine{ + cluster: bc, + mach: instance, + } + + // machine to destroy + m := mach + defer func() { + if m != nil { + m.Destroy() + } + }() + + mach.dir = filepath.Join(bc.RuntimeConf().OutputDir, mach.ID()) + if err := os.Mkdir(mach.dir, 0777); err != nil { + return nil, err + } + + confPath := filepath.Join(mach.dir, "ignition.json") + if err := conf.WriteFile(confPath); err != nil { + return nil, err + } + + if mach.journal, err = platform.NewJournal(mach.dir); err != nil { + return nil, err + } + + if err := platform.StartMachine(mach, mach.journal); err != nil { + return nil, err + } + + m = nil + bc.AddMach(mach) + + return mach, nil +} + +func (bc *cluster) vmname() string { + b := make([]byte, 5) + rand.Read(b) + return fmt.Sprintf("%s-%x", bc.Name()[0:13], b) +} + +func (bc *cluster) Destroy() { + bc.BaseCluster.Destroy() + if bc.network != nil { + if err := bc.flight.api.DeleteNetwork(context.TODO(), bc.network); err != nil { + plog.Errorf("deleting network %v: %v", bc.network.Name, err) + } + + } + + bc.flight.DelCluster(bc) +} diff --git a/platform/machine/hetzner/flight.go b/platform/machine/hetzner/flight.go new file mode 100644 index 000000000..1e4624d06 --- /dev/null +++ b/platform/machine/hetzner/flight.go @@ -0,0 +1,98 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "context" + "fmt" + + "github.com/coreos/pkg/capnslog" + ctplatform "github.com/flatcar/container-linux-config-transpiler/config/platform" + + "github.com/flatcar/mantle/platform" + "github.com/flatcar/mantle/platform/api/hetzner" +) + +const ( + Platform platform.Name = "hetzner" +) + +var ( + plog = capnslog.NewPackageLogger("github.com/flatcar/mantle", "platform/machine/hetzner") +) + +type flight struct { + *platform.BaseFlight + api *hetzner.API + + sshKey *hetzner.SSHKey +} + +func NewFlight(opts *hetzner.Options) (platform.Flight, error) { + api, err := hetzner.New(opts) + if err != nil { + return nil, fmt.Errorf("creating hetzner API client: %w", err) + } + + // TODO: Rework the Base Flight to remove the CT dependency. + base, err := platform.NewBaseFlight(opts.Options, Platform, ctplatform.Custom) + if err != nil { + return nil, fmt.Errorf("creating base flight: %w", err) + } + + bf := &flight{ + BaseFlight: base, + api: api, + } + + keys, err := bf.Keys() + if err != nil { + bf.Destroy() + return nil, err + } + if len(keys) > 0 { + bf.sshKey, err = api.CreateSSHKey(context.TODO(), bf.Name(), keys[0].String()) + if err != nil { + bf.Destroy() + return nil, err + } + } + + return bf, nil +} + +// NewCluster creates an instance of a Cluster suitable for spawning +// instances on the Hetzner platform. +func (bf *flight) NewCluster(rconf *platform.RuntimeConfig) (platform.Cluster, error) { + bc, err := platform.NewBaseCluster(bf.BaseFlight, rconf) + if err != nil { + return nil, fmt.Errorf("creating hetzner base cluster: %w", err) + } + + c := &cluster{ + BaseCluster: bc, + flight: bf, + } + + if !rconf.NoSSHKeyInMetadata { + c.sshKey = bf.sshKey + } + + c.network, err = bf.api.CreateNetwork(context.TODO(), bc.Name()) + if err != nil { + return nil, fmt.Errorf("creating network for cluster: %w", err) + } + + bf.AddCluster(c) + + return c, nil +} + +func (bf *flight) Destroy() { + if bf.sshKey != nil { + _ = bf.api.DeleteSSHKey(context.TODO(), bf.sshKey) + } + + bf.BaseFlight.Destroy() +} diff --git a/platform/machine/hetzner/machine.go b/platform/machine/hetzner/machine.go new file mode 100644 index 000000000..df28bafeb --- /dev/null +++ b/platform/machine/hetzner/machine.go @@ -0,0 +1,96 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "context" + "strconv" + + "golang.org/x/crypto/ssh" + + "github.com/flatcar/mantle/platform" + "github.com/flatcar/mantle/platform/api/hetzner" +) + +type machine struct { + cluster *cluster + mach *hetzner.Server + dir string + journal *platform.Journal + console string +} + +// ID returns the ID of the machine. +func (bm *machine) ID() string { + return strconv.FormatInt(bm.mach.Server.ID, 10) +} + +// IP returns the IP of the machine. +func (bm *machine) IP() string { + return bm.mach.Server.PublicNet.IPv4.IP.String() +} + +// PrivateIP returns the private IP of the machine. +func (bm *machine) PrivateIP() string { + if len(bm.mach.Server.PrivateNet) > 0 { + return bm.mach.Server.PrivateNet[0].IP.String() + } + + return "" +} + +// RuntimeConf returns the runtime configuration of the cluster. +func (bm *machine) RuntimeConf() *platform.RuntimeConfig { + return bm.cluster.RuntimeConf() +} + +func (bm *machine) SSHClient() (*ssh.Client, error) { + return bm.cluster.SSHClient(bm.IP()) +} + +func (bm *machine) PasswordSSHClient(user string, password string) (*ssh.Client, error) { + return bm.cluster.PasswordSSHClient(bm.IP(), user, password) +} + +func (bm *machine) SSH(cmd string) ([]byte, []byte, error) { + return bm.cluster.SSH(bm, cmd) +} + +func (bm *machine) Reboot() error { + return platform.RebootMachine(bm, bm.journal) +} + +func (bm *machine) Destroy() { + // TODO: Add "saveConsole" logic here when Hetzner API will support fetching the console output. + + if err := bm.cluster.flight.api.DeleteServer(context.TODO(), bm.mach.ID); err != nil { + plog.Errorf("deleting server %v: %v", bm.ID(), err) + } + + if bm.journal != nil { + bm.journal.Destroy() + } + + bm.cluster.DelMach(bm) +} + +func (bm *machine) ConsoleOutput() string { + return bm.console +} + +func (bm *machine) JournalOutput() string { + if bm.journal == nil { + return "" + } + + data, err := bm.journal.Read() + if err != nil { + plog.Errorf("Reading journal for instance %v: %v", bm.ID(), err) + } + return string(data) +} + +func (bm *machine) Board() string { + return bm.cluster.flight.Options().Board +} From a1e4ce4a310fdf50219d4435a9f8460f99d1abcf Mon Sep 17 00:00:00 2001 From: Mathieu Tortuyaux Date: Mon, 10 Jun 2024 15:28:19 +0200 Subject: [PATCH 5/6] ore/hetzner: add image upload and garbage collection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Tortuyaux Co-authored-by: Julian Tölle --- cmd/ore/hetzner.go | 12 +++++++++++ cmd/ore/hetzner/create.go | 44 ++++++++++++++++++++++++++++++++++++++ cmd/ore/hetzner/gc.go | 35 ++++++++++++++++++++++++++++++ cmd/ore/hetzner/hetzner.go | 42 ++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 cmd/ore/hetzner.go create mode 100644 cmd/ore/hetzner/create.go create mode 100644 cmd/ore/hetzner/gc.go create mode 100644 cmd/ore/hetzner/hetzner.go diff --git a/cmd/ore/hetzner.go b/cmd/ore/hetzner.go new file mode 100644 index 000000000..cb2845211 --- /dev/null +++ b/cmd/ore/hetzner.go @@ -0,0 +1,12 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "github.com/flatcar/mantle/cmd/ore/hetzner" +) + +func init() { + root.AddCommand(hetzner.Hetzner) +} diff --git a/cmd/ore/hetzner/create.go b/cmd/ore/hetzner/create.go new file mode 100644 index 000000000..ec19d0336 --- /dev/null +++ b/cmd/ore/hetzner/create.go @@ -0,0 +1,44 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var ( + cmdCreate = &cobra.Command{ + Use: "create-image", + Short: "Create image on Hetzner", + Long: `Upload an image to Hetzner. + +After a successful run, the final line of output will be the ID of the image. +`, + RunE: runCreate, + } + + path string + name string + board string +) + +func init() { + Hetzner.AddCommand(cmdCreate) + cmdCreate.Flags().StringVar(&path, "file", + "https://alpha.release.flatcar-linux.net/amd64-usr/current/flatcar_production_hetzner_image.bin.bz2", + "Flatcar image (can be an absolute path or an URL)") + cmdCreate.Flags().StringVar(&name, "name", "", "image name") + cmdCreate.Flags().StringVar(&board, "board", "amd64-usr", "board of the image") +} + +func runCreate(cmd *cobra.Command, args []string) error { + id, err := API.UploadImage(cmd.Context(), name, path, board) + if err != nil { + return fmt.Errorf("creating an image: %w", err) + } + fmt.Println(id) + return nil +} diff --git a/cmd/ore/hetzner/gc.go b/cmd/ore/hetzner/gc.go new file mode 100644 index 000000000..16e377fb9 --- /dev/null +++ b/cmd/ore/hetzner/gc.go @@ -0,0 +1,35 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "fmt" + "time" + + "github.com/spf13/cobra" +) + +var ( + cmdGC = &cobra.Command{ + Use: "gc", + Short: "GC resources in Hetzner", + Long: `Delete instances and images created over the given duration ago`, + RunE: runGC, + } + + gcDuration time.Duration +) + +func init() { + Hetzner.AddCommand(cmdGC) + cmdGC.Flags().DurationVar(&gcDuration, "duration", 5*time.Hour, "how old resources must be before they're considered garbage") +} + +func runGC(cmd *cobra.Command, args []string) error { + if err := API.GC(cmd.Context(), gcDuration); err != nil { + return fmt.Errorf("running garbage collection: %w", err) + } + + return nil +} diff --git a/cmd/ore/hetzner/hetzner.go b/cmd/ore/hetzner/hetzner.go new file mode 100644 index 000000000..b04431cf1 --- /dev/null +++ b/cmd/ore/hetzner/hetzner.go @@ -0,0 +1,42 @@ +// Copyright The Mantle Authors. +// SPDX-License-Identifier: Apache-2.0 + +package hetzner + +import ( + "fmt" + + "github.com/coreos/pkg/capnslog" + "github.com/spf13/cobra" + + "github.com/flatcar/mantle/cli" + "github.com/flatcar/mantle/platform/api/hetzner" +) + +var ( + plog = capnslog.NewPackageLogger("github.com/flatcar/mantle", "ore/hetzner") + + Hetzner = &cobra.Command{ + Use: "hetzner [command]", + Short: "hetzner image utilities", + } + + API *hetzner.API + options hetzner.Options +) + +func init() { + cli.WrapPreRun(Hetzner, preflightCheck) + Hetzner.PersistentFlags().StringVar(&options.Token, "hetzner-token", "", "Hetzner token for client authentication") + Hetzner.PersistentFlags().StringVar(&options.Location, "hetzner-location", "", "Hetzner location name") +} + +func preflightCheck(cmd *cobra.Command, args []string) error { + api, err := hetzner.New(&options) + if err != nil { + return fmt.Errorf("creating the Hetner API client: %w", err) + } + + API = api + return nil +} From 1ce68f96df08893734d5f0b40c576ad3928dcc1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20T=C3=B6lle?= Date: Wed, 21 Aug 2024 15:53:10 +0200 Subject: [PATCH 6/6] kola: disable cloudinit tests for Hetzner coreos-cloudinit does not support Hetzner. --- kola/tests/misc/cloudinit.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kola/tests/misc/cloudinit.go b/kola/tests/misc/cloudinit.go index 9ef74d541..44a916db0 100644 --- a/kola/tests/misc/cloudinit.go +++ b/kola/tests/misc/cloudinit.go @@ -155,8 +155,9 @@ hostname: "core1" write_files: - path: "/foo" content: bar`), - Distros: []string{"cl"}, - ExcludePlatforms: []string{"qemu-unpriv"}, + Distros: []string{"cl"}, + // Hetzner: we need to implement coreos-cloudinit support for Hetzner. + ExcludePlatforms: []string{"qemu-unpriv", "hetzner"}, // This should run on all clouds }) register.Register(®ister.Test{