Update swagger to 0.20.1 (#8010)
* update swagger to 0.20.1 * fiw swagger version for validaterelease/v1.15
parent
e0f95d1545
commit
256b178176
4
Makefile
4
Makefile
|
@ -102,7 +102,7 @@ generate:
|
||||||
.PHONY: generate-swagger
|
.PHONY: generate-swagger
|
||||||
generate-swagger:
|
generate-swagger:
|
||||||
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||||
GO111MODULE="on" $(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.19.0; \
|
GO111MODULE="on" $(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.20.1; \
|
||||||
fi
|
fi
|
||||||
swagger generate spec -o './$(SWAGGER_SPEC)'
|
swagger generate spec -o './$(SWAGGER_SPEC)'
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||||
|
@ -120,7 +120,7 @@ swagger-check: generate-swagger
|
||||||
.PHONY: swagger-validate
|
.PHONY: swagger-validate
|
||||||
swagger-validate:
|
swagger-validate:
|
||||||
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||||
$(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger; \
|
GO111MODULE="on" $(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.20.1; \
|
||||||
fi
|
fi
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
|
||||||
swagger validate './$(SWAGGER_SPEC)'
|
swagger validate './$(SWAGGER_SPEC)'
|
||||||
|
|
23
go.mod
23
go.mod
|
@ -3,6 +3,7 @@ module code.gitea.io/gitea
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
cloud.google.com/go v0.44.3 // indirect
|
||||||
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b
|
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b
|
||||||
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76
|
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76
|
||||||
gitea.com/macaron/captcha v0.0.0-20190822015246-daa973478bae
|
gitea.com/macaron/captcha v0.0.0-20190822015246-daa973478bae
|
||||||
|
@ -48,6 +49,8 @@ require (
|
||||||
github.com/go-xorm/xorm v0.7.7-0.20190822154023-17592d96b35b
|
github.com/go-xorm/xorm v0.7.7-0.20190822154023-17592d96b35b
|
||||||
github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561
|
github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561
|
||||||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
|
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
|
||||||
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
|
github.com/google/go-cmp v0.3.1 // indirect
|
||||||
github.com/google/go-github/v24 v24.0.1
|
github.com/google/go-github/v24 v24.0.1
|
||||||
github.com/gorilla/context v1.1.1
|
github.com/gorilla/context v1.1.1
|
||||||
github.com/issue9/assert v1.3.2 // indirect
|
github.com/issue9/assert v1.3.2 // indirect
|
||||||
|
@ -70,13 +73,17 @@ require (
|
||||||
github.com/mattn/go-sqlite3 v1.11.0
|
github.com/mattn/go-sqlite3 v1.11.0
|
||||||
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75
|
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75
|
||||||
github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a
|
github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect
|
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect
|
||||||
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
|
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
|
||||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
|
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
|
||||||
github.com/oliamb/cutter v0.2.2
|
github.com/oliamb/cutter v0.2.2
|
||||||
github.com/philhofer/fwd v1.0.0 // indirect
|
github.com/philhofer/fwd v1.0.0 // indirect
|
||||||
github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e
|
github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e
|
||||||
github.com/prometheus/client_golang v0.9.3
|
github.com/prometheus/client_golang v1.1.0
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect
|
||||||
|
github.com/prometheus/procfs v0.0.4 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect
|
||||||
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff
|
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff
|
||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
|
||||||
|
@ -86,7 +93,7 @@ require (
|
||||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc // indirect
|
github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc // indirect
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
|
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
|
||||||
github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 // indirect
|
github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 // indirect
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect
|
github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect
|
||||||
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 // indirect
|
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 // indirect
|
||||||
github.com/tstranex/u2f v1.0.0
|
github.com/tstranex/u2f v1.0.0
|
||||||
|
@ -97,13 +104,13 @@ require (
|
||||||
github.com/urfave/cli v1.20.0
|
github.com/urfave/cli v1.20.0
|
||||||
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect
|
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect
|
||||||
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
|
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
|
||||||
go.etcd.io/bbolt v1.3.2 // indirect
|
go.etcd.io/bbolt v1.3.3 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456
|
||||||
golang.org/x/text v0.3.2
|
golang.org/x/text v0.3.2
|
||||||
golang.org/x/tools v0.0.0-20190731214159-1e85ed8060aa // indirect
|
golang.org/x/tools v0.0.0-20190827205025-b29f5f60c37a // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
|
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
|
||||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0
|
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0
|
||||||
|
|
106
go.sum
106
go.sum
|
@ -3,6 +3,11 @@ cloud.google.com/go v0.30.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
|
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
|
||||||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.3 h1:0sMegbmn/8uTwpNkB0q9cLEpZ2W5a6kl+wtBQgPWBJQ=
|
||||||
|
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b h1:vXt85uYV17KURaUlhU7v4GbCShkqRZDSfo0TkC0YCjQ=
|
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b h1:vXt85uYV17KURaUlhU7v4GbCShkqRZDSfo0TkC0YCjQ=
|
||||||
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b/go.mod h1:Cxadig6POWpPYYSfg23E7jo35Yf0yvsdC1lifoKWmPo=
|
gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b/go.mod h1:Cxadig6POWpPYYSfg23E7jo35Yf0yvsdC1lifoKWmPo=
|
||||||
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76 h1:mMsMEg90c5KXQgRWsH8D6GHXfZIW1RAe5S9VYIb12lM=
|
gitea.com/macaron/cache v0.0.0-20190822004001-a6e7fee4ee76 h1:mMsMEg90c5KXQgRWsH8D6GHXfZIW1RAe5S9VYIb12lM=
|
||||||
|
@ -27,7 +32,7 @@ gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 h1:N9QFoeNsUXLhl14m
|
||||||
gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7/go.mod h1:kgsbFPPS4P+acDYDOPDa3N4IWWOuDJt5/INKRUz7aks=
|
gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7/go.mod h1:kgsbFPPS4P+acDYDOPDa3N4IWWOuDJt5/INKRUz7aks=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34 h1:UsHpWO0Elp6NaWVARdZHjiYwkhrspHVEGsyIKPb9OI8=
|
github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34 h1:UsHpWO0Elp6NaWVARdZHjiYwkhrspHVEGsyIKPb9OI8=
|
||||||
github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA=
|
github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA=
|
||||||
github.com/RoaringBitmap/roaring v0.4.7 h1:eGUudvFzvF7Kxh7JjYvXfI1f7l22/2duFby7r5+d4oc=
|
github.com/RoaringBitmap/roaring v0.4.7 h1:eGUudvFzvF7Kxh7JjYvXfI1f7l22/2duFby7r5+d4oc=
|
||||||
|
@ -49,6 +54,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3 h1:vinCy/rcjbtxWnMiw11CbMKcuyNi+y4L4MbZUpk7m4M=
|
github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3 h1:vinCy/rcjbtxWnMiw11CbMKcuyNi+y4L4MbZUpk7m4M=
|
||||||
|
@ -63,7 +70,6 @@ github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 h1:NGpwhs9FOwddM
|
||||||
github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA=
|
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
|
||||||
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f h1:REH9VH5ubNR0skLaOxK7TRJeRbE2dDfvaouQo8FsRcA=
|
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f h1:REH9VH5ubNR0skLaOxK7TRJeRbE2dDfvaouQo8FsRcA=
|
||||||
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f/go.mod h1:6QaC0vFoKWYDth94dHFNgRT2YkT5FHdQp/Yx15aAAi0=
|
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f/go.mod h1:6QaC0vFoKWYDth94dHFNgRT2YkT5FHdQp/Yx15aAAi0=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
@ -93,7 +99,6 @@ github.com/denisenkom/go-mssqldb v0.0.0-20190724012636-11b2859924c1 h1:vHTzcl17W
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190724012636-11b2859924c1/go.mod h1:uU0N10vx1abI4qeVe79CxepBP6PPREVTgMS5Gx6/mOk=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190724012636-11b2859924c1/go.mod h1:uU0N10vx1abI4qeVe79CxepBP6PPREVTgMS5Gx6/mOk=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
|
||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
|
@ -138,6 +143,7 @@ github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDA
|
||||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
|
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
|
||||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
|
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
|
||||||
|
@ -154,24 +160,35 @@ github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14/go.mod h1:jPoNZLWDAqA5N3
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||||
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
github.com/google/go-github/v24 v24.0.1 h1:KCt1LjMJEey1qvPXxa9SjaWxwTsCWSq6p2Ju57UR4Q4=
|
github.com/google/go-github/v24 v24.0.1 h1:KCt1LjMJEey1qvPXxa9SjaWxwTsCWSq6p2Ju57UR4Q4=
|
||||||
github.com/google/go-github/v24 v24.0.1/go.mod h1:CRqaW1Uns1TCkP0wqTpxYyRxRjxwvKU/XSS44u6X74M=
|
github.com/google/go-github/v24 v24.0.1/go.mod h1:CRqaW1Uns1TCkP0wqTpxYyRxRjxwvKU/XSS44u6X74M=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
|
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
|
||||||
|
@ -188,6 +205,7 @@ github.com/gorilla/sessions v0.0.0-20160922145804-ca9ada445741/go.mod h1:+WVp8kd
|
||||||
github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0PrE=
|
github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0PrE=
|
||||||
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
|
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/issue9/assert v1.3.2 h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0=
|
github.com/issue9/assert v1.3.2 h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0=
|
||||||
|
@ -203,11 +221,14 @@ github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d h1:ig/iUfDDg06
|
||||||
github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
|
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
|
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
|
||||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
|
@ -265,6 +286,10 @@ github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a h1:d18LCO3
|
||||||
github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA=
|
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA=
|
||||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
|
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
|
||||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
|
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
|
||||||
|
@ -274,7 +299,6 @@ github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6ty
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY=
|
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY=
|
||||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
|
||||||
github.com/oliamb/cutter v0.2.2 h1:Lfwkya0HHNU1YLnGv2hTkzHfasrSMkgv4Dn+5rmlk3k=
|
github.com/oliamb/cutter v0.2.2 h1:Lfwkya0HHNU1YLnGv2hTkzHfasrSMkgv4Dn+5rmlk3k=
|
||||||
github.com/oliamb/cutter v0.2.2/go.mod h1:4BenG2/4GuRBDbVm/OPahDVqbrOemzpPiG5mi1iryBU=
|
github.com/oliamb/cutter v0.2.2/go.mod h1:4BenG2/4GuRBDbVm/OPahDVqbrOemzpPiG5mi1iryBU=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
@ -286,6 +310,7 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||||
|
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
|
||||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||||
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
||||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||||
|
@ -299,21 +324,25 @@ github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e h1:ApqncJ84HYN8x8x5WV1
|
||||||
github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk=
|
github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8=
|
||||||
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo=
|
||||||
|
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/procfs v0.0.4 h1:w8DjqFMJDjuVwdZBQoOozr4MVWOnwF7RcL/7uxBjY78=
|
||||||
|
github.com/prometheus/procfs v0.0.4/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 h1:YDeskXpkNDhPdWN3REluVa46HQOVuVkjkd2sWnrABNQ=
|
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 h1:YDeskXpkNDhPdWN3REluVa46HQOVuVkjkd2sWnrABNQ=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
@ -346,7 +375,6 @@ github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUr
|
||||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
|
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
|
||||||
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||||
github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 h1:JNEGSiWg6D3lcBCMCBqN3ELniXujt+0QNHLhNnO0w3s=
|
github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 h1:JNEGSiWg6D3lcBCMCBqN3ELniXujt+0QNHLhNnO0w3s=
|
||||||
|
@ -357,6 +385,8 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
|
@ -384,9 +414,11 @@ github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53 h1:HsIQ6yAjfjQ3Ix
|
||||||
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53/go.mod h1:f6elajwZV+xceiaqgRL090YzLEDGSbqr3poGL3ZgXYo=
|
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53/go.mod h1:f6elajwZV+xceiaqgRL090YzLEDGSbqr3poGL3ZgXYo=
|
||||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||||
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
|
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
@ -395,10 +427,17 @@ golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
|
||||||
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -408,14 +447,21 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
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-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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/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-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -425,47 +471,69 @@ golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20190412213103-97732733099d/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-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0=
|
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0=
|
||||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
|
||||||
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/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=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||||
golang.org/x/tools v0.0.0-20190731214159-1e85ed8060aa h1:kwa/4M1dbmhZqOIqYiTtbA6JrvPwo1+jqlub2qDXX90=
|
golang.org/x/tools v0.0.0-20190827205025-b29f5f60c37a h1:0JEq5ZQ3TgsRlFmz4BcD+E6U6cOk4pOImCQSyIG59ZM=
|
||||||
golang.org/x/tools v0.0.0-20190731214159-1e85ed8060aa/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
golang.org/x/tools v0.0.0-20190827205025-b29f5f60c37a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||||
|
@ -506,8 +574,10 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
mvdan.cc/xurls/v2 v2.0.0 h1:r1zSOSNS/kqtpmATyMMMvaZ4/djsesbYz5kr0+qMRWc=
|
mvdan.cc/xurls/v2 v2.0.0 h1:r1zSOSNS/kqtpmATyMMMvaZ4/djsesbYz5kr0+qMRWc=
|
||||||
mvdan.cc/xurls/v2 v2.0.0/go.mod h1:2/webFPYOXN9jp/lzuj0zuAVlF+9g4KPFJANH1oJhRU=
|
mvdan.cc/xurls/v2 v2.0.0/go.mod h1:2/webFPYOXN9jp/lzuj0zuAVlF+9g4KPFJANH1oJhRU=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a h1:8q33ShxKXRwQ7JVd1ZnhIU3hZhwwn0Le+4fTeAackuM=
|
strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a h1:8q33ShxKXRwQ7JVd1ZnhIU3hZhwwn0Le+4fTeAackuM=
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
|
strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
|
||||||
xorm.io/builder v0.3.5 h1:EilU39fvWDxjb1cDaELpYhsF+zziRBhew8xk4pngO+A=
|
xorm.io/builder v0.3.5 h1:EilU39fvWDxjb1cDaELpYhsF+zziRBhew8xk4pngO+A=
|
||||||
|
|
|
@ -6944,6 +6944,30 @@
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"AccessToken": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "AccessToken represents an API access token.",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"x-go-name": "ID"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Name"
|
||||||
|
},
|
||||||
|
"sha1": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Token"
|
||||||
|
},
|
||||||
|
"token_last_eight": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "TokenLastEight"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"AddCollaboratorOption": {
|
"AddCollaboratorOption": {
|
||||||
"description": "AddCollaboratorOption options when adding a user as a collaborator of a repository",
|
"description": "AddCollaboratorOption options when adding a user as a collaborator of a repository",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -10051,7 +10075,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AccessTokenList": {
|
"AccessTokenList": {
|
||||||
"description": "AccessTokenList represents a list of API access token."
|
"description": "AccessTokenList represents a list of API access token.",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/AccessToken"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"AnnotatedTag": {
|
"AnnotatedTag": {
|
||||||
"description": "AnnotatedTag",
|
"description": "AnnotatedTag",
|
||||||
|
@ -10296,7 +10326,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"MarkdownRender": {
|
"MarkdownRender": {
|
||||||
"description": "MarkdownRender is a rendered markdown document"
|
"description": "MarkdownRender is a rendered markdown document",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Milestone": {
|
"Milestone": {
|
||||||
"description": "Milestone",
|
"description": "Milestone",
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
# This is the official list of cloud authors for copyright purposes.
|
|
||||||
# This file is distinct from the CONTRIBUTORS files.
|
|
||||||
# See the latter for an explanation.
|
|
||||||
|
|
||||||
# Names should be added to this file as:
|
|
||||||
# Name or Organization <email address>
|
|
||||||
# The email address is not required for organizations.
|
|
||||||
|
|
||||||
Filippo Valsorda <hi@filippo.io>
|
|
||||||
Google Inc.
|
|
||||||
Ingo Oeser <nightlyone@googlemail.com>
|
|
||||||
Palm Stone Games, Inc.
|
|
||||||
Paweł Knap <pawelknap88@gmail.com>
|
|
||||||
Péter Szilágyi <peterke@gmail.com>
|
|
||||||
Tyler Treat <ttreat31@gmail.com>
|
|
|
@ -1,40 +0,0 @@
|
||||||
# People who have agreed to one of the CLAs and can contribute patches.
|
|
||||||
# The AUTHORS file lists the copyright holders; this file
|
|
||||||
# lists people. For example, Google employees are listed here
|
|
||||||
# but not in AUTHORS, because Google holds the copyright.
|
|
||||||
#
|
|
||||||
# https://developers.google.com/open-source/cla/individual
|
|
||||||
# https://developers.google.com/open-source/cla/corporate
|
|
||||||
#
|
|
||||||
# Names should be added to this file as:
|
|
||||||
# Name <email address>
|
|
||||||
|
|
||||||
# Keep the list alphabetically sorted.
|
|
||||||
|
|
||||||
Alexis Hunt <lexer@google.com>
|
|
||||||
Andreas Litt <andreas.litt@gmail.com>
|
|
||||||
Andrew Gerrand <adg@golang.org>
|
|
||||||
Brad Fitzpatrick <bradfitz@golang.org>
|
|
||||||
Burcu Dogan <jbd@google.com>
|
|
||||||
Dave Day <djd@golang.org>
|
|
||||||
David Sansome <me@davidsansome.com>
|
|
||||||
David Symonds <dsymonds@golang.org>
|
|
||||||
Filippo Valsorda <hi@filippo.io>
|
|
||||||
Glenn Lewis <gmlewis@google.com>
|
|
||||||
Ingo Oeser <nightlyone@googlemail.com>
|
|
||||||
James Hall <james.hall@shopify.com>
|
|
||||||
Johan Euphrosine <proppy@google.com>
|
|
||||||
Jonathan Amsterdam <jba@google.com>
|
|
||||||
Kunpei Sakai <namusyaka@gmail.com>
|
|
||||||
Luna Duclos <luna.duclos@palmstonegames.com>
|
|
||||||
Magnus Hiie <magnus.hiie@gmail.com>
|
|
||||||
Mario Castro <mariocaster@gmail.com>
|
|
||||||
Michael McGreevy <mcgreevy@golang.org>
|
|
||||||
Omar Jarjur <ojarjur@google.com>
|
|
||||||
Paweł Knap <pawelknap88@gmail.com>
|
|
||||||
Péter Szilágyi <peterke@gmail.com>
|
|
||||||
Sarah Adams <shadams@google.com>
|
|
||||||
Thanatat Tamtan <acoshift@gmail.com>
|
|
||||||
Toby Burress <kurin@google.com>
|
|
||||||
Tuo Shan <shantuo@google.com>
|
|
||||||
Tyler Treat <ttreat31@gmail.com>
|
|
|
@ -38,7 +38,6 @@ package proto
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -194,7 +193,7 @@ func (p *Properties) Parse(s string) {
|
||||||
// "bytes,49,opt,name=foo,def=hello!"
|
// "bytes,49,opt,name=foo,def=hello!"
|
||||||
fields := strings.Split(s, ",") // breaks def=, but handled below.
|
fields := strings.Split(s, ",") // breaks def=, but handled below.
|
||||||
if len(fields) < 2 {
|
if len(fields) < 2 {
|
||||||
fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
|
log.Printf("proto: tag has too few fields: %q", s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +213,7 @@ func (p *Properties) Parse(s string) {
|
||||||
p.WireType = WireBytes
|
p.WireType = WireBytes
|
||||||
// no numeric converter for non-numeric types
|
// no numeric converter for non-numeric types
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
|
log.Printf("proto: tag has unknown wire type: %q", s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
module github.com/golang/snappy
|
29
vendor/github.com/prometheus/client_golang/prometheus/build_info.go
generated
vendored
Normal file
29
vendor/github.com/prometheus/client_golang/prometheus/build_info.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.12
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import "runtime/debug"
|
||||||
|
|
||||||
|
// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go 1.12+.
|
||||||
|
func readBuildInfo() (path, version, sum string) {
|
||||||
|
path, version, sum = "unknown", "unknown", "unknown"
|
||||||
|
if bi, ok := debug.ReadBuildInfo(); ok {
|
||||||
|
path = bi.Main.Path
|
||||||
|
version = bi.Main.Version
|
||||||
|
sum = bi.Main.Sum
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
22
vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go
generated
vendored
Normal file
22
vendor/github.com/prometheus/client_golang/prometheus/build_info_pre_1.12.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !go1.12
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
// readBuildInfo is a wrapper around debug.ReadBuildInfo for Go versions before
|
||||||
|
// 1.12. Remove this whole file once the minimum supported Go version is 1.12.
|
||||||
|
func readBuildInfo() (path, version, sum string) {
|
||||||
|
return "unknown", "unknown", "unknown"
|
||||||
|
}
|
|
@ -183,7 +183,6 @@
|
||||||
// method can then expose the gathered metrics in some way. Usually, the metrics
|
// 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
|
// 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.
|
// above. The tools to expose metrics via HTTP are in the promhttp sub-package.
|
||||||
// (The top-level functions in the prometheus package are deprecated.)
|
|
||||||
//
|
//
|
||||||
// Pushing to the Pushgateway
|
// Pushing to the Pushgateway
|
||||||
//
|
//
|
||||||
|
|
|
@ -36,7 +36,7 @@ type goCollector struct {
|
||||||
msMaxAge time.Duration // Maximum allowed age of old memstats.
|
msMaxAge time.Duration // Maximum allowed age of old memstats.
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGoCollector returns a collector which exports metrics about the current Go
|
// NewGoCollector returns a collector that exports metrics about the current Go
|
||||||
// process. This includes memory stats. To collect those, runtime.ReadMemStats
|
// process. This includes memory stats. To collect those, runtime.ReadMemStats
|
||||||
// is called. This requires to “stop the world”, which usually only happens for
|
// is called. This requires to “stop the world”, which usually only happens for
|
||||||
// garbage collection (GC). Take the following implications into account when
|
// garbage collection (GC). Take the following implications into account when
|
||||||
|
@ -364,3 +364,33 @@ type memStatsMetrics []struct {
|
||||||
eval func(*runtime.MemStats) float64
|
eval func(*runtime.MemStats) float64
|
||||||
valType ValueType
|
valType ValueType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewBuildInfoCollector returns a collector collecting a single metric
|
||||||
|
// "go_build_info" with the constant value 1 and three labels "path", "version",
|
||||||
|
// and "checksum". Their label values contain the main module path, version, and
|
||||||
|
// checksum, respectively. The labels will only have meaningful values if the
|
||||||
|
// binary is built with Go module support and from source code retrieved from
|
||||||
|
// the source repository (rather than the local file system). This is usually
|
||||||
|
// accomplished by building from outside of GOPATH, specifying the full address
|
||||||
|
// of the main package, e.g. "GO111MODULE=on go run
|
||||||
|
// github.com/prometheus/client_golang/examples/random". If built without Go
|
||||||
|
// module support, all label values will be "unknown". If built with Go module
|
||||||
|
// support but using the source code from the local file system, the "path" will
|
||||||
|
// be set appropriately, but "checksum" will be empty and "version" will be
|
||||||
|
// "(devel)".
|
||||||
|
//
|
||||||
|
// This collector uses only the build information for the main module. See
|
||||||
|
// https://github.com/povilasv/prommod for an example of a collector for the
|
||||||
|
// module dependencies.
|
||||||
|
func NewBuildInfoCollector() Collector {
|
||||||
|
path, version, sum := readBuildInfo()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,505 +0,0 @@
|
||||||
// Copyright 2014 The Prometheus Authors
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package prometheus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"compress/gzip"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/prometheus/common/expfmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO(beorn7): Remove this whole file. It is a partial mirror of
|
|
||||||
// promhttp/http.go (to avoid circular import chains) where everything HTTP
|
|
||||||
// related should live. The functions here are just for avoiding
|
|
||||||
// breakage. Everything is deprecated.
|
|
||||||
|
|
||||||
const (
|
|
||||||
contentTypeHeader = "Content-Type"
|
|
||||||
contentEncodingHeader = "Content-Encoding"
|
|
||||||
acceptEncodingHeader = "Accept-Encoding"
|
|
||||||
)
|
|
||||||
|
|
||||||
var gzipPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return gzip.NewWriter(nil)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handler returns an HTTP handler for the DefaultGatherer. It is
|
|
||||||
// already instrumented with InstrumentHandler (using "prometheus" as handler
|
|
||||||
// name).
|
|
||||||
//
|
|
||||||
// Deprecated: Please note the issues described in the doc comment of
|
|
||||||
// InstrumentHandler. You might want to consider using promhttp.Handler instead.
|
|
||||||
func Handler() http.Handler {
|
|
||||||
return InstrumentHandler("prometheus", UninstrumentedHandler())
|
|
||||||
}
|
|
||||||
|
|
||||||
// UninstrumentedHandler returns an HTTP handler for the DefaultGatherer.
|
|
||||||
//
|
|
||||||
// Deprecated: Use promhttp.HandlerFor(DefaultGatherer, promhttp.HandlerOpts{})
|
|
||||||
// instead. See there for further documentation.
|
|
||||||
func UninstrumentedHandler() http.Handler {
|
|
||||||
return http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
|
|
||||||
mfs, err := DefaultGatherer.Gather()
|
|
||||||
if err != nil {
|
|
||||||
httpError(rsp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType := expfmt.Negotiate(req.Header)
|
|
||||||
header := rsp.Header()
|
|
||||||
header.Set(contentTypeHeader, string(contentType))
|
|
||||||
|
|
||||||
w := io.Writer(rsp)
|
|
||||||
if gzipAccepted(req.Header) {
|
|
||||||
header.Set(contentEncodingHeader, "gzip")
|
|
||||||
gz := gzipPool.Get().(*gzip.Writer)
|
|
||||||
defer gzipPool.Put(gz)
|
|
||||||
|
|
||||||
gz.Reset(w)
|
|
||||||
defer gz.Close()
|
|
||||||
|
|
||||||
w = gz
|
|
||||||
}
|
|
||||||
|
|
||||||
enc := expfmt.NewEncoder(w, contentType)
|
|
||||||
|
|
||||||
for _, mf := range mfs {
|
|
||||||
if err := enc.Encode(mf); err != nil {
|
|
||||||
httpError(rsp, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var instLabels = []string{"method", "code"}
|
|
||||||
|
|
||||||
type nower interface {
|
|
||||||
Now() time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type nowFunc func() time.Time
|
|
||||||
|
|
||||||
func (n nowFunc) Now() time.Time {
|
|
||||||
return n()
|
|
||||||
}
|
|
||||||
|
|
||||||
var now nower = nowFunc(func() time.Time {
|
|
||||||
return time.Now()
|
|
||||||
})
|
|
||||||
|
|
||||||
// InstrumentHandler wraps the given HTTP handler for instrumentation. It
|
|
||||||
// registers four metric collectors (if not already done) and reports HTTP
|
|
||||||
// metrics to the (newly or already) registered collectors: http_requests_total
|
|
||||||
// (CounterVec), http_request_duration_microseconds (Summary),
|
|
||||||
// http_request_size_bytes (Summary), http_response_size_bytes (Summary). Each
|
|
||||||
// has a constant label named "handler" with the provided handlerName as
|
|
||||||
// value. http_requests_total is a metric vector partitioned by HTTP method
|
|
||||||
// (label name "method") and HTTP status code (label name "code").
|
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandler has several issues. Use the tooling provided in
|
|
||||||
// package promhttp instead. The issues are the following: (1) It uses Summaries
|
|
||||||
// rather than Histograms. Summaries are not useful if aggregation across
|
|
||||||
// multiple instances is required. (2) It uses microseconds as unit, which is
|
|
||||||
// deprecated and should be replaced by seconds. (3) The size of the request is
|
|
||||||
// calculated in a separate goroutine. Since this calculator requires access to
|
|
||||||
// the request header, it creates a race with any writes to the header performed
|
|
||||||
// during request handling. httputil.ReverseProxy is a prominent example for a
|
|
||||||
// handler performing such writes. (4) It has additional issues with HTTP/2, cf.
|
|
||||||
// https://github.com/prometheus/client_golang/issues/272.
|
|
||||||
func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc {
|
|
||||||
return InstrumentHandlerFunc(handlerName, handler.ServeHTTP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstrumentHandlerFunc wraps the given function for instrumentation. It
|
|
||||||
// otherwise works in the same way as InstrumentHandler (and shares the same
|
|
||||||
// issues).
|
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandlerFunc is deprecated for the same reasons as
|
|
||||||
// InstrumentHandler is. Use the tooling provided in package promhttp instead.
|
|
||||||
func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
|
||||||
return InstrumentHandlerFuncWithOpts(
|
|
||||||
SummaryOpts{
|
|
||||||
Subsystem: "http",
|
|
||||||
ConstLabels: Labels{"handler": handlerName},
|
|
||||||
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
|
|
||||||
},
|
|
||||||
handlerFunc,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same
|
|
||||||
// issues) but provides more flexibility (at the cost of a more complex call
|
|
||||||
// syntax). As InstrumentHandler, this function registers four metric
|
|
||||||
// collectors, but it uses the provided SummaryOpts to create them. However, the
|
|
||||||
// fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced
|
|
||||||
// by "requests_total", "request_duration_microseconds", "request_size_bytes",
|
|
||||||
// and "response_size_bytes", respectively. "Help" is replaced by an appropriate
|
|
||||||
// help string. The names of the variable labels of the http_requests_total
|
|
||||||
// CounterVec are "method" (get, post, etc.), and "code" (HTTP status code).
|
|
||||||
//
|
|
||||||
// If InstrumentHandlerWithOpts is called as follows, it mimics exactly the
|
|
||||||
// behavior of InstrumentHandler:
|
|
||||||
//
|
|
||||||
// prometheus.InstrumentHandlerWithOpts(
|
|
||||||
// prometheus.SummaryOpts{
|
|
||||||
// Subsystem: "http",
|
|
||||||
// ConstLabels: prometheus.Labels{"handler": handlerName},
|
|
||||||
// },
|
|
||||||
// handler,
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// Technical detail: "requests_total" is a CounterVec, not a SummaryVec, so it
|
|
||||||
// cannot use SummaryOpts. Instead, a CounterOpts struct is created internally,
|
|
||||||
// and all its fields are set to the equally named fields in the provided
|
|
||||||
// SummaryOpts.
|
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as
|
|
||||||
// InstrumentHandler is. Use the tooling provided in package promhttp instead.
|
|
||||||
func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc {
|
|
||||||
return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares
|
|
||||||
// the same issues) but provides more flexibility (at the cost of a more complex
|
|
||||||
// call syntax). See InstrumentHandlerWithOpts for details how the provided
|
|
||||||
// SummaryOpts are used.
|
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons
|
|
||||||
// as InstrumentHandler is. Use the tooling provided in package promhttp instead.
|
|
||||||
func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
|
||||||
reqCnt := NewCounterVec(
|
|
||||||
CounterOpts{
|
|
||||||
Namespace: opts.Namespace,
|
|
||||||
Subsystem: opts.Subsystem,
|
|
||||||
Name: "requests_total",
|
|
||||||
Help: "Total number of HTTP requests made.",
|
|
||||||
ConstLabels: opts.ConstLabels,
|
|
||||||
},
|
|
||||||
instLabels,
|
|
||||||
)
|
|
||||||
if err := Register(reqCnt); err != nil {
|
|
||||||
if are, ok := err.(AlreadyRegisteredError); ok {
|
|
||||||
reqCnt = are.ExistingCollector.(*CounterVec)
|
|
||||||
} else {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.Name = "request_duration_microseconds"
|
|
||||||
opts.Help = "The HTTP request latencies in microseconds."
|
|
||||||
reqDur := NewSummary(opts)
|
|
||||||
if err := Register(reqDur); err != nil {
|
|
||||||
if are, ok := err.(AlreadyRegisteredError); ok {
|
|
||||||
reqDur = are.ExistingCollector.(Summary)
|
|
||||||
} else {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.Name = "request_size_bytes"
|
|
||||||
opts.Help = "The HTTP request sizes in bytes."
|
|
||||||
reqSz := NewSummary(opts)
|
|
||||||
if err := Register(reqSz); err != nil {
|
|
||||||
if are, ok := err.(AlreadyRegisteredError); ok {
|
|
||||||
reqSz = are.ExistingCollector.(Summary)
|
|
||||||
} else {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.Name = "response_size_bytes"
|
|
||||||
opts.Help = "The HTTP response sizes in bytes."
|
|
||||||
resSz := NewSummary(opts)
|
|
||||||
if err := Register(resSz); err != nil {
|
|
||||||
if are, ok := err.(AlreadyRegisteredError); ok {
|
|
||||||
resSz = are.ExistingCollector.(Summary)
|
|
||||||
} else {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
delegate := &responseWriterDelegator{ResponseWriter: w}
|
|
||||||
out := computeApproximateRequestSize(r)
|
|
||||||
|
|
||||||
_, cn := w.(http.CloseNotifier)
|
|
||||||
_, fl := w.(http.Flusher)
|
|
||||||
_, hj := w.(http.Hijacker)
|
|
||||||
_, rf := w.(io.ReaderFrom)
|
|
||||||
var rw http.ResponseWriter
|
|
||||||
if cn && fl && hj && rf {
|
|
||||||
rw = &fancyResponseWriterDelegator{delegate}
|
|
||||||
} else {
|
|
||||||
rw = delegate
|
|
||||||
}
|
|
||||||
handlerFunc(rw, r)
|
|
||||||
|
|
||||||
elapsed := float64(time.Since(now)) / float64(time.Microsecond)
|
|
||||||
|
|
||||||
method := sanitizeMethod(r.Method)
|
|
||||||
code := sanitizeCode(delegate.status)
|
|
||||||
reqCnt.WithLabelValues(method, code).Inc()
|
|
||||||
reqDur.Observe(elapsed)
|
|
||||||
resSz.Observe(float64(delegate.written))
|
|
||||||
reqSz.Observe(float64(<-out))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func computeApproximateRequestSize(r *http.Request) <-chan int {
|
|
||||||
// Get URL length in current goroutine for avoiding a race condition.
|
|
||||||
// HandlerFunc that runs in parallel may modify the URL.
|
|
||||||
s := 0
|
|
||||||
if r.URL != nil {
|
|
||||||
s += len(r.URL.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
out := make(chan int, 1)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
s += len(r.Method)
|
|
||||||
s += len(r.Proto)
|
|
||||||
for name, values := range r.Header {
|
|
||||||
s += len(name)
|
|
||||||
for _, value := range values {
|
|
||||||
s += len(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s += len(r.Host)
|
|
||||||
|
|
||||||
// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
|
|
||||||
|
|
||||||
if r.ContentLength != -1 {
|
|
||||||
s += int(r.ContentLength)
|
|
||||||
}
|
|
||||||
out <- s
|
|
||||||
close(out)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
type responseWriterDelegator struct {
|
|
||||||
http.ResponseWriter
|
|
||||||
|
|
||||||
status int
|
|
||||||
written int64
|
|
||||||
wroteHeader bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *responseWriterDelegator) WriteHeader(code int) {
|
|
||||||
r.status = code
|
|
||||||
r.wroteHeader = true
|
|
||||||
r.ResponseWriter.WriteHeader(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *responseWriterDelegator) Write(b []byte) (int, error) {
|
|
||||||
if !r.wroteHeader {
|
|
||||||
r.WriteHeader(http.StatusOK)
|
|
||||||
}
|
|
||||||
n, err := r.ResponseWriter.Write(b)
|
|
||||||
r.written += int64(n)
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type fancyResponseWriterDelegator struct {
|
|
||||||
*responseWriterDelegator
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fancyResponseWriterDelegator) CloseNotify() <-chan bool {
|
|
||||||
//lint:ignore SA1019 http.CloseNotifier is deprecated but we don't want to
|
|
||||||
//remove support from client_golang yet.
|
|
||||||
return f.ResponseWriter.(http.CloseNotifier).CloseNotify()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fancyResponseWriterDelegator) Flush() {
|
|
||||||
f.ResponseWriter.(http.Flusher).Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fancyResponseWriterDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|
||||||
return f.ResponseWriter.(http.Hijacker).Hijack()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fancyResponseWriterDelegator) ReadFrom(r io.Reader) (int64, error) {
|
|
||||||
if !f.wroteHeader {
|
|
||||||
f.WriteHeader(http.StatusOK)
|
|
||||||
}
|
|
||||||
n, err := f.ResponseWriter.(io.ReaderFrom).ReadFrom(r)
|
|
||||||
f.written += n
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func sanitizeMethod(m string) string {
|
|
||||||
switch m {
|
|
||||||
case "GET", "get":
|
|
||||||
return "get"
|
|
||||||
case "PUT", "put":
|
|
||||||
return "put"
|
|
||||||
case "HEAD", "head":
|
|
||||||
return "head"
|
|
||||||
case "POST", "post":
|
|
||||||
return "post"
|
|
||||||
case "DELETE", "delete":
|
|
||||||
return "delete"
|
|
||||||
case "CONNECT", "connect":
|
|
||||||
return "connect"
|
|
||||||
case "OPTIONS", "options":
|
|
||||||
return "options"
|
|
||||||
case "NOTIFY", "notify":
|
|
||||||
return "notify"
|
|
||||||
default:
|
|
||||||
return strings.ToLower(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sanitizeCode(s int) string {
|
|
||||||
switch s {
|
|
||||||
case 100:
|
|
||||||
return "100"
|
|
||||||
case 101:
|
|
||||||
return "101"
|
|
||||||
|
|
||||||
case 200:
|
|
||||||
return "200"
|
|
||||||
case 201:
|
|
||||||
return "201"
|
|
||||||
case 202:
|
|
||||||
return "202"
|
|
||||||
case 203:
|
|
||||||
return "203"
|
|
||||||
case 204:
|
|
||||||
return "204"
|
|
||||||
case 205:
|
|
||||||
return "205"
|
|
||||||
case 206:
|
|
||||||
return "206"
|
|
||||||
|
|
||||||
case 300:
|
|
||||||
return "300"
|
|
||||||
case 301:
|
|
||||||
return "301"
|
|
||||||
case 302:
|
|
||||||
return "302"
|
|
||||||
case 304:
|
|
||||||
return "304"
|
|
||||||
case 305:
|
|
||||||
return "305"
|
|
||||||
case 307:
|
|
||||||
return "307"
|
|
||||||
|
|
||||||
case 400:
|
|
||||||
return "400"
|
|
||||||
case 401:
|
|
||||||
return "401"
|
|
||||||
case 402:
|
|
||||||
return "402"
|
|
||||||
case 403:
|
|
||||||
return "403"
|
|
||||||
case 404:
|
|
||||||
return "404"
|
|
||||||
case 405:
|
|
||||||
return "405"
|
|
||||||
case 406:
|
|
||||||
return "406"
|
|
||||||
case 407:
|
|
||||||
return "407"
|
|
||||||
case 408:
|
|
||||||
return "408"
|
|
||||||
case 409:
|
|
||||||
return "409"
|
|
||||||
case 410:
|
|
||||||
return "410"
|
|
||||||
case 411:
|
|
||||||
return "411"
|
|
||||||
case 412:
|
|
||||||
return "412"
|
|
||||||
case 413:
|
|
||||||
return "413"
|
|
||||||
case 414:
|
|
||||||
return "414"
|
|
||||||
case 415:
|
|
||||||
return "415"
|
|
||||||
case 416:
|
|
||||||
return "416"
|
|
||||||
case 417:
|
|
||||||
return "417"
|
|
||||||
case 418:
|
|
||||||
return "418"
|
|
||||||
|
|
||||||
case 500:
|
|
||||||
return "500"
|
|
||||||
case 501:
|
|
||||||
return "501"
|
|
||||||
case 502:
|
|
||||||
return "502"
|
|
||||||
case 503:
|
|
||||||
return "503"
|
|
||||||
case 504:
|
|
||||||
return "504"
|
|
||||||
case 505:
|
|
||||||
return "505"
|
|
||||||
|
|
||||||
case 428:
|
|
||||||
return "428"
|
|
||||||
case 429:
|
|
||||||
return "429"
|
|
||||||
case 431:
|
|
||||||
return "431"
|
|
||||||
case 511:
|
|
||||||
return "511"
|
|
||||||
|
|
||||||
default:
|
|
||||||
return strconv.Itoa(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// gzipAccepted returns whether the client will accept gzip-encoded content.
|
|
||||||
func gzipAccepted(header http.Header) bool {
|
|
||||||
a := header.Get(acceptEncodingHeader)
|
|
||||||
parts := strings.Split(a, ",")
|
|
||||||
for _, part := range parts {
|
|
||||||
part = strings.TrimSpace(part)
|
|
||||||
if part == "gzip" || strings.HasPrefix(part, "gzip;") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// httpError removes any content-encoding header and then calls http.Error with
|
|
||||||
// the provided error and http.StatusInternalServerErrer. Error contents is
|
|
||||||
// supposed to be uncompressed plain text. However, same as with a plain
|
|
||||||
// http.Error, any header settings will be void if the header has already been
|
|
||||||
// sent. The error message will still be written to the writer, but it will
|
|
||||||
// probably be of limited use.
|
|
||||||
func httpError(rsp http.ResponseWriter, err error) {
|
|
||||||
rsp.Header().Del(contentEncodingHeader)
|
|
||||||
http.Error(
|
|
||||||
rsp,
|
|
||||||
"An error has occurred while serving metrics:\n\n"+err.Error(),
|
|
||||||
http.StatusInternalServerError,
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -16,8 +16,6 @@ package prometheus
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/prometheus/procfs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type processCollector struct {
|
type processCollector struct {
|
||||||
|
@ -59,20 +57,9 @@ type ProcessCollectorOpts struct {
|
||||||
// collector for the current process with an empty namespace string and no error
|
// collector for the current process with an empty namespace string and no error
|
||||||
// reporting.
|
// reporting.
|
||||||
//
|
//
|
||||||
// Currently, the collector depends on a Linux-style proc filesystem and
|
// The collector only works on operating systems with a Linux-style proc
|
||||||
// therefore only exports metrics for Linux.
|
// filesystem and on Microsoft Windows. On other operating systems, it will not
|
||||||
//
|
// collect any metrics.
|
||||||
// Note: An older version of this function had the following signature:
|
|
||||||
//
|
|
||||||
// NewProcessCollector(pid int, namespace string) Collector
|
|
||||||
//
|
|
||||||
// Most commonly, it was called as
|
|
||||||
//
|
|
||||||
// NewProcessCollector(os.Getpid(), "")
|
|
||||||
//
|
|
||||||
// The following call of the current version is equivalent to the above:
|
|
||||||
//
|
|
||||||
// NewProcessCollector(ProcessCollectorOpts{})
|
|
||||||
func NewProcessCollector(opts ProcessCollectorOpts) Collector {
|
func NewProcessCollector(opts ProcessCollectorOpts) Collector {
|
||||||
ns := ""
|
ns := ""
|
||||||
if len(opts.Namespace) > 0 {
|
if len(opts.Namespace) > 0 {
|
||||||
|
@ -126,7 +113,7 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up process metric collection if supported by the runtime.
|
// Set up process metric collection if supported by the runtime.
|
||||||
if _, err := procfs.NewStat(); err == nil {
|
if canCollectProcess() {
|
||||||
c.collectFn = c.processCollect
|
c.collectFn = c.processCollect
|
||||||
} else {
|
} else {
|
||||||
c.collectFn = func(ch chan<- Metric) {
|
c.collectFn = func(ch chan<- Metric) {
|
||||||
|
@ -153,46 +140,6 @@ func (c *processCollector) Collect(ch chan<- Metric) {
|
||||||
c.collectFn(ch)
|
c.collectFn(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *processCollector) processCollect(ch chan<- Metric) {
|
|
||||||
pid, err := c.pidFn()
|
|
||||||
if err != nil {
|
|
||||||
c.reportError(ch, nil, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := procfs.NewProc(pid)
|
|
||||||
if err != nil {
|
|
||||||
c.reportError(ch, nil, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if stat, err := p.NewStat(); err == nil {
|
|
||||||
ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime())
|
|
||||||
ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory()))
|
|
||||||
ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory()))
|
|
||||||
if startTime, err := stat.StartTime(); err == nil {
|
|
||||||
ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
|
|
||||||
} else {
|
|
||||||
c.reportError(ch, c.startTime, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
c.reportError(ch, nil, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fds, err := p.FileDescriptorsLen(); err == nil {
|
|
||||||
ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds))
|
|
||||||
} else {
|
|
||||||
c.reportError(ch, c.openFDs, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if limits, err := p.NewLimits(); err == nil {
|
|
||||||
ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles))
|
|
||||||
ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace))
|
|
||||||
} else {
|
|
||||||
c.reportError(ch, nil, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
|
func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) {
|
||||||
if !c.reportErrors {
|
if !c.reportErrors {
|
||||||
return
|
return
|
||||||
|
|
65
vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go
generated
vendored
Normal file
65
vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/prometheus/procfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func canCollectProcess() bool {
|
||||||
|
_, err := procfs.NewDefaultFS()
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||||
|
pid, err := c.pidFn()
|
||||||
|
if err != nil {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := procfs.NewProc(pid)
|
||||||
|
if err != nil {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat, err := p.Stat(); err == nil {
|
||||||
|
ch <- MustNewConstMetric(c.cpuTotal, CounterValue, stat.CPUTime())
|
||||||
|
ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(stat.VirtualMemory()))
|
||||||
|
ch <- MustNewConstMetric(c.rss, GaugeValue, float64(stat.ResidentMemory()))
|
||||||
|
if startTime, err := stat.StartTime(); err == nil {
|
||||||
|
ch <- MustNewConstMetric(c.startTime, GaugeValue, startTime)
|
||||||
|
} else {
|
||||||
|
c.reportError(ch, c.startTime, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fds, err := p.FileDescriptorsLen(); err == nil {
|
||||||
|
ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(fds))
|
||||||
|
} else {
|
||||||
|
c.reportError(ch, c.openFDs, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if limits, err := p.Limits(); err == nil {
|
||||||
|
ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(limits.OpenFiles))
|
||||||
|
ch <- MustNewConstMetric(c.maxVsize, GaugeValue, float64(limits.AddressSpace))
|
||||||
|
} else {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
}
|
||||||
|
}
|
112
vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
generated
vendored
Normal file
112
vendor/github.com/prometheus/client_golang/prometheus/process_collector_windows.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
func canCollectProcess() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
modpsapi = syscall.NewLazyDLL("psapi.dll")
|
||||||
|
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
|
||||||
|
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||||||
|
procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount")
|
||||||
|
)
|
||||||
|
|
||||||
|
type processMemoryCounters struct {
|
||||||
|
// https://docs.microsoft.com/en-us/windows/desktop/api/psapi/ns-psapi-_process_memory_counters_ex
|
||||||
|
_ uint32
|
||||||
|
PageFaultCount uint32
|
||||||
|
PeakWorkingSetSize uint64
|
||||||
|
WorkingSetSize uint64
|
||||||
|
QuotaPeakPagedPoolUsage uint64
|
||||||
|
QuotaPagedPoolUsage uint64
|
||||||
|
QuotaPeakNonPagedPoolUsage uint64
|
||||||
|
QuotaNonPagedPoolUsage uint64
|
||||||
|
PagefileUsage uint64
|
||||||
|
PeakPagefileUsage uint64
|
||||||
|
PrivateUsage uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProcessMemoryInfo(handle windows.Handle) (processMemoryCounters, error) {
|
||||||
|
mem := processMemoryCounters{}
|
||||||
|
r1, _, err := procGetProcessMemoryInfo.Call(
|
||||||
|
uintptr(handle),
|
||||||
|
uintptr(unsafe.Pointer(&mem)),
|
||||||
|
uintptr(unsafe.Sizeof(mem)),
|
||||||
|
)
|
||||||
|
if r1 != 1 {
|
||||||
|
return mem, err
|
||||||
|
} else {
|
||||||
|
return mem, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getProcessHandleCount(handle windows.Handle) (uint32, error) {
|
||||||
|
var count uint32
|
||||||
|
r1, _, err := procGetProcessHandleCount.Call(
|
||||||
|
uintptr(handle),
|
||||||
|
uintptr(unsafe.Pointer(&count)),
|
||||||
|
)
|
||||||
|
if r1 != 1 {
|
||||||
|
return 0, err
|
||||||
|
} else {
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *processCollector) processCollect(ch chan<- Metric) {
|
||||||
|
h, err := windows.GetCurrentProcess()
|
||||||
|
if err != nil {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTime, exitTime, kernelTime, userTime windows.Filetime
|
||||||
|
err = windows.GetProcessTimes(h, &startTime, &exitTime, &kernelTime, &userTime)
|
||||||
|
if err != nil {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch <- MustNewConstMetric(c.startTime, GaugeValue, float64(startTime.Nanoseconds()/1e9))
|
||||||
|
ch <- MustNewConstMetric(c.cpuTotal, CounterValue, fileTimeToSeconds(kernelTime)+fileTimeToSeconds(userTime))
|
||||||
|
|
||||||
|
mem, err := getProcessMemoryInfo(h)
|
||||||
|
if err != nil {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch <- MustNewConstMetric(c.vsize, GaugeValue, float64(mem.PrivateUsage))
|
||||||
|
ch <- MustNewConstMetric(c.rss, GaugeValue, float64(mem.WorkingSetSize))
|
||||||
|
|
||||||
|
handles, err := getProcessHandleCount(h)
|
||||||
|
if err != nil {
|
||||||
|
c.reportError(ch, nil, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch <- MustNewConstMetric(c.openFDs, GaugeValue, float64(handles))
|
||||||
|
ch <- MustNewConstMetric(c.maxFDs, GaugeValue, float64(16*1024*1024)) // Windows has a hard-coded max limit, not per-process.
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileTimeToSeconds(ft windows.Filetime) float64 {
|
||||||
|
return float64(uint64(ft.HighDateTime)<<32+uint64(ft.LowDateTime)) / 1e7
|
||||||
|
}
|
|
@ -84,10 +84,32 @@ func Handler() http.Handler {
|
||||||
// instrumentation. Use the InstrumentMetricHandler function to apply the same
|
// instrumentation. Use the InstrumentMetricHandler function to apply the same
|
||||||
// kind of instrumentation as it is used by the Handler function.
|
// kind of instrumentation as it is used by the Handler function.
|
||||||
func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
||||||
var inFlightSem chan struct{}
|
var (
|
||||||
|
inFlightSem chan struct{}
|
||||||
|
errCnt = prometheus.NewCounterVec(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Name: "promhttp_metric_handler_errors_total",
|
||||||
|
Help: "Total number of internal errors encountered by the promhttp metric handler.",
|
||||||
|
},
|
||||||
|
[]string{"cause"},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if opts.MaxRequestsInFlight > 0 {
|
if opts.MaxRequestsInFlight > 0 {
|
||||||
inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight)
|
inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight)
|
||||||
}
|
}
|
||||||
|
if opts.Registry != nil {
|
||||||
|
// Initialize all possibilites that can occur below.
|
||||||
|
errCnt.WithLabelValues("gathering")
|
||||||
|
errCnt.WithLabelValues("encoding")
|
||||||
|
if err := opts.Registry.Register(errCnt); err != nil {
|
||||||
|
if are, ok := err.(prometheus.AlreadyRegisteredError); ok {
|
||||||
|
errCnt = are.ExistingCollector.(*prometheus.CounterVec)
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
|
h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
|
||||||
if inFlightSem != nil {
|
if inFlightSem != nil {
|
||||||
|
@ -106,6 +128,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
||||||
if opts.ErrorLog != nil {
|
if opts.ErrorLog != nil {
|
||||||
opts.ErrorLog.Println("error gathering metrics:", err)
|
opts.ErrorLog.Println("error gathering metrics:", err)
|
||||||
}
|
}
|
||||||
|
errCnt.WithLabelValues("gathering").Inc()
|
||||||
switch opts.ErrorHandling {
|
switch opts.ErrorHandling {
|
||||||
case PanicOnError:
|
case PanicOnError:
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -146,6 +169,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
||||||
if opts.ErrorLog != nil {
|
if opts.ErrorLog != nil {
|
||||||
opts.ErrorLog.Println("error encoding and sending metric family:", err)
|
opts.ErrorLog.Println("error encoding and sending metric family:", err)
|
||||||
}
|
}
|
||||||
|
errCnt.WithLabelValues("encoding").Inc()
|
||||||
switch opts.ErrorHandling {
|
switch opts.ErrorHandling {
|
||||||
case PanicOnError:
|
case PanicOnError:
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -236,9 +260,12 @@ const (
|
||||||
// Ignore errors and try to serve as many metrics as possible. However,
|
// Ignore errors and try to serve as many metrics as possible. However,
|
||||||
// if no metrics can be served, serve an HTTP status code 500 and the
|
// if no metrics can be served, serve an HTTP status code 500 and the
|
||||||
// last error message in the body. Only use this in deliberate "best
|
// last error message in the body. Only use this in deliberate "best
|
||||||
// effort" metrics collection scenarios. It is recommended to at least
|
// effort" metrics collection scenarios. In this case, it is highly
|
||||||
// log errors (by providing an ErrorLog in HandlerOpts) to not mask
|
// recommended to provide other means of detecting errors: By setting an
|
||||||
// errors completely.
|
// ErrorLog in HandlerOpts, the errors are logged. By providing a
|
||||||
|
// Registry in HandlerOpts, the exposed metrics include an error counter
|
||||||
|
// "promhttp_metric_handler_errors_total", which can be used for
|
||||||
|
// alerts.
|
||||||
ContinueOnError
|
ContinueOnError
|
||||||
// Panic upon the first error encountered (useful for "crash only" apps).
|
// Panic upon the first error encountered (useful for "crash only" apps).
|
||||||
PanicOnError
|
PanicOnError
|
||||||
|
@ -261,6 +288,18 @@ type HandlerOpts struct {
|
||||||
// logged regardless of the configured ErrorHandling provided ErrorLog
|
// logged regardless of the configured ErrorHandling provided ErrorLog
|
||||||
// is not nil.
|
// is not nil.
|
||||||
ErrorHandling HandlerErrorHandling
|
ErrorHandling HandlerErrorHandling
|
||||||
|
// If Registry is not nil, it is used to register a metric
|
||||||
|
// "promhttp_metric_handler_errors_total", partitioned by "cause". A
|
||||||
|
// failed registration causes a panic. Note that this error counter is
|
||||||
|
// different from the instrumentation you get from the various
|
||||||
|
// InstrumentHandler... helpers. It counts errors that don't necessarily
|
||||||
|
// result in a non-2xx HTTP status code. There are two typical cases:
|
||||||
|
// (1) Encoding errors that only happen after streaming of the HTTP body
|
||||||
|
// has already started (and the status code 200 has been sent). This
|
||||||
|
// should only happen with custom collectors. (2) Collection errors with
|
||||||
|
// no effect on the HTTP status code because ErrorHandling is set to
|
||||||
|
// ContinueOnError.
|
||||||
|
Registry prometheus.Registerer
|
||||||
// If DisableCompression is true, the handler will never compress the
|
// If DisableCompression is true, the handler will never compress the
|
||||||
// response, even if requested by the client.
|
// response, even if requested by the client.
|
||||||
DisableCompression bool
|
DisableCompression bool
|
||||||
|
|
|
@ -325,10 +325,18 @@ func (r *Registry) Register(c Collector) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if existing, exists := r.collectorsByID[collectorID]; exists {
|
if existing, exists := r.collectorsByID[collectorID]; exists {
|
||||||
|
switch e := existing.(type) {
|
||||||
|
case *wrappingCollector:
|
||||||
return AlreadyRegisteredError{
|
return AlreadyRegisteredError{
|
||||||
ExistingCollector: existing,
|
ExistingCollector: e.unwrapRecursively(),
|
||||||
NewCollector: c,
|
NewCollector: c,
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return AlreadyRegisteredError{
|
||||||
|
ExistingCollector: e,
|
||||||
|
NewCollector: c,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// If the collectorID is new, but at least one of the descs existed
|
// If the collectorID is new, but at least one of the descs existed
|
||||||
// before, we are in trouble.
|
// before, we are in trouble.
|
||||||
|
|
|
@ -39,7 +39,7 @@ const quantileLabel = "quantile"
|
||||||
// A typical use-case is the observation of request latencies. By default, a
|
// A typical use-case is the observation of request latencies. By default, a
|
||||||
// Summary provides the median, the 90th and the 99th percentile of the latency
|
// Summary provides the median, the 90th and the 99th percentile of the latency
|
||||||
// as rank estimations. However, the default behavior will change in the
|
// as rank estimations. However, the default behavior will change in the
|
||||||
// upcoming v0.10 of the library. There will be no rank estimations at all by
|
// upcoming v1.0.0 of the library. There will be no rank estimations at all by
|
||||||
// default. For a sane transition, it is recommended to set the desired rank
|
// default. For a sane transition, it is recommended to set the desired rank
|
||||||
// estimations explicitly.
|
// estimations explicitly.
|
||||||
//
|
//
|
||||||
|
@ -58,17 +58,9 @@ type Summary interface {
|
||||||
Observe(float64)
|
Observe(float64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefObjectives are the default Summary quantile values.
|
var errQuantileLabelNotAllowed = fmt.Errorf(
|
||||||
//
|
|
||||||
// Deprecated: DefObjectives will not be used as the default objectives in
|
|
||||||
// v0.10 of the library. The default Summary will have no quantiles then.
|
|
||||||
var (
|
|
||||||
DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
|
|
||||||
|
|
||||||
errQuantileLabelNotAllowed = fmt.Errorf(
|
|
||||||
"%q is not allowed as label name in summaries", quantileLabel,
|
"%q is not allowed as label name in summaries", quantileLabel,
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
// Default values for SummaryOpts.
|
// Default values for SummaryOpts.
|
||||||
const (
|
const (
|
||||||
|
@ -86,7 +78,7 @@ const (
|
||||||
// mandatory to set Name to a non-empty string. While all other fields are
|
// mandatory to set Name to a non-empty string. While all other fields are
|
||||||
// optional and can safely be left at their zero value, it is recommended to set
|
// optional and can safely be left at their zero value, it is recommended to set
|
||||||
// a help string and to explicitly set the Objectives field to the desired value
|
// a help string and to explicitly set the Objectives field to the desired value
|
||||||
// as the default value will change in the upcoming v0.10 of the library.
|
// as the default value will change in the upcoming v1.0.0 of the library.
|
||||||
type SummaryOpts struct {
|
type SummaryOpts struct {
|
||||||
// Namespace, Subsystem, and Name are components of the fully-qualified
|
// Namespace, Subsystem, and Name are components of the fully-qualified
|
||||||
// name of the Summary (created by joining these components with
|
// name of the Summary (created by joining these components with
|
||||||
|
@ -123,14 +115,8 @@ type SummaryOpts struct {
|
||||||
// Objectives defines the quantile rank estimates with their respective
|
// Objectives defines the quantile rank estimates with their respective
|
||||||
// absolute error. If Objectives[q] = e, then the value reported for q
|
// absolute error. If Objectives[q] = e, then the value reported for q
|
||||||
// will be the φ-quantile value for some φ between q-e and q+e. The
|
// will be the φ-quantile value for some φ between q-e and q+e. The
|
||||||
// default value is DefObjectives. It is used if Objectives is left at
|
// default value is an empty map, resulting in a summary without
|
||||||
// its zero value (i.e. nil). To create a Summary without Objectives,
|
// quantiles.
|
||||||
// set it to an empty map (i.e. map[float64]float64{}).
|
|
||||||
//
|
|
||||||
// Note that the current value of DefObjectives is deprecated. It will
|
|
||||||
// be replaced by an empty map in v0.10 of the library. Please
|
|
||||||
// explicitly set Objectives to the desired value to avoid problems
|
|
||||||
// during the transition.
|
|
||||||
Objectives map[float64]float64
|
Objectives map[float64]float64
|
||||||
|
|
||||||
// MaxAge defines the duration for which an observation stays relevant
|
// MaxAge defines the duration for which an observation stays relevant
|
||||||
|
@ -199,7 +185,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Objectives == nil {
|
if opts.Objectives == nil {
|
||||||
opts.Objectives = DefObjectives
|
opts.Objectives = map[float64]float64{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.MaxAge < 0 {
|
if opts.MaxAge < 0 {
|
||||||
|
|
|
@ -32,6 +32,12 @@ import (
|
||||||
// WrapRegistererWith provides a way to add fixed labels to a subset of
|
// WrapRegistererWith provides a way to add fixed labels to a subset of
|
||||||
// Collectors. It should not be used to add fixed labels to all metrics exposed.
|
// Collectors. It should not be used to add fixed labels to all metrics exposed.
|
||||||
//
|
//
|
||||||
|
// Conflicts between Collectors registered through the original Registerer with
|
||||||
|
// Collectors registered through the wrapping Registerer will still be
|
||||||
|
// detected. Any AlreadyRegisteredError returned by the Register method of
|
||||||
|
// either Registerer will contain the ExistingCollector in the form it was
|
||||||
|
// provided to the respective registry.
|
||||||
|
//
|
||||||
// The Collector example demonstrates a use of WrapRegistererWith.
|
// The Collector example demonstrates a use of WrapRegistererWith.
|
||||||
func WrapRegistererWith(labels Labels, reg Registerer) Registerer {
|
func WrapRegistererWith(labels Labels, reg Registerer) Registerer {
|
||||||
return &wrappingRegisterer{
|
return &wrappingRegisterer{
|
||||||
|
@ -54,6 +60,12 @@ func WrapRegistererWith(labels Labels, reg Registerer) Registerer {
|
||||||
// (see NewGoCollector) and the process collector (see NewProcessCollector). (In
|
// (see NewGoCollector) and the process collector (see NewProcessCollector). (In
|
||||||
// fact, those metrics are already prefixed with “go_” or “process_”,
|
// fact, those metrics are already prefixed with “go_” or “process_”,
|
||||||
// respectively.)
|
// respectively.)
|
||||||
|
//
|
||||||
|
// Conflicts between Collectors registered through the original Registerer with
|
||||||
|
// Collectors registered through the wrapping Registerer will still be
|
||||||
|
// detected. Any AlreadyRegisteredError returned by the Register method of
|
||||||
|
// either Registerer will contain the ExistingCollector in the form it was
|
||||||
|
// provided to the respective registry.
|
||||||
func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer {
|
func WrapRegistererWithPrefix(prefix string, reg Registerer) Registerer {
|
||||||
return &wrappingRegisterer{
|
return &wrappingRegisterer{
|
||||||
wrappedRegisterer: reg,
|
wrappedRegisterer: reg,
|
||||||
|
@ -123,6 +135,15 @@ func (c *wrappingCollector) Describe(ch chan<- *Desc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *wrappingCollector) unwrapRecursively() Collector {
|
||||||
|
switch wc := c.wrappedCollector.(type) {
|
||||||
|
case *wrappingCollector:
|
||||||
|
return wc.unwrapRecursively()
|
||||||
|
default:
|
||||||
|
return wc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type wrappingMetric struct {
|
type wrappingMetric struct {
|
||||||
wrappedMetric Metric
|
wrappedMetric Metric
|
||||||
prefix string
|
prefix string
|
||||||
|
|
|
@ -150,7 +150,13 @@ func (t *Time) UnmarshalJSON(b []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the value was something like -0.1 the negative is lost in the
|
||||||
|
// parsing because of the leading zero, this ensures that we capture it.
|
||||||
|
if len(p[0]) > 0 && p[0][0] == '-' && v+va > 0 {
|
||||||
|
*t = Time(v+va) * -1
|
||||||
|
} else {
|
||||||
*t = Time(v + va)
|
*t = Time(v + va)
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid time %q", string(b))
|
return fmt.Errorf("invalid time %q", string(b))
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
include Makefile.common
|
include Makefile.common
|
||||||
|
|
||||||
%/.unpacked: %.ttar
|
%/.unpacked: %.ttar
|
||||||
|
@echo ">> extracting fixtures"
|
||||||
./ttar -C $(dir $*) -x -f $*.ttar
|
./ttar -C $(dir $*) -x -f $*.ttar
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ else
|
||||||
GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)
|
GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PROMU_VERSION ?= 0.3.0
|
PROMU_VERSION ?= 0.4.0
|
||||||
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
|
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
|
||||||
|
|
||||||
GOLANGCI_LINT :=
|
GOLANGCI_LINT :=
|
||||||
|
@ -86,6 +86,7 @@ endif
|
||||||
PREFIX ?= $(shell pwd)
|
PREFIX ?= $(shell pwd)
|
||||||
BIN_DIR ?= $(shell pwd)
|
BIN_DIR ?= $(shell pwd)
|
||||||
DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
|
DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
|
||||||
|
DOCKERFILE_PATH ?= ./
|
||||||
DOCKER_REPO ?= prom
|
DOCKER_REPO ?= prom
|
||||||
|
|
||||||
DOCKER_ARCHS ?= amd64
|
DOCKER_ARCHS ?= amd64
|
||||||
|
@ -212,7 +213,7 @@ $(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-$*:$(DOCKER_IMAGE_TAG)" \
|
||||||
--build-arg ARCH="$*" \
|
--build-arg ARCH="$*" \
|
||||||
--build-arg OS="linux" \
|
--build-arg OS="linux" \
|
||||||
.
|
$(DOCKERFILE_PATH)
|
||||||
|
|
||||||
.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS)
|
.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS)
|
||||||
common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
|
common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
|
||||||
|
@ -247,7 +248,9 @@ proto:
|
||||||
ifdef GOLANGCI_LINT
|
ifdef GOLANGCI_LINT
|
||||||
$(GOLANGCI_LINT):
|
$(GOLANGCI_LINT):
|
||||||
mkdir -p $(FIRST_GOPATH)/bin
|
mkdir -p $(FIRST_GOPATH)/bin
|
||||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION)
|
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_LINT_VERSION)/install.sh \
|
||||||
|
| sed -e '/install -d/d' \
|
||||||
|
| sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef GOVENDOR
|
ifdef GOVENDOR
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# procfs
|
# procfs
|
||||||
|
|
||||||
This procfs package provides functions to retrieve system, kernel and process
|
This procfs package provides functions to retrieve system, kernel and process
|
||||||
metrics from the pseudo-filesystem proc.
|
metrics from the pseudo-filesystems /proc and /sys.
|
||||||
|
|
||||||
*WARNING*: This package is a work in progress. Its API may still break in
|
*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.
|
backwards-incompatible ways without warnings. Use it at your own risk.
|
||||||
|
@ -9,3 +9,45 @@ 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)
|
[![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)
|
[![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The procfs library is organized by packages based on whether the gathered data is coming from
|
||||||
|
/proc, /sys, or both. Each package contains an `FS` type which represents the path to either /proc, /sys, or both. For example, current cpu statistics are gathered from
|
||||||
|
`/proc/stat` and are available via the root procfs package. First, the proc filesystem mount
|
||||||
|
point is initialized, and then the stat information is read.
|
||||||
|
|
||||||
|
```go
|
||||||
|
fs, err := procfs.NewFS("/proc")
|
||||||
|
stats, err := fs.Stat()
|
||||||
|
```
|
||||||
|
|
||||||
|
Some sub-packages such as `blockdevice`, require access to both the proc and sys filesystems.
|
||||||
|
|
||||||
|
```go
|
||||||
|
fs, err := blockdevice.NewFS("/proc", "/sys")
|
||||||
|
stats, err := fs.ProcDiskstats()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building and Testing
|
||||||
|
|
||||||
|
The procfs library is normally built as part of another application. However, when making
|
||||||
|
changes to the library, the `make test` command can be used to run the API test suite.
|
||||||
|
|
||||||
|
### Updating Test Fixtures
|
||||||
|
|
||||||
|
The procfs library includes a set of test fixtures which include many example files from
|
||||||
|
the `/proc` and `/sys` filesystems. These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file
|
||||||
|
which is extracted automatically during testing. To add/update the test fixtures, first
|
||||||
|
ensure the `fixtures` directory is up to date by removing the existing directory and then
|
||||||
|
extracting the ttar file using `make fixtures/.unpacked` or just `make test`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf 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`.
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ARPEntry contains a single row of the columnar data represented in
|
||||||
|
// /proc/net/arp.
|
||||||
|
type ARPEntry struct {
|
||||||
|
// IP address
|
||||||
|
IPAddr net.IP
|
||||||
|
// MAC address
|
||||||
|
HWAddr net.HardwareAddr
|
||||||
|
// Name of the device
|
||||||
|
Device string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading arp %s: %s", fs.proc.Path("net/arp"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseARPEntries(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseARPEntries(data []byte) ([]ARPEntry, error) {
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
entries := make([]ARPEntry, 0)
|
||||||
|
var err error
|
||||||
|
const (
|
||||||
|
expectedDataWidth = 6
|
||||||
|
expectedHeaderWidth = 9
|
||||||
|
)
|
||||||
|
for _, line := range lines {
|
||||||
|
columns := strings.Fields(line)
|
||||||
|
width := len(columns)
|
||||||
|
|
||||||
|
if width == expectedHeaderWidth || width == 0 {
|
||||||
|
continue
|
||||||
|
} else if width == expectedDataWidth {
|
||||||
|
entry, err := parseARPEntry(columns)
|
||||||
|
if err != nil {
|
||||||
|
return []ARPEntry{}, fmt.Errorf("failed to parse ARP entry: %s", err)
|
||||||
|
}
|
||||||
|
entries = append(entries, entry)
|
||||||
|
} else {
|
||||||
|
return []ARPEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedDataWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseARPEntry(columns []string) (ARPEntry, error) {
|
||||||
|
ip := net.ParseIP(columns[0])
|
||||||
|
mac := net.HardwareAddr(columns[3])
|
||||||
|
|
||||||
|
entry := ARPEntry{
|
||||||
|
IPAddr: ip,
|
||||||
|
HWAddr: mac,
|
||||||
|
Device: columns[5],
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry, nil
|
||||||
|
}
|
|
@ -31,18 +31,8 @@ type BuddyInfo struct {
|
||||||
Sizes []float64
|
Sizes []float64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBuddyInfo reads the buddyinfo statistics.
|
|
||||||
func NewBuddyInfo() ([]BuddyInfo, error) {
|
|
||||||
fs, err := NewFS(DefaultMountPoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.NewBuddyInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem.
|
// NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem.
|
||||||
func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) {
|
func (fs FS) BuddyInfo() ([]BuddyInfo, error) {
|
||||||
file, err := os.Open(fs.proc.Path("buddyinfo"))
|
file, err := os.Open(fs.proc.Path("buddyinfo"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Crypto holds info parsed from /proc/crypto.
|
||||||
|
type Crypto struct {
|
||||||
|
Alignmask *uint64
|
||||||
|
Async bool
|
||||||
|
Blocksize *uint64
|
||||||
|
Chunksize *uint64
|
||||||
|
Ctxsize *uint64
|
||||||
|
Digestsize *uint64
|
||||||
|
Driver string
|
||||||
|
Geniv string
|
||||||
|
Internal string
|
||||||
|
Ivsize *uint64
|
||||||
|
Maxauthsize *uint64
|
||||||
|
MaxKeysize *uint64
|
||||||
|
MinKeysize *uint64
|
||||||
|
Module string
|
||||||
|
Name string
|
||||||
|
Priority *int64
|
||||||
|
Refcnt *int64
|
||||||
|
Seedsize *uint64
|
||||||
|
Selftest string
|
||||||
|
Type string
|
||||||
|
Walksize *uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crypto parses an crypto-file (/proc/crypto) and returns a slice of
|
||||||
|
// structs containing the relevant info. More information available here:
|
||||||
|
// https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html
|
||||||
|
func (fs FS) Crypto() ([]Crypto, error) {
|
||||||
|
data, err := ioutil.ReadFile(fs.proc.Path("crypto"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing crypto %s: %s", fs.proc.Path("crypto"), err)
|
||||||
|
}
|
||||||
|
crypto, err := parseCrypto(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing crypto %s: %s", fs.proc.Path("crypto"), err)
|
||||||
|
}
|
||||||
|
return crypto, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCrypto(cryptoData []byte) ([]Crypto, error) {
|
||||||
|
crypto := []Crypto{}
|
||||||
|
|
||||||
|
cryptoBlocks := bytes.Split(cryptoData, []byte("\n\n"))
|
||||||
|
|
||||||
|
for _, block := range cryptoBlocks {
|
||||||
|
var newCryptoElem Crypto
|
||||||
|
|
||||||
|
lines := strings.Split(string(block), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if strings.TrimSpace(line) == "" || line[0] == ' ' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields := strings.Split(line, ":")
|
||||||
|
key := strings.TrimSpace(fields[0])
|
||||||
|
value := strings.TrimSpace(fields[1])
|
||||||
|
vp := util.NewValueParser(value)
|
||||||
|
|
||||||
|
switch strings.TrimSpace(key) {
|
||||||
|
case "async":
|
||||||
|
b, err := strconv.ParseBool(value)
|
||||||
|
if err == nil {
|
||||||
|
newCryptoElem.Async = b
|
||||||
|
}
|
||||||
|
case "blocksize":
|
||||||
|
newCryptoElem.Blocksize = vp.PUInt64()
|
||||||
|
case "chunksize":
|
||||||
|
newCryptoElem.Chunksize = vp.PUInt64()
|
||||||
|
case "digestsize":
|
||||||
|
newCryptoElem.Digestsize = vp.PUInt64()
|
||||||
|
case "driver":
|
||||||
|
newCryptoElem.Driver = value
|
||||||
|
case "geniv":
|
||||||
|
newCryptoElem.Geniv = value
|
||||||
|
case "internal":
|
||||||
|
newCryptoElem.Internal = value
|
||||||
|
case "ivsize":
|
||||||
|
newCryptoElem.Ivsize = vp.PUInt64()
|
||||||
|
case "maxauthsize":
|
||||||
|
newCryptoElem.Maxauthsize = vp.PUInt64()
|
||||||
|
case "max keysize":
|
||||||
|
newCryptoElem.MaxKeysize = vp.PUInt64()
|
||||||
|
case "min keysize":
|
||||||
|
newCryptoElem.MinKeysize = vp.PUInt64()
|
||||||
|
case "module":
|
||||||
|
newCryptoElem.Module = value
|
||||||
|
case "name":
|
||||||
|
newCryptoElem.Name = value
|
||||||
|
case "priority":
|
||||||
|
newCryptoElem.Priority = vp.PInt64()
|
||||||
|
case "refcnt":
|
||||||
|
newCryptoElem.Refcnt = vp.PInt64()
|
||||||
|
case "seedsize":
|
||||||
|
newCryptoElem.Seedsize = vp.PUInt64()
|
||||||
|
case "selftest":
|
||||||
|
newCryptoElem.Selftest = value
|
||||||
|
case "type":
|
||||||
|
newCryptoElem.Type = value
|
||||||
|
case "walksize":
|
||||||
|
newCryptoElem.Walksize = vp.PUInt64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crypto = append(crypto, newCryptoElem)
|
||||||
|
}
|
||||||
|
return crypto, nil
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -26,8 +26,14 @@ type FS struct {
|
||||||
// DefaultMountPoint is the common mount point of the proc filesystem.
|
// DefaultMountPoint is the common mount point of the proc filesystem.
|
||||||
const DefaultMountPoint = fs.DefaultProcMountPoint
|
const DefaultMountPoint = fs.DefaultProcMountPoint
|
||||||
|
|
||||||
|
// NewDefaultFS returns a new proc FS mounted under the default proc mountPoint.
|
||||||
|
// It will error if the mount point directory can't be read or is a file.
|
||||||
|
func NewDefaultFS() (FS, error) {
|
||||||
|
return NewFS(DefaultMountPoint)
|
||||||
|
}
|
||||||
|
|
||||||
// NewFS returns a new proc FS mounted under the given proc mountPoint. It will error
|
// NewFS returns a new proc FS mounted under the given proc mountPoint. It will error
|
||||||
// if the mount point dirctory can't be read or is a file.
|
// if the mount point directory can't be read or is a file.
|
||||||
func NewFS(mountPoint string) (FS, error) {
|
func NewFS(mountPoint string) (FS, error) {
|
||||||
fs, err := fs.NewFS(mountPoint)
|
fs, err := fs.NewFS(mountPoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
module github.com/prometheus/procfs
|
module github.com/prometheus/procfs
|
||||||
|
|
||||||
require golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4
|
require (
|
||||||
|
github.com/google/go-cmp v0.3.0
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4
|
||||||
|
)
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|
|
@ -25,6 +25,9 @@ const (
|
||||||
|
|
||||||
// DefaultSysMountPoint is the common mount point of the sys filesystem.
|
// DefaultSysMountPoint is the common mount point of the sys filesystem.
|
||||||
DefaultSysMountPoint = "/sys"
|
DefaultSysMountPoint = "/sys"
|
||||||
|
|
||||||
|
// DefaultConfigfsMountPoint is the commont mount point of the configfs
|
||||||
|
DefaultConfigfsMountPoint = "/sys/kernel/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FS represents a pseudo-filesystem, normally /proc or /sys, which provides an
|
// FS represents a pseudo-filesystem, normally /proc or /sys, which provides an
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseUint32s parses a slice of strings into a slice of uint32s.
|
||||||
|
func ParseUint32s(ss []string) ([]uint32, error) {
|
||||||
|
us := make([]uint32, 0, len(ss))
|
||||||
|
for _, s := range ss {
|
||||||
|
u, err := strconv.ParseUint(s, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
us = append(us, uint32(u))
|
||||||
|
}
|
||||||
|
|
||||||
|
return us, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseUint64s parses a slice of strings into a slice of uint64s.
|
||||||
|
func ParseUint64s(ss []string) ([]uint64, error) {
|
||||||
|
us := make([]uint64, 0, len(ss))
|
||||||
|
for _, s := range ss {
|
||||||
|
u, err := strconv.ParseUint(s, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
us = append(us, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return us, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParsePInt64s parses a slice of strings into a slice of int64 pointers.
|
||||||
|
func ParsePInt64s(ss []string) ([]*int64, error) {
|
||||||
|
us := make([]*int64, 0, len(ss))
|
||||||
|
for _, s := range ss {
|
||||||
|
u, err := strconv.ParseInt(s, 10, 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)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseBool parses a string into a boolean pointer.
|
||||||
|
func ParseBool(b string) *bool {
|
||||||
|
var truth bool
|
||||||
|
switch b {
|
||||||
|
case "enabled":
|
||||||
|
truth = true
|
||||||
|
case "disabled":
|
||||||
|
truth = false
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &truth
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build linux,!appengine
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SysReadFile is a simplified ioutil.ReadFile that invokes syscall.Read directly.
|
||||||
|
// https://github.com/prometheus/node_exporter/pull/728/files
|
||||||
|
func SysReadFile(file string) (string, error) {
|
||||||
|
f, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// On some machines, hwmon drivers are broken and return EAGAIN. This causes
|
||||||
|
// Go's ioutil.ReadFile implementation to poll forever.
|
||||||
|
//
|
||||||
|
// Since we either want to read data or bail immediately, do the simplest
|
||||||
|
// possible read using syscall directly.
|
||||||
|
b := make([]byte, 128)
|
||||||
|
n, err := syscall.Read(int(f.Fd()), b)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(bytes.TrimSpace(b[:n])), nil
|
||||||
|
}
|
26
vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go
generated
vendored
Normal file
26
vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go
generated
vendored
Normal file
|
@ -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.
|
||||||
|
|
||||||
|
// +build linux,appengine !linux
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SysReadFile is here implemented as a noop for builds that do not support
|
||||||
|
// the read syscall. For example Windows, or Linux on Google App Engine.
|
||||||
|
func SysReadFile(file string) (string, error) {
|
||||||
|
return "", fmt.Errorf("not supported on this platform")
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(mdlayher): util packages are an anti-pattern and this should be moved
|
||||||
|
// somewhere else that is more focused in the future.
|
||||||
|
|
||||||
|
// A ValueParser enables parsing a single string into a variety of data types
|
||||||
|
// in a concise and safe way. The Err method must be invoked after invoking
|
||||||
|
// any other methods to ensure a value was successfully parsed.
|
||||||
|
type ValueParser struct {
|
||||||
|
v string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewValueParser creates a ValueParser using the input string.
|
||||||
|
func NewValueParser(v string) *ValueParser {
|
||||||
|
return &ValueParser{v: v}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PInt64 interprets the underlying value as an int64 and returns a pointer to
|
||||||
|
// that value.
|
||||||
|
func (vp *ValueParser) PInt64() *int64 {
|
||||||
|
if vp.err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A base value of zero makes ParseInt infer the correct base using the
|
||||||
|
// string's prefix, if any.
|
||||||
|
const base = 0
|
||||||
|
v, err := strconv.ParseInt(vp.v, base, 64)
|
||||||
|
if err != nil {
|
||||||
|
vp.err = err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUInt64 interprets the underlying value as an uint64 and returns a pointer to
|
||||||
|
// that value.
|
||||||
|
func (vp *ValueParser) PUInt64() *uint64 {
|
||||||
|
if vp.err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A base value of zero makes ParseInt infer the correct base using the
|
||||||
|
// string's prefix, if any.
|
||||||
|
const base = 0
|
||||||
|
v, err := strconv.ParseUint(vp.v, base, 64)
|
||||||
|
if err != nil {
|
||||||
|
vp.err = err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err returns the last error, if any, encountered by the ValueParser.
|
||||||
|
func (vp *ValueParser) Err() error {
|
||||||
|
return vp.err
|
||||||
|
}
|
|
@ -62,18 +62,8 @@ type IPVSBackendStatus struct {
|
||||||
Weight uint64
|
Weight uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIPVSStats reads the IPVS statistics.
|
// IPVSStats reads the IPVS statistics from the specified `proc` filesystem.
|
||||||
func NewIPVSStats() (IPVSStats, error) {
|
func (fs FS) IPVSStats() (IPVSStats, error) {
|
||||||
fs, err := NewFS(DefaultMountPoint)
|
|
||||||
if err != nil {
|
|
||||||
return IPVSStats{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.NewIPVSStats()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem.
|
|
||||||
func (fs FS) NewIPVSStats() (IPVSStats, error) {
|
|
||||||
file, err := os.Open(fs.proc.Path("net/ip_vs_stats"))
|
file, err := os.Open(fs.proc.Path("net/ip_vs_stats"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return IPVSStats{}, err
|
return IPVSStats{}, err
|
||||||
|
@ -131,18 +121,8 @@ func parseIPVSStats(file io.Reader) (IPVSStats, error) {
|
||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs.
|
// IPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
|
||||||
func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
|
func (fs FS) IPVSBackendStatus() ([]IPVSBackendStatus, error) {
|
||||||
fs, err := NewFS(DefaultMountPoint)
|
|
||||||
if err != nil {
|
|
||||||
return []IPVSBackendStatus{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.NewIPVSBackendStatus()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
|
|
||||||
func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
|
|
||||||
file, err := os.Open(fs.proc.Path("net/ip_vs"))
|
file, err := os.Open(fs.proc.Path("net/ip_vs"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -22,8 +22,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`)
|
statusLineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`)
|
||||||
buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`)
|
recoveryLineRE = regexp.MustCompile(`\((\d+)/\d+\)`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// MDStat holds info parsed from /proc/mdstat.
|
// MDStat holds info parsed from /proc/mdstat.
|
||||||
|
@ -34,117 +34,160 @@ type MDStat struct {
|
||||||
ActivityState string
|
ActivityState string
|
||||||
// Number of active disks.
|
// Number of active disks.
|
||||||
DisksActive int64
|
DisksActive int64
|
||||||
// Total number of disks the device consists of.
|
// Total number of disks the device requires.
|
||||||
DisksTotal int64
|
DisksTotal int64
|
||||||
|
// Number of failed disks.
|
||||||
|
DisksFailed int64
|
||||||
|
// Spare disks in the device.
|
||||||
|
DisksSpare int64
|
||||||
// Number of blocks the device holds.
|
// Number of blocks the device holds.
|
||||||
BlocksTotal int64
|
BlocksTotal int64
|
||||||
// Number of blocks on the device that are in sync.
|
// Number of blocks on the device that are in sync.
|
||||||
BlocksSynced int64
|
BlocksSynced int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseMDStat parses an mdstat-file and returns a struct with the relevant infos.
|
// MDStat parses an mdstat-file (/proc/mdstat) and returns a slice of
|
||||||
func (fs FS) ParseMDStat() (mdstates []MDStat, err error) {
|
// structs containing the relevant info. More information available here:
|
||||||
mdStatusFilePath := fs.proc.Path("mdstat")
|
// https://raid.wiki.kernel.org/index.php/Mdstat
|
||||||
content, err := ioutil.ReadFile(mdStatusFilePath)
|
func (fs FS) MDStat() ([]MDStat, error) {
|
||||||
|
data, err := ioutil.ReadFile(fs.proc.Path("mdstat"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
|
return nil, fmt.Errorf("error parsing mdstat %s: %s", fs.proc.Path("mdstat"), err)
|
||||||
|
}
|
||||||
|
mdstat, err := parseMDStat(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing mdstat %s: %s", fs.proc.Path("mdstat"), err)
|
||||||
|
}
|
||||||
|
return mdstat, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mdStates := []MDStat{}
|
// parseMDStat parses data from mdstat file (/proc/mdstat) and returns a slice of
|
||||||
lines := strings.Split(string(content), "\n")
|
// structs containing the relevant info.
|
||||||
for i, l := range lines {
|
func parseMDStat(mdStatData []byte) ([]MDStat, error) {
|
||||||
if l == "" {
|
mdStats := []MDStat{}
|
||||||
continue
|
lines := strings.Split(string(mdStatData), "\n")
|
||||||
}
|
|
||||||
if l[0] == ' ' {
|
for i, line := range lines {
|
||||||
continue
|
if strings.TrimSpace(line) == "" || line[0] == ' ' ||
|
||||||
}
|
strings.HasPrefix(line, "Personalities") ||
|
||||||
if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") {
|
strings.HasPrefix(line, "unused") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLine := strings.Split(l, " ")
|
deviceFields := strings.Fields(line)
|
||||||
if len(mainLine) < 3 {
|
if len(deviceFields) < 3 {
|
||||||
return mdStates, fmt.Errorf("error parsing mdline: %s", l)
|
return nil, fmt.Errorf("not enough fields in mdline (expected at least 3): %s", line)
|
||||||
}
|
}
|
||||||
mdName := mainLine[0]
|
mdName := deviceFields[0] // mdx
|
||||||
activityState := mainLine[2]
|
state := deviceFields[2] // active or inactive
|
||||||
|
|
||||||
if len(lines) <= i+3 {
|
if len(lines) <= i+3 {
|
||||||
return mdStates, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"error parsing %s: too few lines for md device %s",
|
"error parsing %s: too few lines for md device",
|
||||||
mdStatusFilePath,
|
|
||||||
mdName,
|
mdName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
active, total, size, err := evalStatusline(lines[i+1])
|
// 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])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
|
return nil, fmt.Errorf("error parsing md device lines: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// j is the line number of the syncing-line.
|
syncLineIdx := i + 2
|
||||||
j := i + 2
|
|
||||||
if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line
|
if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line
|
||||||
j = i + 3
|
syncLineIdx++
|
||||||
}
|
}
|
||||||
|
|
||||||
// If device is syncing at the moment, get the number of currently
|
// If device is syncing at the moment, get the number of currently
|
||||||
// synced bytes, otherwise that number equals the size of the device.
|
// synced bytes, otherwise that number equals the size of the device.
|
||||||
syncedBlocks := size
|
syncedBlocks := size
|
||||||
if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") {
|
recovering := strings.Contains(lines[syncLineIdx], "recovery")
|
||||||
syncedBlocks, err = evalBuildline(lines[j])
|
resyncing := strings.Contains(lines[syncLineIdx], "resync")
|
||||||
|
|
||||||
|
// Append recovery and resyncing state info.
|
||||||
|
if recovering || resyncing {
|
||||||
|
if recovering {
|
||||||
|
state = "recovering"
|
||||||
|
} else {
|
||||||
|
state = "resyncing"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle case when resync=PENDING or resync=DELAYED.
|
||||||
|
if strings.Contains(lines[syncLineIdx], "PENDING") ||
|
||||||
|
strings.Contains(lines[syncLineIdx], "DELAYED") {
|
||||||
|
syncedBlocks = 0
|
||||||
|
} else {
|
||||||
|
syncedBlocks, err = evalRecoveryLine(lines[syncLineIdx])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
|
return nil, fmt.Errorf("error parsing sync line in md device %s: %s", mdName, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mdStates = append(mdStates, MDStat{
|
mdStats = append(mdStats, MDStat{
|
||||||
Name: mdName,
|
Name: mdName,
|
||||||
ActivityState: activityState,
|
ActivityState: state,
|
||||||
DisksActive: active,
|
DisksActive: active,
|
||||||
|
DisksFailed: fail,
|
||||||
|
DisksSpare: spare,
|
||||||
DisksTotal: total,
|
DisksTotal: total,
|
||||||
BlocksTotal: size,
|
BlocksTotal: size,
|
||||||
BlocksSynced: syncedBlocks,
|
BlocksSynced: syncedBlocks,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return mdStates, nil
|
return mdStats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalStatusline(statusline string) (active, total, size int64, err error) {
|
func evalStatusLine(deviceLine, statusLine string) (active, total, size int64, err error) {
|
||||||
matches := statuslineRE.FindStringSubmatch(statusline)
|
|
||||||
if len(matches) != 4 {
|
|
||||||
return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline)
|
|
||||||
}
|
|
||||||
|
|
||||||
size, err = strconv.ParseInt(matches[1], 10, 64)
|
sizeStr := strings.Fields(statusLine)[0]
|
||||||
|
size, err = strconv.ParseInt(sizeStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
|
return 0, 0, 0, fmt.Errorf("unexpected statusLine %s: %s", 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
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(deviceLine, "inactive") {
|
||||||
|
return 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
total, err = strconv.ParseInt(matches[2], 10, 64)
|
total, err = strconv.ParseInt(matches[2], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
|
return 0, 0, 0, fmt.Errorf("unexpected statusLine %s: %s", statusLine, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
active, err = strconv.ParseInt(matches[3], 10, 64)
|
active, err = strconv.ParseInt(matches[3], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
|
return 0, 0, 0, fmt.Errorf("unexpected statusLine %s: %s", statusLine, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return active, total, size, nil
|
return active, total, size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalBuildline(buildline string) (syncedBlocks int64, err error) {
|
func evalRecoveryLine(recoveryLine string) (syncedBlocks int64, err error) {
|
||||||
matches := buildlineRE.FindStringSubmatch(buildline)
|
matches := recoveryLineRE.FindStringSubmatch(recoveryLine)
|
||||||
if len(matches) != 2 {
|
if len(matches) != 2 {
|
||||||
return 0, fmt.Errorf("unexpected buildline: %s", buildline)
|
return 0, fmt.Errorf("unexpected recoveryLine: %s", recoveryLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64)
|
syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("%s in buildline: %s", err, buildline)
|
return 0, fmt.Errorf("%s in recoveryLine: %s", err, recoveryLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
return syncedBlocks, nil
|
return syncedBlocks, nil
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var validOptionalFields = map[string]bool{
|
||||||
|
"shared": true,
|
||||||
|
"master": true,
|
||||||
|
"propagate_from": true,
|
||||||
|
"unbindable": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// A MountInfo is a type that describes the details, options
|
||||||
|
// for each mount, parsed from /proc/self/mountinfo.
|
||||||
|
// The fields described in each entry of /proc/self/mountinfo
|
||||||
|
// is described in the following man page.
|
||||||
|
// http://man7.org/linux/man-pages/man5/proc.5.html
|
||||||
|
type MountInfo struct {
|
||||||
|
// Unique Id for the mount
|
||||||
|
MountId int
|
||||||
|
// The Id of the parent mount
|
||||||
|
ParentId int
|
||||||
|
// The value of `st_dev` for the files on this FS
|
||||||
|
MajorMinorVer string
|
||||||
|
// The pathname of the directory in the FS that forms
|
||||||
|
// the root for this mount
|
||||||
|
Root string
|
||||||
|
// The pathname of the mount point relative to the root
|
||||||
|
MountPoint string
|
||||||
|
// Mount options
|
||||||
|
Options map[string]string
|
||||||
|
// Zero or more optional fields
|
||||||
|
OptionalFields map[string]string
|
||||||
|
// The Filesystem type
|
||||||
|
FSType string
|
||||||
|
// FS specific information or "none"
|
||||||
|
Source string
|
||||||
|
// Superblock options
|
||||||
|
SuperOptions map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns part of the mountinfo line, if it exists, else an empty string.
|
||||||
|
func getStringSliceElement(parts []string, idx int, defaultValue string) string {
|
||||||
|
if idx >= len(parts) {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
return parts[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads each line of the mountinfo file, and returns a list of formatted MountInfo structs.
|
||||||
|
func parseMountInfo(r io.Reader) ([]*MountInfo, error) {
|
||||||
|
mounts := []*MountInfo{}
|
||||||
|
scanner := bufio.NewScanner(r)
|
||||||
|
for scanner.Scan() {
|
||||||
|
mountString := scanner.Text()
|
||||||
|
parsedMounts, err := parseMountInfoString(mountString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mounts = append(mounts, parsedMounts)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := scanner.Err()
|
||||||
|
return mounts, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses a mountinfo file line, and converts it to a MountInfo struct.
|
||||||
|
// An important check here is to see if the hyphen separator, as if it does not exist,
|
||||||
|
// it means that the line is malformed.
|
||||||
|
func parseMountInfoString(mountString string) (*MountInfo, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// OptionalFields can be zero, hence these checks to ensure we do not populate the wrong values in the wrong spots
|
||||||
|
separatorIndex := strings.Index(mountString, "-")
|
||||||
|
if separatorIndex == -1 {
|
||||||
|
return nil, fmt.Errorf("no separator found in mountinfo string: %s", mountString)
|
||||||
|
}
|
||||||
|
beforeFields := strings.Fields(mountString[:separatorIndex])
|
||||||
|
afterFields := strings.Fields(mountString[separatorIndex+1:])
|
||||||
|
if (len(beforeFields) + len(afterFields)) < 7 {
|
||||||
|
return nil, fmt.Errorf("too few fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
mount := &MountInfo{
|
||||||
|
MajorMinorVer: getStringSliceElement(beforeFields, 2, ""),
|
||||||
|
Root: getStringSliceElement(beforeFields, 3, ""),
|
||||||
|
MountPoint: getStringSliceElement(beforeFields, 4, ""),
|
||||||
|
Options: mountOptionsParser(getStringSliceElement(beforeFields, 5, "")),
|
||||||
|
OptionalFields: nil,
|
||||||
|
FSType: getStringSliceElement(afterFields, 0, ""),
|
||||||
|
Source: getStringSliceElement(afterFields, 1, ""),
|
||||||
|
SuperOptions: mountOptionsParser(getStringSliceElement(afterFields, 2, "")),
|
||||||
|
}
|
||||||
|
|
||||||
|
mount.MountId, err = strconv.Atoi(getStringSliceElement(beforeFields, 0, ""))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse mount ID")
|
||||||
|
}
|
||||||
|
mount.ParentId, err = strconv.Atoi(getStringSliceElement(beforeFields, 1, ""))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse parent ID")
|
||||||
|
}
|
||||||
|
// Has optional fields, which is a space separated list of values.
|
||||||
|
// Example: shared:2 master:7
|
||||||
|
if len(beforeFields) > 6 {
|
||||||
|
mount.OptionalFields = make(map[string]string)
|
||||||
|
optionalFields := beforeFields[6:]
|
||||||
|
for _, field := range optionalFields {
|
||||||
|
optionSplit := strings.Split(field, ":")
|
||||||
|
target, value := optionSplit[0], ""
|
||||||
|
if len(optionSplit) == 2 {
|
||||||
|
value = optionSplit[1]
|
||||||
|
}
|
||||||
|
// Checks if the 'keys' in the optional fields in the mountinfo line are acceptable.
|
||||||
|
// Allowed 'keys' are shared, master, propagate_from, unbindable.
|
||||||
|
if _, ok := validOptionalFields[target]; ok {
|
||||||
|
mount.OptionalFields[target] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses the mount options, superblock options.
|
||||||
|
func mountOptionsParser(mountOptions string) map[string]string {
|
||||||
|
opts := make(map[string]string)
|
||||||
|
options := strings.Split(mountOptions, ",")
|
||||||
|
for _, opt := range options {
|
||||||
|
splitOption := strings.Split(opt, "=")
|
||||||
|
if len(splitOption) < 2 {
|
||||||
|
key := splitOption[0]
|
||||||
|
opts[key] = ""
|
||||||
|
} else {
|
||||||
|
key, value := splitOption[0], splitOption[1]
|
||||||
|
opts[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieves mountinfo information from `/proc/self/mountinfo`.
|
||||||
|
func GetMounts() ([]*MountInfo, error) {
|
||||||
|
f, err := os.Open("/proc/self/mountinfo")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return parseMountInfo(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieves mountinfo information from a processes' `/proc/<pid>/mountinfo`.
|
||||||
|
func GetProcMounts(pid int) ([]*MountInfo, error) {
|
||||||
|
f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return parseMountInfo(f)
|
||||||
|
}
|
|
@ -69,8 +69,8 @@ type MountStats interface {
|
||||||
type MountStatsNFS struct {
|
type MountStatsNFS struct {
|
||||||
// The version of statistics provided.
|
// The version of statistics provided.
|
||||||
StatVersion string
|
StatVersion string
|
||||||
// The optional mountaddr of the NFS mount.
|
// The mount options of the NFS mount.
|
||||||
MountAddress string
|
Opts map[string]string
|
||||||
// The age of the NFS mount.
|
// The age of the NFS mount.
|
||||||
Age time.Duration
|
Age time.Duration
|
||||||
// Statistics related to byte counters for various operations.
|
// Statistics related to byte counters for various operations.
|
||||||
|
@ -181,11 +181,11 @@ type NFSOperationStats struct {
|
||||||
// Number of bytes received for this operation, including RPC headers and payload.
|
// Number of bytes received for this operation, including RPC headers and payload.
|
||||||
BytesReceived uint64
|
BytesReceived uint64
|
||||||
// Duration all requests spent queued for transmission before they were sent.
|
// Duration all requests spent queued for transmission before they were sent.
|
||||||
CumulativeQueueTime time.Duration
|
CumulativeQueueMilliseconds uint64
|
||||||
// Duration it took to get a reply back after the request was transmitted.
|
// Duration it took to get a reply back after the request was transmitted.
|
||||||
CumulativeTotalResponseTime time.Duration
|
CumulativeTotalResponseMilliseconds uint64
|
||||||
// Duration from when a request was enqueued to when it was completely handled.
|
// Duration from when a request was enqueued to when it was completely handled.
|
||||||
CumulativeTotalRequestTime time.Duration
|
CumulativeTotalRequestMilliseconds uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// A NFSTransportStats contains statistics for the NFS mount RPC requests and
|
// A NFSTransportStats contains statistics for the NFS mount RPC requests and
|
||||||
|
@ -204,7 +204,7 @@ type NFSTransportStats struct {
|
||||||
// spent waiting for connections to the server to be established.
|
// spent waiting for connections to the server to be established.
|
||||||
ConnectIdleTime uint64
|
ConnectIdleTime uint64
|
||||||
// Duration since the NFS mount last saw any RPC traffic.
|
// Duration since the NFS mount last saw any RPC traffic.
|
||||||
IdleTime time.Duration
|
IdleTimeSeconds uint64
|
||||||
// Number of RPC requests for this mount sent to the NFS server.
|
// Number of RPC requests for this mount sent to the NFS server.
|
||||||
Sends uint64
|
Sends uint64
|
||||||
// Number of RPC responses for this mount received from the NFS server.
|
// Number of RPC responses for this mount received from the NFS server.
|
||||||
|
@ -342,10 +342,15 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e
|
||||||
|
|
||||||
switch ss[0] {
|
switch ss[0] {
|
||||||
case fieldOpts:
|
case fieldOpts:
|
||||||
|
if stats.Opts == nil {
|
||||||
|
stats.Opts = map[string]string{}
|
||||||
|
}
|
||||||
for _, opt := range strings.Split(ss[1], ",") {
|
for _, opt := range strings.Split(ss[1], ",") {
|
||||||
split := strings.Split(opt, "=")
|
split := strings.Split(opt, "=")
|
||||||
if len(split) == 2 && split[0] == "mountaddr" {
|
if len(split) == 2 {
|
||||||
stats.MountAddress = split[1]
|
stats.Opts[split[0]] = split[1]
|
||||||
|
} else {
|
||||||
|
stats.Opts[opt] = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case fieldAge:
|
case fieldAge:
|
||||||
|
@ -525,9 +530,9 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
|
||||||
MajorTimeouts: ns[2],
|
MajorTimeouts: ns[2],
|
||||||
BytesSent: ns[3],
|
BytesSent: ns[3],
|
||||||
BytesReceived: ns[4],
|
BytesReceived: ns[4],
|
||||||
CumulativeQueueTime: time.Duration(ns[5]) * time.Millisecond,
|
CumulativeQueueMilliseconds: ns[5],
|
||||||
CumulativeTotalResponseTime: time.Duration(ns[6]) * time.Millisecond,
|
CumulativeTotalResponseMilliseconds: ns[6],
|
||||||
CumulativeTotalRequestTime: time.Duration(ns[7]) * time.Millisecond,
|
CumulativeTotalRequestMilliseconds: ns[7],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,7 +608,7 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats
|
||||||
Bind: ns[1],
|
Bind: ns[1],
|
||||||
Connect: ns[2],
|
Connect: ns[2],
|
||||||
ConnectIdleTime: ns[3],
|
ConnectIdleTime: ns[3],
|
||||||
IdleTime: time.Duration(ns[4]) * time.Second,
|
IdleTimeSeconds: ns[4],
|
||||||
Sends: ns[5],
|
Sends: ns[5],
|
||||||
Receives: ns[6],
|
Receives: ns[6],
|
||||||
BadTransactionIDs: ns[7],
|
BadTransactionIDs: ns[7],
|
||||||
|
|
|
@ -47,23 +47,13 @@ type NetDevLine struct {
|
||||||
// are interface names.
|
// are interface names.
|
||||||
type NetDev map[string]NetDevLine
|
type NetDev map[string]NetDevLine
|
||||||
|
|
||||||
// NewNetDev returns kernel/system statistics read from /proc/net/dev.
|
// NetDev returns kernel/system statistics read from /proc/net/dev.
|
||||||
func NewNetDev() (NetDev, error) {
|
func (fs FS) NetDev() (NetDev, error) {
|
||||||
fs, err := NewFS(DefaultMountPoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.NewNetDev()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewNetDev returns kernel/system statistics read from /proc/net/dev.
|
|
||||||
func (fs FS) NewNetDev() (NetDev, error) {
|
|
||||||
return newNetDev(fs.proc.Path("net/dev"))
|
return newNetDev(fs.proc.Path("net/dev"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
|
// NetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
|
||||||
func (p Proc) NewNetDev() (NetDev, error) {
|
func (p Proc) NetDev() (NetDev, error) {
|
||||||
return newNetDev(p.path("net/dev"))
|
return newNetDev(p.path("net/dev"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +65,7 @@ func newNetDev(file string) (NetDev, error) {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
nd := NetDev{}
|
netDev := NetDev{}
|
||||||
s := bufio.NewScanner(f)
|
s := bufio.NewScanner(f)
|
||||||
for n := 0; s.Scan(); n++ {
|
for n := 0; s.Scan(); n++ {
|
||||||
// Skip the 2 header lines.
|
// Skip the 2 header lines.
|
||||||
|
@ -83,20 +73,20 @@ func newNetDev(file string) (NetDev, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
line, err := nd.parseLine(s.Text())
|
line, err := netDev.parseLine(s.Text())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nd, err
|
return netDev, err
|
||||||
}
|
}
|
||||||
|
|
||||||
nd[line.Name] = *line
|
netDev[line.Name] = *line
|
||||||
}
|
}
|
||||||
|
|
||||||
return nd, s.Err()
|
return netDev, s.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseLine parses a single line from the /proc/net/dev file. Header lines
|
// parseLine parses a single line from the /proc/net/dev file. Header lines
|
||||||
// must be filtered prior to calling this method.
|
// must be filtered prior to calling this method.
|
||||||
func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
|
func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) {
|
||||||
parts := strings.SplitN(rawLine, ":", 2)
|
parts := strings.SplitN(rawLine, ":", 2)
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
return nil, errors.New("invalid net/dev line, missing colon")
|
return nil, errors.New("invalid net/dev line, missing colon")
|
||||||
|
@ -185,11 +175,11 @@ func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
|
||||||
|
|
||||||
// Total aggregates the values across interfaces and returns a new NetDevLine.
|
// Total aggregates the values across interfaces and returns a new NetDevLine.
|
||||||
// The Name field will be a sorted comma separated list of interface names.
|
// The Name field will be a sorted comma separated list of interface names.
|
||||||
func (nd NetDev) Total() NetDevLine {
|
func (netDev NetDev) Total() NetDevLine {
|
||||||
total := NetDevLine{}
|
total := NetDevLine{}
|
||||||
|
|
||||||
names := make([]string, 0, len(nd))
|
names := make([]string, 0, len(netDev))
|
||||||
for _, ifc := range nd {
|
for _, ifc := range netDev {
|
||||||
names = append(names, ifc.Name)
|
names = append(names, ifc.Name)
|
||||||
total.RxBytes += ifc.RxBytes
|
total.RxBytes += ifc.RxBytes
|
||||||
total.RxPackets += ifc.RxPackets
|
total.RxPackets += ifc.RxPackets
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// For the proc file format details,
|
||||||
|
// see 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.
|
||||||
|
|
||||||
|
// SoftnetEntry contains a single row of data from /proc/net/softnet_stat
|
||||||
|
type SoftnetEntry struct {
|
||||||
|
// Number of processed packets
|
||||||
|
Processed uint
|
||||||
|
// Number of dropped packets
|
||||||
|
Dropped uint
|
||||||
|
// Number of times processing packets ran out of quota
|
||||||
|
TimeSqueezed uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// GatherSoftnetStats reads /proc/net/softnet_stat, parse the relevant columns,
|
||||||
|
// and then return a slice of SoftnetEntry's.
|
||||||
|
func (fs FS) GatherSoftnetStats() ([]SoftnetEntry, error) {
|
||||||
|
data, err := ioutil.ReadFile(fs.proc.Path("net/softnet_stat"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading softnet %s: %s", fs.proc.Path("net/softnet_stat"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseSoftnetEntries(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSoftnetEntries(data []byte) ([]SoftnetEntry, error) {
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
entries := make([]SoftnetEntry, 0)
|
||||||
|
var err error
|
||||||
|
const (
|
||||||
|
expectedColumns = 11
|
||||||
|
)
|
||||||
|
for _, line := range lines {
|
||||||
|
columns := strings.Fields(line)
|
||||||
|
width := len(columns)
|
||||||
|
if width == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if width != expectedColumns {
|
||||||
|
return []SoftnetEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedColumns)
|
||||||
|
}
|
||||||
|
var entry SoftnetEntry
|
||||||
|
if entry, err = parseSoftnetEntry(columns); err != nil {
|
||||||
|
return []SoftnetEntry{}, err
|
||||||
|
}
|
||||||
|
entries = append(entries, entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSoftnetEntry(columns []string) (SoftnetEntry, error) {
|
||||||
|
var err error
|
||||||
|
var processed, dropped, timeSqueezed uint64
|
||||||
|
if processed, err = strconv.ParseUint(columns[0], 16, 32); err != nil {
|
||||||
|
return SoftnetEntry{}, fmt.Errorf("Unable to parse column 0: %s", err)
|
||||||
|
}
|
||||||
|
if dropped, err = strconv.ParseUint(columns[1], 16, 32); err != nil {
|
||||||
|
return SoftnetEntry{}, fmt.Errorf("Unable to parse column 1: %s", err)
|
||||||
|
}
|
||||||
|
if timeSqueezed, err = strconv.ParseUint(columns[2], 16, 32); err != nil {
|
||||||
|
return SoftnetEntry{}, fmt.Errorf("Unable to parse column 2: %s", err)
|
||||||
|
}
|
||||||
|
return SoftnetEntry{
|
||||||
|
Processed: uint(processed),
|
||||||
|
Dropped: uint(dropped),
|
||||||
|
TimeSqueezed: uint(timeSqueezed),
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,275 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// For the proc file format details,
|
||||||
|
// see https://elixir.bootlin.com/linux/v4.17/source/net/unix/af_unix.c#L2815
|
||||||
|
// and https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/net.h#L48.
|
||||||
|
|
||||||
|
const (
|
||||||
|
netUnixKernelPtrIdx = iota
|
||||||
|
netUnixRefCountIdx
|
||||||
|
_
|
||||||
|
netUnixFlagsIdx
|
||||||
|
netUnixTypeIdx
|
||||||
|
netUnixStateIdx
|
||||||
|
netUnixInodeIdx
|
||||||
|
|
||||||
|
// Inode and Path are optional.
|
||||||
|
netUnixStaticFieldsCnt = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
netUnixTypeStream = 1
|
||||||
|
netUnixTypeDgram = 2
|
||||||
|
netUnixTypeSeqpacket = 5
|
||||||
|
|
||||||
|
netUnixFlagListen = 1 << 16
|
||||||
|
|
||||||
|
netUnixStateUnconnected = 1
|
||||||
|
netUnixStateConnecting = 2
|
||||||
|
netUnixStateConnected = 3
|
||||||
|
netUnixStateDisconnected = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
var errInvalidKernelPtrFmt = errors.New("Invalid Num(the kernel table slot number) format")
|
||||||
|
|
||||||
|
// NetUnixType is the type of the type field.
|
||||||
|
type NetUnixType uint64
|
||||||
|
|
||||||
|
// NetUnixFlags is the type of the flags field.
|
||||||
|
type NetUnixFlags uint64
|
||||||
|
|
||||||
|
// NetUnixState is the type of the state field.
|
||||||
|
type NetUnixState uint64
|
||||||
|
|
||||||
|
// NetUnixLine represents a line of /proc/net/unix.
|
||||||
|
type NetUnixLine struct {
|
||||||
|
KernelPtr string
|
||||||
|
RefCount uint64
|
||||||
|
Protocol uint64
|
||||||
|
Flags NetUnixFlags
|
||||||
|
Type NetUnixType
|
||||||
|
State NetUnixState
|
||||||
|
Inode uint64
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetUnix holds the data read from /proc/net/unix.
|
||||||
|
type NetUnix struct {
|
||||||
|
Rows []*NetUnixLine
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNetUnix returns data read from /proc/net/unix.
|
||||||
|
func NewNetUnix() (*NetUnix, error) {
|
||||||
|
fs, err := NewFS(DefaultMountPoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs.NewNetUnix()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNetUnix returns data read from /proc/net/unix.
|
||||||
|
func (fs FS) NewNetUnix() (*NetUnix, error) {
|
||||||
|
return NewNetUnixByPath(fs.proc.Path("net/unix"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNetUnixByPath returns data read from /proc/net/unix by file path.
|
||||||
|
// It might returns an error with partial parsed data, if an error occur after some data parsed.
|
||||||
|
func NewNetUnixByPath(path string) (*NetUnix, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return NewNetUnixByReader(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNetUnixByReader returns data read from /proc/net/unix by a reader.
|
||||||
|
// It might returns an error with partial parsed data, if an error occur after some data parsed.
|
||||||
|
func NewNetUnixByReader(reader io.Reader) (*NetUnix, error) {
|
||||||
|
nu := &NetUnix{
|
||||||
|
Rows: make([]*NetUnixLine, 0, 32),
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
// Omit the header line.
|
||||||
|
scanner.Scan()
|
||||||
|
header := scanner.Text()
|
||||||
|
// From the man page of proc(5), it does not contain an Inode field,
|
||||||
|
// but in actually it exists.
|
||||||
|
// This code works for both cases.
|
||||||
|
hasInode := strings.Contains(header, "Inode")
|
||||||
|
|
||||||
|
minFieldsCnt := netUnixStaticFieldsCnt
|
||||||
|
if hasInode {
|
||||||
|
minFieldsCnt++
|
||||||
|
}
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
item, err := nu.parseLine(line, hasInode, minFieldsCnt)
|
||||||
|
if err != nil {
|
||||||
|
return nu, err
|
||||||
|
}
|
||||||
|
nu.Rows = append(nu.Rows, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nu, scanner.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *NetUnix) parseLine(line string, hasInode bool, minFieldsCnt int) (*NetUnixLine, error) {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
fieldsLen := len(fields)
|
||||||
|
if fieldsLen < minFieldsCnt {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Parse Unix domain failed: expect at least %d fields but got %d",
|
||||||
|
minFieldsCnt, fieldsLen)
|
||||||
|
}
|
||||||
|
kernelPtr, err := u.parseKernelPtr(fields[netUnixKernelPtrIdx])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Parse Unix domain num(%s) failed: %s", fields[netUnixKernelPtrIdx], err)
|
||||||
|
}
|
||||||
|
users, err := u.parseUsers(fields[netUnixRefCountIdx])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Parse Unix domain ref count(%s) failed: %s", fields[netUnixRefCountIdx], err)
|
||||||
|
}
|
||||||
|
flags, err := u.parseFlags(fields[netUnixFlagsIdx])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Parse Unix domain flags(%s) failed: %s", fields[netUnixFlagsIdx], err)
|
||||||
|
}
|
||||||
|
typ, err := u.parseType(fields[netUnixTypeIdx])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Parse Unix domain type(%s) failed: %s", fields[netUnixTypeIdx], err)
|
||||||
|
}
|
||||||
|
state, err := u.parseState(fields[netUnixStateIdx])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Parse Unix domain state(%s) failed: %s", fields[netUnixStateIdx], err)
|
||||||
|
}
|
||||||
|
var inode uint64
|
||||||
|
if hasInode {
|
||||||
|
inodeStr := fields[netUnixInodeIdx]
|
||||||
|
inode, err = u.parseInode(inodeStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Parse Unix domain inode(%s) failed: %s", inodeStr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nuLine := &NetUnixLine{
|
||||||
|
KernelPtr: kernelPtr,
|
||||||
|
RefCount: users,
|
||||||
|
Type: typ,
|
||||||
|
Flags: flags,
|
||||||
|
State: state,
|
||||||
|
Inode: inode,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path field is optional.
|
||||||
|
if fieldsLen > minFieldsCnt {
|
||||||
|
pathIdx := netUnixInodeIdx + 1
|
||||||
|
if !hasInode {
|
||||||
|
pathIdx--
|
||||||
|
}
|
||||||
|
nuLine.Path = fields[pathIdx]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nuLine, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NetUnix) parseKernelPtr(str string) (string, error) {
|
||||||
|
if !strings.HasSuffix(str, ":") {
|
||||||
|
return "", errInvalidKernelPtrFmt
|
||||||
|
}
|
||||||
|
return str[:len(str)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NetUnix) parseUsers(hexStr string) (uint64, error) {
|
||||||
|
return strconv.ParseUint(hexStr, 16, 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NetUnix) parseProtocol(hexStr string) (uint64, error) {
|
||||||
|
return strconv.ParseUint(hexStr, 16, 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NetUnix) parseType(hexStr string) (NetUnixType, error) {
|
||||||
|
typ, err := strconv.ParseUint(hexStr, 16, 16)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return NetUnixType(typ), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NetUnix) parseFlags(hexStr string) (NetUnixFlags, error) {
|
||||||
|
flags, err := strconv.ParseUint(hexStr, 16, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return NetUnixFlags(flags), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NetUnix) parseState(hexStr string) (NetUnixState, error) {
|
||||||
|
st, err := strconv.ParseInt(hexStr, 16, 8)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return NetUnixState(st), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u NetUnix) parseInode(inodeStr string) (uint64, error) {
|
||||||
|
return strconv.ParseUint(inodeStr, 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t NetUnixType) String() string {
|
||||||
|
switch t {
|
||||||
|
case netUnixTypeStream:
|
||||||
|
return "stream"
|
||||||
|
case netUnixTypeDgram:
|
||||||
|
return "dgram"
|
||||||
|
case netUnixTypeSeqpacket:
|
||||||
|
return "seqpacket"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f NetUnixFlags) String() string {
|
||||||
|
switch f {
|
||||||
|
case netUnixFlagListen:
|
||||||
|
return "listen"
|
||||||
|
default:
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s NetUnixState) String() string {
|
||||||
|
switch s {
|
||||||
|
case netUnixStateUnconnected:
|
||||||
|
return "unconnected"
|
||||||
|
case netUnixStateConnecting:
|
||||||
|
return "connecting"
|
||||||
|
case netUnixStateConnected:
|
||||||
|
return "connected"
|
||||||
|
case netUnixStateDisconnected:
|
||||||
|
return "disconnected"
|
||||||
|
}
|
||||||
|
return "unknown"
|
||||||
|
}
|
|
@ -54,7 +54,7 @@ func NewProc(pid int) (Proc, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Proc{}, err
|
return Proc{}, err
|
||||||
}
|
}
|
||||||
return fs.NewProc(pid)
|
return fs.Proc(pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllProcs returns a list of all currently available processes under /proc.
|
// AllProcs returns a list of all currently available processes under /proc.
|
||||||
|
@ -76,11 +76,18 @@ func (fs FS) Self() (Proc, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Proc{}, err
|
return Proc{}, err
|
||||||
}
|
}
|
||||||
return fs.NewProc(pid)
|
return fs.Proc(pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProc returns a process for the given pid.
|
// NewProc returns a process for the given pid.
|
||||||
|
//
|
||||||
|
// Deprecated: use fs.Proc() instead
|
||||||
func (fs FS) NewProc(pid int) (Proc, error) {
|
func (fs FS) NewProc(pid int) (Proc, error) {
|
||||||
|
return fs.Proc(pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proc returns a process for the given pid.
|
||||||
|
func (fs FS) Proc(pid int) (Proc, error) {
|
||||||
if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil {
|
if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil {
|
||||||
return Proc{}, err
|
return Proc{}, err
|
||||||
}
|
}
|
||||||
|
@ -240,6 +247,20 @@ func (p Proc) MountStats() ([]*Mount, error) {
|
||||||
return parseMountStats(f)
|
return parseMountStats(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MountInfo retrieves mount information for mount points in a
|
||||||
|
// process's namespace.
|
||||||
|
// It supplies information missing in `/proc/self/mounts` and
|
||||||
|
// fixes various other problems with that file too.
|
||||||
|
func (p Proc) MountInfo() ([]*MountInfo, error) {
|
||||||
|
f, err := os.Open(p.path("mountinfo"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
return parseMountInfo(f)
|
||||||
|
}
|
||||||
|
|
||||||
func (p Proc) fileDescriptors() ([]string, error) {
|
func (p Proc) fileDescriptors() ([]string, error) {
|
||||||
d, err := os.Open(p.path("fd"))
|
d, err := os.Open(p.path("fd"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -258,3 +279,33 @@ func (p Proc) fileDescriptors() ([]string, error) {
|
||||||
func (p Proc) path(pa ...string) string {
|
func (p Proc) path(pa ...string) string {
|
||||||
return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
|
return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileDescriptorsInfo retrieves information about all file descriptors of
|
||||||
|
// the process.
|
||||||
|
func (p Proc) FileDescriptorsInfo() (ProcFDInfos, error) {
|
||||||
|
names, err := p.fileDescriptors()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var fdinfos ProcFDInfos
|
||||||
|
|
||||||
|
for _, n := range names {
|
||||||
|
fdinfo, err := p.FDInfo(n)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fdinfos = append(fdinfos, *fdinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fdinfos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedstat returns task scheduling information for the process.
|
||||||
|
func (p Proc) Schedstat() (ProcSchedstat, error) {
|
||||||
|
contents, err := ioutil.ReadFile(p.path("schedstat"))
|
||||||
|
if err != nil {
|
||||||
|
return ProcSchedstat{}, err
|
||||||
|
}
|
||||||
|
return parseProcSchedstat(string(contents))
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Environ reads process environments from /proc/<pid>/environ
|
||||||
|
func (p Proc) Environ() ([]string, error) {
|
||||||
|
environments := make([]string, 0)
|
||||||
|
|
||||||
|
f, err := os.Open(p.path("environ"))
|
||||||
|
if err != nil {
|
||||||
|
return environments, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return environments, err
|
||||||
|
}
|
||||||
|
|
||||||
|
environments = strings.Split(string(data), "\000")
|
||||||
|
if len(environments) > 0 {
|
||||||
|
environments = environments[:len(environments)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return environments, nil
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Regexp variables
|
||||||
|
var (
|
||||||
|
rPos = regexp.MustCompile(`^pos:\s+(\d+)$`)
|
||||||
|
rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`)
|
||||||
|
rMntID = regexp.MustCompile(`^mnt_id:\s+(\d+)$`)
|
||||||
|
rInotify = regexp.MustCompile(`^inotify`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProcFDInfo contains represents file descriptor information.
|
||||||
|
type ProcFDInfo struct {
|
||||||
|
// File descriptor
|
||||||
|
FD string
|
||||||
|
// File offset
|
||||||
|
Pos string
|
||||||
|
// File access mode and status flags
|
||||||
|
Flags string
|
||||||
|
// Mount point ID
|
||||||
|
MntID string
|
||||||
|
// List of inotify lines (structed) in the fdinfo file (kernel 3.8+ only)
|
||||||
|
InotifyInfos []InotifyInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// FDInfo constructor. On kernels older than 3.8, InotifyInfos will always be empty.
|
||||||
|
func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) {
|
||||||
|
f, err := os.Open(p.path("fdinfo", fd))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
fdinfo, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read %s: %s", f.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var text, pos, flags, mntid string
|
||||||
|
var inotify []InotifyInfo
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(strings.NewReader(string(fdinfo)))
|
||||||
|
for scanner.Scan() {
|
||||||
|
text = scanner.Text()
|
||||||
|
if rPos.MatchString(text) {
|
||||||
|
pos = rPos.FindStringSubmatch(text)[1]
|
||||||
|
} else if rFlags.MatchString(text) {
|
||||||
|
flags = rFlags.FindStringSubmatch(text)[1]
|
||||||
|
} else if rMntID.MatchString(text) {
|
||||||
|
mntid = rMntID.FindStringSubmatch(text)[1]
|
||||||
|
} else if rInotify.MatchString(text) {
|
||||||
|
newInotify, err := parseInotifyInfo(text)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inotify = append(inotify, *newInotify)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i := &ProcFDInfo{
|
||||||
|
FD: fd,
|
||||||
|
Pos: pos,
|
||||||
|
Flags: flags,
|
||||||
|
MntID: mntid,
|
||||||
|
InotifyInfos: inotify,
|
||||||
|
}
|
||||||
|
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InotifyInfo represents a single inotify line in the fdinfo file.
|
||||||
|
type InotifyInfo struct {
|
||||||
|
// Watch descriptor number
|
||||||
|
WD string
|
||||||
|
// Inode number
|
||||||
|
Ino string
|
||||||
|
// Device ID
|
||||||
|
Sdev string
|
||||||
|
// Mask of events being monitored
|
||||||
|
Mask string
|
||||||
|
}
|
||||||
|
|
||||||
|
// InotifyInfo constructor. Only available on kernel 3.8+.
|
||||||
|
func parseInotifyInfo(line string) (*InotifyInfo, error) {
|
||||||
|
r := regexp.MustCompile(`^inotify\s+wd:([0-9a-f]+)\s+ino:([0-9a-f]+)\s+sdev:([0-9a-f]+)\s+mask:([0-9a-f]+)`)
|
||||||
|
m := r.FindStringSubmatch(line)
|
||||||
|
i := &InotifyInfo{
|
||||||
|
WD: m[1],
|
||||||
|
Ino: m[2],
|
||||||
|
Sdev: m[3],
|
||||||
|
Mask: m[4],
|
||||||
|
}
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcFDInfos represents a list of ProcFDInfo structs.
|
||||||
|
type ProcFDInfos []ProcFDInfo
|
||||||
|
|
||||||
|
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
|
||||||
|
func (p ProcFDInfos) InotifyWatchLen() (int, error) {
|
||||||
|
length := 0
|
||||||
|
for _, f := range p {
|
||||||
|
length += len(f.InotifyInfos)
|
||||||
|
}
|
||||||
|
|
||||||
|
return length, nil
|
||||||
|
}
|
|
@ -39,8 +39,8 @@ type ProcIO struct {
|
||||||
CancelledWriteBytes int64
|
CancelledWriteBytes int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIO creates a new ProcIO instance from a given Proc instance.
|
// IO creates a new ProcIO instance from a given Proc instance.
|
||||||
func (p Proc) NewIO() (ProcIO, error) {
|
func (p Proc) IO() (ProcIO, error) {
|
||||||
pio := ProcIO{}
|
pio := ProcIO{}
|
||||||
|
|
||||||
f, err := os.Open(p.path("io"))
|
f, err := os.Open(p.path("io"))
|
||||||
|
|
|
@ -78,7 +78,14 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewLimits returns the current soft limits of the process.
|
// NewLimits returns the current soft limits of the process.
|
||||||
|
//
|
||||||
|
// Deprecated: use p.Limits() instead
|
||||||
func (p Proc) NewLimits() (ProcLimits, error) {
|
func (p Proc) NewLimits() (ProcLimits, error) {
|
||||||
|
return p.Limits()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limits returns the current soft limits of the process.
|
||||||
|
func (p Proc) Limits() (ProcLimits, error) {
|
||||||
f, err := os.Open(p.path("limits"))
|
f, err := os.Open(p.path("limits"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ProcLimits{}, err
|
return ProcLimits{}, err
|
||||||
|
|
|
@ -29,9 +29,9 @@ type Namespace struct {
|
||||||
// Namespaces contains all of the namespaces that the process is contained in.
|
// Namespaces contains all of the namespaces that the process is contained in.
|
||||||
type Namespaces map[string]Namespace
|
type Namespaces map[string]Namespace
|
||||||
|
|
||||||
// NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the
|
// Namespaces reads from /proc/<pid>/ns/* to get the namespaces of which the
|
||||||
// process is a member.
|
// process is a member.
|
||||||
func (p Proc) NewNamespaces() (Namespaces, error) {
|
func (p Proc) Namespaces() (Namespaces, error) {
|
||||||
d, err := os.Open(p.path("ns"))
|
d, err := os.Open(p.path("ns"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -51,19 +51,10 @@ type PSIStats struct {
|
||||||
Full *PSILine
|
Full *PSILine
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPSIStatsForResource reads pressure stall information for the specified
|
// PSIStatsForResource reads pressure stall information for the specified
|
||||||
// resource. At time of writing this can be either "cpu", "memory" or "io".
|
// resource from /proc/pressure/<resource>. At time of writing this can be
|
||||||
func NewPSIStatsForResource(resource string) (PSIStats, error) {
|
// either "cpu", "memory" or "io".
|
||||||
fs, err := NewFS(DefaultMountPoint)
|
func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) {
|
||||||
if err != nil {
|
|
||||||
return PSIStats{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.NewPSIStatsForResource(resource)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPSIStatsForResource reads pressure stall information from /proc/pressure/<resource>
|
|
||||||
func (fs FS) NewPSIStatsForResource(resource string) (PSIStats, error) {
|
|
||||||
file, err := os.Open(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource)))
|
file, err := os.Open(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %s", resource)
|
return PSIStats{}, fmt.Errorf("psi_stats: unavailable for %s", resource)
|
||||||
|
|
|
@ -105,7 +105,14 @@ type ProcStat struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStat returns the current status information of the process.
|
// NewStat returns the current status information of the process.
|
||||||
|
//
|
||||||
|
// Deprecated: use p.Stat() instead
|
||||||
func (p Proc) NewStat() (ProcStat, error) {
|
func (p Proc) NewStat() (ProcStat, error) {
|
||||||
|
return p.Stat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat returns the current status information of the process.
|
||||||
|
func (p Proc) Stat() (ProcStat, error) {
|
||||||
f, err := os.Open(p.path("stat"))
|
f, err := os.Open(p.path("stat"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ProcStat{}, err
|
return ProcStat{}, err
|
||||||
|
@ -178,7 +185,7 @@ func (s ProcStat) ResidentMemory() int {
|
||||||
// StartTime returns the unix timestamp of the process in seconds.
|
// StartTime returns the unix timestamp of the process in seconds.
|
||||||
func (s ProcStat) StartTime() (float64, error) {
|
func (s ProcStat) StartTime() (float64, error) {
|
||||||
fs := FS{proc: s.proc}
|
fs := FS{proc: s.proc}
|
||||||
stat, err := fs.NewStat()
|
stat, err := fs.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProcStat provides status information about the process,
|
||||||
|
// read from /proc/[pid]/stat.
|
||||||
|
type ProcStatus struct {
|
||||||
|
// The process ID.
|
||||||
|
PID int
|
||||||
|
// The process name.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// Peak virtual memory size.
|
||||||
|
VmPeak uint64
|
||||||
|
// Virtual memory size.
|
||||||
|
VmSize uint64
|
||||||
|
// Locked memory size.
|
||||||
|
VmLck uint64
|
||||||
|
// Pinned memory size.
|
||||||
|
VmPin uint64
|
||||||
|
// Peak resident set size.
|
||||||
|
VmHWM uint64
|
||||||
|
// Resident set size (sum of RssAnnon RssFile and RssShmem).
|
||||||
|
VmRSS uint64
|
||||||
|
// Size of resident anonymous memory.
|
||||||
|
RssAnon uint64
|
||||||
|
// Size of resident file mappings.
|
||||||
|
RssFile uint64
|
||||||
|
// Size of resident shared memory.
|
||||||
|
RssShmem uint64
|
||||||
|
// Size of data segments.
|
||||||
|
VmData uint64
|
||||||
|
// Size of stack segments.
|
||||||
|
VmStk uint64
|
||||||
|
// Size of text segments.
|
||||||
|
VmExe uint64
|
||||||
|
// Shared library code size.
|
||||||
|
VmLib uint64
|
||||||
|
// Page table entries size.
|
||||||
|
VmPTE uint64
|
||||||
|
// Size of second-level page tables.
|
||||||
|
VmPMD uint64
|
||||||
|
// Swapped-out virtual memory size by anonymous private.
|
||||||
|
VmSwap uint64
|
||||||
|
// Size of hugetlb memory portions
|
||||||
|
HugetlbPages uint64
|
||||||
|
|
||||||
|
// Number of voluntary context switches.
|
||||||
|
VoluntaryCtxtSwitches uint64
|
||||||
|
// Number of involuntary context switches.
|
||||||
|
NonVoluntaryCtxtSwitches uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStatus returns the current status information of the process.
|
||||||
|
func (p Proc) NewStatus() (ProcStatus, error) {
|
||||||
|
f, err := os.Open(p.path("status"))
|
||||||
|
if err != nil {
|
||||||
|
return ProcStatus{}, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return ProcStatus{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := ProcStatus{PID: p.PID}
|
||||||
|
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
if !bytes.Contains([]byte(line), []byte(":")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
kv := strings.SplitN(line, ":", 2)
|
||||||
|
|
||||||
|
// removes spaces
|
||||||
|
k := string(strings.TrimSpace(kv[0]))
|
||||||
|
v := string(strings.TrimSpace(kv[1]))
|
||||||
|
// removes "kB"
|
||||||
|
v = string(bytes.Trim([]byte(v), " kB"))
|
||||||
|
|
||||||
|
// value to int when possible
|
||||||
|
// we can skip error check here, 'cause vKBytes is not used when value is a string
|
||||||
|
vKBytes, _ := strconv.ParseUint(v, 10, 64)
|
||||||
|
// convert kB to B
|
||||||
|
vBytes := vKBytes * 1024
|
||||||
|
|
||||||
|
s.fillStatus(k, v, vKBytes, vBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintBytes uint64) {
|
||||||
|
switch k {
|
||||||
|
case "Name":
|
||||||
|
s.Name = vString
|
||||||
|
case "VmPeak":
|
||||||
|
s.VmPeak = vUintBytes
|
||||||
|
case "VmSize":
|
||||||
|
s.VmSize = vUintBytes
|
||||||
|
case "VmLck":
|
||||||
|
s.VmLck = vUintBytes
|
||||||
|
case "VmPin":
|
||||||
|
s.VmPin = vUintBytes
|
||||||
|
case "VmHWM":
|
||||||
|
s.VmHWM = vUintBytes
|
||||||
|
case "VmRSS":
|
||||||
|
s.VmRSS = vUintBytes
|
||||||
|
case "RssAnon":
|
||||||
|
s.RssAnon = vUintBytes
|
||||||
|
case "RssFile":
|
||||||
|
s.RssFile = vUintBytes
|
||||||
|
case "RssShmem":
|
||||||
|
s.RssShmem = vUintBytes
|
||||||
|
case "VmData":
|
||||||
|
s.VmData = vUintBytes
|
||||||
|
case "VmStk":
|
||||||
|
s.VmStk = vUintBytes
|
||||||
|
case "VmExe":
|
||||||
|
s.VmExe = vUintBytes
|
||||||
|
case "VmLib":
|
||||||
|
s.VmLib = vUintBytes
|
||||||
|
case "VmPTE":
|
||||||
|
s.VmPTE = vUintBytes
|
||||||
|
case "VmPMD":
|
||||||
|
s.VmPMD = vUintBytes
|
||||||
|
case "VmSwap":
|
||||||
|
s.VmSwap = vUintBytes
|
||||||
|
case "HugetlbPages":
|
||||||
|
s.HugetlbPages = vUintBytes
|
||||||
|
case "voluntary_ctxt_switches":
|
||||||
|
s.VoluntaryCtxtSwitches = vUint
|
||||||
|
case "nonvoluntary_ctxt_switches":
|
||||||
|
s.NonVoluntaryCtxtSwitches = vUint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalCtxtSwitches returns the total context switch.
|
||||||
|
func (s ProcStatus) TotalCtxtSwitches() uint64 {
|
||||||
|
return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cpuLineRE = regexp.MustCompile(`cpu(\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+)`)
|
||||||
|
procLineRE = regexp.MustCompile(`(\d+) (\d+) (\d+)`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Schedstat contains scheduler statistics from /proc/schedstats
|
||||||
|
//
|
||||||
|
// See
|
||||||
|
// https://www.kernel.org/doc/Documentation/scheduler/sched-stats.txt
|
||||||
|
// for a detailed description of what these numbers mean.
|
||||||
|
//
|
||||||
|
// Note the current kernel documentation claims some of the time units are in
|
||||||
|
// jiffies when they are actually in nanoseconds since 2.6.23 with the
|
||||||
|
// introduction of CFS. A fix to the documentation is pending. See
|
||||||
|
// https://lore.kernel.org/patchwork/project/lkml/list/?series=403473
|
||||||
|
|
||||||
|
type Schedstat struct {
|
||||||
|
CPUs []*SchedstatCPU
|
||||||
|
}
|
||||||
|
|
||||||
|
// SchedstatCPU contains the values from one "cpu<N>" line
|
||||||
|
type SchedstatCPU struct {
|
||||||
|
CPUNum string
|
||||||
|
|
||||||
|
RunningNanoseconds uint64
|
||||||
|
WaitingNanoseconds uint64
|
||||||
|
RunTimeslices uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcSchedstat contains the values from /proc/<pid>/schedstat
|
||||||
|
type ProcSchedstat struct {
|
||||||
|
RunningNanoseconds uint64
|
||||||
|
WaitingNanoseconds uint64
|
||||||
|
RunTimeslices uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs FS) Schedstat() (*Schedstat, error) {
|
||||||
|
file, err := os.Open(fs.proc.Path("schedstat"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
stats := &Schedstat{}
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
match := cpuLineRE.FindStringSubmatch(scanner.Text())
|
||||||
|
if match != nil {
|
||||||
|
cpu := &SchedstatCPU{}
|
||||||
|
cpu.CPUNum = match[1]
|
||||||
|
|
||||||
|
cpu.RunningNanoseconds, err = strconv.ParseUint(match[8], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu.WaitingNanoseconds, err = strconv.ParseUint(match[9], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu.RunTimeslices, err = strconv.ParseUint(match[10], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.CPUs = append(stats.CPUs, cpu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseProcSchedstat(contents string) (stats ProcSchedstat, err error) {
|
||||||
|
match := procLineRE.FindStringSubmatch(contents)
|
||||||
|
|
||||||
|
if match != nil {
|
||||||
|
stats.RunningNanoseconds, err = strconv.ParseUint(match[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.WaitingNanoseconds, err = strconv.ParseUint(match[2], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.RunTimeslices, err = strconv.ParseUint(match[3], 10, 64)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = errors.New("could not parse schedstat")
|
||||||
|
return
|
||||||
|
}
|
|
@ -20,6 +20,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CPUStat shows how much time the cpu spend in various stages.
|
// CPUStat shows how much time the cpu spend in various stages.
|
||||||
|
@ -78,16 +80,6 @@ type Stat struct {
|
||||||
SoftIRQ SoftIRQStat
|
SoftIRQ SoftIRQStat
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStat returns kernel/system statistics read from /proc/stat.
|
|
||||||
func NewStat() (Stat, error) {
|
|
||||||
fs, err := NewFS(DefaultMountPoint)
|
|
||||||
if err != nil {
|
|
||||||
return Stat{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fs.NewStat()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum).
|
// Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum).
|
||||||
func parseCPUStat(line string) (CPUStat, int64, error) {
|
func parseCPUStat(line string) (CPUStat, int64, error) {
|
||||||
cpuStat := CPUStat{}
|
cpuStat := CPUStat{}
|
||||||
|
@ -149,9 +141,29 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) {
|
||||||
return softIRQStat, total, nil
|
return softIRQStat, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStat returns an information about current kernel/system statistics.
|
// NewStat returns information about current cpu/process statistics.
|
||||||
func (fs FS) NewStat() (Stat, error) {
|
|
||||||
// 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
|
||||||
|
func NewStat() (Stat, error) {
|
||||||
|
fs, err := NewFS(fs.DefaultProcMountPoint)
|
||||||
|
if err != nil {
|
||||||
|
return Stat{}, err
|
||||||
|
}
|
||||||
|
return fs.Stat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStat returns information about current cpu/process statistics.
|
||||||
|
// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
func (fs FS) Stat() (Stat, error) {
|
||||||
|
|
||||||
f, err := os.Open(fs.proc.Path("stat"))
|
f, err := os.Open(fs.proc.Path("stat"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -88,6 +88,8 @@ Usage: $bname [-C <DIR>] -c -f <ARCHIVE> <FILE...> (create archive)
|
||||||
Options:
|
Options:
|
||||||
-C <DIR> (change directory)
|
-C <DIR> (change directory)
|
||||||
-v (verbose)
|
-v (verbose)
|
||||||
|
--recursive-unlink (recursively delete existing directory if path
|
||||||
|
collides with file or directory to extract)
|
||||||
|
|
||||||
Example: Change to sysfs directory, create ttar file from fixtures directory
|
Example: Change to sysfs directory, create ttar file from fixtures directory
|
||||||
$bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/
|
$bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/
|
||||||
|
@ -111,8 +113,9 @@ function set_cmd {
|
||||||
}
|
}
|
||||||
|
|
||||||
unset VERBOSE
|
unset VERBOSE
|
||||||
|
unset RECURSIVE_UNLINK
|
||||||
|
|
||||||
while getopts :cf:htxvC: opt; do
|
while getopts :cf:-:htxvC: opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
c)
|
c)
|
||||||
set_cmd "create"
|
set_cmd "create"
|
||||||
|
@ -136,6 +139,18 @@ while getopts :cf:htxvC: opt; do
|
||||||
C)
|
C)
|
||||||
CDIR=$OPTARG
|
CDIR=$OPTARG
|
||||||
;;
|
;;
|
||||||
|
-)
|
||||||
|
case $OPTARG in
|
||||||
|
recursive-unlink)
|
||||||
|
RECURSIVE_UNLINK="yes"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "Error: invalid option -$OPTARG"
|
||||||
|
echo
|
||||||
|
usage 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo >&2 "ERROR: invalid option -$OPTARG"
|
echo >&2 "ERROR: invalid option -$OPTARG"
|
||||||
echo
|
echo
|
||||||
|
@ -212,16 +227,16 @@ function extract {
|
||||||
local eof_without_newline
|
local eof_without_newline
|
||||||
if [ "$size" -gt 0 ]; then
|
if [ "$size" -gt 0 ]; then
|
||||||
if [[ "$line" =~ [^\\]EOF ]]; then
|
if [[ "$line" =~ [^\\]EOF ]]; then
|
||||||
# An EOF not preceeded by a backslash indicates that the line
|
# An EOF not preceded by a backslash indicates that the line
|
||||||
# does not end with a newline
|
# does not end with a newline
|
||||||
eof_without_newline=1
|
eof_without_newline=1
|
||||||
else
|
else
|
||||||
eof_without_newline=0
|
eof_without_newline=0
|
||||||
fi
|
fi
|
||||||
# Replace NULLBYTE with null byte if at beginning of line
|
# Replace NULLBYTE with null byte if at beginning of line
|
||||||
# Replace NULLBYTE with null byte unless preceeded by backslash
|
# Replace NULLBYTE with null byte unless preceded by backslash
|
||||||
# Remove one backslash in front of NULLBYTE (if any)
|
# Remove one backslash in front of NULLBYTE (if any)
|
||||||
# Remove EOF unless preceeded by backslash
|
# Remove EOF unless preceded by backslash
|
||||||
# Remove one backslash in front of EOF
|
# Remove one backslash in front of EOF
|
||||||
if [ $USE_PYTHON -eq 1 ]; then
|
if [ $USE_PYTHON -eq 1 ]; then
|
||||||
echo -n "$line" | python -c "$PYTHON_EXTRACT_FILTER" >> "$path"
|
echo -n "$line" | python -c "$PYTHON_EXTRACT_FILTER" >> "$path"
|
||||||
|
@ -245,7 +260,16 @@ function extract {
|
||||||
fi
|
fi
|
||||||
if [[ $line =~ ^Path:\ (.*)$ ]]; then
|
if [[ $line =~ ^Path:\ (.*)$ ]]; then
|
||||||
path=${BASH_REMATCH[1]}
|
path=${BASH_REMATCH[1]}
|
||||||
if [ -e "$path" ] || [ -L "$path" ]; then
|
if [ -L "$path" ]; then
|
||||||
|
rm "$path"
|
||||||
|
elif [ -d "$path" ]; then
|
||||||
|
if [ "${RECURSIVE_UNLINK:-}" == "yes" ]; then
|
||||||
|
rm -r "$path"
|
||||||
|
else
|
||||||
|
# Safe because symlinks to directories are dealt with above
|
||||||
|
rmdir "$path"
|
||||||
|
fi
|
||||||
|
elif [ -e "$path" ]; then
|
||||||
rm "$path"
|
rm "$path"
|
||||||
fi
|
fi
|
||||||
elif [[ $line =~ ^Lines:\ (.*)$ ]]; then
|
elif [[ $line =~ ^Lines:\ (.*)$ ]]; then
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The VM interface is described at
|
||||||
|
// 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
|
||||||
|
type VM struct {
|
||||||
|
AdminReserveKbytes *int64 // /proc/sys/vm/admin_reserve_kbytes
|
||||||
|
BlockDump *int64 // /proc/sys/vm/block_dump
|
||||||
|
CompactUnevictableAllowed *int64 // /proc/sys/vm/compact_unevictable_allowed
|
||||||
|
DirtyBackgroundBytes *int64 // /proc/sys/vm/dirty_background_bytes
|
||||||
|
DirtyBackgroundRatio *int64 // /proc/sys/vm/dirty_background_ratio
|
||||||
|
DirtyBytes *int64 // /proc/sys/vm/dirty_bytes
|
||||||
|
DirtyExpireCentisecs *int64 // /proc/sys/vm/dirty_expire_centisecs
|
||||||
|
DirtyRatio *int64 // /proc/sys/vm/dirty_ratio
|
||||||
|
DirtytimeExpireSeconds *int64 // /proc/sys/vm/dirtytime_expire_seconds
|
||||||
|
DirtyWritebackCentisecs *int64 // /proc/sys/vm/dirty_writeback_centisecs
|
||||||
|
DropCaches *int64 // /proc/sys/vm/drop_caches
|
||||||
|
ExtfragThreshold *int64 // /proc/sys/vm/extfrag_threshold
|
||||||
|
HugetlbShmGroup *int64 // /proc/sys/vm/hugetlb_shm_group
|
||||||
|
LaptopMode *int64 // /proc/sys/vm/laptop_mode
|
||||||
|
LegacyVaLayout *int64 // /proc/sys/vm/legacy_va_layout
|
||||||
|
LowmemReserveRatio []*int64 // /proc/sys/vm/lowmem_reserve_ratio
|
||||||
|
MaxMapCount *int64 // /proc/sys/vm/max_map_count
|
||||||
|
MemoryFailureEarlyKill *int64 // /proc/sys/vm/memory_failure_early_kill
|
||||||
|
MemoryFailureRecovery *int64 // /proc/sys/vm/memory_failure_recovery
|
||||||
|
MinFreeKbytes *int64 // /proc/sys/vm/min_free_kbytes
|
||||||
|
MinSlabRatio *int64 // /proc/sys/vm/min_slab_ratio
|
||||||
|
MinUnmappedRatio *int64 // /proc/sys/vm/min_unmapped_ratio
|
||||||
|
MmapMinAddr *int64 // /proc/sys/vm/mmap_min_addr
|
||||||
|
NrHugepages *int64 // /proc/sys/vm/nr_hugepages
|
||||||
|
NrHugepagesMempolicy *int64 // /proc/sys/vm/nr_hugepages_mempolicy
|
||||||
|
NrOvercommitHugepages *int64 // /proc/sys/vm/nr_overcommit_hugepages
|
||||||
|
NumaStat *int64 // /proc/sys/vm/numa_stat
|
||||||
|
NumaZonelistOrder string // /proc/sys/vm/numa_zonelist_order
|
||||||
|
OomDumpTasks *int64 // /proc/sys/vm/oom_dump_tasks
|
||||||
|
OomKillAllocatingTask *int64 // /proc/sys/vm/oom_kill_allocating_task
|
||||||
|
OvercommitKbytes *int64 // /proc/sys/vm/overcommit_kbytes
|
||||||
|
OvercommitMemory *int64 // /proc/sys/vm/overcommit_memory
|
||||||
|
OvercommitRatio *int64 // /proc/sys/vm/overcommit_ratio
|
||||||
|
PageCluster *int64 // /proc/sys/vm/page-cluster
|
||||||
|
PanicOnOom *int64 // /proc/sys/vm/panic_on_oom
|
||||||
|
PercpuPagelistFraction *int64 // /proc/sys/vm/percpu_pagelist_fraction
|
||||||
|
StatInterval *int64 // /proc/sys/vm/stat_interval
|
||||||
|
Swappiness *int64 // /proc/sys/vm/swappiness
|
||||||
|
UserReserveKbytes *int64 // /proc/sys/vm/user_reserve_kbytes
|
||||||
|
VfsCachePressure *int64 // /proc/sys/vm/vfs_cache_pressure
|
||||||
|
WatermarkBoostFactor *int64 // /proc/sys/vm/watermark_boost_factor
|
||||||
|
WatermarkScaleFactor *int64 // /proc/sys/vm/watermark_scale_factor
|
||||||
|
ZoneReclaimMode *int64 // /proc/sys/vm/zone_reclaim_mode
|
||||||
|
}
|
||||||
|
|
||||||
|
// VM reads the VM statistics from the specified `proc` filesystem.
|
||||||
|
func (fs FS) VM() (*VM, error) {
|
||||||
|
path := fs.proc.Path("sys/vm")
|
||||||
|
file, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !file.Mode().IsDir() {
|
||||||
|
return nil, fmt.Errorf("%s is not a directory", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := ioutil.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var vm VM
|
||||||
|
for _, f := range files {
|
||||||
|
if f.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name := filepath.Join(path, f.Name())
|
||||||
|
// ignore errors on read, as there are some write only
|
||||||
|
// in /proc/sys/vm
|
||||||
|
value, err := util.SysReadFile(name)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vp := util.NewValueParser(value)
|
||||||
|
|
||||||
|
switch f.Name() {
|
||||||
|
case "admin_reserve_kbytes":
|
||||||
|
vm.AdminReserveKbytes = vp.PInt64()
|
||||||
|
case "block_dump":
|
||||||
|
vm.BlockDump = vp.PInt64()
|
||||||
|
case "compact_unevictable_allowed":
|
||||||
|
vm.CompactUnevictableAllowed = vp.PInt64()
|
||||||
|
case "dirty_background_bytes":
|
||||||
|
vm.DirtyBackgroundBytes = vp.PInt64()
|
||||||
|
case "dirty_background_ratio":
|
||||||
|
vm.DirtyBackgroundRatio = vp.PInt64()
|
||||||
|
case "dirty_bytes":
|
||||||
|
vm.DirtyBytes = vp.PInt64()
|
||||||
|
case "dirty_expire_centisecs":
|
||||||
|
vm.DirtyExpireCentisecs = vp.PInt64()
|
||||||
|
case "dirty_ratio":
|
||||||
|
vm.DirtyRatio = vp.PInt64()
|
||||||
|
case "dirtytime_expire_seconds":
|
||||||
|
vm.DirtytimeExpireSeconds = vp.PInt64()
|
||||||
|
case "dirty_writeback_centisecs":
|
||||||
|
vm.DirtyWritebackCentisecs = vp.PInt64()
|
||||||
|
case "drop_caches":
|
||||||
|
vm.DropCaches = vp.PInt64()
|
||||||
|
case "extfrag_threshold":
|
||||||
|
vm.ExtfragThreshold = vp.PInt64()
|
||||||
|
case "hugetlb_shm_group":
|
||||||
|
vm.HugetlbShmGroup = vp.PInt64()
|
||||||
|
case "laptop_mode":
|
||||||
|
vm.LaptopMode = vp.PInt64()
|
||||||
|
case "legacy_va_layout":
|
||||||
|
vm.LegacyVaLayout = vp.PInt64()
|
||||||
|
case "lowmem_reserve_ratio":
|
||||||
|
stringSlice := strings.Fields(value)
|
||||||
|
pint64Slice := make([]*int64, 0, len(stringSlice))
|
||||||
|
for _, value := range stringSlice {
|
||||||
|
vp := util.NewValueParser(value)
|
||||||
|
pint64Slice = append(pint64Slice, vp.PInt64())
|
||||||
|
}
|
||||||
|
vm.LowmemReserveRatio = pint64Slice
|
||||||
|
case "max_map_count":
|
||||||
|
vm.MaxMapCount = vp.PInt64()
|
||||||
|
case "memory_failure_early_kill":
|
||||||
|
vm.MemoryFailureEarlyKill = vp.PInt64()
|
||||||
|
case "memory_failure_recovery":
|
||||||
|
vm.MemoryFailureRecovery = vp.PInt64()
|
||||||
|
case "min_free_kbytes":
|
||||||
|
vm.MinFreeKbytes = vp.PInt64()
|
||||||
|
case "min_slab_ratio":
|
||||||
|
vm.MinSlabRatio = vp.PInt64()
|
||||||
|
case "min_unmapped_ratio":
|
||||||
|
vm.MinUnmappedRatio = vp.PInt64()
|
||||||
|
case "mmap_min_addr":
|
||||||
|
vm.MmapMinAddr = vp.PInt64()
|
||||||
|
case "nr_hugepages":
|
||||||
|
vm.NrHugepages = vp.PInt64()
|
||||||
|
case "nr_hugepages_mempolicy":
|
||||||
|
vm.NrHugepagesMempolicy = vp.PInt64()
|
||||||
|
case "nr_overcommit_hugepages":
|
||||||
|
vm.NrOvercommitHugepages = vp.PInt64()
|
||||||
|
case "numa_stat":
|
||||||
|
vm.NumaStat = vp.PInt64()
|
||||||
|
case "numa_zonelist_order":
|
||||||
|
vm.NumaZonelistOrder = value
|
||||||
|
case "oom_dump_tasks":
|
||||||
|
vm.OomDumpTasks = vp.PInt64()
|
||||||
|
case "oom_kill_allocating_task":
|
||||||
|
vm.OomKillAllocatingTask = vp.PInt64()
|
||||||
|
case "overcommit_kbytes":
|
||||||
|
vm.OvercommitKbytes = vp.PInt64()
|
||||||
|
case "overcommit_memory":
|
||||||
|
vm.OvercommitMemory = vp.PInt64()
|
||||||
|
case "overcommit_ratio":
|
||||||
|
vm.OvercommitRatio = vp.PInt64()
|
||||||
|
case "page-cluster":
|
||||||
|
vm.PageCluster = vp.PInt64()
|
||||||
|
case "panic_on_oom":
|
||||||
|
vm.PanicOnOom = vp.PInt64()
|
||||||
|
case "percpu_pagelist_fraction":
|
||||||
|
vm.PercpuPagelistFraction = vp.PInt64()
|
||||||
|
case "stat_interval":
|
||||||
|
vm.StatInterval = vp.PInt64()
|
||||||
|
case "swappiness":
|
||||||
|
vm.Swappiness = vp.PInt64()
|
||||||
|
case "user_reserve_kbytes":
|
||||||
|
vm.UserReserveKbytes = vp.PInt64()
|
||||||
|
case "vfs_cache_pressure":
|
||||||
|
vm.VfsCachePressure = vp.PInt64()
|
||||||
|
case "watermark_boost_factor":
|
||||||
|
vm.WatermarkBoostFactor = vp.PInt64()
|
||||||
|
case "watermark_scale_factor":
|
||||||
|
vm.WatermarkScaleFactor = vp.PInt64()
|
||||||
|
case "zone_reclaim_mode":
|
||||||
|
vm.ZoneReclaimMode = vp.PInt64()
|
||||||
|
}
|
||||||
|
if err := vp.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &vm, nil
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package procfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/procfs/internal/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Zoneinfo holds info parsed from /proc/zoneinfo.
|
||||||
|
type Zoneinfo struct {
|
||||||
|
Node string
|
||||||
|
Zone string
|
||||||
|
NrFreePages *int64
|
||||||
|
Min *int64
|
||||||
|
Low *int64
|
||||||
|
High *int64
|
||||||
|
Scanned *int64
|
||||||
|
Spanned *int64
|
||||||
|
Present *int64
|
||||||
|
Managed *int64
|
||||||
|
NrActiveAnon *int64
|
||||||
|
NrInactiveAnon *int64
|
||||||
|
NrIsolatedAnon *int64
|
||||||
|
NrAnonPages *int64
|
||||||
|
NrAnonTransparentHugepages *int64
|
||||||
|
NrActiveFile *int64
|
||||||
|
NrInactiveFile *int64
|
||||||
|
NrIsolatedFile *int64
|
||||||
|
NrFilePages *int64
|
||||||
|
NrSlabReclaimable *int64
|
||||||
|
NrSlabUnreclaimable *int64
|
||||||
|
NrMlockStack *int64
|
||||||
|
NrKernelStack *int64
|
||||||
|
NrMapped *int64
|
||||||
|
NrDirty *int64
|
||||||
|
NrWriteback *int64
|
||||||
|
NrUnevictable *int64
|
||||||
|
NrShmem *int64
|
||||||
|
NrDirtied *int64
|
||||||
|
NrWritten *int64
|
||||||
|
NumaHit *int64
|
||||||
|
NumaMiss *int64
|
||||||
|
NumaForeign *int64
|
||||||
|
NumaInterleave *int64
|
||||||
|
NumaLocal *int64
|
||||||
|
NumaOther *int64
|
||||||
|
Protection []*int64
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`)
|
||||||
|
|
||||||
|
// Zoneinfo parses an zoneinfo-file (/proc/zoneinfo) and returns a slice of
|
||||||
|
// 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"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading zoneinfo %s: %s", fs.proc.Path("zoneinfo"), err)
|
||||||
|
}
|
||||||
|
zoneinfo, err := parseZoneinfo(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error parsing zoneinfo %s: %s", fs.proc.Path("zoneinfo"), err)
|
||||||
|
}
|
||||||
|
return zoneinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseZoneinfo(zoneinfoData []byte) ([]Zoneinfo, error) {
|
||||||
|
|
||||||
|
zoneinfo := []Zoneinfo{}
|
||||||
|
|
||||||
|
zoneinfoBlocks := bytes.Split(zoneinfoData, []byte("\nNode"))
|
||||||
|
for _, block := range zoneinfoBlocks {
|
||||||
|
var zoneinfoElement Zoneinfo
|
||||||
|
lines := strings.Split(string(block), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
|
||||||
|
if nodeZone := nodeZoneRE.FindStringSubmatch(line); nodeZone != nil {
|
||||||
|
zoneinfoElement.Node = nodeZone[1]
|
||||||
|
zoneinfoElement.Zone = nodeZone[2]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(strings.TrimSpace(line), "per-node stats") {
|
||||||
|
zoneinfoElement.Zone = ""
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
parts := strings.Fields(strings.TrimSpace(line))
|
||||||
|
if len(parts) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vp := util.NewValueParser(parts[1])
|
||||||
|
switch parts[0] {
|
||||||
|
case "nr_free_pages":
|
||||||
|
zoneinfoElement.NrFreePages = vp.PInt64()
|
||||||
|
case "min":
|
||||||
|
zoneinfoElement.Min = vp.PInt64()
|
||||||
|
case "low":
|
||||||
|
zoneinfoElement.Low = vp.PInt64()
|
||||||
|
case "high":
|
||||||
|
zoneinfoElement.High = vp.PInt64()
|
||||||
|
case "scanned":
|
||||||
|
zoneinfoElement.Scanned = vp.PInt64()
|
||||||
|
case "spanned":
|
||||||
|
zoneinfoElement.Spanned = vp.PInt64()
|
||||||
|
case "present":
|
||||||
|
zoneinfoElement.Present = vp.PInt64()
|
||||||
|
case "managed":
|
||||||
|
zoneinfoElement.Managed = vp.PInt64()
|
||||||
|
case "nr_active_anon":
|
||||||
|
zoneinfoElement.NrActiveAnon = vp.PInt64()
|
||||||
|
case "nr_inactive_anon":
|
||||||
|
zoneinfoElement.NrInactiveAnon = vp.PInt64()
|
||||||
|
case "nr_isolated_anon":
|
||||||
|
zoneinfoElement.NrIsolatedAnon = vp.PInt64()
|
||||||
|
case "nr_anon_pages":
|
||||||
|
zoneinfoElement.NrAnonPages = vp.PInt64()
|
||||||
|
case "nr_anon_transparent_hugepages":
|
||||||
|
zoneinfoElement.NrAnonTransparentHugepages = vp.PInt64()
|
||||||
|
case "nr_active_file":
|
||||||
|
zoneinfoElement.NrActiveFile = vp.PInt64()
|
||||||
|
case "nr_inactive_file":
|
||||||
|
zoneinfoElement.NrInactiveFile = vp.PInt64()
|
||||||
|
case "nr_isolated_file":
|
||||||
|
zoneinfoElement.NrIsolatedFile = vp.PInt64()
|
||||||
|
case "nr_file_pages":
|
||||||
|
zoneinfoElement.NrFilePages = vp.PInt64()
|
||||||
|
case "nr_slab_reclaimable":
|
||||||
|
zoneinfoElement.NrSlabReclaimable = vp.PInt64()
|
||||||
|
case "nr_slab_unreclaimable":
|
||||||
|
zoneinfoElement.NrSlabUnreclaimable = vp.PInt64()
|
||||||
|
case "nr_mlock_stack":
|
||||||
|
zoneinfoElement.NrMlockStack = vp.PInt64()
|
||||||
|
case "nr_kernel_stack":
|
||||||
|
zoneinfoElement.NrKernelStack = vp.PInt64()
|
||||||
|
case "nr_mapped":
|
||||||
|
zoneinfoElement.NrMapped = vp.PInt64()
|
||||||
|
case "nr_dirty":
|
||||||
|
zoneinfoElement.NrDirty = vp.PInt64()
|
||||||
|
case "nr_writeback":
|
||||||
|
zoneinfoElement.NrWriteback = vp.PInt64()
|
||||||
|
case "nr_unevictable":
|
||||||
|
zoneinfoElement.NrUnevictable = vp.PInt64()
|
||||||
|
case "nr_shmem":
|
||||||
|
zoneinfoElement.NrShmem = vp.PInt64()
|
||||||
|
case "nr_dirtied":
|
||||||
|
zoneinfoElement.NrDirtied = vp.PInt64()
|
||||||
|
case "nr_written":
|
||||||
|
zoneinfoElement.NrWritten = vp.PInt64()
|
||||||
|
case "numa_hit":
|
||||||
|
zoneinfoElement.NumaHit = vp.PInt64()
|
||||||
|
case "numa_miss":
|
||||||
|
zoneinfoElement.NumaMiss = vp.PInt64()
|
||||||
|
case "numa_foreign":
|
||||||
|
zoneinfoElement.NumaForeign = vp.PInt64()
|
||||||
|
case "numa_interleave":
|
||||||
|
zoneinfoElement.NumaInterleave = vp.PInt64()
|
||||||
|
case "numa_local":
|
||||||
|
zoneinfoElement.NumaLocal = vp.PInt64()
|
||||||
|
case "numa_other":
|
||||||
|
zoneinfoElement.NumaOther = vp.PInt64()
|
||||||
|
case "protection:":
|
||||||
|
protectionParts := strings.Split(line, ":")
|
||||||
|
protectionValues := strings.Replace(protectionParts[1], "(", "", 1)
|
||||||
|
protectionValues = strings.Replace(protectionValues, ")", "", 1)
|
||||||
|
protectionValues = strings.TrimSpace(protectionValues)
|
||||||
|
protectionStringMap := strings.Split(protectionValues, ", ")
|
||||||
|
val, err := util.ParsePInt64s(protectionStringMap)
|
||||||
|
if err == nil {
|
||||||
|
zoneinfoElement.Protection = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
zoneinfo = append(zoneinfo, zoneinfoElement)
|
||||||
|
}
|
||||||
|
return zoneinfo, nil
|
||||||
|
}
|
|
@ -113,6 +113,17 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
|
||||||
return Error(t, err, append([]interface{}{msg}, args...)...)
|
return Error(t, err, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Eventuallyf asserts that given condition will be met in waitFor time,
|
||||||
|
// periodically checking target function each tick.
|
||||||
|
//
|
||||||
|
// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
|
||||||
|
func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// Exactlyf asserts that two objects are equal in value and type.
|
// Exactlyf asserts that two objects are equal in value and type.
|
||||||
//
|
//
|
||||||
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
|
||||||
|
@ -157,6 +168,31 @@ func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool
|
||||||
return FileExists(t, path, append([]interface{}{msg}, args...)...)
|
return FileExists(t, path, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Greaterf asserts that the first element is greater than the second
|
||||||
|
//
|
||||||
|
// assert.Greaterf(t, 2, 1, "error message %s", "formatted")
|
||||||
|
// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1))
|
||||||
|
// assert.Greaterf(t, "b", "a", "error message %s", "formatted")
|
||||||
|
func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Greater(t, e1, e2, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterOrEqualf asserts that the first element is greater than or equal to the second
|
||||||
|
//
|
||||||
|
// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted")
|
||||||
|
// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted")
|
||||||
|
// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted")
|
||||||
|
// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted")
|
||||||
|
func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPBodyContainsf asserts that a specified handler returns a
|
// HTTPBodyContainsf asserts that a specified handler returns a
|
||||||
// body that contains a string.
|
// body that contains a string.
|
||||||
//
|
//
|
||||||
|
@ -289,6 +325,14 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int
|
||||||
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
|
return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YAMLEqf asserts that two YAML strings are equivalent.
|
||||||
|
func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// Lenf asserts that the specified object has specific length.
|
// Lenf asserts that the specified object has specific length.
|
||||||
// Lenf also fails if the object has a type that len() not accept.
|
// Lenf also fails if the object has a type that len() not accept.
|
||||||
//
|
//
|
||||||
|
@ -300,6 +344,31 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf
|
||||||
return Len(t, object, length, append([]interface{}{msg}, args...)...)
|
return Len(t, object, length, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lessf asserts that the first element is less than the second
|
||||||
|
//
|
||||||
|
// assert.Lessf(t, 1, 2, "error message %s", "formatted")
|
||||||
|
// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2))
|
||||||
|
// assert.Lessf(t, "a", "b", "error message %s", "formatted")
|
||||||
|
func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Less(t, e1, e2, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessOrEqualf asserts that the first element is less than or equal to the second
|
||||||
|
//
|
||||||
|
// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted")
|
||||||
|
// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted")
|
||||||
|
// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted")
|
||||||
|
// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted")
|
||||||
|
func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// Nilf asserts that the specified object is nil.
|
// Nilf asserts that the specified object is nil.
|
||||||
//
|
//
|
||||||
// assert.Nilf(t, err, "error message %s", "formatted")
|
// assert.Nilf(t, err, "error message %s", "formatted")
|
||||||
|
@ -444,6 +513,19 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in
|
||||||
return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Samef asserts that two pointers reference the same object.
|
||||||
|
//
|
||||||
|
// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Both arguments must be pointer variables. Pointer variable sameness is
|
||||||
|
// determined based on the equality of both type and value.
|
||||||
|
func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Same(t, expected, actual, append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
// Subsetf asserts that the specified list(array, slice...) contains all
|
// Subsetf asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset(array, slice...).
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
|
|
|
@ -215,6 +215,28 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
|
||||||
return Errorf(a.t, err, msg, args...)
|
return Errorf(a.t, err, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Eventually asserts that given condition will be met in waitFor time,
|
||||||
|
// periodically checking target function each tick.
|
||||||
|
//
|
||||||
|
// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
|
||||||
|
func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eventuallyf asserts that given condition will be met in waitFor time,
|
||||||
|
// periodically checking target function each tick.
|
||||||
|
//
|
||||||
|
// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
|
||||||
|
func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Eventuallyf(a.t, condition, waitFor, tick, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Exactly asserts that two objects are equal in value and type.
|
// Exactly asserts that two objects are equal in value and type.
|
||||||
//
|
//
|
||||||
// a.Exactly(int32(123), int64(123))
|
// a.Exactly(int32(123), int64(123))
|
||||||
|
@ -303,6 +325,56 @@ func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) b
|
||||||
return FileExistsf(a.t, path, msg, args...)
|
return FileExistsf(a.t, path, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Greater asserts that the first element is greater than the second
|
||||||
|
//
|
||||||
|
// a.Greater(2, 1)
|
||||||
|
// a.Greater(float64(2), float64(1))
|
||||||
|
// a.Greater("b", "a")
|
||||||
|
func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Greater(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
||||||
|
//
|
||||||
|
// a.GreaterOrEqual(2, 1)
|
||||||
|
// a.GreaterOrEqual(2, 2)
|
||||||
|
// a.GreaterOrEqual("b", "a")
|
||||||
|
// a.GreaterOrEqual("b", "b")
|
||||||
|
func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return GreaterOrEqual(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterOrEqualf asserts that the first element is greater than or equal to the second
|
||||||
|
//
|
||||||
|
// a.GreaterOrEqualf(2, 1, "error message %s", "formatted")
|
||||||
|
// a.GreaterOrEqualf(2, 2, "error message %s", "formatted")
|
||||||
|
// a.GreaterOrEqualf("b", "a", "error message %s", "formatted")
|
||||||
|
// a.GreaterOrEqualf("b", "b", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return GreaterOrEqualf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Greaterf asserts that the first element is greater than the second
|
||||||
|
//
|
||||||
|
// a.Greaterf(2, 1, "error message %s", "formatted")
|
||||||
|
// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1))
|
||||||
|
// a.Greaterf("b", "a", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Greaterf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPBodyContains asserts that a specified handler returns a
|
// HTTPBodyContains asserts that a specified handler returns a
|
||||||
// body that contains a string.
|
// body that contains a string.
|
||||||
//
|
//
|
||||||
|
@ -567,6 +639,22 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
|
||||||
return JSONEqf(a.t, expected, actual, msg, args...)
|
return JSONEqf(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YAMLEq asserts that two YAML strings are equivalent.
|
||||||
|
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return YAMLEq(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// YAMLEqf asserts that two YAML strings are equivalent.
|
||||||
|
func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return YAMLEqf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Len asserts that the specified object has specific length.
|
// Len asserts that the specified object has specific length.
|
||||||
// Len also fails if the object has a type that len() not accept.
|
// Len also fails if the object has a type that len() not accept.
|
||||||
//
|
//
|
||||||
|
@ -589,6 +677,56 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in
|
||||||
return Lenf(a.t, object, length, msg, args...)
|
return Lenf(a.t, object, length, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Less asserts that the first element is less than the second
|
||||||
|
//
|
||||||
|
// a.Less(1, 2)
|
||||||
|
// a.Less(float64(1), float64(2))
|
||||||
|
// a.Less("a", "b")
|
||||||
|
func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Less(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessOrEqual asserts that the first element is less than or equal to the second
|
||||||
|
//
|
||||||
|
// a.LessOrEqual(1, 2)
|
||||||
|
// a.LessOrEqual(2, 2)
|
||||||
|
// a.LessOrEqual("a", "b")
|
||||||
|
// a.LessOrEqual("b", "b")
|
||||||
|
func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return LessOrEqual(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessOrEqualf asserts that the first element is less than or equal to the second
|
||||||
|
//
|
||||||
|
// a.LessOrEqualf(1, 2, "error message %s", "formatted")
|
||||||
|
// a.LessOrEqualf(2, 2, "error message %s", "formatted")
|
||||||
|
// a.LessOrEqualf("a", "b", "error message %s", "formatted")
|
||||||
|
// a.LessOrEqualf("b", "b", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return LessOrEqualf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lessf asserts that the first element is less than the second
|
||||||
|
//
|
||||||
|
// a.Lessf(1, 2, "error message %s", "formatted")
|
||||||
|
// a.Lessf(float64(1, "error message %s", "formatted"), float64(2))
|
||||||
|
// a.Lessf("a", "b", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Lessf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Nil asserts that the specified object is nil.
|
// Nil asserts that the specified object is nil.
|
||||||
//
|
//
|
||||||
// a.Nil(err)
|
// a.Nil(err)
|
||||||
|
@ -877,6 +1015,32 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args .
|
||||||
return Regexpf(a.t, rx, str, msg, args...)
|
return Regexpf(a.t, rx, str, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same asserts that two pointers reference the same object.
|
||||||
|
//
|
||||||
|
// a.Same(ptr1, ptr2)
|
||||||
|
//
|
||||||
|
// Both arguments must be pointer variables. Pointer variable sameness is
|
||||||
|
// determined based on the equality of both type and value.
|
||||||
|
func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Same(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Samef asserts that two pointers reference the same object.
|
||||||
|
//
|
||||||
|
// a.Samef(ptr1, ptr2, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Both arguments must be pointer variables. Pointer variable sameness is
|
||||||
|
// determined based on the equality of both type and value.
|
||||||
|
func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
return Samef(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Subset asserts that the specified list(array, slice...) contains all
|
// Subset asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset(array, slice...).
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
|
|
|
@ -0,0 +1,309 @@
|
||||||
|
package assert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) {
|
||||||
|
switch kind {
|
||||||
|
case reflect.Int:
|
||||||
|
{
|
||||||
|
intobj1 := obj1.(int)
|
||||||
|
intobj2 := obj2.(int)
|
||||||
|
if intobj1 > intobj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if intobj1 == intobj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if intobj1 < intobj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Int8:
|
||||||
|
{
|
||||||
|
int8obj1 := obj1.(int8)
|
||||||
|
int8obj2 := obj2.(int8)
|
||||||
|
if int8obj1 > int8obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if int8obj1 == int8obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if int8obj1 < int8obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Int16:
|
||||||
|
{
|
||||||
|
int16obj1 := obj1.(int16)
|
||||||
|
int16obj2 := obj2.(int16)
|
||||||
|
if int16obj1 > int16obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if int16obj1 == int16obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if int16obj1 < int16obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Int32:
|
||||||
|
{
|
||||||
|
int32obj1 := obj1.(int32)
|
||||||
|
int32obj2 := obj2.(int32)
|
||||||
|
if int32obj1 > int32obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if int32obj1 == int32obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if int32obj1 < int32obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Int64:
|
||||||
|
{
|
||||||
|
int64obj1 := obj1.(int64)
|
||||||
|
int64obj2 := obj2.(int64)
|
||||||
|
if int64obj1 > int64obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if int64obj1 == int64obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if int64obj1 < int64obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint:
|
||||||
|
{
|
||||||
|
uintobj1 := obj1.(uint)
|
||||||
|
uintobj2 := obj2.(uint)
|
||||||
|
if uintobj1 > uintobj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if uintobj1 == uintobj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if uintobj1 < uintobj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint8:
|
||||||
|
{
|
||||||
|
uint8obj1 := obj1.(uint8)
|
||||||
|
uint8obj2 := obj2.(uint8)
|
||||||
|
if uint8obj1 > uint8obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if uint8obj1 == uint8obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if uint8obj1 < uint8obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint16:
|
||||||
|
{
|
||||||
|
uint16obj1 := obj1.(uint16)
|
||||||
|
uint16obj2 := obj2.(uint16)
|
||||||
|
if uint16obj1 > uint16obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if uint16obj1 == uint16obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if uint16obj1 < uint16obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint32:
|
||||||
|
{
|
||||||
|
uint32obj1 := obj1.(uint32)
|
||||||
|
uint32obj2 := obj2.(uint32)
|
||||||
|
if uint32obj1 > uint32obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if uint32obj1 == uint32obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if uint32obj1 < uint32obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Uint64:
|
||||||
|
{
|
||||||
|
uint64obj1 := obj1.(uint64)
|
||||||
|
uint64obj2 := obj2.(uint64)
|
||||||
|
if uint64obj1 > uint64obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if uint64obj1 == uint64obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if uint64obj1 < uint64obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Float32:
|
||||||
|
{
|
||||||
|
float32obj1 := obj1.(float32)
|
||||||
|
float32obj2 := obj2.(float32)
|
||||||
|
if float32obj1 > float32obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if float32obj1 == float32obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if float32obj1 < float32obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Float64:
|
||||||
|
{
|
||||||
|
float64obj1 := obj1.(float64)
|
||||||
|
float64obj2 := obj2.(float64)
|
||||||
|
if float64obj1 > float64obj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if float64obj1 == float64obj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if float64obj1 < float64obj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
{
|
||||||
|
stringobj1 := obj1.(string)
|
||||||
|
stringobj2 := obj2.(string)
|
||||||
|
if stringobj1 > stringobj2 {
|
||||||
|
return -1, true
|
||||||
|
}
|
||||||
|
if stringobj1 == stringobj2 {
|
||||||
|
return 0, true
|
||||||
|
}
|
||||||
|
if stringobj1 < stringobj2 {
|
||||||
|
return 1, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Greater asserts that the first element is greater than the second
|
||||||
|
//
|
||||||
|
// assert.Greater(t, 2, 1)
|
||||||
|
// assert.Greater(t, float64(2), float64(1))
|
||||||
|
// assert.Greater(t, "b", "a")
|
||||||
|
func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
e1Kind := reflect.ValueOf(e1).Kind()
|
||||||
|
e2Kind := reflect.ValueOf(e2).Kind()
|
||||||
|
if e1Kind != e2Kind {
|
||||||
|
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, isComparable := compare(e1, e2, e1Kind)
|
||||||
|
if !isComparable {
|
||||||
|
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res != -1 {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
||||||
|
//
|
||||||
|
// assert.GreaterOrEqual(t, 2, 1)
|
||||||
|
// assert.GreaterOrEqual(t, 2, 2)
|
||||||
|
// assert.GreaterOrEqual(t, "b", "a")
|
||||||
|
// assert.GreaterOrEqual(t, "b", "b")
|
||||||
|
func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
e1Kind := reflect.ValueOf(e1).Kind()
|
||||||
|
e2Kind := reflect.ValueOf(e2).Kind()
|
||||||
|
if e1Kind != e2Kind {
|
||||||
|
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, isComparable := compare(e1, e2, e1Kind)
|
||||||
|
if !isComparable {
|
||||||
|
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res != -1 && res != 0 {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less asserts that the first element is less than the second
|
||||||
|
//
|
||||||
|
// assert.Less(t, 1, 2)
|
||||||
|
// assert.Less(t, float64(1), float64(2))
|
||||||
|
// assert.Less(t, "a", "b")
|
||||||
|
func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
e1Kind := reflect.ValueOf(e1).Kind()
|
||||||
|
e2Kind := reflect.ValueOf(e2).Kind()
|
||||||
|
if e1Kind != e2Kind {
|
||||||
|
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, isComparable := compare(e1, e2, e1Kind)
|
||||||
|
if !isComparable {
|
||||||
|
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res != 1 {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessOrEqual asserts that the first element is less than or equal to the second
|
||||||
|
//
|
||||||
|
// assert.LessOrEqual(t, 1, 2)
|
||||||
|
// assert.LessOrEqual(t, 2, 2)
|
||||||
|
// assert.LessOrEqual(t, "a", "b")
|
||||||
|
// assert.LessOrEqual(t, "b", "b")
|
||||||
|
func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
e1Kind := reflect.ValueOf(e1).Kind()
|
||||||
|
e2Kind := reflect.ValueOf(e2).Kind()
|
||||||
|
if e1Kind != e2Kind {
|
||||||
|
return Fail(t, "Elements should be the same type", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, isComparable := compare(e1, e2, e1Kind)
|
||||||
|
if !isComparable {
|
||||||
|
return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res != 1 && res != 0 {
|
||||||
|
return Fail(t, fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/pmezard/go-difflib/difflib"
|
"github.com/pmezard/go-difflib/difflib"
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
|
//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
|
||||||
|
@ -350,6 +351,37 @@ func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same asserts that two pointers reference the same object.
|
||||||
|
//
|
||||||
|
// assert.Same(t, ptr1, ptr2)
|
||||||
|
//
|
||||||
|
// Both arguments must be pointer variables. Pointer variable sameness is
|
||||||
|
// determined based on the equality of both type and value.
|
||||||
|
func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedPtr, actualPtr := reflect.ValueOf(expected), reflect.ValueOf(actual)
|
||||||
|
if expectedPtr.Kind() != reflect.Ptr || actualPtr.Kind() != reflect.Ptr {
|
||||||
|
return Fail(t, "Invalid operation: both arguments must be pointers", msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedType, actualType := reflect.TypeOf(expected), reflect.TypeOf(actual)
|
||||||
|
if expectedType != actualType {
|
||||||
|
return Fail(t, fmt.Sprintf("Pointer expected to be of type %v, but was %v",
|
||||||
|
expectedType, actualType), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
return Fail(t, fmt.Sprintf("Not same: \n"+
|
||||||
|
"expected: %p %#v\n"+
|
||||||
|
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// formatUnequalValues takes two values of arbitrary types and returns string
|
// formatUnequalValues takes two values of arbitrary types and returns string
|
||||||
// representations appropriate to be presented to the user.
|
// representations appropriate to be presented to the user.
|
||||||
//
|
//
|
||||||
|
@ -629,7 +661,7 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{
|
||||||
func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
||||||
|
|
||||||
listValue := reflect.ValueOf(list)
|
listValue := reflect.ValueOf(list)
|
||||||
elementValue := reflect.ValueOf(element)
|
listKind := reflect.TypeOf(list).Kind()
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
ok = false
|
ok = false
|
||||||
|
@ -637,11 +669,12 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if reflect.TypeOf(list).Kind() == reflect.String {
|
if listKind == reflect.String {
|
||||||
|
elementValue := reflect.ValueOf(element)
|
||||||
return true, strings.Contains(listValue.String(), elementValue.String())
|
return true, strings.Contains(listValue.String(), elementValue.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.TypeOf(list).Kind() == reflect.Map {
|
if listKind == reflect.Map {
|
||||||
mapKeys := listValue.MapKeys()
|
mapKeys := listValue.MapKeys()
|
||||||
for i := 0; i < len(mapKeys); i++ {
|
for i := 0; i < len(mapKeys); i++ {
|
||||||
if ObjectsAreEqual(mapKeys[i].Interface(), element) {
|
if ObjectsAreEqual(mapKeys[i].Interface(), element) {
|
||||||
|
@ -1337,6 +1370,24 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{
|
||||||
return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
|
return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YAMLEq asserts that two YAML strings are equivalent.
|
||||||
|
func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
var expectedYAMLAsInterface, actualYAMLAsInterface interface{}
|
||||||
|
|
||||||
|
if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil {
|
||||||
|
return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil {
|
||||||
|
return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
|
func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
|
||||||
t := reflect.TypeOf(v)
|
t := reflect.TypeOf(v)
|
||||||
k := t.Kind()
|
k := t.Kind()
|
||||||
|
@ -1371,8 +1422,8 @@ func diff(expected interface{}, actual interface{}) string {
|
||||||
e = spewConfig.Sdump(expected)
|
e = spewConfig.Sdump(expected)
|
||||||
a = spewConfig.Sdump(actual)
|
a = spewConfig.Sdump(actual)
|
||||||
} else {
|
} else {
|
||||||
e = expected.(string)
|
e = reflect.ValueOf(expected).String()
|
||||||
a = actual.(string)
|
a = reflect.ValueOf(actual).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
||||||
|
@ -1414,3 +1465,34 @@ var spewConfig = spew.ConfigState{
|
||||||
type tHelper interface {
|
type tHelper interface {
|
||||||
Helper()
|
Helper()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Eventually asserts that given condition will be met in waitFor time,
|
||||||
|
// periodically checking target function each tick.
|
||||||
|
//
|
||||||
|
// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond)
|
||||||
|
func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool {
|
||||||
|
if h, ok := t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
|
||||||
|
timer := time.NewTimer(waitFor)
|
||||||
|
ticker := time.NewTicker(tick)
|
||||||
|
checkPassed := make(chan bool)
|
||||||
|
defer timer.Stop()
|
||||||
|
defer ticker.Stop()
|
||||||
|
defer close(checkPassed)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
return Fail(t, "Condition never satisfied", msgAndArgs...)
|
||||||
|
case result := <-checkPassed:
|
||||||
|
if result {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case <-ticker.C:
|
||||||
|
go func() {
|
||||||
|
checkPassed <- condition()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
{{.Comment}}
|
{{.Comment}}
|
||||||
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
|
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
|
||||||
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
|
|
||||||
if h, ok := t.(tHelper); ok { h.Helper() }
|
if h, ok := t.(tHelper); ok { h.Helper() }
|
||||||
|
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,6 +216,28 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) {
|
||||||
Errorf(a.t, err, msg, args...)
|
Errorf(a.t, err, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Eventually asserts that given condition will be met in waitFor time,
|
||||||
|
// periodically checking target function each tick.
|
||||||
|
//
|
||||||
|
// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond)
|
||||||
|
func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Eventually(a.t, condition, waitFor, tick, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eventuallyf asserts that given condition will be met in waitFor time,
|
||||||
|
// periodically checking target function each tick.
|
||||||
|
//
|
||||||
|
// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted")
|
||||||
|
func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Eventuallyf(a.t, condition, waitFor, tick, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Exactly asserts that two objects are equal in value and type.
|
// Exactly asserts that two objects are equal in value and type.
|
||||||
//
|
//
|
||||||
// a.Exactly(int32(123), int64(123))
|
// a.Exactly(int32(123), int64(123))
|
||||||
|
@ -304,6 +326,56 @@ func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) {
|
||||||
FileExistsf(a.t, path, msg, args...)
|
FileExistsf(a.t, path, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Greater asserts that the first element is greater than the second
|
||||||
|
//
|
||||||
|
// a.Greater(2, 1)
|
||||||
|
// a.Greater(float64(2), float64(1))
|
||||||
|
// a.Greater("b", "a")
|
||||||
|
func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Greater(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterOrEqual asserts that the first element is greater than or equal to the second
|
||||||
|
//
|
||||||
|
// a.GreaterOrEqual(2, 1)
|
||||||
|
// a.GreaterOrEqual(2, 2)
|
||||||
|
// a.GreaterOrEqual("b", "a")
|
||||||
|
// a.GreaterOrEqual("b", "b")
|
||||||
|
func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
GreaterOrEqual(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterOrEqualf asserts that the first element is greater than or equal to the second
|
||||||
|
//
|
||||||
|
// a.GreaterOrEqualf(2, 1, "error message %s", "formatted")
|
||||||
|
// a.GreaterOrEqualf(2, 2, "error message %s", "formatted")
|
||||||
|
// a.GreaterOrEqualf("b", "a", "error message %s", "formatted")
|
||||||
|
// a.GreaterOrEqualf("b", "b", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
GreaterOrEqualf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Greaterf asserts that the first element is greater than the second
|
||||||
|
//
|
||||||
|
// a.Greaterf(2, 1, "error message %s", "formatted")
|
||||||
|
// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1))
|
||||||
|
// a.Greaterf("b", "a", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Greaterf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPBodyContains asserts that a specified handler returns a
|
// HTTPBodyContains asserts that a specified handler returns a
|
||||||
// body that contains a string.
|
// body that contains a string.
|
||||||
//
|
//
|
||||||
|
@ -568,6 +640,22 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ..
|
||||||
JSONEqf(a.t, expected, actual, msg, args...)
|
JSONEqf(a.t, expected, actual, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YAMLEq asserts that two YAML strings are equivalent.
|
||||||
|
func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
YAMLEq(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// YAMLEqf asserts that two YAML strings are equivalent.
|
||||||
|
func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
YAMLEqf(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Len asserts that the specified object has specific length.
|
// Len asserts that the specified object has specific length.
|
||||||
// Len also fails if the object has a type that len() not accept.
|
// Len also fails if the object has a type that len() not accept.
|
||||||
//
|
//
|
||||||
|
@ -590,6 +678,56 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in
|
||||||
Lenf(a.t, object, length, msg, args...)
|
Lenf(a.t, object, length, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Less asserts that the first element is less than the second
|
||||||
|
//
|
||||||
|
// a.Less(1, 2)
|
||||||
|
// a.Less(float64(1), float64(2))
|
||||||
|
// a.Less("a", "b")
|
||||||
|
func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Less(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessOrEqual asserts that the first element is less than or equal to the second
|
||||||
|
//
|
||||||
|
// a.LessOrEqual(1, 2)
|
||||||
|
// a.LessOrEqual(2, 2)
|
||||||
|
// a.LessOrEqual("a", "b")
|
||||||
|
// a.LessOrEqual("b", "b")
|
||||||
|
func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
LessOrEqual(a.t, e1, e2, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LessOrEqualf asserts that the first element is less than or equal to the second
|
||||||
|
//
|
||||||
|
// a.LessOrEqualf(1, 2, "error message %s", "formatted")
|
||||||
|
// a.LessOrEqualf(2, 2, "error message %s", "formatted")
|
||||||
|
// a.LessOrEqualf("a", "b", "error message %s", "formatted")
|
||||||
|
// a.LessOrEqualf("b", "b", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
LessOrEqualf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lessf asserts that the first element is less than the second
|
||||||
|
//
|
||||||
|
// a.Lessf(1, 2, "error message %s", "formatted")
|
||||||
|
// a.Lessf(float64(1, "error message %s", "formatted"), float64(2))
|
||||||
|
// a.Lessf("a", "b", "error message %s", "formatted")
|
||||||
|
func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Lessf(a.t, e1, e2, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Nil asserts that the specified object is nil.
|
// Nil asserts that the specified object is nil.
|
||||||
//
|
//
|
||||||
// a.Nil(err)
|
// a.Nil(err)
|
||||||
|
@ -878,6 +1016,32 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args .
|
||||||
Regexpf(a.t, rx, str, msg, args...)
|
Regexpf(a.t, rx, str, msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same asserts that two pointers reference the same object.
|
||||||
|
//
|
||||||
|
// a.Same(ptr1, ptr2)
|
||||||
|
//
|
||||||
|
// Both arguments must be pointer variables. Pointer variable sameness is
|
||||||
|
// determined based on the equality of both type and value.
|
||||||
|
func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Same(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Samef asserts that two pointers reference the same object.
|
||||||
|
//
|
||||||
|
// a.Samef(ptr1, ptr2, "error message %s", "formatted")
|
||||||
|
//
|
||||||
|
// Both arguments must be pointer variables. Pointer variable sameness is
|
||||||
|
// determined based on the equality of both type and value.
|
||||||
|
func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) {
|
||||||
|
if h, ok := a.t.(tHelper); ok {
|
||||||
|
h.Helper()
|
||||||
|
}
|
||||||
|
Samef(a.t, expected, actual, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Subset asserts that the specified list(array, slice...) contains all
|
// Subset asserts that the specified list(array, slice...) contains all
|
||||||
// elements given in the specified subset(array, slice...).
|
// elements given in the specified subset(array, slice...).
|
||||||
//
|
//
|
||||||
|
|
|
@ -77,6 +77,7 @@ func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
|
||||||
if tmp, err = d.writeTempFile(name, data); err != nil {
|
if tmp, err = d.writeTempFile(name, data); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer os.Remove(tmp)
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
// Don't overwrite the file if the context was canceled.
|
// Don't overwrite the file if the context was canceled.
|
||||||
|
@ -116,12 +117,17 @@ func (d DirCache) Delete(ctx context.Context, name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeTempFile writes b to a temporary file, closes the file and returns its path.
|
// writeTempFile writes b to a temporary file, closes the file and returns its path.
|
||||||
func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
|
func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) {
|
||||||
// TempFile uses 0600 permissions
|
// TempFile uses 0600 permissions
|
||||||
f, err := ioutil.TempFile(string(d), prefix)
|
f, err := ioutil.TempFile(string(d), prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if reterr != nil {
|
||||||
|
os.Remove(f.Name())
|
||||||
|
}
|
||||||
|
}()
|
||||||
if _, err := f.Write(b); err != nil {
|
if _, err := f.Write(b); err != nil {
|
||||||
f.Close()
|
f.Close()
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -63,16 +63,12 @@ type tokenJSON struct {
|
||||||
TokenType string `json:"token_type"`
|
TokenType string `json:"token_type"`
|
||||||
RefreshToken string `json:"refresh_token"`
|
RefreshToken string `json:"refresh_token"`
|
||||||
ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
|
ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
|
||||||
Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *tokenJSON) expiry() (t time.Time) {
|
func (e *tokenJSON) expiry() (t time.Time) {
|
||||||
if v := e.ExpiresIn; v != 0 {
|
if v := e.ExpiresIn; v != 0 {
|
||||||
return time.Now().Add(time.Duration(v) * time.Second)
|
return time.Now().Add(time.Duration(v) * time.Second)
|
||||||
}
|
}
|
||||||
if v := e.Expires; v != 0 {
|
|
||||||
return time.Now().Add(time.Duration(v) * time.Second)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,12 +260,6 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
|
||||||
Raw: vals,
|
Raw: vals,
|
||||||
}
|
}
|
||||||
e := vals.Get("expires_in")
|
e := vals.Get("expires_in")
|
||||||
if e == "" || e == "null" {
|
|
||||||
// TODO(jbd): Facebook's OAuth2 implementation is broken and
|
|
||||||
// returns expires_in field in expires. Remove the fallback to expires,
|
|
||||||
// when Facebook fixes their implementation.
|
|
||||||
e = vals.Get("expires")
|
|
||||||
}
|
|
||||||
expires, _ := strconv.Atoi(e)
|
expires, _ := strconv.Atoi(e)
|
||||||
if expires != 0 {
|
if expires != 0 {
|
||||||
token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
|
token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
|
||||||
|
|
|
@ -117,7 +117,7 @@ var (
|
||||||
// ApprovalForce forces the users to view the consent dialog
|
// ApprovalForce forces the users to view the consent dialog
|
||||||
// and confirm the permissions request at the URL returned
|
// and confirm the permissions request at the URL returned
|
||||||
// from AuthCodeURL, even if they've already done so.
|
// from AuthCodeURL, even if they've already done so.
|
||||||
ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force")
|
ApprovalForce AuthCodeOption = SetAuthURLParam("prompt", "consent")
|
||||||
)
|
)
|
||||||
|
|
||||||
// An AuthCodeOption is passed to Config.AuthCodeURL.
|
// An AuthCodeOption is passed to Config.AuthCodeURL.
|
||||||
|
|
|
@ -89,7 +89,6 @@ func direntNamlen(buf []byte) (uint64, bool) {
|
||||||
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
|
||||||
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
|
||||||
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error)
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: sec, Nsec: nsec}
|
return Timespec{Sec: sec, Nsec: nsec}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,10 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||||
|
return ENOTSUP
|
||||||
|
}
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,10 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) error {
|
||||||
|
return ENOTSUP
|
||||||
|
}
|
||||||
|
|
||||||
func setTimespec(sec, nsec int64) Timespec {
|
func setTimespec(sec, nsec int64) Timespec {
|
||||||
return Timespec{Sec: sec, Nsec: nsec}
|
return Timespec{Sec: sec, Nsec: nsec}
|
||||||
}
|
}
|
||||||
|
|
|
@ -722,6 +722,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -987,6 +988,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -722,6 +722,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -987,6 +988,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -724,6 +724,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -989,6 +990,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -721,6 +721,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x0
|
F_RDLCK = 0x0
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -986,6 +987,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -725,6 +725,7 @@ const (
|
||||||
F_OFD_SETLKW = 0x26
|
F_OFD_SETLKW = 0x26
|
||||||
F_OK = 0x0
|
F_OK = 0x0
|
||||||
F_RDLCK = 0x1
|
F_RDLCK = 0x1
|
||||||
|
F_SEAL_FUTURE_WRITE = 0x10
|
||||||
F_SEAL_GROW = 0x4
|
F_SEAL_GROW = 0x4
|
||||||
F_SEAL_SEAL = 0x1
|
F_SEAL_SEAL = 0x1
|
||||||
F_SEAL_SHRINK = 0x2
|
F_SEAL_SHRINK = 0x2
|
||||||
|
@ -990,6 +991,7 @@ const (
|
||||||
IPV6_RECVRTHDR = 0x38
|
IPV6_RECVRTHDR = 0x38
|
||||||
IPV6_RECVTCLASS = 0x42
|
IPV6_RECVTCLASS = 0x42
|
||||||
IPV6_ROUTER_ALERT = 0x16
|
IPV6_ROUTER_ALERT = 0x16
|
||||||
|
IPV6_ROUTER_ALERT_ISOLATE = 0x1e
|
||||||
IPV6_RTHDR = 0x39
|
IPV6_RTHDR = 0x39
|
||||||
IPV6_RTHDRDSTOPTS = 0x37
|
IPV6_RTHDRDSTOPTS = 0x37
|
||||||
IPV6_RTHDR_LOOSE = 0x0
|
IPV6_RTHDR_LOOSE = 0x0
|
||||||
|
|
|
@ -377,16 +377,6 @@ func Munlockall() (err error) {
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
|
||||||
_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
|
||||||
|
|
||||||
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
||||||
_, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
_, _, e1 := Syscall6(SYS_GETATTRLIST, uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
@ -1691,6 +1681,16 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
||||||
|
_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
|
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
|
||||||
r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
|
r0, r1, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tp)), 0, 0)
|
||||||
sec = int32(r0)
|
sec = int32(r0)
|
||||||
|
|
|
@ -527,21 +527,6 @@ func libc_munlockall_trampoline()
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func libc_ptrace_trampoline()
|
|
||||||
|
|
||||||
//go:linkname libc_ptrace libc_ptrace
|
|
||||||
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
|
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
|
||||||
|
|
||||||
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
@ -2341,6 +2326,21 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
||||||
|
_, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func libc_ptrace_trampoline()
|
||||||
|
|
||||||
|
//go:linkname libc_ptrace libc_ptrace
|
||||||
|
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
|
func gettimeofday(tp *Timeval) (sec int32, usec int32, err error) {
|
||||||
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
|
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
|
||||||
sec = int32(r0)
|
sec = int32(r0)
|
||||||
|
|
|
@ -64,8 +64,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlock(SB)
|
JMP libc_munlock(SB)
|
||||||
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlockall(SB)
|
JMP libc_munlockall(SB)
|
||||||
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
|
||||||
JMP libc_ptrace(SB)
|
|
||||||
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_getattrlist(SB)
|
JMP libc_getattrlist(SB)
|
||||||
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
@ -264,6 +262,8 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_mmap(SB)
|
JMP libc_mmap(SB)
|
||||||
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munmap(SB)
|
JMP libc_munmap(SB)
|
||||||
|
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ptrace(SB)
|
||||||
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_gettimeofday(SB)
|
JMP libc_gettimeofday(SB)
|
||||||
TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
|
|
@ -527,21 +527,6 @@ func libc_munlockall_trampoline()
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func libc_ptrace_trampoline()
|
|
||||||
|
|
||||||
//go:linkname libc_ptrace libc_ptrace
|
|
||||||
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
|
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
|
||||||
|
|
||||||
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
@ -2356,6 +2341,21 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
||||||
|
_, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func libc_ptrace_trampoline()
|
||||||
|
|
||||||
|
//go:linkname libc_ptrace libc_ptrace
|
||||||
|
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) {
|
func gettimeofday(tp *Timeval) (sec int64, usec int32, err error) {
|
||||||
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
|
r0, r1, e1 := syscall_rawSyscall(funcPC(libc_gettimeofday_trampoline), uintptr(unsafe.Pointer(tp)), 0, 0)
|
||||||
sec = int64(r0)
|
sec = int64(r0)
|
||||||
|
|
|
@ -64,8 +64,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlock(SB)
|
JMP libc_munlock(SB)
|
||||||
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlockall(SB)
|
JMP libc_munlockall(SB)
|
||||||
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
|
||||||
JMP libc_ptrace(SB)
|
|
||||||
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_getattrlist(SB)
|
JMP libc_getattrlist(SB)
|
||||||
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
@ -266,6 +264,8 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_mmap(SB)
|
JMP libc_mmap(SB)
|
||||||
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munmap(SB)
|
JMP libc_munmap(SB)
|
||||||
|
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
JMP libc_ptrace(SB)
|
||||||
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_gettimeofday(SB)
|
JMP libc_gettimeofday(SB)
|
||||||
TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
|
|
@ -527,21 +527,6 @@ func libc_munlockall_trampoline()
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func libc_ptrace_trampoline()
|
|
||||||
|
|
||||||
//go:linkname libc_ptrace libc_ptrace
|
|
||||||
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
|
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
|
||||||
|
|
||||||
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
|
|
@ -64,8 +64,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlock(SB)
|
JMP libc_munlock(SB)
|
||||||
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlockall(SB)
|
JMP libc_munlockall(SB)
|
||||||
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
|
||||||
JMP libc_ptrace(SB)
|
|
||||||
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_getattrlist(SB)
|
JMP libc_getattrlist(SB)
|
||||||
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
|
|
@ -527,21 +527,6 @@ func libc_munlockall_trampoline()
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
|
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func libc_ptrace_trampoline()
|
|
||||||
|
|
||||||
//go:linkname libc_ptrace libc_ptrace
|
|
||||||
//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib"
|
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
|
||||||
|
|
||||||
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) {
|
||||||
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
_, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
|
|
@ -64,8 +64,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlock(SB)
|
JMP libc_munlock(SB)
|
||||||
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_munlockall(SB)
|
JMP libc_munlockall(SB)
|
||||||
TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
|
|
||||||
JMP libc_ptrace(SB)
|
|
||||||
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
|
||||||
JMP libc_getattrlist(SB)
|
JMP libc_getattrlist(SB)
|
||||||
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0
|
||||||
|
|
|
@ -808,6 +808,7 @@ type Ustat_t struct {
|
||||||
|
|
||||||
type EpollEvent struct {
|
type EpollEvent struct {
|
||||||
Events uint32
|
Events uint32
|
||||||
|
_ int32
|
||||||
Fd int32
|
Fd int32
|
||||||
Pad int32
|
Pad int32
|
||||||
}
|
}
|
||||||
|
|
|
@ -644,6 +644,8 @@ func (tml *Tokenmandatorylabel) Size() uint32 {
|
||||||
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
|
//sys DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) = advapi32.DuplicateTokenEx
|
||||||
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
|
||||||
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
|
||||||
|
//sys getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetWindowsDirectoryW
|
||||||
|
//sys getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemWindowsDirectoryW
|
||||||
|
|
||||||
// An access token contains the security information for a logon session.
|
// An access token contains the security information for a logon session.
|
||||||
// The system creates an access token when a user logs on, and every
|
// The system creates an access token when a user logs on, and every
|
||||||
|
@ -785,8 +787,8 @@ func (token Token) GetLinkedToken() (Token, error) {
|
||||||
return linkedToken, nil
|
return linkedToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSystemDirectory retrieves path to current location of the system
|
// GetSystemDirectory retrieves the path to current location of the system
|
||||||
// directory, which is typically, though not always, C:\Windows\System32.
|
// directory, which is typically, though not always, `C:\Windows\System32`.
|
||||||
func GetSystemDirectory() (string, error) {
|
func GetSystemDirectory() (string, error) {
|
||||||
n := uint32(MAX_PATH)
|
n := uint32(MAX_PATH)
|
||||||
for {
|
for {
|
||||||
|
@ -802,6 +804,42 @@ func GetSystemDirectory() (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetWindowsDirectory retrieves the path to current location of the Windows
|
||||||
|
// directory, which is typically, though not always, `C:\Windows`. This may
|
||||||
|
// be a private user directory in the case that the application is running
|
||||||
|
// under a terminal server.
|
||||||
|
func GetWindowsDirectory() (string, error) {
|
||||||
|
n := uint32(MAX_PATH)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
l, e := getWindowsDirectory(&b[0], n)
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
if l <= n {
|
||||||
|
return UTF16ToString(b[:l]), nil
|
||||||
|
}
|
||||||
|
n = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSystemWindowsDirectory retrieves the path to current location of the
|
||||||
|
// Windows directory, which is typically, though not always, `C:\Windows`.
|
||||||
|
func GetSystemWindowsDirectory() (string, error) {
|
||||||
|
n := uint32(MAX_PATH)
|
||||||
|
for {
|
||||||
|
b := make([]uint16, n)
|
||||||
|
l, e := getSystemWindowsDirectory(&b[0], n)
|
||||||
|
if e != nil {
|
||||||
|
return "", e
|
||||||
|
}
|
||||||
|
if l <= n {
|
||||||
|
return UTF16ToString(b[:l]), nil
|
||||||
|
}
|
||||||
|
n = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IsMember reports whether the access token t is a member of the provided SID.
|
// IsMember reports whether the access token t is a member of the provided SID.
|
||||||
func (t Token) IsMember(sid *SID) (bool, error) {
|
func (t Token) IsMember(sid *SID) (bool, error) {
|
||||||
var b int32
|
var b int32
|
||||||
|
|
|
@ -159,6 +159,10 @@ type SERVICE_DESCRIPTION struct {
|
||||||
Description *uint16
|
Description *uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SERVICE_DELAYED_AUTO_START_INFO struct {
|
||||||
|
IsDelayedAutoStartUp uint32
|
||||||
|
}
|
||||||
|
|
||||||
type SERVICE_STATUS_PROCESS struct {
|
type SERVICE_STATUS_PROCESS struct {
|
||||||
ServiceType uint32
|
ServiceType uint32
|
||||||
CurrentState uint32
|
CurrentState uint32
|
||||||
|
|
|
@ -269,6 +269,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||||
//sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error)
|
//sys GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error)
|
||||||
//sys GetProcessId(process Handle) (id uint32, err error)
|
//sys GetProcessId(process Handle) (id uint32, err error)
|
||||||
//sys OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error)
|
//sys OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error)
|
||||||
|
//sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost
|
||||||
|
|
||||||
// Volume Management Functions
|
// Volume Management Functions
|
||||||
//sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW
|
//sys DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) = DefineDosDeviceW
|
||||||
|
@ -296,6 +297,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||||
//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid
|
//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid
|
||||||
//sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree
|
//sys CoTaskMemFree(address unsafe.Pointer) = ole32.CoTaskMemFree
|
||||||
//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion
|
//sys rtlGetVersion(info *OsVersionInfoEx) (ret error) = ntdll.RtlGetVersion
|
||||||
|
//sys rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) = ntdll.RtlGetNtVersionNumbers
|
||||||
|
|
||||||
// syscall interface implementation for other packages
|
// syscall interface implementation for other packages
|
||||||
|
|
||||||
|
@ -1306,8 +1308,8 @@ func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, e
|
||||||
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil
|
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RtlGetVersion returns the true version of the underlying operating system, ignoring
|
// RtlGetVersion returns the version of the underlying operating system, ignoring
|
||||||
// any manifesting or compatibility layers on top of the win32 layer.
|
// manifest semantics but is affected by the application compatibility layer.
|
||||||
func RtlGetVersion() *OsVersionInfoEx {
|
func RtlGetVersion() *OsVersionInfoEx {
|
||||||
info := &OsVersionInfoEx{}
|
info := &OsVersionInfoEx{}
|
||||||
info.osVersionInfoSize = uint32(unsafe.Sizeof(*info))
|
info.osVersionInfoSize = uint32(unsafe.Sizeof(*info))
|
||||||
|
@ -1318,3 +1320,11 @@ func RtlGetVersion() *OsVersionInfoEx {
|
||||||
_ = rtlGetVersion(info)
|
_ = rtlGetVersion(info)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RtlGetNtVersionNumbers returns the version of the underlying operating system,
|
||||||
|
// ignoring manifest semantics and the application compatibility layer.
|
||||||
|
func RtlGetNtVersionNumbers() (majorVersion, minorVersion, buildNumber uint32) {
|
||||||
|
rtlGetNtVersionNumbers(&majorVersion, &minorVersion, &buildNumber)
|
||||||
|
buildNumber &= 0xffff
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -209,6 +209,7 @@ var (
|
||||||
procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent")
|
procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent")
|
||||||
procGetProcessId = modkernel32.NewProc("GetProcessId")
|
procGetProcessId = modkernel32.NewProc("GetProcessId")
|
||||||
procOpenThread = modkernel32.NewProc("OpenThread")
|
procOpenThread = modkernel32.NewProc("OpenThread")
|
||||||
|
procSetProcessPriorityBoost = modkernel32.NewProc("SetProcessPriorityBoost")
|
||||||
procDefineDosDeviceW = modkernel32.NewProc("DefineDosDeviceW")
|
procDefineDosDeviceW = modkernel32.NewProc("DefineDosDeviceW")
|
||||||
procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW")
|
procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW")
|
||||||
procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW")
|
procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW")
|
||||||
|
@ -234,6 +235,7 @@ var (
|
||||||
procCoCreateGuid = modole32.NewProc("CoCreateGuid")
|
procCoCreateGuid = modole32.NewProc("CoCreateGuid")
|
||||||
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
|
||||||
procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
|
procRtlGetVersion = modntdll.NewProc("RtlGetVersion")
|
||||||
|
procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers")
|
||||||
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
procWSAStartup = modws2_32.NewProc("WSAStartup")
|
||||||
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
procWSACleanup = modws2_32.NewProc("WSACleanup")
|
||||||
procWSAIoctl = modws2_32.NewProc("WSAIoctl")
|
procWSAIoctl = modws2_32.NewProc("WSAIoctl")
|
||||||
|
@ -303,6 +305,8 @@ var (
|
||||||
procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx")
|
procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx")
|
||||||
procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW")
|
procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW")
|
||||||
procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW")
|
procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW")
|
||||||
|
procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW")
|
||||||
|
procGetSystemWindowsDirectoryW = modkernel32.NewProc("GetSystemWindowsDirectoryW")
|
||||||
procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken")
|
procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken")
|
||||||
procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW")
|
procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW")
|
||||||
procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory")
|
procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory")
|
||||||
|
@ -2255,6 +2259,24 @@ func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (hand
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetProcessPriorityBoost(process Handle, disable bool) (err error) {
|
||||||
|
var _p0 uint32
|
||||||
|
if disable {
|
||||||
|
_p0 = 1
|
||||||
|
} else {
|
||||||
|
_p0 = 0
|
||||||
|
}
|
||||||
|
r1, _, e1 := syscall.Syscall(procSetProcessPriorityBoost.Addr(), 2, uintptr(process), uintptr(_p0), 0)
|
||||||
|
if r1 == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) {
|
func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) {
|
||||||
r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)))
|
r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)))
|
||||||
if r1 == 0 {
|
if r1 == 0 {
|
||||||
|
@ -2530,6 +2552,11 @@ func rtlGetVersion(info *OsVersionInfoEx) (ret error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) {
|
||||||
|
syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
|
func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
|
||||||
r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
|
r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
|
||||||
if r0 != 0 {
|
if r0 != 0 {
|
||||||
|
@ -3307,6 +3334,32 @@ func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0)
|
||||||
|
len = uint32(r0)
|
||||||
|
if len == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) {
|
||||||
|
r0, _, e1 := syscall.Syscall(procGetSystemWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0)
|
||||||
|
len = uint32(r0)
|
||||||
|
if len == 0 {
|
||||||
|
if e1 != 0 {
|
||||||
|
err = errnoErr(e1)
|
||||||
|
} else {
|
||||||
|
err = syscall.EINVAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func WTSQueryUserToken(session uint32, token *Token) (err error) {
|
func WTSQueryUserToken(session uint32, token *Token) (err error) {
|
||||||
r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0)
|
r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0)
|
||||||
if r1 == 0 {
|
if r1 == 0 {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# cloud.google.com/go v0.37.4
|
# cloud.google.com/go v0.44.3
|
||||||
cloud.google.com/go/civil
|
cloud.google.com/go/civil
|
||||||
# gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b
|
# gitea.com/macaron/binding v0.0.0-20190822013154-a5f53841ed2b
|
||||||
gitea.com/macaron/binding
|
gitea.com/macaron/binding
|
||||||
|
@ -38,7 +38,7 @@ github.com/RoaringBitmap/roaring
|
||||||
github.com/andybalholm/cascadia
|
github.com/andybalholm/cascadia
|
||||||
# github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239
|
# github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239
|
||||||
github.com/anmitsu/go-shlex
|
github.com/anmitsu/go-shlex
|
||||||
# github.com/beorn7/perks v1.0.0
|
# github.com/beorn7/perks v1.0.1
|
||||||
github.com/beorn7/perks/quantile
|
github.com/beorn7/perks/quantile
|
||||||
# github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3
|
# github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3
|
||||||
github.com/blevesearch/bleve
|
github.com/blevesearch/bleve
|
||||||
|
@ -154,9 +154,9 @@ github.com/go-xorm/xorm
|
||||||
github.com/gogits/chardet
|
github.com/gogits/chardet
|
||||||
# github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
|
# github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
|
||||||
github.com/gogs/cron
|
github.com/gogs/cron
|
||||||
# github.com/golang/protobuf v1.3.1
|
# github.com/golang/protobuf v1.3.2
|
||||||
github.com/golang/protobuf/proto
|
github.com/golang/protobuf/proto
|
||||||
# github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db
|
# github.com/golang/snappy v0.0.1
|
||||||
github.com/golang/snappy
|
github.com/golang/snappy
|
||||||
# github.com/google/go-github/v24 v24.0.1
|
# github.com/google/go-github/v24 v24.0.1
|
||||||
github.com/google/go-github/v24/github
|
github.com/google/go-github/v24/github
|
||||||
|
@ -264,19 +264,20 @@ github.com/pmezard/go-difflib/difflib
|
||||||
github.com/pquerna/otp/totp
|
github.com/pquerna/otp/totp
|
||||||
github.com/pquerna/otp
|
github.com/pquerna/otp
|
||||||
github.com/pquerna/otp/hotp
|
github.com/pquerna/otp/hotp
|
||||||
# github.com/prometheus/client_golang v0.9.3
|
# github.com/prometheus/client_golang v1.1.0
|
||||||
github.com/prometheus/client_golang/prometheus
|
github.com/prometheus/client_golang/prometheus
|
||||||
github.com/prometheus/client_golang/prometheus/promhttp
|
github.com/prometheus/client_golang/prometheus/promhttp
|
||||||
github.com/prometheus/client_golang/prometheus/internal
|
github.com/prometheus/client_golang/prometheus/internal
|
||||||
# github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90
|
# github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4
|
||||||
github.com/prometheus/client_model/go
|
github.com/prometheus/client_model/go
|
||||||
# github.com/prometheus/common v0.4.0
|
# github.com/prometheus/common v0.6.0
|
||||||
github.com/prometheus/common/expfmt
|
github.com/prometheus/common/expfmt
|
||||||
github.com/prometheus/common/model
|
github.com/prometheus/common/model
|
||||||
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
||||||
# github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084
|
# github.com/prometheus/procfs v0.0.4
|
||||||
github.com/prometheus/procfs
|
github.com/prometheus/procfs
|
||||||
github.com/prometheus/procfs/internal/fs
|
github.com/prometheus/procfs/internal/fs
|
||||||
|
github.com/prometheus/procfs/internal/util
|
||||||
# github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff
|
# github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff
|
||||||
github.com/russross/blackfriday
|
github.com/russross/blackfriday
|
||||||
# github.com/satori/go.uuid v1.2.0
|
# github.com/satori/go.uuid v1.2.0
|
||||||
|
@ -298,7 +299,7 @@ github.com/src-d/gcfg/token
|
||||||
github.com/src-d/gcfg/types
|
github.com/src-d/gcfg/types
|
||||||
# github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2
|
# github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2
|
||||||
github.com/steveyen/gtreap
|
github.com/steveyen/gtreap
|
||||||
# github.com/stretchr/testify v1.3.0
|
# github.com/stretchr/testify v1.4.0
|
||||||
github.com/stretchr/testify/assert
|
github.com/stretchr/testify/assert
|
||||||
github.com/stretchr/testify/require
|
github.com/stretchr/testify/require
|
||||||
# github.com/syndtr/goleveldb v1.0.0
|
# github.com/syndtr/goleveldb v1.0.0
|
||||||
|
@ -335,7 +336,7 @@ github.com/willf/bitset
|
||||||
github.com/xanzy/ssh-agent
|
github.com/xanzy/ssh-agent
|
||||||
# github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
|
# github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
|
||||||
github.com/yohcop/openid-go
|
github.com/yohcop/openid-go
|
||||||
# golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
# golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
|
||||||
golang.org/x/crypto/acme/autocert
|
golang.org/x/crypto/acme/autocert
|
||||||
golang.org/x/crypto/argon2
|
golang.org/x/crypto/argon2
|
||||||
golang.org/x/crypto/bcrypt
|
golang.org/x/crypto/bcrypt
|
||||||
|
@ -361,7 +362,7 @@ golang.org/x/crypto/cast5
|
||||||
golang.org/x/crypto/openpgp/elgamal
|
golang.org/x/crypto/openpgp/elgamal
|
||||||
golang.org/x/crypto/ssh/knownhosts
|
golang.org/x/crypto/ssh/knownhosts
|
||||||
golang.org/x/crypto/ssh/agent
|
golang.org/x/crypto/ssh/agent
|
||||||
# golang.org/x/net v0.0.0-20190724013045-ca1201d0de80
|
# golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||||
golang.org/x/net/html/charset
|
golang.org/x/net/html/charset
|
||||||
golang.org/x/net/html
|
golang.org/x/net/html
|
||||||
golang.org/x/net/html/atom
|
golang.org/x/net/html/atom
|
||||||
|
@ -370,10 +371,10 @@ golang.org/x/net/context/ctxhttp
|
||||||
golang.org/x/net/proxy
|
golang.org/x/net/proxy
|
||||||
golang.org/x/net/context
|
golang.org/x/net/context
|
||||||
golang.org/x/net/internal/socks
|
golang.org/x/net/internal/socks
|
||||||
# golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
|
# golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||||
golang.org/x/oauth2
|
golang.org/x/oauth2
|
||||||
golang.org/x/oauth2/internal
|
golang.org/x/oauth2/internal
|
||||||
# golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3
|
# golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456
|
||||||
golang.org/x/sys/windows
|
golang.org/x/sys/windows
|
||||||
golang.org/x/sys/windows/svc
|
golang.org/x/sys/windows/svc
|
||||||
golang.org/x/sys/cpu
|
golang.org/x/sys/cpu
|
||||||
|
|
Loading…
Reference in New Issue