A few fixes
* CLI properly formats the IP addresses in runner show * LXD provider now waits for an IP address before returning on Create * Added a few mocks for testing Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
afb1d31394
commit
5566cde77f
46 changed files with 8829 additions and 6 deletions
|
|
@ -218,7 +218,7 @@ func formatSingleInstance(instance params.Instance) {
|
||||||
|
|
||||||
if len(instance.Addresses) > 0 {
|
if len(instance.Addresses) > 0 {
|
||||||
for _, addr := range instance.Addresses {
|
for _, addr := range instance.Addresses {
|
||||||
t.AppendRow(table.Row{"Addresses", addr}, table.RowConfig{AutoMerge: true})
|
t.AppendRow(table.Row{"Addresses", addr.Address}, table.RowConfig{AutoMerge: true})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
6
go.mod
6
go.mod
|
|
@ -11,6 +11,8 @@ require (
|
||||||
github.com/gorilla/handlers v1.5.1
|
github.com/gorilla/handlers v1.5.1
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/jedib0t/go-pretty/v6 v6.3.1
|
github.com/jedib0t/go-pretty/v6 v6.3.1
|
||||||
|
github.com/juju/clock v0.0.0-20220704231616-a2b96c8eeb27
|
||||||
|
github.com/juju/retry v0.0.0-20220204093819-62423bf33287
|
||||||
github.com/lxc/lxd v0.0.0-20220415052741-1170f2806124
|
github.com/lxc/lxd v0.0.0-20220415052741-1170f2806124
|
||||||
github.com/manifoldco/promptui v0.9.0
|
github.com/manifoldco/promptui v0.9.0
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
|
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
|
||||||
|
|
@ -41,6 +43,7 @@ require (
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/juju/errors v0.0.0-20220328032053-6664a20db930 // indirect
|
||||||
github.com/juju/webbrowser v1.0.0 // indirect
|
github.com/juju/webbrowser v1.0.0 // indirect
|
||||||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
|
|
@ -56,11 +59,12 @@ require (
|
||||||
github.com/rogpeppe/fastuuid v1.2.0 // indirect
|
github.com/rogpeppe/fastuuid v1.2.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/stretchr/objx v0.4.0 // indirect
|
||||||
|
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de // indirect
|
golang.org/x/net v0.0.0-20220325170049-de3da57026de // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.28.0 // indirect
|
google.golang.org/protobuf v1.28.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/errgo.v1 v1.0.1 // indirect
|
gopkg.in/errgo.v1 v1.0.1 // indirect
|
||||||
gopkg.in/httprequest.v1 v1.2.1 // indirect
|
gopkg.in/httprequest.v1 v1.2.1 // indirect
|
||||||
gopkg.in/macaroon-bakery.v2 v2.3.0 // indirect
|
gopkg.in/macaroon-bakery.v2 v2.3.0 // indirect
|
||||||
|
|
|
||||||
20
go.sum
20
go.sum
|
|
@ -156,12 +156,26 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
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/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
|
github.com/juju/clock v0.0.0-20220704231616-a2b96c8eeb27 h1:tzBYJiWEx2HcWUSdfBzdj9+FTQGWzsuSiiYgutZl2kA=
|
||||||
|
github.com/juju/clock v0.0.0-20220704231616-a2b96c8eeb27/go.mod h1:GZ/FY8Cqw3KHG6DwRVPUKbSPTAwyrU28xFi5cqZnLsc=
|
||||||
|
github.com/juju/collections v0.0.0-20220203020748-febd7cad8a7a h1:d7eZO8OS/ZXxdP0uq3E8CdoA1qNFaecAv90UxrxaY2k=
|
||||||
|
github.com/juju/errors v0.0.0-20220328032053-6664a20db930 h1:NavIEjCH2y/svEZ8mOSnFofpFeiAQTzUpByc28R6Hhc=
|
||||||
|
github.com/juju/errors v0.0.0-20220328032053-6664a20db930/go.mod h1:jMGj9DWF/qbo91ODcfJq6z/RYc3FX3taCBZMCcpI4Ls=
|
||||||
|
github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY=
|
||||||
|
github.com/juju/mgo/v2 v2.0.0-20220111072304-f200228f1090 h1:zX5GoH3Jp8k1EjUFkApu/YZAYEn0PYQfg/U6IDyNyYs=
|
||||||
github.com/juju/mgotest v1.0.1/go.mod h1:vTaDufYul+Ps8D7bgseHjq87X8eu0ivlKLp9mVc/Bfc=
|
github.com/juju/mgotest v1.0.1/go.mod h1:vTaDufYul+Ps8D7bgseHjq87X8eu0ivlKLp9mVc/Bfc=
|
||||||
github.com/juju/postgrestest v1.1.0/go.mod h1:/n17Y2T6iFozzXwSCO0JYJ5gSiz2caEtSwAjh/uLXDM=
|
github.com/juju/postgrestest v1.1.0/go.mod h1:/n17Y2T6iFozzXwSCO0JYJ5gSiz2caEtSwAjh/uLXDM=
|
||||||
github.com/juju/qthttptest v0.0.1/go.mod h1://LCf/Ls22/rPw2u1yWukUJvYtfPY4nYpWUl2uZhryo=
|
github.com/juju/qthttptest v0.0.1/go.mod h1://LCf/Ls22/rPw2u1yWukUJvYtfPY4nYpWUl2uZhryo=
|
||||||
github.com/juju/qthttptest v0.1.1 h1:JPju5P5CDMCy8jmBJV2wGLjDItUsx2KKL514EfOYueM=
|
github.com/juju/qthttptest v0.1.1 h1:JPju5P5CDMCy8jmBJV2wGLjDItUsx2KKL514EfOYueM=
|
||||||
github.com/juju/qthttptest v0.1.1/go.mod h1:aTlAv8TYaflIiTDIQYzxnl1QdPjAg8Q8qJMErpKy6A4=
|
github.com/juju/qthttptest v0.1.1/go.mod h1:aTlAv8TYaflIiTDIQYzxnl1QdPjAg8Q8qJMErpKy6A4=
|
||||||
|
github.com/juju/retry v0.0.0-20220204093819-62423bf33287 h1:U+7oMWEglXfiikIppNexButZRwKPlzLBGKYSNCXzXf8=
|
||||||
|
github.com/juju/retry v0.0.0-20220204093819-62423bf33287/go.mod h1:SssN1eYeK3A2qjnFGTiVMbdzGJ2BfluaJblJXvuvgqA=
|
||||||
github.com/juju/schema v1.0.0/go.mod h1:Y+ThzXpUJ0E7NYYocAbuvJ7vTivXfrof/IfRPq/0abI=
|
github.com/juju/schema v1.0.0/go.mod h1:Y+ThzXpUJ0E7NYYocAbuvJ7vTivXfrof/IfRPq/0abI=
|
||||||
|
github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494 h1:XEDzpuZb8Ma7vLja3+5hzUqVTvAqm5Y+ygvnDs5iTMM=
|
||||||
|
github.com/juju/utils v0.0.0-20200604140309-9d78121a29e0 h1:4XlJ/Wj/bH3zGa2GU+Us72FgtmL1n3dwjP7LW7+TF/o=
|
||||||
|
github.com/juju/utils/v3 v3.0.0-20220203023959-c3fbc78a33b0 h1:bn+2Adl1yWqYjm3KSFlFqsvfLg2eq+XNL7GGMYApdVw=
|
||||||
|
github.com/juju/version v0.0.0-20210303051006-2015802527a8 h1:BTo6HzRR0zPBcXbs1Sy08aQNfvdm3ey8O+mBTiO3g00=
|
||||||
|
github.com/juju/version/v2 v2.0.0-20211007103408-2e8da085dc23 h1:wtEPbidt1VyHlb8RSztU6ySQj29FLsOQiI9XiJhXDM4=
|
||||||
github.com/juju/webbrowser v0.0.0-20160309143629-54b8c57083b4/go.mod h1:G6PCelgkM6cuvyD10iYJsjLBsSadVXtJ+nBxFAxE2BU=
|
github.com/juju/webbrowser v0.0.0-20160309143629-54b8c57083b4/go.mod h1:G6PCelgkM6cuvyD10iYJsjLBsSadVXtJ+nBxFAxE2BU=
|
||||||
github.com/juju/webbrowser v1.0.0 h1:JLdmbFtCGY6Qf2jmS6bVaenJFGIFkdF1/BjUm76af78=
|
github.com/juju/webbrowser v1.0.0 h1:JLdmbFtCGY6Qf2jmS6bVaenJFGIFkdF1/BjUm76af78=
|
||||||
github.com/juju/webbrowser v1.0.0/go.mod h1:RwVlbBcF91Q4vS+iwlkJ6bZTE3EwlrjbYlM3WMVD6Bc=
|
github.com/juju/webbrowser v1.0.0/go.mod h1:RwVlbBcF91Q4vS+iwlkJ6bZTE3EwlrjbYlM3WMVD6Bc=
|
||||||
|
|
@ -225,6 +239,7 @@ github.com/spf13/cobra v1.4.1-0.20220504202302-9e88759b19cd/go.mod h1:Wo4iy3BUC+
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
|
@ -233,6 +248,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
|
||||||
|
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
|
@ -371,6 +388,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
||||||
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/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
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/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|
@ -504,7 +523,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
|
||||||
gopkg.in/errgo.v1 v1.0.0/go.mod h1:CxwszS/Xz1C49Ucd2i6Zil5UToP1EmyrFhKaMVbg1mk=
|
gopkg.in/errgo.v1 v1.0.0/go.mod h1:CxwszS/Xz1C49Ucd2i6Zil5UToP1EmyrFhKaMVbg1mk=
|
||||||
gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso=
|
gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso=
|
||||||
gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo=
|
gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo=
|
||||||
|
|
|
||||||
268
runner/common/mocks/GithubClient.go
Normal file
268
runner/common/mocks/GithubClient.go
Normal file
|
|
@ -0,0 +1,268 @@
|
||||||
|
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
github "github.com/google/go-github/v43/github"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GithubClient is an autogenerated mock type for the GithubClient type
|
||||||
|
type GithubClient struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrganizationRegistrationToken provides a mock function with given fields: ctx, owner
|
||||||
|
func (_m *GithubClient) CreateOrganizationRegistrationToken(ctx context.Context, owner string) (*github.RegistrationToken, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner)
|
||||||
|
|
||||||
|
var r0 *github.RegistrationToken
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) *github.RegistrationToken); ok {
|
||||||
|
r0 = rf(ctx, owner)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.RegistrationToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string) error); ok {
|
||||||
|
r2 = rf(ctx, owner)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRegistrationToken provides a mock function with given fields: ctx, owner, repo
|
||||||
|
func (_m *GithubClient) CreateRegistrationToken(ctx context.Context, owner string, repo string) (*github.RegistrationToken, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo)
|
||||||
|
|
||||||
|
var r0 *github.RegistrationToken
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string) *github.RegistrationToken); ok {
|
||||||
|
r0 = rf(ctx, owner, repo)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.RegistrationToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrganizationRunnerApplicationDownloads provides a mock function with given fields: ctx, owner
|
||||||
|
func (_m *GithubClient) ListOrganizationRunnerApplicationDownloads(ctx context.Context, owner string) ([]*github.RunnerApplicationDownload, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner)
|
||||||
|
|
||||||
|
var r0 []*github.RunnerApplicationDownload
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) []*github.RunnerApplicationDownload); ok {
|
||||||
|
r0 = rf(ctx, owner)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*github.RunnerApplicationDownload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string) error); ok {
|
||||||
|
r2 = rf(ctx, owner)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListOrganizationRunners provides a mock function with given fields: ctx, owner, opts
|
||||||
|
func (_m *GithubClient) ListOrganizationRunners(ctx context.Context, owner string, opts *github.ListOptions) (*github.Runners, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, opts)
|
||||||
|
|
||||||
|
var r0 *github.Runners
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, *github.ListOptions) *github.Runners); ok {
|
||||||
|
r0 = rf(ctx, owner, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.Runners)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, *github.ListOptions) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, *github.ListOptions) error); ok {
|
||||||
|
r2 = rf(ctx, owner, opts)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRunnerApplicationDownloads provides a mock function with given fields: ctx, owner, repo
|
||||||
|
func (_m *GithubClient) ListRunnerApplicationDownloads(ctx context.Context, owner string, repo string) ([]*github.RunnerApplicationDownload, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo)
|
||||||
|
|
||||||
|
var r0 []*github.RunnerApplicationDownload
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string) []*github.RunnerApplicationDownload); ok {
|
||||||
|
r0 = rf(ctx, owner, repo)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*github.RunnerApplicationDownload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRunners provides a mock function with given fields: ctx, owner, repo, opts
|
||||||
|
func (_m *GithubClient) ListRunners(ctx context.Context, owner string, repo string, opts *github.ListOptions) (*github.Runners, *github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, opts)
|
||||||
|
|
||||||
|
var r0 *github.Runners
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, *github.ListOptions) *github.Runners); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.Runners)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *github.Response
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, *github.ListOptions) *github.Response); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(2).(func(context.Context, string, string, *github.ListOptions) error); ok {
|
||||||
|
r2 = rf(ctx, owner, repo, opts)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOrganizationRunner provides a mock function with given fields: ctx, owner, runnerID
|
||||||
|
func (_m *GithubClient) RemoveOrganizationRunner(ctx context.Context, owner string, runnerID int64) (*github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, runnerID)
|
||||||
|
|
||||||
|
var r0 *github.Response
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, int64) *github.Response); ok {
|
||||||
|
r0 = rf(ctx, owner, runnerID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
|
||||||
|
r1 = rf(ctx, owner, runnerID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveRunner provides a mock function with given fields: ctx, owner, repo, runnerID
|
||||||
|
func (_m *GithubClient) RemoveRunner(ctx context.Context, owner string, repo string, runnerID int64) (*github.Response, error) {
|
||||||
|
ret := _m.Called(ctx, owner, repo, runnerID)
|
||||||
|
|
||||||
|
var r0 *github.Response
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, int64) *github.Response); ok {
|
||||||
|
r0 = rf(ctx, owner, repo, runnerID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*github.Response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, int64) error); ok {
|
||||||
|
r1 = rf(ctx, owner, repo, runnerID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockConstructorTestingTNewGithubClient interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGithubClient creates a new instance of GithubClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
func NewGithubClient(t mockConstructorTestingTNewGithubClient) *GithubClient {
|
||||||
|
mock := &GithubClient{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
||||||
141
runner/common/mocks/PoolManager.go
Normal file
141
runner/common/mocks/PoolManager.go
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
params "garm/params"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PoolManager is an autogenerated mock type for the PoolManager type
|
||||||
|
type PoolManager struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForceDeleteRunner provides a mock function with given fields: runner
|
||||||
|
func (_m *PoolManager) ForceDeleteRunner(runner params.Instance) error {
|
||||||
|
ret := _m.Called(runner)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(params.Instance) error); ok {
|
||||||
|
r0 = rf(runner)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleWorkflowJob provides a mock function with given fields: job
|
||||||
|
func (_m *PoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
||||||
|
ret := _m.Called(job)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(params.WorkflowJob) error); ok {
|
||||||
|
r0 = rf(job)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID provides a mock function with given fields:
|
||||||
|
func (_m *PoolManager) ID() string {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 string
|
||||||
|
if rf, ok := ret.Get(0).(func() string); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshState provides a mock function with given fields: param
|
||||||
|
func (_m *PoolManager) RefreshState(param params.UpdatePoolStateParams) error {
|
||||||
|
ret := _m.Called(param)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(params.UpdatePoolStateParams) error); ok {
|
||||||
|
r0 = rf(param)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start provides a mock function with given fields:
|
||||||
|
func (_m *PoolManager) Start() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop provides a mock function with given fields:
|
||||||
|
func (_m *PoolManager) Stop() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait provides a mock function with given fields:
|
||||||
|
func (_m *PoolManager) Wait() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebhookSecret provides a mock function with given fields:
|
||||||
|
func (_m *PoolManager) WebhookSecret() string {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 string
|
||||||
|
if rf, ok := ret.Get(0).(func() string); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockConstructorTestingTNewPoolManager interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPoolManager creates a new instance of PoolManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
func NewPoolManager(t mockConstructorTestingTNewPoolManager) *PoolManager {
|
||||||
|
mock := &PoolManager{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
||||||
165
runner/common/mocks/Provider.go
Normal file
165
runner/common/mocks/Provider.go
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
params "garm/params"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider is an autogenerated mock type for the Provider type
|
||||||
|
type Provider struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsParams provides a mock function with given fields:
|
||||||
|
func (_m *Provider) AsParams() params.Provider {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 params.Provider
|
||||||
|
if rf, ok := ret.Get(0).(func() params.Provider); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(params.Provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateInstance provides a mock function with given fields: ctx, bootstrapParams
|
||||||
|
func (_m *Provider) CreateInstance(ctx context.Context, bootstrapParams params.BootstrapInstance) (params.Instance, error) {
|
||||||
|
ret := _m.Called(ctx, bootstrapParams)
|
||||||
|
|
||||||
|
var r0 params.Instance
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, params.BootstrapInstance) params.Instance); ok {
|
||||||
|
r0 = rf(ctx, bootstrapParams)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(params.Instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, params.BootstrapInstance) error); ok {
|
||||||
|
r1 = rf(ctx, bootstrapParams)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteInstance provides a mock function with given fields: ctx, instance
|
||||||
|
func (_m *Provider) DeleteInstance(ctx context.Context, instance string) error {
|
||||||
|
ret := _m.Called(ctx, instance)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||||
|
r0 = rf(ctx, instance)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInstance provides a mock function with given fields: ctx, instance
|
||||||
|
func (_m *Provider) GetInstance(ctx context.Context, instance string) (params.Instance, error) {
|
||||||
|
ret := _m.Called(ctx, instance)
|
||||||
|
|
||||||
|
var r0 params.Instance
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) params.Instance); ok {
|
||||||
|
r0 = rf(ctx, instance)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(params.Instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||||
|
r1 = rf(ctx, instance)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListInstances provides a mock function with given fields: ctx, poolID
|
||||||
|
func (_m *Provider) ListInstances(ctx context.Context, poolID string) ([]params.Instance, error) {
|
||||||
|
ret := _m.Called(ctx, poolID)
|
||||||
|
|
||||||
|
var r0 []params.Instance
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) []params.Instance); ok {
|
||||||
|
r0 = rf(ctx, poolID)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]params.Instance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||||
|
r1 = rf(ctx, poolID)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAllInstances provides a mock function with given fields: ctx
|
||||||
|
func (_m *Provider) RemoveAllInstances(ctx context.Context) error {
|
||||||
|
ret := _m.Called(ctx)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
|
||||||
|
r0 = rf(ctx)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start provides a mock function with given fields: ctx, instance
|
||||||
|
func (_m *Provider) Start(ctx context.Context, instance string) error {
|
||||||
|
ret := _m.Called(ctx, instance)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||||
|
r0 = rf(ctx, instance)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop provides a mock function with given fields: ctx, instance, force
|
||||||
|
func (_m *Provider) Stop(ctx context.Context, instance string, force bool) error {
|
||||||
|
ret := _m.Called(ctx, instance, force)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, bool) error); ok {
|
||||||
|
r0 = rf(ctx, instance, force)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockConstructorTestingTNewProvider interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProvider creates a new instance of Provider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
func NewProvider(t mockConstructorTestingTNewProvider) *Provider {
|
||||||
|
mock := &Provider{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
@ -298,7 +298,7 @@ func (l *LXD) CreateInstance(ctx context.Context, bootstrapParams params.Bootstr
|
||||||
return params.Instance{}, errors.Wrap(err, "creating instance")
|
return params.Instance{}, errors.Wrap(err, "creating instance")
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err := l.GetInstance(ctx, args.Name)
|
ret, err := l.waitInstanceHasIP(ctx, args.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return params.Instance{}, errors.Wrap(err, "fetching instance")
|
return params.Instance{}, errors.Wrap(err, "fetching instance")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,19 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"garm/config"
|
"garm/config"
|
||||||
"garm/params"
|
"garm/params"
|
||||||
"garm/runner/providers/common"
|
"garm/runner/providers/common"
|
||||||
"garm/util"
|
"garm/util"
|
||||||
|
|
||||||
|
"github.com/juju/clock"
|
||||||
|
"github.com/juju/retry"
|
||||||
lxd "github.com/lxc/lxd/client"
|
lxd "github.com/lxc/lxd/client"
|
||||||
"github.com/lxc/lxd/shared/api"
|
"github.com/lxc/lxd/shared/api"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
@ -177,3 +181,39 @@ func resolveArchitecture(osArch config.OSArch) (string, error) {
|
||||||
}
|
}
|
||||||
return arch, nil
|
return arch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitDeviceActive is a function capable of figuring out when a Equinix Metal
|
||||||
|
// device is active
|
||||||
|
func (l *LXD) waitInstanceHasIP(ctx context.Context, instanceName string) (params.Instance, error) {
|
||||||
|
var p params.Instance
|
||||||
|
var errIPNotFound error = fmt.Errorf("ip not found")
|
||||||
|
err := retry.Call(retry.CallArgs{
|
||||||
|
Func: func() error {
|
||||||
|
var err error
|
||||||
|
p, err = l.GetInstance(ctx, instanceName)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "fetching instance")
|
||||||
|
}
|
||||||
|
for _, addr := range p.Addresses {
|
||||||
|
ip := net.ParseIP(addr.Address)
|
||||||
|
if ip == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ip.To4() == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errIPNotFound
|
||||||
|
},
|
||||||
|
Attempts: 20,
|
||||||
|
Delay: 5 * time.Second,
|
||||||
|
Clock: clock.WallClock,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil && err != errIPNotFound {
|
||||||
|
return params.Instance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
191
vendor/github.com/juju/clock/LICENSE
generated
vendored
Normal file
191
vendor/github.com/juju/clock/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
All files in this repository are licensed as follows. If you contribute
|
||||||
|
to this repository, it is assumed that you license your contribution
|
||||||
|
under the same license unless you state otherwise.
|
||||||
|
|
||||||
|
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
||||||
|
|
||||||
|
This software is licensed under the LGPLv3, included below.
|
||||||
|
|
||||||
|
As a special exception to the GNU Lesser General Public License version 3
|
||||||
|
("LGPL3"), the copyright holders of this Library give you permission to
|
||||||
|
convey to a third party a Combined Work that links statically or dynamically
|
||||||
|
to this Library without providing any Minimal Corresponding Source or
|
||||||
|
Minimal Application Code as set out in 4d or providing the installation
|
||||||
|
information set out in section 4e, provided that you comply with the other
|
||||||
|
provisions of LGPL3 and provided that you meet, for the Application the
|
||||||
|
terms and conditions of the license(s) which apply to the Application.
|
||||||
|
|
||||||
|
Except as stated in this special exception, the provisions of LGPL3 will
|
||||||
|
continue to comply in full to this Library. If you modify this Library, you
|
||||||
|
may apply this exception to your version of this Library, but you are not
|
||||||
|
obliged to do so. If you do not wish to do so, delete this exception
|
||||||
|
statement from your version. This exception does not (and cannot) modify any
|
||||||
|
license terms which apply to the Application, with which you must still
|
||||||
|
comply.
|
||||||
|
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
20
vendor/github.com/juju/clock/Makefile
generated
vendored
Normal file
20
vendor/github.com/juju/clock/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
PROJECT := github.com/juju/clock
|
||||||
|
|
||||||
|
.PHONY: check-licence check-go check
|
||||||
|
|
||||||
|
check: check-licence check-go
|
||||||
|
go test $(PROJECT)/...
|
||||||
|
|
||||||
|
check-licence:
|
||||||
|
@(fgrep -rl "Licensed under the LGPLv3" --exclude *.s .;\
|
||||||
|
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" --exclude *.s .;\
|
||||||
|
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
|
||||||
|
xargs -I {} echo FAIL: licence missed: {}
|
||||||
|
|
||||||
|
check-go:
|
||||||
|
$(eval GOFMT := $(strip $(shell gofmt -l .| sed -e "s/^/ /g")))
|
||||||
|
@(if [ x$(GOFMT) != x"" ]; then \
|
||||||
|
echo go fmt is sad: $(GOFMT); \
|
||||||
|
exit 1; \
|
||||||
|
fi )
|
||||||
|
@(go vet -all -composites=false -copylocks=false .)
|
||||||
7
vendor/github.com/juju/clock/README.md
generated
vendored
Normal file
7
vendor/github.com/juju/clock/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# clock
|
||||||
|
|
||||||
|
An interface definition for a fully defined clock.
|
||||||
|
|
||||||
|
An WallClock implementation of that interface using the time package.
|
||||||
|
|
||||||
|
A testing clock.
|
||||||
53
vendor/github.com/juju/clock/clock.go
generated
vendored
Normal file
53
vendor/github.com/juju/clock/clock.go
generated
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright 2015 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package clock
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Clock provides an interface for dealing with clocks.
|
||||||
|
type Clock interface {
|
||||||
|
// Now returns the current clock time.
|
||||||
|
Now() time.Time
|
||||||
|
|
||||||
|
// After waits for the duration to elapse and then sends the
|
||||||
|
// current time on the returned channel.
|
||||||
|
After(time.Duration) <-chan time.Time
|
||||||
|
|
||||||
|
// AfterFunc waits for the duration to elapse and then calls f in its own goroutine.
|
||||||
|
// It returns a Timer that can be used to cancel the call using its Stop method.
|
||||||
|
AfterFunc(d time.Duration, f func()) Timer
|
||||||
|
|
||||||
|
// NewTimer creates a new Timer that will send the current time
|
||||||
|
// on its channel after at least duration d.
|
||||||
|
NewTimer(d time.Duration) Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alarm returns a channel that will have the time sent on it at some point
|
||||||
|
// after the supplied time occurs.
|
||||||
|
//
|
||||||
|
// This is short for c.After(t.Sub(c.Now())).
|
||||||
|
func Alarm(c Clock, t time.Time) <-chan time.Time {
|
||||||
|
return c.After(t.Sub(c.Now()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Timer type represents a single event.
|
||||||
|
// A Timer must be created with AfterFunc.
|
||||||
|
// This interface follows time.Timer's methods but provides easier mocking.
|
||||||
|
type Timer interface {
|
||||||
|
// When the Timer expires, the current time will be sent on the
|
||||||
|
// channel returned from Chan, unless the Timer was created by
|
||||||
|
// AfterFunc.
|
||||||
|
Chan() <-chan time.Time
|
||||||
|
|
||||||
|
// Reset changes the timer to expire after duration d.
|
||||||
|
// It returns true if the timer had been active, false if
|
||||||
|
// the timer had expired or been stopped.
|
||||||
|
Reset(time.Duration) bool
|
||||||
|
|
||||||
|
// Stop prevents the Timer from firing. It returns true if
|
||||||
|
// the call stops the timer, false if the timer has already expired or been stopped.
|
||||||
|
// Stop does not close the channel, to prevent a read
|
||||||
|
// from the channel succeeding incorrectly.
|
||||||
|
Stop() bool
|
||||||
|
}
|
||||||
47
vendor/github.com/juju/clock/wall.go
generated
vendored
Normal file
47
vendor/github.com/juju/clock/wall.go
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2015 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package clock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WallClock exposes wall-clock time via the Clock interface.
|
||||||
|
var WallClock wallClock
|
||||||
|
|
||||||
|
// ensure that WallClock does actually implement the Clock interface.
|
||||||
|
var _ Clock = WallClock
|
||||||
|
|
||||||
|
// WallClock exposes wall-clock time as returned by time.Now.
|
||||||
|
type wallClock struct{}
|
||||||
|
|
||||||
|
// Now is part of the Clock interface.
|
||||||
|
func (wallClock) Now() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// After implements Clock.After.
|
||||||
|
func (wallClock) After(d time.Duration) <-chan time.Time {
|
||||||
|
return time.After(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterFunc implements Clock.AfterFunc.
|
||||||
|
func (wallClock) AfterFunc(d time.Duration, f func()) Timer {
|
||||||
|
return wallTimer{time.AfterFunc(d, f)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTimer implements Clock.NewTimer.
|
||||||
|
func (wallClock) NewTimer(d time.Duration) Timer {
|
||||||
|
return wallTimer{time.NewTimer(d)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wallTimer implements the Timer interface.
|
||||||
|
type wallTimer struct {
|
||||||
|
*time.Timer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chan implements Timer.Chan.
|
||||||
|
func (t wallTimer) Chan() <-chan time.Time {
|
||||||
|
return t.C
|
||||||
|
}
|
||||||
23
vendor/github.com/juju/errors/.gitignore
generated
vendored
Normal file
23
vendor/github.com/juju/errors/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
Normal file
191
vendor/github.com/juju/errors/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
All files in this repository are licensed as follows. If you contribute
|
||||||
|
to this repository, it is assumed that you license your contribution
|
||||||
|
under the same license unless you state otherwise.
|
||||||
|
|
||||||
|
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
||||||
|
|
||||||
|
This software is licensed under the LGPLv3, included below.
|
||||||
|
|
||||||
|
As a special exception to the GNU Lesser General Public License version 3
|
||||||
|
("LGPL3"), the copyright holders of this Library give you permission to
|
||||||
|
convey to a third party a Combined Work that links statically or dynamically
|
||||||
|
to this Library without providing any Minimal Corresponding Source or
|
||||||
|
Minimal Application Code as set out in 4d or providing the installation
|
||||||
|
information set out in section 4e, provided that you comply with the other
|
||||||
|
provisions of LGPL3 and provided that you meet, for the Application the
|
||||||
|
terms and conditions of the license(s) which apply to the Application.
|
||||||
|
|
||||||
|
Except as stated in this special exception, the provisions of LGPL3 will
|
||||||
|
continue to comply in full to this Library. If you modify this Library, you
|
||||||
|
may apply this exception to your version of this Library, but you are not
|
||||||
|
obliged to do so. If you do not wish to do so, delete this exception
|
||||||
|
statement from your version. This exception does not (and cannot) modify any
|
||||||
|
license terms which apply to the Application, with which you must still
|
||||||
|
comply.
|
||||||
|
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
24
vendor/github.com/juju/errors/Makefile
generated
vendored
Normal file
24
vendor/github.com/juju/errors/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
PROJECT := github.com/juju/errors
|
||||||
|
|
||||||
|
.PHONY: check-licence check-go check docs
|
||||||
|
|
||||||
|
check: check-licence check-go
|
||||||
|
go test $(PROJECT)/...
|
||||||
|
|
||||||
|
check-licence:
|
||||||
|
@(fgrep -rl "Licensed under the LGPLv3" --exclude *.s .;\
|
||||||
|
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" --exclude *.s .;\
|
||||||
|
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
|
||||||
|
xargs -I {} echo FAIL: licence missed: {}
|
||||||
|
|
||||||
|
check-go:
|
||||||
|
$(eval GOFMT := $(strip $(shell gofmt -l .| sed -e "s/^/ /g")))
|
||||||
|
@(if [ x$(GOFMT) != x"" ]; then \
|
||||||
|
echo go fmt is sad: $(GOFMT); \
|
||||||
|
exit 1; \
|
||||||
|
fi )
|
||||||
|
@(go vet -all -composites=false -copylocks=false .)
|
||||||
|
|
||||||
|
docs:
|
||||||
|
godoc2md github.com/juju/errors > README.md
|
||||||
|
sed -i '5i[\[GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)' README.md
|
||||||
707
vendor/github.com/juju/errors/README.md
generated
vendored
Normal file
707
vendor/github.com/juju/errors/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,707 @@
|
||||||
|
|
||||||
|
# errors
|
||||||
|
import "github.com/juju/errors"
|
||||||
|
|
||||||
|
[](https://godoc.org/github.com/juju/errors)
|
||||||
|
|
||||||
|
The juju/errors provides an easy way to annotate errors without losing the
|
||||||
|
original error context.
|
||||||
|
|
||||||
|
The exported `New` and `Errorf` functions are designed to replace the
|
||||||
|
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
||||||
|
error is there, but the package also records the location at which the error
|
||||||
|
was created.
|
||||||
|
|
||||||
|
A primary use case for this library is to add extra context any time an
|
||||||
|
error is returned from a function.
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
This instead becomes:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
which just records the file and line number of the Trace call, or
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotate(err, "more context")
|
||||||
|
}
|
||||||
|
|
||||||
|
which also adds an annotation to the error.
|
||||||
|
|
||||||
|
When you want to check to see if an error is of a particular type, a helper
|
||||||
|
function is normally exported by the package that returned the error, like the
|
||||||
|
`os` package does. The underlying cause of the error is available using the
|
||||||
|
`Cause` function.
|
||||||
|
|
||||||
|
|
||||||
|
os.IsNotExist(errors.Cause(err))
|
||||||
|
|
||||||
|
The result of the `Error()` call on an annotated error is the annotations joined
|
||||||
|
with colons, then the result of the `Error()` method for the underlying error
|
||||||
|
that was the cause.
|
||||||
|
|
||||||
|
|
||||||
|
err := errors.Errorf("original")
|
||||||
|
err = errors.Annotatef(err, "context")
|
||||||
|
err = errors.Annotatef(err, "more context")
|
||||||
|
err.Error() -> "more context: context: original"
|
||||||
|
|
||||||
|
Obviously recording the file, line and functions is not very useful if you
|
||||||
|
cannot get them back out again.
|
||||||
|
|
||||||
|
|
||||||
|
errors.ErrorStack(err)
|
||||||
|
|
||||||
|
will return something like:
|
||||||
|
|
||||||
|
|
||||||
|
first error
|
||||||
|
github.com/juju/errors/annotation_test.go:193:
|
||||||
|
github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
github.com/juju/errors/annotation_test.go:195:
|
||||||
|
github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
github.com/juju/errors/annotation_test.go:197:
|
||||||
|
|
||||||
|
The first error was generated by an external system, so there was no location
|
||||||
|
associated. The second, fourth, and last lines were generated with Trace calls,
|
||||||
|
and the other two through Annotate.
|
||||||
|
|
||||||
|
Sometimes when responding to an error you want to return a more specific error
|
||||||
|
for the situation.
|
||||||
|
|
||||||
|
|
||||||
|
if err := FindField(field); err != nil {
|
||||||
|
return errors.Wrap(err, errors.NotFoundf(field))
|
||||||
|
}
|
||||||
|
|
||||||
|
This returns an error where the complete error stack is still available, and
|
||||||
|
`errors.Cause()` will return the `NotFound` error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## func AlreadyExistsf
|
||||||
|
``` go
|
||||||
|
func AlreadyExistsf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
AlreadyExistsf returns an error which satisfies IsAlreadyExists().
|
||||||
|
|
||||||
|
|
||||||
|
## func Annotate
|
||||||
|
``` go
|
||||||
|
func Annotate(other error, message string) error
|
||||||
|
```
|
||||||
|
Annotate is used to add extra context to an existing error. The location of
|
||||||
|
the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
function are also recorded.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotate(err, "failed to frombulate")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func Annotatef
|
||||||
|
``` go
|
||||||
|
func Annotatef(other error, format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Annotatef is used to add extra context to an existing error. The location of
|
||||||
|
the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
function are also recorded.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func BadRequestf
|
||||||
|
``` go
|
||||||
|
func BadRequestf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
BadRequestf returns an error which satisfies IsBadRequest().
|
||||||
|
|
||||||
|
|
||||||
|
## func Cause
|
||||||
|
``` go
|
||||||
|
func Cause(err error) error
|
||||||
|
```
|
||||||
|
Cause returns the cause of the given error. This will be either the
|
||||||
|
original error, or the result of a Wrap or Mask call.
|
||||||
|
|
||||||
|
Cause is the usual way to diagnose errors that may have been wrapped by
|
||||||
|
the other errors functions.
|
||||||
|
|
||||||
|
|
||||||
|
## func DeferredAnnotatef
|
||||||
|
``` go
|
||||||
|
func DeferredAnnotatef(err *error, format string, args ...interface{})
|
||||||
|
```
|
||||||
|
DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
||||||
|
format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
||||||
|
does nothing. This method is used in a defer statement in order to annotate any
|
||||||
|
resulting error with the same message.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
||||||
|
|
||||||
|
|
||||||
|
## func Details
|
||||||
|
``` go
|
||||||
|
func Details(err error) string
|
||||||
|
```
|
||||||
|
Details returns information about the stack of errors wrapped by err, in
|
||||||
|
the format:
|
||||||
|
|
||||||
|
|
||||||
|
[{filename:99: error one} {otherfile:55: cause of error one}]
|
||||||
|
|
||||||
|
This is a terse alternative to ErrorStack as it returns a single line.
|
||||||
|
|
||||||
|
|
||||||
|
## func ErrorStack
|
||||||
|
``` go
|
||||||
|
func ErrorStack(err error) string
|
||||||
|
```
|
||||||
|
ErrorStack returns a string representation of the annotated error. If the
|
||||||
|
error passed as the parameter is not an annotated error, the result is
|
||||||
|
simply the result of the Error() method on that error.
|
||||||
|
|
||||||
|
If the error is an annotated error, a multi-line string is returned where
|
||||||
|
each line represents one entry in the annotation stack. The full filename
|
||||||
|
from the call stack is used in the output.
|
||||||
|
|
||||||
|
|
||||||
|
first error
|
||||||
|
github.com/juju/errors/annotation_test.go:193:
|
||||||
|
github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
github.com/juju/errors/annotation_test.go:195:
|
||||||
|
github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
github.com/juju/errors/annotation_test.go:197:
|
||||||
|
|
||||||
|
|
||||||
|
## func Errorf
|
||||||
|
``` go
|
||||||
|
func Errorf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Errorf creates a new annotated error and records the location that the
|
||||||
|
error is created. This should be a drop in replacement for fmt.Errorf.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
return errors.Errorf("validation failed: %s", message)
|
||||||
|
|
||||||
|
|
||||||
|
## func Forbiddenf
|
||||||
|
``` go
|
||||||
|
func Forbiddenf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Forbiddenf returns an error which satistifes IsForbidden()
|
||||||
|
|
||||||
|
|
||||||
|
## func IsAlreadyExists
|
||||||
|
``` go
|
||||||
|
func IsAlreadyExists(err error) bool
|
||||||
|
```
|
||||||
|
IsAlreadyExists reports whether the error was created with
|
||||||
|
AlreadyExistsf() or NewAlreadyExists().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsBadRequest
|
||||||
|
``` go
|
||||||
|
func IsBadRequest(err error) bool
|
||||||
|
```
|
||||||
|
IsBadRequest reports whether err was created with BadRequestf() or
|
||||||
|
NewBadRequest().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsForbidden
|
||||||
|
``` go
|
||||||
|
func IsForbidden(err error) bool
|
||||||
|
```
|
||||||
|
IsForbidden reports whether err was created with Forbiddenf() or
|
||||||
|
NewForbidden().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsMethodNotAllowed
|
||||||
|
``` go
|
||||||
|
func IsMethodNotAllowed(err error) bool
|
||||||
|
```
|
||||||
|
IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
|
||||||
|
NewMethodNotAllowed().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotAssigned
|
||||||
|
``` go
|
||||||
|
func IsNotAssigned(err error) bool
|
||||||
|
```
|
||||||
|
IsNotAssigned reports whether err was created with NotAssignedf() or
|
||||||
|
NewNotAssigned().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotFound
|
||||||
|
``` go
|
||||||
|
func IsNotFound(err error) bool
|
||||||
|
```
|
||||||
|
IsNotFound reports whether err was created with NotFoundf() or
|
||||||
|
NewNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotImplemented
|
||||||
|
``` go
|
||||||
|
func IsNotImplemented(err error) bool
|
||||||
|
```
|
||||||
|
IsNotImplemented reports whether err was created with
|
||||||
|
NotImplementedf() or NewNotImplemented().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotProvisioned
|
||||||
|
``` go
|
||||||
|
func IsNotProvisioned(err error) bool
|
||||||
|
```
|
||||||
|
IsNotProvisioned reports whether err was created with NotProvisionedf() or
|
||||||
|
NewNotProvisioned().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotSupported
|
||||||
|
``` go
|
||||||
|
func IsNotSupported(err error) bool
|
||||||
|
```
|
||||||
|
IsNotSupported reports whether the error was created with
|
||||||
|
NotSupportedf() or NewNotSupported().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsNotValid
|
||||||
|
``` go
|
||||||
|
func IsNotValid(err error) bool
|
||||||
|
```
|
||||||
|
IsNotValid reports whether the error was created with NotValidf() or
|
||||||
|
NewNotValid().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsUnauthorized
|
||||||
|
``` go
|
||||||
|
func IsUnauthorized(err error) bool
|
||||||
|
```
|
||||||
|
IsUnauthorized reports whether err was created with Unauthorizedf() or
|
||||||
|
NewUnauthorized().
|
||||||
|
|
||||||
|
|
||||||
|
## func IsUserNotFound
|
||||||
|
``` go
|
||||||
|
func IsUserNotFound(err error) bool
|
||||||
|
```
|
||||||
|
IsUserNotFound reports whether err was created with UserNotFoundf() or
|
||||||
|
NewUserNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func Mask
|
||||||
|
``` go
|
||||||
|
func Mask(other error) error
|
||||||
|
```
|
||||||
|
Mask hides the underlying error type, and records the location of the masking.
|
||||||
|
|
||||||
|
|
||||||
|
## func Maskf
|
||||||
|
``` go
|
||||||
|
func Maskf(other error, format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Mask masks the given error with the given format string and arguments (like
|
||||||
|
fmt.Sprintf), returning a new error that maintains the error stack, but
|
||||||
|
hides the underlying error type. The error string still contains the full
|
||||||
|
annotations. If you want to hide the annotations, call Wrap.
|
||||||
|
|
||||||
|
|
||||||
|
## func MethodNotAllowedf
|
||||||
|
``` go
|
||||||
|
func MethodNotAllowedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
|
||||||
|
|
||||||
|
|
||||||
|
## func New
|
||||||
|
``` go
|
||||||
|
func New(message string) error
|
||||||
|
```
|
||||||
|
New is a drop in replacement for the standard library errors module that records
|
||||||
|
the location that the error is created.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
return errors.New("validation failed")
|
||||||
|
|
||||||
|
|
||||||
|
## func NewAlreadyExists
|
||||||
|
``` go
|
||||||
|
func NewAlreadyExists(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewAlreadyExists returns an error which wraps err and satisfies
|
||||||
|
IsAlreadyExists().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewBadRequest
|
||||||
|
``` go
|
||||||
|
func NewBadRequest(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewBadRequest returns an error which wraps err that satisfies
|
||||||
|
IsBadRequest().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewForbidden
|
||||||
|
``` go
|
||||||
|
func NewForbidden(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewForbidden returns an error which wraps err that satisfies
|
||||||
|
IsForbidden().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewMethodNotAllowed
|
||||||
|
``` go
|
||||||
|
func NewMethodNotAllowed(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewMethodNotAllowed returns an error which wraps err that satisfies
|
||||||
|
IsMethodNotAllowed().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotAssigned
|
||||||
|
``` go
|
||||||
|
func NewNotAssigned(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotAssigned returns an error which wraps err that satisfies
|
||||||
|
IsNotAssigned().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotFound
|
||||||
|
``` go
|
||||||
|
func NewNotFound(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotFound returns an error which wraps err that satisfies
|
||||||
|
IsNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotImplemented
|
||||||
|
``` go
|
||||||
|
func NewNotImplemented(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotImplemented returns an error which wraps err and satisfies
|
||||||
|
IsNotImplemented().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotProvisioned
|
||||||
|
``` go
|
||||||
|
func NewNotProvisioned(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotProvisioned returns an error which wraps err that satisfies
|
||||||
|
IsNotProvisioned().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotSupported
|
||||||
|
``` go
|
||||||
|
func NewNotSupported(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotSupported returns an error which wraps err and satisfies
|
||||||
|
IsNotSupported().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewNotValid
|
||||||
|
``` go
|
||||||
|
func NewNotValid(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewNotValid returns an error which wraps err and satisfies IsNotValid().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewUnauthorized
|
||||||
|
``` go
|
||||||
|
func NewUnauthorized(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewUnauthorized returns an error which wraps err and satisfies
|
||||||
|
IsUnauthorized().
|
||||||
|
|
||||||
|
|
||||||
|
## func NewUserNotFound
|
||||||
|
``` go
|
||||||
|
func NewUserNotFound(err error, msg string) error
|
||||||
|
```
|
||||||
|
NewUserNotFound returns an error which wraps err and satisfies
|
||||||
|
IsUserNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotAssignedf
|
||||||
|
``` go
|
||||||
|
func NotAssignedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotAssignedf returns an error which satisfies IsNotAssigned().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotFoundf
|
||||||
|
``` go
|
||||||
|
func NotFoundf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotFoundf returns an error which satisfies IsNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotImplementedf
|
||||||
|
``` go
|
||||||
|
func NotImplementedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotImplementedf returns an error which satisfies IsNotImplemented().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotProvisionedf
|
||||||
|
``` go
|
||||||
|
func NotProvisionedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotProvisionedf returns an error which satisfies IsNotProvisioned().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotSupportedf
|
||||||
|
``` go
|
||||||
|
func NotSupportedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotSupportedf returns an error which satisfies IsNotSupported().
|
||||||
|
|
||||||
|
|
||||||
|
## func NotValidf
|
||||||
|
``` go
|
||||||
|
func NotValidf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
NotValidf returns an error which satisfies IsNotValid().
|
||||||
|
|
||||||
|
|
||||||
|
## func Trace
|
||||||
|
``` go
|
||||||
|
func Trace(other error) error
|
||||||
|
```
|
||||||
|
Trace adds the location of the Trace call to the stack. The Cause of the
|
||||||
|
resulting error is the same as the error parameter. If the other error is
|
||||||
|
nil, the result will be nil.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func Unauthorizedf
|
||||||
|
``` go
|
||||||
|
func Unauthorizedf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Unauthorizedf returns an error which satisfies IsUnauthorized().
|
||||||
|
|
||||||
|
|
||||||
|
## func UserNotFoundf
|
||||||
|
``` go
|
||||||
|
func UserNotFoundf(format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
UserNotFoundf returns an error which satisfies IsUserNotFound().
|
||||||
|
|
||||||
|
|
||||||
|
## func Wrap
|
||||||
|
``` go
|
||||||
|
func Wrap(other, newDescriptive error) error
|
||||||
|
```
|
||||||
|
Wrap changes the Cause of the error. The location of the Wrap call is also
|
||||||
|
stored in the error stack.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
newErr := &packageError{"more context", private_value}
|
||||||
|
return errors.Wrap(err, newErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## func Wrapf
|
||||||
|
``` go
|
||||||
|
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error
|
||||||
|
```
|
||||||
|
Wrapf changes the Cause of the error, and adds an annotation. The location
|
||||||
|
of the Wrap call is also stored in the error stack.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## type Err
|
||||||
|
``` go
|
||||||
|
type Err struct {
|
||||||
|
// contains filtered or unexported fields
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Err holds a description of an error along with information about
|
||||||
|
where the error was created.
|
||||||
|
|
||||||
|
It may be embedded in custom error types to add extra information that
|
||||||
|
this errors package can understand.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func NewErr
|
||||||
|
``` go
|
||||||
|
func NewErr(format string, args ...interface{}) Err
|
||||||
|
```
|
||||||
|
NewErr is used to return an Err for the purpose of embedding in other
|
||||||
|
structures. The location is not specified, and needs to be set with a call
|
||||||
|
to SetLocation.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
type FooError struct {
|
||||||
|
errors.Err
|
||||||
|
code int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFooError(code int) error {
|
||||||
|
err := &FooError{errors.NewErr("foo"), code}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### func NewErrWithCause
|
||||||
|
``` go
|
||||||
|
func NewErrWithCause(other error, format string, args ...interface{}) Err
|
||||||
|
```
|
||||||
|
NewErrWithCause is used to return an Err with cause by other error for the purpose of embedding in other
|
||||||
|
structures. The location is not specified, and needs to be set with a call
|
||||||
|
to SetLocation.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
|
||||||
|
type FooError struct {
|
||||||
|
errors.Err
|
||||||
|
code int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *FooError) Annotate(format string, args ...interface{}) error {
|
||||||
|
err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Cause
|
||||||
|
``` go
|
||||||
|
func (e *Err) Cause() error
|
||||||
|
```
|
||||||
|
The Cause of an error is the most recent error in the error stack that
|
||||||
|
meets one of these criteria: the original error that was raised; the new
|
||||||
|
error that was passed into the Wrap function; the most recently masked
|
||||||
|
error; or nil if the error itself is considered the Cause. Normally this
|
||||||
|
method is not invoked directly, but instead through the Cause stand alone
|
||||||
|
function.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Error
|
||||||
|
``` go
|
||||||
|
func (e *Err) Error() string
|
||||||
|
```
|
||||||
|
Error implements error.Error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Format
|
||||||
|
``` go
|
||||||
|
func (e *Err) Format(s fmt.State, verb rune)
|
||||||
|
```
|
||||||
|
Format implements fmt.Formatter
|
||||||
|
When printing errors with %+v it also prints the stack trace.
|
||||||
|
%#v unsurprisingly will print the real underlying type.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Location
|
||||||
|
``` go
|
||||||
|
func (e *Err) Location() (filename string, line int)
|
||||||
|
```
|
||||||
|
Location is the file and line of where the error was most recently
|
||||||
|
created or annotated.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Message
|
||||||
|
``` go
|
||||||
|
func (e *Err) Message() string
|
||||||
|
```
|
||||||
|
Message returns the message stored with the most recent location. This is
|
||||||
|
the empty string if the most recent call was Trace, or the message stored
|
||||||
|
with Annotate or Mask.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) SetLocation
|
||||||
|
``` go
|
||||||
|
func (e *Err) SetLocation(callDepth int)
|
||||||
|
```
|
||||||
|
SetLocation records the source location of the error at callDepth stack
|
||||||
|
frames above the call.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) StackTrace
|
||||||
|
``` go
|
||||||
|
func (e *Err) StackTrace() []string
|
||||||
|
```
|
||||||
|
StackTrace returns one string for each location recorded in the stack of
|
||||||
|
errors. The first value is the originating error, with a line for each
|
||||||
|
other annotation or tracing of the error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*Err) Underlying
|
||||||
|
``` go
|
||||||
|
func (e *Err) Underlying() error
|
||||||
|
```
|
||||||
|
Underlying returns the previous error in the error stack, if any. A client
|
||||||
|
should not ever really call this method. It is used to build the error
|
||||||
|
stack and should not be introspected by client calls. Or more
|
||||||
|
specifically, clients should not depend on anything but the `Cause` of an
|
||||||
|
error.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- - -
|
||||||
|
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
||||||
79
vendor/github.com/juju/errors/doc.go
generated
vendored
Normal file
79
vendor/github.com/juju/errors/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright 2013, 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package errors provides an easy way to annotate errors without losing the
|
||||||
|
original error context.
|
||||||
|
|
||||||
|
The exported `New` and `Errorf` functions are designed to replace the
|
||||||
|
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
|
||||||
|
error is there, but the package also records the location at which the error
|
||||||
|
was created.
|
||||||
|
|
||||||
|
A primary use case for this library is to add extra context any time an
|
||||||
|
error is returned from a function.
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
This instead becomes:
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
which just records the file and line number of the Trace call, or
|
||||||
|
|
||||||
|
if err := SomeFunc(); err != nil {
|
||||||
|
return errors.Annotate(err, "more context")
|
||||||
|
}
|
||||||
|
|
||||||
|
which also adds an annotation to the error.
|
||||||
|
|
||||||
|
When you want to check to see if an error is of a particular type, a helper
|
||||||
|
function is normally exported by the package that returned the error, like the
|
||||||
|
`os` package does. The underlying cause of the error is available using the
|
||||||
|
`Cause` function.
|
||||||
|
|
||||||
|
os.IsNotExist(errors.Cause(err))
|
||||||
|
|
||||||
|
The result of the `Error()` call on an annotated error is the annotations joined
|
||||||
|
with colons, then the result of the `Error()` method for the underlying error
|
||||||
|
that was the cause.
|
||||||
|
|
||||||
|
err := errors.Errorf("original")
|
||||||
|
err = errors.Annotatef(err, "context")
|
||||||
|
err = errors.Annotatef(err, "more context")
|
||||||
|
err.Error() -> "more context: context: original"
|
||||||
|
|
||||||
|
Obviously recording the file, line and functions is not very useful if you
|
||||||
|
cannot get them back out again.
|
||||||
|
|
||||||
|
errors.ErrorStack(err)
|
||||||
|
|
||||||
|
will return something like:
|
||||||
|
|
||||||
|
first error
|
||||||
|
github.com/juju/errors/annotation_test.go:193:
|
||||||
|
github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
github.com/juju/errors/annotation_test.go:195:
|
||||||
|
github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
github.com/juju/errors/annotation_test.go:197:
|
||||||
|
|
||||||
|
The first error was generated by an external system, so there was no location
|
||||||
|
associated. The second, fourth, and last lines were generated with Trace calls,
|
||||||
|
and the other two through Annotate.
|
||||||
|
|
||||||
|
Sometimes when responding to an error you want to return a more specific error
|
||||||
|
for the situation.
|
||||||
|
|
||||||
|
if err := FindField(field); err != nil {
|
||||||
|
return errors.Wrap(err, errors.NotFoundf(field))
|
||||||
|
}
|
||||||
|
|
||||||
|
This returns an error where the complete error stack is still available, and
|
||||||
|
`errors.Cause()` will return the `NotFound` error.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package errors
|
||||||
227
vendor/github.com/juju/errors/error.go
generated
vendored
Normal file
227
vendor/github.com/juju/errors/error.go
generated
vendored
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Err holds a description of an error along with information about
|
||||||
|
// where the error was created.
|
||||||
|
//
|
||||||
|
// It may be embedded in custom error types to add extra information that
|
||||||
|
// this errors package can understand.
|
||||||
|
type Err struct {
|
||||||
|
// message holds an annotation of the error.
|
||||||
|
message string
|
||||||
|
|
||||||
|
// cause holds the cause of the error as returned
|
||||||
|
// by the Cause method.
|
||||||
|
cause error
|
||||||
|
|
||||||
|
// previous holds the previous error in the error stack, if any.
|
||||||
|
previous error
|
||||||
|
|
||||||
|
// function is the package path-qualified function name where the
|
||||||
|
// error was created.
|
||||||
|
function string
|
||||||
|
|
||||||
|
// line is the line number the error was created on inside of function
|
||||||
|
line int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locationer is an interface that represents a certain class of errors that
|
||||||
|
// contain the location information from where they were raised.
|
||||||
|
type Locationer interface {
|
||||||
|
// Location returns the path-qualified function name where the error was
|
||||||
|
// created and the line number
|
||||||
|
Location() (function string, line int)
|
||||||
|
}
|
||||||
|
|
||||||
|
// locationError is the internal implementation of the Locationer interface.
|
||||||
|
type locationError struct {
|
||||||
|
error
|
||||||
|
|
||||||
|
// function is the package path-qualified function name where the
|
||||||
|
// error was created.
|
||||||
|
function string
|
||||||
|
|
||||||
|
// line is the line number the error was created on inside of function
|
||||||
|
line int
|
||||||
|
}
|
||||||
|
|
||||||
|
// newLocationError constructs a new Locationer error from the supplied error
|
||||||
|
// with the location set to callDepth in the stack. If a nill error is provided
|
||||||
|
// to this function then a new empty error is constructed.
|
||||||
|
func newLocationError(err error, callDepth int) *locationError {
|
||||||
|
le := &locationError{error: err}
|
||||||
|
le.function, le.line = getLocation(callDepth + 1)
|
||||||
|
return le
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implementes the error interface.
|
||||||
|
func (l *locationError) Error() string {
|
||||||
|
if l.error == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return l.error.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// *locationError implements Locationer.Location interface
|
||||||
|
func (l *locationError) Location() (string, int) {
|
||||||
|
return l.function, l.line
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *locationError) Unwrap() error {
|
||||||
|
return l.error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewErr is used to return an Err for the purpose of embedding in other
|
||||||
|
// structures. The location is not specified, and needs to be set with a call
|
||||||
|
// to SetLocation.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// type FooError struct {
|
||||||
|
// errors.Err
|
||||||
|
// code int
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func NewFooError(code int) error {
|
||||||
|
// err := &FooError{errors.NewErr("foo"), code}
|
||||||
|
// err.SetLocation(1)
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
func NewErr(format string, args ...interface{}) Err {
|
||||||
|
return Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewErrWithCause is used to return an Err with cause by other error for the purpose of embedding in other
|
||||||
|
// structures. The location is not specified, and needs to be set with a call
|
||||||
|
// to SetLocation.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// type FooError struct {
|
||||||
|
// errors.Err
|
||||||
|
// code int
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (e *FooError) Annotate(format string, args ...interface{}) error {
|
||||||
|
// err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
|
||||||
|
// err.SetLocation(1)
|
||||||
|
// return err
|
||||||
|
// })
|
||||||
|
func NewErrWithCause(other error, format string, args ...interface{}) Err {
|
||||||
|
return Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
cause: Cause(other),
|
||||||
|
previous: other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Location returns the package path-qualified function name and line of where
|
||||||
|
// the error was most recently created or annotated.
|
||||||
|
func (e *Err) Location() (function string, line int) {
|
||||||
|
return e.function, e.line
|
||||||
|
}
|
||||||
|
|
||||||
|
// Underlying returns the previous error in the error stack, if any. A client
|
||||||
|
// should not ever really call this method. It is used to build the error
|
||||||
|
// stack and should not be introspected by client calls. Or more
|
||||||
|
// specifically, clients should not depend on anything but the `Cause` of an
|
||||||
|
// error.
|
||||||
|
func (e *Err) Underlying() error {
|
||||||
|
return e.previous
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cause returns the most recent error in the error stack that
|
||||||
|
// meets one of these criteria: the original error that was raised; the new
|
||||||
|
// error that was passed into the Wrap function; the most recently masked
|
||||||
|
// error; or nil if the error itself is considered the Cause. Normally this
|
||||||
|
// method is not invoked directly, but instead through the Cause stand alone
|
||||||
|
// function.
|
||||||
|
func (e *Err) Cause() error {
|
||||||
|
return e.cause
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message returns the message stored with the most recent location. This is
|
||||||
|
// the empty string if the most recent call was Trace, or the message stored
|
||||||
|
// with Annotate or Mask.
|
||||||
|
func (e *Err) Message() string {
|
||||||
|
return e.message
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements error.Error.
|
||||||
|
func (e *Err) Error() string {
|
||||||
|
// We want to walk up the stack of errors showing the annotations
|
||||||
|
// as long as the cause is the same.
|
||||||
|
err := e.previous
|
||||||
|
if !sameError(Cause(err), e.cause) && e.cause != nil {
|
||||||
|
err = e.cause
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
return e.message
|
||||||
|
case e.message == "":
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s: %v", e.message, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format implements fmt.Formatter
|
||||||
|
// When printing errors with %+v it also prints the stack trace.
|
||||||
|
// %#v unsurprisingly will print the real underlying type.
|
||||||
|
func (e *Err) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
switch {
|
||||||
|
case s.Flag('+'):
|
||||||
|
fmt.Fprintf(s, "%s", ErrorStack(e))
|
||||||
|
return
|
||||||
|
case s.Flag('#'):
|
||||||
|
// avoid infinite recursion by wrapping e into a type
|
||||||
|
// that doesn't implement Formatter.
|
||||||
|
fmt.Fprintf(s, "%#v", (*unformatter)(e))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case 's':
|
||||||
|
fmt.Fprintf(s, "%s", e.Error())
|
||||||
|
case 'q':
|
||||||
|
fmt.Fprintf(s, "%q", e.Error())
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(s, "%%!%c(%T=%s)", verb, e, e.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper for Format
|
||||||
|
type unformatter Err
|
||||||
|
|
||||||
|
func (unformatter) Format() { /* break the fmt.Formatter interface */ }
|
||||||
|
|
||||||
|
// SetLocation records the package path-qualified function name of the error at
|
||||||
|
// callDepth stack frames above the call.
|
||||||
|
func (e *Err) SetLocation(callDepth int) {
|
||||||
|
e.function, e.line = getLocation(callDepth + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StackTrace returns one string for each location recorded in the stack of
|
||||||
|
// errors. The first value is the originating error, with a line for each
|
||||||
|
// other annotation or tracing of the error.
|
||||||
|
func (e *Err) StackTrace() []string {
|
||||||
|
return errorStack(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ideally we'd have a way to check identity, but deep equals will do.
|
||||||
|
func sameError(e1, e2 error) bool {
|
||||||
|
return reflect.DeepEqual(e1, e2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap is a synonym for Underlying, which allows Err to be used with the
|
||||||
|
// Unwrap, Is and As functions in Go's standard `errors` library.
|
||||||
|
func (e *Err) Unwrap() error {
|
||||||
|
return e.previous
|
||||||
|
}
|
||||||
463
vendor/github.com/juju/errors/errortypes.go
generated
vendored
Normal file
463
vendor/github.com/juju/errors/errortypes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,463 @@
|
||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
stderror "errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// a ConstError is a prototype for a certain type of error
|
||||||
|
type ConstError string
|
||||||
|
|
||||||
|
// ConstError implements error
|
||||||
|
func (e ConstError) Error() string {
|
||||||
|
return string(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different types of errors
|
||||||
|
const (
|
||||||
|
// Timeout represents an error on timeout.
|
||||||
|
Timeout = ConstError("timeout")
|
||||||
|
// NotFound represents an error when something has not been found.
|
||||||
|
NotFound = ConstError("not found")
|
||||||
|
// UserNotFound represents an error when a non-existent user is looked up.
|
||||||
|
UserNotFound = ConstError("user not found")
|
||||||
|
// Unauthorized represents an error when an operation is unauthorized.
|
||||||
|
Unauthorized = ConstError("unauthorized")
|
||||||
|
// NotImplemented represents an error when something is not
|
||||||
|
// implemented.
|
||||||
|
NotImplemented = ConstError("not implemented")
|
||||||
|
// AlreadyExists represents and error when something already exists.
|
||||||
|
AlreadyExists = ConstError("already exists")
|
||||||
|
// NotSupported represents an error when something is not supported.
|
||||||
|
NotSupported = ConstError("not supported")
|
||||||
|
// NotValid represents an error when something is not valid.
|
||||||
|
NotValid = ConstError("not valid")
|
||||||
|
// NotProvisioned represents an error when something is not yet provisioned.
|
||||||
|
NotProvisioned = ConstError("not provisioned")
|
||||||
|
// NotAssigned represents an error when something is not yet assigned to
|
||||||
|
// something else.
|
||||||
|
NotAssigned = ConstError("not assigned")
|
||||||
|
// BadRequest represents an error when a request has bad parameters.
|
||||||
|
BadRequest = ConstError("bad request")
|
||||||
|
// MethodNotAllowed represents an error when an HTTP request
|
||||||
|
// is made with an inappropriate method.
|
||||||
|
MethodNotAllowed = ConstError("method not allowed")
|
||||||
|
// Forbidden represents an error when a request cannot be completed because of
|
||||||
|
// missing privileges.
|
||||||
|
Forbidden = ConstError("forbidden")
|
||||||
|
// QuotaLimitExceeded is emitted when an action failed due to a quota limit check.
|
||||||
|
QuotaLimitExceeded = ConstError("quota limit exceeded")
|
||||||
|
// NotYetAvailable is the error returned when a resource is not yet available
|
||||||
|
// but it might be in the future.
|
||||||
|
NotYetAvailable = ConstError("not yet available")
|
||||||
|
)
|
||||||
|
|
||||||
|
// constSuppressor is a small type wrapper for ConstError to surpress the error
|
||||||
|
// value from returning an error value. This allows us to maintain backwards
|
||||||
|
// compatibility.
|
||||||
|
type constSuppressor ConstError
|
||||||
|
|
||||||
|
func (c constSuppressor) Error() string { return "" }
|
||||||
|
|
||||||
|
func (c constSuppressor) Unwrap() error { return ConstError(c) }
|
||||||
|
|
||||||
|
// errWithType is an Err bundled with its error type (a ConstError)
|
||||||
|
type errWithType struct {
|
||||||
|
error
|
||||||
|
errType ConstError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is compares `target` with e's error type
|
||||||
|
func (e *errWithType) Is(target error) bool {
|
||||||
|
if &e.errType == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return target == e.errType
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap an errWithType gives the underlying Err
|
||||||
|
func (e *errWithType) Unwrap() error {
|
||||||
|
return e.error
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapErrorWithMsg(err error, msg string) error {
|
||||||
|
if err == nil {
|
||||||
|
return stderror.New(msg)
|
||||||
|
}
|
||||||
|
if msg == "" {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s: %w", msg, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeWrappedConstError(err error, format string, args ...interface{}) error {
|
||||||
|
separator := " "
|
||||||
|
if err.Error() == "" {
|
||||||
|
separator = ""
|
||||||
|
}
|
||||||
|
return fmt.Errorf(strings.Join([]string{format, "%w"}, separator), append(args, err)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timeoutf returns an error which satisfies Is(err, Timeout) and the Locationer
|
||||||
|
// interface.
|
||||||
|
func Timeoutf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(Timeout, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTimeout returns an error which wraps err and satisfies Is(err, Timeout)
|
||||||
|
// and the Locationer interface.
|
||||||
|
func NewTimeout(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: Timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsTimeout reports whether err is a Timeout error. Use
|
||||||
|
// Is(err, Timeout).
|
||||||
|
func IsTimeout(err error) bool {
|
||||||
|
return Is(err, Timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotFoundf returns an error which satisfies Is(err, NotFound) and the
|
||||||
|
// Locationer interface.
|
||||||
|
func NotFoundf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(NotFound, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotFound returns an error which wraps err and satisfies Is(err, NotFound)
|
||||||
|
// and the Locationer interface.
|
||||||
|
func NewNotFound(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: NotFound,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsNotFound reports whether err is a NotFound error. Use
|
||||||
|
// Is(err, NotFound).
|
||||||
|
func IsNotFound(err error) bool {
|
||||||
|
return Is(err, NotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserNotFoundf returns an error which satisfies Is(err, UserNotFound) and the
|
||||||
|
// Locationer interface.
|
||||||
|
func UserNotFoundf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(UserNotFound, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUserNotFound returns an error which wraps err and satisfies
|
||||||
|
// Is(err, UserNotFound) and the Locationer interface.
|
||||||
|
func NewUserNotFound(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: UserNotFound,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsUserNotFound reports whether err is a UserNotFound error. Use
|
||||||
|
// Is(err, UserNotFound).
|
||||||
|
func IsUserNotFound(err error) bool {
|
||||||
|
return Is(err, UserNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unauthorizedf returns an error that satisfies Is(err, Unauthorized) and
|
||||||
|
// the Locationer interface.
|
||||||
|
func Unauthorizedf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(constSuppressor(Unauthorized), format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUnauthorized returns an error which wraps err and satisfies
|
||||||
|
// Is(err, Unathorized) and the Locationer interface.
|
||||||
|
func NewUnauthorized(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: Unauthorized,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsUnauthorized reports whether err is a Unauthorized error. Use
|
||||||
|
// Is(err, Unauthorized).
|
||||||
|
func IsUnauthorized(err error) bool {
|
||||||
|
return Is(err, Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotImplementedf returns an error which satisfies Is(err, NotImplemented) and
|
||||||
|
// the Locationer interface.
|
||||||
|
func NotImplementedf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(NotImplemented, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotImplemented returns an error which wraps err and satisfies
|
||||||
|
// Is(err, NotImplemented) and the Locationer interface.
|
||||||
|
func NewNotImplemented(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: NotImplemented,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsNotImplemented reports whether err is a NotImplemented error.
|
||||||
|
// Use Is(err, NotImplemented).
|
||||||
|
func IsNotImplemented(err error) bool {
|
||||||
|
return Is(err, NotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlreadyExistsf returns an error which satisfies Is(err, AlreadyExists) and
|
||||||
|
// the Locationer interface.
|
||||||
|
func AlreadyExistsf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(AlreadyExists, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAlreadyExists returns an error which wraps err and satisfies
|
||||||
|
// Is(err, AlreadyExists) and the Locationer interface.
|
||||||
|
func NewAlreadyExists(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: AlreadyExists,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsAlreadyExists reports whether the err is a AlreadyExists
|
||||||
|
// error. Use Is(err, AlreadyExists).
|
||||||
|
func IsAlreadyExists(err error) bool {
|
||||||
|
return Is(err, AlreadyExists)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotSupportedf returns an error which satisfies Is(err, NotSupported) and the
|
||||||
|
// Locationer interface.
|
||||||
|
func NotSupportedf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(NotSupported, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotSupported returns an error which satisfies Is(err, NotSupported) and
|
||||||
|
// the Locationer interface.
|
||||||
|
func NewNotSupported(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: NotSupported,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsNotSupported reports whether err is a NotSupported error. Use
|
||||||
|
// Is(err, NotSupported).
|
||||||
|
func IsNotSupported(err error) bool {
|
||||||
|
return Is(err, NotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotValidf returns an error which satisfies Is(err, NotValid) and the
|
||||||
|
// Locationer interface.
|
||||||
|
func NotValidf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(NotValid, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotValid returns an error which wraps err and satisfies Is(err, NotValid)
|
||||||
|
// and the Locationer interface.
|
||||||
|
func NewNotValid(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: NotValid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsNotValid reports whether err is a NotValid error. Use
|
||||||
|
// Is(err, NotValid).
|
||||||
|
func IsNotValid(err error) bool {
|
||||||
|
return Is(err, NotValid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotProvisionedf returns an error which satisfies Is(err, NotProvisioned) and
|
||||||
|
// the Locationer interface.
|
||||||
|
func NotProvisionedf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(NotProvisioned, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotProvisioned returns an error which wraps err and satisfies
|
||||||
|
// Is(err, NotProvisioned) and the Locationer interface.
|
||||||
|
func NewNotProvisioned(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: NotProvisioned,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsNotProvisioned reports whether err is a NotProvisioned error.
|
||||||
|
// Use Is(err, NotProvisioned).
|
||||||
|
func IsNotProvisioned(err error) bool {
|
||||||
|
return Is(err, NotProvisioned)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotAssignedf returns an error which satisfies Is(err, NotAssigned) and the
|
||||||
|
// Locationer interface.
|
||||||
|
func NotAssignedf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(NotAssigned, format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotAssigned returns an error which wraps err and satisfies
|
||||||
|
// Is(err, NotAssigned) and the Locationer interface.
|
||||||
|
func NewNotAssigned(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: NotAssigned,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsNotAssigned reports whether err is a NotAssigned error.
|
||||||
|
// Use Is(err, NotAssigned)
|
||||||
|
func IsNotAssigned(err error) bool {
|
||||||
|
return Is(err, NotAssigned)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BadRequestf returns an error which satisfies Is(err, BadRequest) and the
|
||||||
|
// Locationer interface.
|
||||||
|
func BadRequestf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(constSuppressor(BadRequest), format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBadRequest returns an error which wraps err and satisfies
|
||||||
|
// Is(err, BadRequest) and the Locationer interface.
|
||||||
|
func NewBadRequest(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: BadRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsBadRequest reports whether err is a BadRequest error.
|
||||||
|
// Use Is(err, BadRequest)
|
||||||
|
func IsBadRequest(err error) bool {
|
||||||
|
return Is(err, BadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodNotAllowedf returns an error which satisfies Is(err, MethodNotAllowed)
|
||||||
|
// and the Locationer interface.
|
||||||
|
func MethodNotAllowedf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(constSuppressor(MethodNotAllowed), format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMethodNotAllowed returns an error which wraps err and satisfies
|
||||||
|
// Is(err, MethodNotAllowed) and the Locationer interface.
|
||||||
|
func NewMethodNotAllowed(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: MethodNotAllowed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsMethodNotAllowed reports whether err is a MethodNotAllowed
|
||||||
|
// error. Use Is(err, MethodNotAllowed)
|
||||||
|
func IsMethodNotAllowed(err error) bool {
|
||||||
|
return Is(err, MethodNotAllowed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forbiddenf returns an error which satistifes Is(err, Forbidden) and the
|
||||||
|
// Locationer interface.
|
||||||
|
func Forbiddenf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(constSuppressor(Forbidden), format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForbidden returns an error which wraps err and satisfies
|
||||||
|
// Is(err, Forbidden) and the Locationer interface.
|
||||||
|
func NewForbidden(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: Forbidden,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsForbidden reports whether err is a Forbidden error. Use
|
||||||
|
// Is(err, Forbidden).
|
||||||
|
func IsForbidden(err error) bool {
|
||||||
|
return Is(err, Forbidden)
|
||||||
|
}
|
||||||
|
|
||||||
|
// QuotaLimitExceededf returns an error which satisfies
|
||||||
|
// Is(err, QuotaLimitExceeded) and the Locationer interface.
|
||||||
|
func QuotaLimitExceededf(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(constSuppressor(QuotaLimitExceeded), format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewQuotaLimitExceeded returns an error which wraps err and satisfies
|
||||||
|
// Is(err, QuotaLimitExceeded) and the Locationer interface.
|
||||||
|
func NewQuotaLimitExceeded(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: QuotaLimitExceeded,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsQuotaLimitExceeded reports whether err is a QuoteLimitExceeded
|
||||||
|
// err. Use Is(err, QuotaLimitExceeded).
|
||||||
|
func IsQuotaLimitExceeded(err error) bool {
|
||||||
|
return Is(err, QuotaLimitExceeded)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotYetAvailablef returns an error which satisfies Is(err, NotYetAvailable)
|
||||||
|
// and the Locationer interface.
|
||||||
|
func NotYetAvailablef(format string, args ...interface{}) error {
|
||||||
|
return newLocationError(
|
||||||
|
makeWrappedConstError(constSuppressor(NotYetAvailable), format, args...),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotYetAvailable returns an error which wraps err and satisfies
|
||||||
|
// Is(err, NotYetAvailable) and the Locationer interface.
|
||||||
|
func NewNotYetAvailable(err error, msg string) error {
|
||||||
|
return &errWithType{
|
||||||
|
error: newLocationError(wrapErrorWithMsg(err, msg), 1),
|
||||||
|
errType: NotYetAvailable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: IsNotYetAvailable reports whether err is a NotYetAvailable err.
|
||||||
|
// Use Is(err, NotYetAvailable)
|
||||||
|
func IsNotYetAvailable(err error) bool {
|
||||||
|
return Is(err, NotYetAvailable)
|
||||||
|
}
|
||||||
357
vendor/github.com/juju/errors/functions.go
generated
vendored
Normal file
357
vendor/github.com/juju/errors/functions.go
generated
vendored
Normal file
|
|
@ -0,0 +1,357 @@
|
||||||
|
// Copyright 2014 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
stderrors "errors"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New is a drop in replacement for the standard library errors module that records
|
||||||
|
// the location that the error is created.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// return errors.New("validation failed")
|
||||||
|
//
|
||||||
|
func New(message string) error {
|
||||||
|
err := &Err{message: message}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf creates a new annotated error and records the location that the
|
||||||
|
// error is created. This should be a drop in replacement for fmt.Errorf.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// return errors.Errorf("validation failed: %s", message)
|
||||||
|
//
|
||||||
|
func Errorf(format string, args ...interface{}) error {
|
||||||
|
err := &Err{message: fmt.Sprintf(format, args...)}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// getLocation records the package path-qualified function name of the error at
|
||||||
|
// callDepth stack frames above the call.
|
||||||
|
func getLocation(callDepth int) (string, int) {
|
||||||
|
rpc := make([]uintptr, 1)
|
||||||
|
n := runtime.Callers(callDepth+2, rpc[:])
|
||||||
|
if n < 1 {
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
frame, _ := runtime.CallersFrames(rpc).Next()
|
||||||
|
return frame.Function, frame.Line
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trace adds the location of the Trace call to the stack. The Cause of the
|
||||||
|
// resulting error is the same as the error parameter. If the other error is
|
||||||
|
// nil, the result will be nil.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Trace(err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Trace(other error) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{previous: other, cause: Cause(other)}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotate is used to add extra context to an existing error. The location of
|
||||||
|
// the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
// function are also recorded.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Annotate(err, "failed to frombulate")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Annotate(other error, message string) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
cause: Cause(other),
|
||||||
|
message: message,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annotatef is used to add extra context to an existing error. The location of
|
||||||
|
// the Annotate call is recorded with the annotations. The file, line and
|
||||||
|
// function are also recorded.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Annotatef(err, "failed to frombulate the %s", arg)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Annotatef(other error, format string, args ...interface{}) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
cause: Cause(other),
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeferredAnnotatef annotates the given error (when it is not nil) with the given
|
||||||
|
// format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
|
||||||
|
// does nothing. This method is used in a defer statement in order to annotate any
|
||||||
|
// resulting error with the same message.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
|
||||||
|
//
|
||||||
|
func DeferredAnnotatef(err *error, format string, args ...interface{}) {
|
||||||
|
if *err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newErr := &Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
cause: Cause(*err),
|
||||||
|
previous: *err,
|
||||||
|
}
|
||||||
|
newErr.SetLocation(1)
|
||||||
|
*err = newErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap changes the Cause of the error. The location of the Wrap call is also
|
||||||
|
// stored in the error stack.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// newErr := &packageError{"more context", private_value}
|
||||||
|
// return errors.Wrap(err, newErr)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Wrap(other, newDescriptive error) error {
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
cause: newDescriptive,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapf changes the Cause of the error, and adds an annotation. The location
|
||||||
|
// of the Wrap call is also stored in the error stack.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// if err := SomeFunc(); err != nil {
|
||||||
|
// return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error {
|
||||||
|
err := &Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
previous: other,
|
||||||
|
cause: newDescriptive,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maskf masks the given error with the given format string and arguments (like
|
||||||
|
// fmt.Sprintf), returning a new error that maintains the error stack, but
|
||||||
|
// hides the underlying error type. The error string still contains the full
|
||||||
|
// annotations. If you want to hide the annotations, call Wrap.
|
||||||
|
func Maskf(other error, format string, args ...interface{}) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
message: fmt.Sprintf(format, args...),
|
||||||
|
previous: other,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask hides the underlying error type, and records the location of the masking.
|
||||||
|
func Mask(other error) error {
|
||||||
|
if other == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := &Err{
|
||||||
|
previous: other,
|
||||||
|
}
|
||||||
|
err.SetLocation(1)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cause returns the cause of the given error. This will be either the
|
||||||
|
// original error, or the result of a Wrap or Mask call.
|
||||||
|
//
|
||||||
|
// Cause is the usual way to diagnose errors that may have been wrapped by
|
||||||
|
// the other errors functions.
|
||||||
|
func Cause(err error) error {
|
||||||
|
var diag error
|
||||||
|
if err, ok := err.(causer); ok {
|
||||||
|
diag = err.Cause()
|
||||||
|
}
|
||||||
|
if diag != nil {
|
||||||
|
return diag
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type causer interface {
|
||||||
|
Cause() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type wrapper interface {
|
||||||
|
// Message returns the top level error message,
|
||||||
|
// not including the message from the Previous
|
||||||
|
// error.
|
||||||
|
Message() string
|
||||||
|
|
||||||
|
// Underlying returns the Previous error, or nil
|
||||||
|
// if there is none.
|
||||||
|
Underlying() error
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ wrapper = (*Err)(nil)
|
||||||
|
_ Locationer = (*Err)(nil)
|
||||||
|
_ causer = (*Err)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Details returns information about the stack of errors wrapped by err, in
|
||||||
|
// the format:
|
||||||
|
//
|
||||||
|
// [{filename:99: error one} {otherfile:55: cause of error one}]
|
||||||
|
//
|
||||||
|
// This is a terse alternative to ErrorStack as it returns a single line.
|
||||||
|
func Details(err error) string {
|
||||||
|
if err == nil {
|
||||||
|
return "[]"
|
||||||
|
}
|
||||||
|
var s []byte
|
||||||
|
s = append(s, '[')
|
||||||
|
for {
|
||||||
|
s = append(s, '{')
|
||||||
|
if err, ok := err.(Locationer); ok {
|
||||||
|
file, line := err.Location()
|
||||||
|
if file != "" {
|
||||||
|
s = append(s, fmt.Sprintf("%s:%d", file, line)...)
|
||||||
|
s = append(s, ": "...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cerr, ok := err.(wrapper); ok {
|
||||||
|
s = append(s, cerr.Message()...)
|
||||||
|
err = cerr.Underlying()
|
||||||
|
} else {
|
||||||
|
s = append(s, err.Error()...)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
s = append(s, '}')
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s = append(s, ' ')
|
||||||
|
}
|
||||||
|
s = append(s, ']')
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorStack returns a string representation of the annotated error. If the
|
||||||
|
// error passed as the parameter is not an annotated error, the result is
|
||||||
|
// simply the result of the Error() method on that error.
|
||||||
|
//
|
||||||
|
// If the error is an annotated error, a multi-line string is returned where
|
||||||
|
// each line represents one entry in the annotation stack. The full filename
|
||||||
|
// from the call stack is used in the output.
|
||||||
|
//
|
||||||
|
// first error
|
||||||
|
// github.com/juju/errors/annotation_test.go:193:
|
||||||
|
// github.com/juju/errors/annotation_test.go:194: annotation
|
||||||
|
// github.com/juju/errors/annotation_test.go:195:
|
||||||
|
// github.com/juju/errors/annotation_test.go:196: more context
|
||||||
|
// github.com/juju/errors/annotation_test.go:197:
|
||||||
|
func ErrorStack(err error) string {
|
||||||
|
return strings.Join(errorStack(err), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorStack(err error) []string {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want the first error first
|
||||||
|
var lines []string
|
||||||
|
for {
|
||||||
|
var buff []byte
|
||||||
|
if err, ok := err.(Locationer); ok {
|
||||||
|
file, line := err.Location()
|
||||||
|
// Strip off the leading GOPATH/src path elements.
|
||||||
|
if file != "" {
|
||||||
|
buff = append(buff, fmt.Sprintf("%s:%d", file, line)...)
|
||||||
|
buff = append(buff, ": "...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cerr, ok := err.(wrapper); ok {
|
||||||
|
message := cerr.Message()
|
||||||
|
buff = append(buff, message...)
|
||||||
|
// If there is a cause for this error, and it is different to the cause
|
||||||
|
// of the underlying error, then output the error string in the stack trace.
|
||||||
|
var cause error
|
||||||
|
if err1, ok := err.(causer); ok {
|
||||||
|
cause = err1.Cause()
|
||||||
|
}
|
||||||
|
err = cerr.Underlying()
|
||||||
|
if cause != nil && !sameError(Cause(err), cause) {
|
||||||
|
if message != "" {
|
||||||
|
buff = append(buff, ": "...)
|
||||||
|
}
|
||||||
|
buff = append(buff, cause.Error()...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buff = append(buff, err.Error()...)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
lines = append(lines, string(buff))
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// reverse the lines to get the original error, which was at the end of
|
||||||
|
// the list, back to the start.
|
||||||
|
var result []string
|
||||||
|
for i := len(lines); i > 0; i-- {
|
||||||
|
result = append(result, lines[i-1])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unwrap is a proxy for the Unwrap function in Go's standard `errors` library
|
||||||
|
// (pkg.go.dev/errors).
|
||||||
|
func Unwrap(err error) error {
|
||||||
|
return stderrors.Unwrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is is a proxy for the Is function in Go's standard `errors` library
|
||||||
|
// (pkg.go.dev/errors).
|
||||||
|
func Is(err, target error) bool {
|
||||||
|
return stderrors.Is(err, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// As is a proxy for the As function in Go's standard `errors` library
|
||||||
|
// (pkg.go.dev/errors).
|
||||||
|
func As(err error, target interface{}) bool {
|
||||||
|
return stderrors.As(err, target)
|
||||||
|
}
|
||||||
1
vendor/github.com/juju/retry/.gitignore
generated
vendored
Normal file
1
vendor/github.com/juju/retry/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*.test
|
||||||
191
vendor/github.com/juju/retry/LICENSE
generated
vendored
Normal file
191
vendor/github.com/juju/retry/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
All files in this repository are licensed as follows. If you contribute
|
||||||
|
to this repository, it is assumed that you license your contribution
|
||||||
|
under the same license unless you state otherwise.
|
||||||
|
|
||||||
|
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
|
||||||
|
|
||||||
|
This software is licensed under the LGPLv3, included below.
|
||||||
|
|
||||||
|
As a special exception to the GNU Lesser General Public License version 3
|
||||||
|
("LGPL3"), the copyright holders of this Library give you permission to
|
||||||
|
convey to a third party a Combined Work that links statically or dynamically
|
||||||
|
to this Library without providing any Minimal Corresponding Source or
|
||||||
|
Minimal Application Code as set out in 4d or providing the installation
|
||||||
|
information set out in section 4e, provided that you comply with the other
|
||||||
|
provisions of LGPL3 and provided that you meet, for the Application the
|
||||||
|
terms and conditions of the license(s) which apply to the Application.
|
||||||
|
|
||||||
|
Except as stated in this special exception, the provisions of LGPL3 will
|
||||||
|
continue to comply in full to this Library. If you modify this Library, you
|
||||||
|
may apply this exception to your version of this Library, but you are not
|
||||||
|
obliged to do so. If you do not wish to do so, delete this exception
|
||||||
|
statement from your version. This exception does not (and cannot) modify any
|
||||||
|
license terms which apply to the Application, with which you must still
|
||||||
|
comply.
|
||||||
|
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
15
vendor/github.com/juju/retry/Makefile
generated
vendored
Normal file
15
vendor/github.com/juju/retry/Makefile
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
PROJECT := github.com/juju/retry
|
||||||
|
|
||||||
|
default: check
|
||||||
|
|
||||||
|
check-licence:
|
||||||
|
@(fgrep -rl "Licensed under the LGPLv3" .;\
|
||||||
|
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" .;\
|
||||||
|
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
|
||||||
|
xargs -I {} echo FAIL: licence missed: {}
|
||||||
|
|
||||||
|
check: check-licence
|
||||||
|
go test $(PROJECT)/...
|
||||||
|
|
||||||
|
docs:
|
||||||
|
godoc2md $(PROJECT) > README.md
|
||||||
277
vendor/github.com/juju/retry/README.md
generated
vendored
Normal file
277
vendor/github.com/juju/retry/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
|
||||||
|
# retry
|
||||||
|
import "github.com/juju/retry"
|
||||||
|
|
||||||
|
The retry package encapsulates the mechanism around retrying commands.
|
||||||
|
|
||||||
|
The simple use is to call retry.Call with a function closure.
|
||||||
|
|
||||||
|
```go
|
||||||
|
|
||||||
|
|
||||||
|
err := retry.Call(retry.CallArgs{
|
||||||
|
Func: func() error { ... },
|
||||||
|
Attempts: 5,
|
||||||
|
Delay: time.Minute,
|
||||||
|
Clock: clock.WallClock,
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The bare minimum arguments that need to be specified are:
|
||||||
|
* Func - the function to call
|
||||||
|
* Attempts - the number of times to try Func before giving up, or a negative number for unlimited attempts (`retry.UnlimitedAttempts`)
|
||||||
|
* Delay - how long to wait between each try that returns an error
|
||||||
|
* Clock - either the wall clock, or some testing clock
|
||||||
|
|
||||||
|
Any error that is returned from the `Func` is considered transient.
|
||||||
|
In order to identify some errors as fatal, pass in a function for the
|
||||||
|
`IsFatalError` CallArgs value.
|
||||||
|
|
||||||
|
In order to have the `Delay` change for each iteration, a `BackoffFunc`
|
||||||
|
needs to be set on the CallArgs. A simple doubling delay function is
|
||||||
|
provided by `DoubleDelay`.
|
||||||
|
|
||||||
|
An example of a more complex `BackoffFunc` could be a stepped function such
|
||||||
|
as:
|
||||||
|
|
||||||
|
```go
|
||||||
|
|
||||||
|
|
||||||
|
func StepDelay(last time.Duration, attempt int) time.Duration {
|
||||||
|
switch attempt{
|
||||||
|
case 1:
|
||||||
|
return time.Second
|
||||||
|
case 2:
|
||||||
|
return 5 * time.Second
|
||||||
|
case 3:
|
||||||
|
return 20 * time.Second
|
||||||
|
case 4:
|
||||||
|
return time.Minute
|
||||||
|
case 5:
|
||||||
|
return 5 * time.Minute
|
||||||
|
default:
|
||||||
|
return 2 * last
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Consider some package `foo` that has a `TryAgainError`, which looks something
|
||||||
|
like this:
|
||||||
|
```go
|
||||||
|
|
||||||
|
|
||||||
|
type TryAgainError struct {
|
||||||
|
After time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
and we create something that looks like this:
|
||||||
|
|
||||||
|
```go
|
||||||
|
|
||||||
|
|
||||||
|
type TryAgainHelper struct {
|
||||||
|
next time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *TryAgainHelper) notify(lastError error, attempt int) {
|
||||||
|
if tryAgain, ok := lastError.(*foo.TryAgainError); ok {
|
||||||
|
h.next = tryAgain.After
|
||||||
|
} else {
|
||||||
|
h.next = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *TryAgainHelper) next(last time.Duration) time.Duration {
|
||||||
|
if h.next != 0 {
|
||||||
|
return h.next
|
||||||
|
}
|
||||||
|
return last
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Then we could do this:
|
||||||
|
```go
|
||||||
|
|
||||||
|
|
||||||
|
helper := TryAgainHelper{}
|
||||||
|
retry.Call(retry.CallArgs{
|
||||||
|
Func: func() error {
|
||||||
|
return foo.SomeFunc()
|
||||||
|
},
|
||||||
|
NotifyFunc: helper.notify,
|
||||||
|
BackoffFunc: helper.next,
|
||||||
|
Attempts: 20,
|
||||||
|
Delay: 100 * time.Millisecond,
|
||||||
|
Clock: clock.WallClock,
|
||||||
|
})
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Constants
|
||||||
|
``` go
|
||||||
|
const (
|
||||||
|
// UnlimitedAttempts can be used as a value for `Attempts` to clearly
|
||||||
|
// show to the reader that there is no limit to the number of attempts.
|
||||||
|
UnlimitedAttempts = -1
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## func Call
|
||||||
|
``` go
|
||||||
|
func Call(args CallArgs) error
|
||||||
|
```
|
||||||
|
Call will repeatedly execute the Func until either the function returns no
|
||||||
|
error, the retry count is exceeded or the stop channel is closed.
|
||||||
|
|
||||||
|
|
||||||
|
## func DoubleDelay
|
||||||
|
``` go
|
||||||
|
func DoubleDelay(delay time.Duration, attempt int) time.Duration
|
||||||
|
```
|
||||||
|
DoubleDelay provides a simple function that doubles the duration passed in.
|
||||||
|
This can then be easily used as the `BackoffFunc` in the `CallArgs`
|
||||||
|
structure.
|
||||||
|
|
||||||
|
## func ExpBackoff
|
||||||
|
``` go
|
||||||
|
func ExpBackoff(minDelay, maxDelay time.Duration, exp float64, applyJitter bool) func(time.Duration, int) time.Duration {
|
||||||
|
```
|
||||||
|
ExpBackoff returns a function a which generates time.Duration values using an
|
||||||
|
exponential back-off algorithm with the specified parameters. The returned value
|
||||||
|
can then be easily used as the `BackoffFunc` in the `CallArgs` structure.
|
||||||
|
|
||||||
|
The next delay value is calculated using the following formula:
|
||||||
|
`newDelay = min(minDelay * exp^attempt, maxDelay)`
|
||||||
|
|
||||||
|
If `applyJitter` is set to `true`, the function will randomly select and return
|
||||||
|
back a value in the `[minDelay, newDelay]` range.
|
||||||
|
|
||||||
|
## func IsAttemptsExceeded
|
||||||
|
``` go
|
||||||
|
func IsAttemptsExceeded(err error) bool
|
||||||
|
```
|
||||||
|
IsAttemptsExceeded returns true if the error is the result of the `Call`
|
||||||
|
function finishing due to hitting the requested number of `Attempts`.
|
||||||
|
|
||||||
|
|
||||||
|
## func IsDurationExceeded
|
||||||
|
``` go
|
||||||
|
func IsDurationExceeded(err error) bool
|
||||||
|
```
|
||||||
|
IsDurationExceeded returns true if the error is the result of the `Call`
|
||||||
|
function finishing due to the total duration exceeding the specified
|
||||||
|
`MaxDuration` value.
|
||||||
|
|
||||||
|
|
||||||
|
## func IsRetryStopped
|
||||||
|
``` go
|
||||||
|
func IsRetryStopped(err error) bool
|
||||||
|
```
|
||||||
|
IsRetryStopped returns true if the error is the result of the `Call`
|
||||||
|
function finishing due to the stop channel being closed.
|
||||||
|
|
||||||
|
|
||||||
|
## func LastError
|
||||||
|
``` go
|
||||||
|
func LastError(err error) error
|
||||||
|
```
|
||||||
|
LastError retrieves the last error returned from `Func` before iteration
|
||||||
|
was terminated due to the attempt count being exceeded, the maximum
|
||||||
|
duration being exceeded, or the stop channel being closed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## type CallArgs
|
||||||
|
``` go
|
||||||
|
type CallArgs struct {
|
||||||
|
// Func is the function that will be retried if it returns an error result.
|
||||||
|
Func func() error
|
||||||
|
|
||||||
|
// IsFatalError is a function that, if set, will be called for every non-
|
||||||
|
// nil error result from `Func`. If `IsFatalError` returns true, the error
|
||||||
|
// is immediately returned breaking out from any further retries.
|
||||||
|
IsFatalError func(error) bool
|
||||||
|
|
||||||
|
// NotifyFunc is a function that is called if Func fails, and the attempt
|
||||||
|
// number. The first time this function is called attempt is 1, the second
|
||||||
|
// time, attempt is 2 and so on.
|
||||||
|
NotifyFunc func(lastError error, attempt int)
|
||||||
|
|
||||||
|
// Attempts specifies the number of times Func should be retried before
|
||||||
|
// giving up and returning the `AttemptsExceeded` error. If a negative
|
||||||
|
// value is specified, the `Call` will retry forever.
|
||||||
|
Attempts int
|
||||||
|
|
||||||
|
// Delay specifies how long to wait between retries.
|
||||||
|
Delay time.Duration
|
||||||
|
|
||||||
|
// MaxDelay specifies how longest time to wait between retries. If no
|
||||||
|
// value is specified there is no maximum delay.
|
||||||
|
MaxDelay time.Duration
|
||||||
|
|
||||||
|
// MaxDuration specifies the maximum time the `Call` function should spend
|
||||||
|
// iterating over `Func`. The duration is calculated from the start of the
|
||||||
|
// `Call` function. If the next delay time would take the total duration
|
||||||
|
// of the call over MaxDuration, then a DurationExceeded error is
|
||||||
|
// returned. If no value is specified, Call will continue until the number
|
||||||
|
// of attempts is complete.
|
||||||
|
MaxDuration time.Duration
|
||||||
|
|
||||||
|
// BackoffFunc allows the caller to provide a function that alters the
|
||||||
|
// delay each time through the loop. If this function is not provided the
|
||||||
|
// delay is the same each iteration. Alternatively a function such as
|
||||||
|
// `retry.DoubleDelay` can be used that will provide an exponential
|
||||||
|
// backoff. The first time this function is called attempt is 1, the
|
||||||
|
// second time, attempt is 2 and so on.
|
||||||
|
BackoffFunc func(delay time.Duration, attempt int) time.Duration
|
||||||
|
|
||||||
|
// Clock provides the mechanism for waiting. Normal program execution is
|
||||||
|
// expected to use something like clock.WallClock, and tests can override
|
||||||
|
// this to not actually sleep in tests.
|
||||||
|
Clock clock.Clock
|
||||||
|
|
||||||
|
// Stop is a channel that can be used to indicate that the waiting should
|
||||||
|
// be interrupted. If Stop is nil, then the Call function cannot be interrupted.
|
||||||
|
// If the channel is closed prior to the Call function being executed, the
|
||||||
|
// Func is still attempted once.
|
||||||
|
Stop <-chan struct{}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
CallArgs is a simple structure used to define the behaviour of the Call
|
||||||
|
function.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### func (\*CallArgs) Validate
|
||||||
|
``` go
|
||||||
|
func (args *CallArgs) Validate() error
|
||||||
|
```
|
||||||
|
Validate the values are valid. The ensures that the Func, Delay, Attempts
|
||||||
|
and Clock have been specified.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- - -
|
||||||
|
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
|
||||||
16
vendor/github.com/juju/retry/clock.go
generated
vendored
Normal file
16
vendor/github.com/juju/retry/clock.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2015 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package retry
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Clock provides an interface for dealing with clocks.
|
||||||
|
type Clock interface {
|
||||||
|
// Now returns the current clock time.
|
||||||
|
Now() time.Time
|
||||||
|
|
||||||
|
// After waits for the duration to elapse and then sends the
|
||||||
|
// current time on the returned channel.
|
||||||
|
After(time.Duration) <-chan time.Time
|
||||||
|
}
|
||||||
91
vendor/github.com/juju/retry/doc.go
generated
vendored
Normal file
91
vendor/github.com/juju/retry/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
// Copyright 2015 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
// The retry package encapsulates the mechanism around retrying commands.
|
||||||
|
//
|
||||||
|
// The simple use is to call retry.Call with a function closure.
|
||||||
|
//
|
||||||
|
// err := retry.Call(retry.CallArgs{
|
||||||
|
// Func: func() error { ... },
|
||||||
|
// Attempts: 5,
|
||||||
|
// Delay: time.Minute,
|
||||||
|
// Clock: clock.WallClock,
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// The bare minimum arguments that need to be specified are:
|
||||||
|
// * Func - the function to call
|
||||||
|
// * Attempts - the number of times to try Func before giving up, or a negative number for unlimited attempts (`retry.UnlimitedAttempts`)
|
||||||
|
// * Delay - how long to wait between each try that returns an error
|
||||||
|
// * Clock - either the wall clock, or some testing clock
|
||||||
|
//
|
||||||
|
// Any error that is returned from the Func is considered transient.
|
||||||
|
// In order to identify some errors as fatal, pass in a function for the
|
||||||
|
// IsFatalError CallArgs value.
|
||||||
|
//
|
||||||
|
// In order to have the Delay change for each iteration, a BackoffFunc
|
||||||
|
// needs to be set on the CallArgs. A simple doubling delay function is
|
||||||
|
// provided by DoubleDelay.
|
||||||
|
//
|
||||||
|
// An example of a more complex BackoffFunc could be a stepped function such
|
||||||
|
// as:
|
||||||
|
//
|
||||||
|
// func StepDelay(last time.Duration, attempt int) time.Duration {
|
||||||
|
// switch attempt{
|
||||||
|
// case 1:
|
||||||
|
// return time.Second
|
||||||
|
// case 2:
|
||||||
|
// return 5 * time.Second
|
||||||
|
// case 3:
|
||||||
|
// return 20 * time.Second
|
||||||
|
// case 4:
|
||||||
|
// return time.Minute
|
||||||
|
// case 5:
|
||||||
|
// return 5 * time.Minute
|
||||||
|
// default:
|
||||||
|
// return 2 * last
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Consider some package foo that has a TryAgainError, which looks something
|
||||||
|
// like this:
|
||||||
|
//
|
||||||
|
// type TryAgainError struct {
|
||||||
|
// After time.Duration
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// and we create something that looks like this:
|
||||||
|
//
|
||||||
|
// type TryAgainHelper struct {
|
||||||
|
// next time.Duration
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (h *TryAgainHelper) notify(lastError error, attempt int) {
|
||||||
|
// if tryAgain, ok := lastError.(*foo.TryAgainError); ok {
|
||||||
|
// h.next = tryAgain.After
|
||||||
|
// } else {
|
||||||
|
// h.next = 0
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (h *TryAgainHelper) next(last time.Duration) time.Duration {
|
||||||
|
// if h.next != 0 {
|
||||||
|
// return h.next
|
||||||
|
// }
|
||||||
|
// return last
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Then we could do this:
|
||||||
|
//
|
||||||
|
// helper := TryAgainHelper{}
|
||||||
|
// retry.Call(retry.CallArgs{
|
||||||
|
// Func: func() error {
|
||||||
|
// return foo.SomeFunc()
|
||||||
|
// },
|
||||||
|
// NotifyFunc: helper.notify,
|
||||||
|
// BackoffFunc: helper.next,
|
||||||
|
// Attempts: 20,
|
||||||
|
// Delay: 100 * time.Millisecond,
|
||||||
|
// Clock: clock.WallClock,
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
package retry
|
||||||
258
vendor/github.com/juju/retry/retry.go
generated
vendored
Normal file
258
vendor/github.com/juju/retry/retry.go
generated
vendored
Normal file
|
|
@ -0,0 +1,258 @@
|
||||||
|
// Copyright 2015 Canonical Ltd.
|
||||||
|
// Licensed under the LGPLv3, see LICENCE file for details.
|
||||||
|
|
||||||
|
package retry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// UnlimitedAttempts can be used as a value for Attempts to clearly
|
||||||
|
// show to the reader that there is no limit to the number of attempts.
|
||||||
|
UnlimitedAttempts = -1
|
||||||
|
)
|
||||||
|
|
||||||
|
// retryStopped is the error that is returned from the Call function
|
||||||
|
// when the stop channel has been closed.
|
||||||
|
type retryStopped struct {
|
||||||
|
lastError error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error provides the implementation for the error interface method.
|
||||||
|
func (e *retryStopped) Error() string {
|
||||||
|
return fmt.Sprintf("retry stopped")
|
||||||
|
}
|
||||||
|
|
||||||
|
// attemptsExceeded is the error that is returned when the retry count has
|
||||||
|
// been hit without the function returning a nil error result. The last error
|
||||||
|
// returned from the function being retried is available as the LastError
|
||||||
|
// attribute.
|
||||||
|
type attemptsExceeded struct {
|
||||||
|
lastError error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error provides the implementation for the error interface method.
|
||||||
|
func (e *attemptsExceeded) Error() string {
|
||||||
|
return fmt.Sprintf("attempt count exceeded: %s", e.lastError)
|
||||||
|
}
|
||||||
|
|
||||||
|
// durationExceeded is the error that is returned when the total time that the
|
||||||
|
// Call function would have executed exceeds the MaxDuration specified.
|
||||||
|
// The last error returned from the function being retried is available as the
|
||||||
|
// LastError attribute.
|
||||||
|
type durationExceeded struct {
|
||||||
|
lastError error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error provides the implementation for the error interface method.
|
||||||
|
func (e *durationExceeded) Error() string {
|
||||||
|
return fmt.Sprintf("max duration exceeded: %s", e.lastError)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LastError retrieves the last error returned from Func before iteration
|
||||||
|
// was terminated due to the attempt count being exceeded, the maximum
|
||||||
|
// duration being exceeded, or the stop channel being closed.
|
||||||
|
func LastError(err error) error {
|
||||||
|
cause := errors.Cause(err)
|
||||||
|
switch err := cause.(type) {
|
||||||
|
case *attemptsExceeded:
|
||||||
|
return err.lastError
|
||||||
|
case *retryStopped:
|
||||||
|
return err.lastError
|
||||||
|
case *durationExceeded:
|
||||||
|
return err.lastError
|
||||||
|
}
|
||||||
|
return errors.Errorf("unexpected error type: %T, %s", cause, cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAttemptsExceeded returns true if the error is the result of the Call
|
||||||
|
// function finishing due to hitting the requested number of Attempts.
|
||||||
|
func IsAttemptsExceeded(err error) bool {
|
||||||
|
cause := errors.Cause(err)
|
||||||
|
_, ok := cause.(*attemptsExceeded)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsDurationExceeded returns true if the error is the result of the Call
|
||||||
|
// function finishing due to the total duration exceeding the specified
|
||||||
|
// MaxDuration value.
|
||||||
|
func IsDurationExceeded(err error) bool {
|
||||||
|
cause := errors.Cause(err)
|
||||||
|
_, ok := cause.(*durationExceeded)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRetryStopped returns true if the error is the result of the Call
|
||||||
|
// function finishing due to the stop channel being closed.
|
||||||
|
func IsRetryStopped(err error) bool {
|
||||||
|
cause := errors.Cause(err)
|
||||||
|
_, ok := cause.(*retryStopped)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallArgs is a simple structure used to define the behaviour of the Call
|
||||||
|
// function.
|
||||||
|
type CallArgs struct {
|
||||||
|
// Func is the function that will be retried if it returns an error result.
|
||||||
|
Func func() error
|
||||||
|
|
||||||
|
// IsFatalError is a function that, if set, will be called for every non-
|
||||||
|
// nil error result from Func. If IsFatalError returns true, the error
|
||||||
|
// is immediately returned breaking out from any further retries.
|
||||||
|
IsFatalError func(error) bool
|
||||||
|
|
||||||
|
// NotifyFunc is a function that is called if Func fails, and the attempt
|
||||||
|
// number. The first time this function is called attempt is 1, the second
|
||||||
|
// time, attempt is 2 and so on.
|
||||||
|
NotifyFunc func(lastError error, attempt int)
|
||||||
|
|
||||||
|
// Attempts specifies the number of times Func should be retried before
|
||||||
|
// giving up and returning the AttemptsExceeded error. If a negative
|
||||||
|
// value is specified, the Call will retry forever.
|
||||||
|
Attempts int
|
||||||
|
|
||||||
|
// Delay specifies how long to wait between retries.
|
||||||
|
Delay time.Duration
|
||||||
|
|
||||||
|
// MaxDelay specifies how longest time to wait between retries. If no
|
||||||
|
// value is specified there is no maximum delay.
|
||||||
|
MaxDelay time.Duration
|
||||||
|
|
||||||
|
// MaxDuration specifies the maximum time the Call function should spend
|
||||||
|
// iterating over Func. The duration is calculated from the start of the
|
||||||
|
// Call function. If the next delay time would take the total duration
|
||||||
|
// of the call over MaxDuration, then a DurationExceeded error is
|
||||||
|
// returned. If no value is specified, Call will continue until the number
|
||||||
|
// of attempts is complete.
|
||||||
|
MaxDuration time.Duration
|
||||||
|
|
||||||
|
// BackoffFunc allows the caller to provide a function that alters the
|
||||||
|
// delay each time through the loop. If this function is not provided the
|
||||||
|
// delay is the same each iteration. Alternatively a function such as
|
||||||
|
// retry.DoubleDelay can be used that will provide an exponential
|
||||||
|
// backoff. The first time this function is called attempt is 1, the
|
||||||
|
// second time, attempt is 2 and so on.
|
||||||
|
BackoffFunc func(delay time.Duration, attempt int) time.Duration
|
||||||
|
|
||||||
|
// Clock provides the mechanism for waiting. Normal program execution is
|
||||||
|
// expected to use something like clock.WallClock, and tests can override
|
||||||
|
// this to not actually sleep in tests.
|
||||||
|
Clock Clock
|
||||||
|
|
||||||
|
// Stop is a channel that can be used to indicate that the waiting should
|
||||||
|
// be interrupted. If Stop is nil, then the Call function cannot be interrupted.
|
||||||
|
// If the channel is closed prior to the Call function being executed, the
|
||||||
|
// Func is still attempted once.
|
||||||
|
Stop <-chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the values are valid. The ensures that the Func, Delay, Attempts
|
||||||
|
// and Clock have been specified.
|
||||||
|
func (args *CallArgs) Validate() error {
|
||||||
|
if args.Func == nil {
|
||||||
|
return errors.NotValidf("missing Func")
|
||||||
|
}
|
||||||
|
if args.Delay == 0 {
|
||||||
|
return errors.NotValidf("missing Delay")
|
||||||
|
}
|
||||||
|
if args.Clock == nil {
|
||||||
|
return errors.NotValidf("missing Clock")
|
||||||
|
}
|
||||||
|
// One of Attempts or MaxDuration need to be specified
|
||||||
|
if args.Attempts == 0 && args.MaxDuration == 0 {
|
||||||
|
return errors.NotValidf("missing Attempts or MaxDuration")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call will repeatedly execute the Func until either the function returns no
|
||||||
|
// error, the retry count is exceeded or the stop channel is closed.
|
||||||
|
func Call(args CallArgs) error {
|
||||||
|
err := args.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
start := args.Clock.Now()
|
||||||
|
for i := 1; args.Attempts <= 0 || i <= args.Attempts; i++ {
|
||||||
|
err = args.Func()
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if args.IsFatalError != nil && args.IsFatalError(err) {
|
||||||
|
return errors.Trace(err)
|
||||||
|
}
|
||||||
|
if args.NotifyFunc != nil {
|
||||||
|
args.NotifyFunc(err, i)
|
||||||
|
}
|
||||||
|
if i == args.Attempts && args.Attempts > 0 {
|
||||||
|
break // don't wait before returning the error
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.BackoffFunc != nil {
|
||||||
|
delay := args.BackoffFunc(args.Delay, i)
|
||||||
|
if delay > args.MaxDelay && args.MaxDelay > 0 {
|
||||||
|
delay = args.MaxDelay
|
||||||
|
}
|
||||||
|
args.Delay = delay
|
||||||
|
}
|
||||||
|
elapsedTime := args.Clock.Now().Sub(start)
|
||||||
|
if args.MaxDuration > 0 && (elapsedTime+args.Delay) > args.MaxDuration {
|
||||||
|
return errors.Wrap(err, &durationExceeded{err})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the delay, and retry
|
||||||
|
select {
|
||||||
|
case <-args.Clock.After(args.Delay):
|
||||||
|
case <-args.Stop:
|
||||||
|
return errors.Wrap(err, &retryStopped{err})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.Wrap(err, &attemptsExceeded{err})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DoubleDelay provides a simple function that doubles the duration passed in.
|
||||||
|
// This can then be easily used as the BackoffFunc in the CallArgs
|
||||||
|
// structure.
|
||||||
|
func DoubleDelay(delay time.Duration, attempt int) time.Duration {
|
||||||
|
if attempt == 1 {
|
||||||
|
return delay
|
||||||
|
}
|
||||||
|
return delay * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpBackoff returns a function a which generates time.Duration values using
|
||||||
|
// an exponential back-off algorithm with the specified parameters. The
|
||||||
|
// returned value can then be easily used as the BackoffFunc in the CallArgs
|
||||||
|
// structure.
|
||||||
|
//
|
||||||
|
// The next delay value is calculated using the following formula:
|
||||||
|
// newDelay = min(minDelay * exp^attempt, maxDelay)
|
||||||
|
//
|
||||||
|
// If applyJitter is set to true, the function will randomly select and return
|
||||||
|
// back a value in the [minDelay, newDelay] range.
|
||||||
|
func ExpBackoff(minDelay, maxDelay time.Duration, exp float64, applyJitter bool) func(time.Duration, int) time.Duration {
|
||||||
|
minDelayF := float64(minDelay)
|
||||||
|
maxDelayF := float64(maxDelay)
|
||||||
|
return func(_ time.Duration, attempt int) time.Duration {
|
||||||
|
newDelay := minDelayF * math.Pow(exp, float64(attempt))
|
||||||
|
if newDelay > maxDelayF {
|
||||||
|
newDelay = maxDelayF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a random value in the [minDelay, newDelay) range.
|
||||||
|
if applyJitter {
|
||||||
|
newDelay = rand.Float64() * newDelay
|
||||||
|
if newDelay < minDelayF {
|
||||||
|
newDelay = minDelayF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Duration(newDelay).Round(time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
21
vendor/github.com/stretchr/objx/.codeclimate.yml
generated
vendored
Normal file
21
vendor/github.com/stretchr/objx/.codeclimate.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
engines:
|
||||||
|
gofmt:
|
||||||
|
enabled: true
|
||||||
|
golint:
|
||||||
|
enabled: true
|
||||||
|
govet:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
exclude_patterns:
|
||||||
|
- ".github/"
|
||||||
|
- "vendor/"
|
||||||
|
- "codegen/"
|
||||||
|
- "*.yml"
|
||||||
|
- ".*.yml"
|
||||||
|
- "*.md"
|
||||||
|
- "Gopkg.*"
|
||||||
|
- "doc.go"
|
||||||
|
- "type_specific_codegen_test.go"
|
||||||
|
- "type_specific_codegen.go"
|
||||||
|
- ".gitignore"
|
||||||
|
- "LICENSE"
|
||||||
11
vendor/github.com/stretchr/objx/.gitignore
generated
vendored
Normal file
11
vendor/github.com/stretchr/objx/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
22
vendor/github.com/stretchr/objx/LICENSE
generated
vendored
Normal file
22
vendor/github.com/stretchr/objx/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2014 Stretchr, Inc.
|
||||||
|
Copyright (c) 2017-2018 objx contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
80
vendor/github.com/stretchr/objx/README.md
generated
vendored
Normal file
80
vendor/github.com/stretchr/objx/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
# Objx
|
||||||
|
[](https://travis-ci.org/stretchr/objx)
|
||||||
|
[](https://goreportcard.com/report/github.com/stretchr/objx)
|
||||||
|
[](https://codeclimate.com/github/stretchr/objx/maintainability)
|
||||||
|
[](https://codeclimate.com/github/stretchr/objx/test_coverage)
|
||||||
|
[](https://sourcegraph.com/github.com/stretchr/objx)
|
||||||
|
[](https://godoc.org/github.com/stretchr/objx)
|
||||||
|
|
||||||
|
Objx - Go package for dealing with maps, slices, JSON and other data.
|
||||||
|
|
||||||
|
Get started:
|
||||||
|
|
||||||
|
- Install Objx with [one line of code](#installation), or [update it with another](#staying-up-to-date)
|
||||||
|
- Check out the API Documentation http://godoc.org/github.com/stretchr/objx
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes a powerful `Get` method (among others) that allows you to easily and quickly get access to data within the map, without having to worry too much about type assertions, missing data, default values etc.
|
||||||
|
|
||||||
|
### Pattern
|
||||||
|
Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going:
|
||||||
|
|
||||||
|
m, err := objx.FromJSON(json)
|
||||||
|
|
||||||
|
NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, the rest will be optimistic and try to figure things out without panicking.
|
||||||
|
|
||||||
|
Use `Get` to access the value you're interested in. You can use dot and array
|
||||||
|
notation too:
|
||||||
|
|
||||||
|
m.Get("places[0].latlng")
|
||||||
|
|
||||||
|
Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type.
|
||||||
|
|
||||||
|
if m.Get("code").IsStr() { // Your code... }
|
||||||
|
|
||||||
|
Or you can just assume the type, and use one of the strong type methods to extract the real value:
|
||||||
|
|
||||||
|
m.Get("code").Int()
|
||||||
|
|
||||||
|
If there's no value there (or if it's the wrong type) then a default value will be returned, or you can be explicit about the default value.
|
||||||
|
|
||||||
|
Get("code").Int(-1)
|
||||||
|
|
||||||
|
If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating, manipulating and selecting that data. You can find out more by exploring the index below.
|
||||||
|
|
||||||
|
### Reading data
|
||||||
|
A simple example of how to use Objx:
|
||||||
|
|
||||||
|
// Use MustFromJSON to make an objx.Map from some JSON
|
||||||
|
m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`)
|
||||||
|
|
||||||
|
// Get the details
|
||||||
|
name := m.Get("name").Str()
|
||||||
|
age := m.Get("age").Int()
|
||||||
|
|
||||||
|
// Get their nickname (or use their name if they don't have one)
|
||||||
|
nickname := m.Get("nickname").Str(name)
|
||||||
|
|
||||||
|
### Ranging
|
||||||
|
Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For example, to `range` the data, do what you would expect:
|
||||||
|
|
||||||
|
m := objx.MustFromJSON(json)
|
||||||
|
for key, value := range m {
|
||||||
|
// Your code...
|
||||||
|
}
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
To install Objx, use go get:
|
||||||
|
|
||||||
|
go get github.com/stretchr/objx
|
||||||
|
|
||||||
|
### Staying up to date
|
||||||
|
To update Objx to the latest version, run:
|
||||||
|
|
||||||
|
go get -u github.com/stretchr/objx
|
||||||
|
|
||||||
|
### Supported go versions
|
||||||
|
We support the lastest three major Go versions, which are 1.10, 1.11 and 1.12 at the moment.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
Please feel free to submit issues, fork the repository and send pull requests!
|
||||||
30
vendor/github.com/stretchr/objx/Taskfile.yml
generated
vendored
Normal file
30
vendor/github.com/stretchr/objx/Taskfile.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
version: '2'
|
||||||
|
|
||||||
|
env:
|
||||||
|
GOFLAGS: -mod=vendor
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
deps: [test]
|
||||||
|
|
||||||
|
lint:
|
||||||
|
desc: Checks code style
|
||||||
|
cmds:
|
||||||
|
- gofmt -d -s *.go
|
||||||
|
- go vet ./...
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
lint-fix:
|
||||||
|
desc: Fixes code style
|
||||||
|
cmds:
|
||||||
|
- gofmt -w -s *.go
|
||||||
|
|
||||||
|
test:
|
||||||
|
desc: Runs go tests
|
||||||
|
cmds:
|
||||||
|
- go test -race ./...
|
||||||
|
|
||||||
|
test-coverage:
|
||||||
|
desc: Runs go tests and calucates test coverage
|
||||||
|
cmds:
|
||||||
|
- go test -race -coverprofile=c.out ./...
|
||||||
197
vendor/github.com/stretchr/objx/accessors.go
generated
vendored
Normal file
197
vendor/github.com/stretchr/objx/accessors.go
generated
vendored
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PathSeparator is the character used to separate the elements
|
||||||
|
// of the keypath.
|
||||||
|
//
|
||||||
|
// For example, `location.address.city`
|
||||||
|
PathSeparator string = "."
|
||||||
|
|
||||||
|
// arrayAccesRegexString is the regex used to extract the array number
|
||||||
|
// from the access path
|
||||||
|
arrayAccesRegexString = `^(.+)\[([0-9]+)\]$`
|
||||||
|
|
||||||
|
// mapAccessRegexString is the regex used to extract the map key
|
||||||
|
// from the access path
|
||||||
|
mapAccessRegexString = `^([^\[]*)\[([^\]]+)\](.*)$`
|
||||||
|
)
|
||||||
|
|
||||||
|
// arrayAccesRegex is the compiled arrayAccesRegexString
|
||||||
|
var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
|
||||||
|
|
||||||
|
// mapAccessRegex is the compiled mapAccessRegexString
|
||||||
|
var mapAccessRegex = regexp.MustCompile(mapAccessRegexString)
|
||||||
|
|
||||||
|
// Get gets the value using the specified selector and
|
||||||
|
// returns it inside a new Obj object.
|
||||||
|
//
|
||||||
|
// If it cannot find the value, Get will return a nil
|
||||||
|
// value inside an instance of Obj.
|
||||||
|
//
|
||||||
|
// Get can only operate directly on map[string]interface{} and []interface.
|
||||||
|
//
|
||||||
|
// Example
|
||||||
|
//
|
||||||
|
// To access the title of the third chapter of the second book, do:
|
||||||
|
//
|
||||||
|
// o.Get("books[1].chapters[2].title")
|
||||||
|
func (m Map) Get(selector string) *Value {
|
||||||
|
rawObj := access(m, selector, nil, false)
|
||||||
|
return &Value{data: rawObj}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the value using the specified selector and
|
||||||
|
// returns the object on which Set was called.
|
||||||
|
//
|
||||||
|
// Set can only operate directly on map[string]interface{} and []interface
|
||||||
|
//
|
||||||
|
// Example
|
||||||
|
//
|
||||||
|
// To set the title of the third chapter of the second book, do:
|
||||||
|
//
|
||||||
|
// o.Set("books[1].chapters[2].title","Time to Go")
|
||||||
|
func (m Map) Set(selector string, value interface{}) Map {
|
||||||
|
access(m, selector, value, true)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// getIndex returns the index, which is hold in s by two braches.
|
||||||
|
// It also returns s withour the index part, e.g. name[1] will return (1, name).
|
||||||
|
// If no index is found, -1 is returned
|
||||||
|
func getIndex(s string) (int, string) {
|
||||||
|
arrayMatches := arrayAccesRegex.FindStringSubmatch(s)
|
||||||
|
if len(arrayMatches) > 0 {
|
||||||
|
// Get the key into the map
|
||||||
|
selector := arrayMatches[1]
|
||||||
|
// Get the index into the array at the key
|
||||||
|
// We know this cannt fail because arrayMatches[2] is an int for sure
|
||||||
|
index, _ := strconv.Atoi(arrayMatches[2])
|
||||||
|
return index, selector
|
||||||
|
}
|
||||||
|
return -1, s
|
||||||
|
}
|
||||||
|
|
||||||
|
// getKey returns the key which is held in s by two brackets.
|
||||||
|
// It also returns the next selector.
|
||||||
|
func getKey(s string) (string, string) {
|
||||||
|
selSegs := strings.SplitN(s, PathSeparator, 2)
|
||||||
|
thisSel := selSegs[0]
|
||||||
|
nextSel := ""
|
||||||
|
|
||||||
|
if len(selSegs) > 1 {
|
||||||
|
nextSel = selSegs[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
mapMatches := mapAccessRegex.FindStringSubmatch(s)
|
||||||
|
if len(mapMatches) > 0 {
|
||||||
|
if _, err := strconv.Atoi(mapMatches[2]); err != nil {
|
||||||
|
thisSel = mapMatches[1]
|
||||||
|
nextSel = "[" + mapMatches[2] + "]" + mapMatches[3]
|
||||||
|
|
||||||
|
if thisSel == "" {
|
||||||
|
thisSel = mapMatches[2]
|
||||||
|
nextSel = mapMatches[3]
|
||||||
|
}
|
||||||
|
|
||||||
|
if nextSel == "" {
|
||||||
|
selSegs = []string{"", ""}
|
||||||
|
} else if nextSel[0] == '.' {
|
||||||
|
nextSel = nextSel[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisSel, nextSel
|
||||||
|
}
|
||||||
|
|
||||||
|
// access accesses the object using the selector and performs the
|
||||||
|
// appropriate action.
|
||||||
|
func access(current interface{}, selector string, value interface{}, isSet bool) interface{} {
|
||||||
|
thisSel, nextSel := getKey(selector)
|
||||||
|
|
||||||
|
indexes := []int{}
|
||||||
|
for strings.Contains(thisSel, "[") {
|
||||||
|
prevSel := thisSel
|
||||||
|
index := -1
|
||||||
|
index, thisSel = getIndex(thisSel)
|
||||||
|
indexes = append(indexes, index)
|
||||||
|
if prevSel == thisSel {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if curMap, ok := current.(Map); ok {
|
||||||
|
current = map[string]interface{}(curMap)
|
||||||
|
}
|
||||||
|
// get the object in question
|
||||||
|
switch current.(type) {
|
||||||
|
case map[string]interface{}:
|
||||||
|
curMSI := current.(map[string]interface{})
|
||||||
|
if nextSel == "" && isSet {
|
||||||
|
curMSI[thisSel] = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := curMSI[thisSel].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
_, ok = curMSI[thisSel].(Map)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curMSI[thisSel] == nil || !ok) && len(indexes) == 0 && isSet {
|
||||||
|
curMSI[thisSel] = map[string]interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
current = curMSI[thisSel]
|
||||||
|
default:
|
||||||
|
current = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// do we need to access the item of an array?
|
||||||
|
if len(indexes) > 0 {
|
||||||
|
num := len(indexes)
|
||||||
|
for num > 0 {
|
||||||
|
num--
|
||||||
|
index := indexes[num]
|
||||||
|
indexes = indexes[:num]
|
||||||
|
if array, ok := interSlice(current); ok {
|
||||||
|
if index < len(array) {
|
||||||
|
current = array[index]
|
||||||
|
} else {
|
||||||
|
current = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nextSel != "" {
|
||||||
|
current = access(current, nextSel, value, isSet)
|
||||||
|
}
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
func interSlice(slice interface{}) ([]interface{}, bool) {
|
||||||
|
if array, ok := slice.([]interface{}); ok {
|
||||||
|
return array, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
s := reflect.ValueOf(slice)
|
||||||
|
if s.Kind() != reflect.Slice {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make([]interface{}, s.Len())
|
||||||
|
|
||||||
|
for i := 0; i < s.Len(); i++ {
|
||||||
|
ret[i] = s.Index(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, true
|
||||||
|
}
|
||||||
280
vendor/github.com/stretchr/objx/conversions.go
generated
vendored
Normal file
280
vendor/github.com/stretchr/objx/conversions.go
generated
vendored
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SignatureSeparator is the character that is used to
|
||||||
|
// separate the Base64 string from the security signature.
|
||||||
|
const SignatureSeparator = "_"
|
||||||
|
|
||||||
|
// URLValuesSliceKeySuffix is the character that is used to
|
||||||
|
// specify a suffic for slices parsed by URLValues.
|
||||||
|
// If the suffix is set to "[i]", then the index of the slice
|
||||||
|
// is used in place of i
|
||||||
|
// Ex: Suffix "[]" would have the form a[]=b&a[]=c
|
||||||
|
// OR Suffix "[i]" would have the form a[0]=b&a[1]=c
|
||||||
|
// OR Suffix "" would have the form a=b&a=c
|
||||||
|
var urlValuesSliceKeySuffix = "[]"
|
||||||
|
|
||||||
|
const (
|
||||||
|
URLValuesSliceKeySuffixEmpty = ""
|
||||||
|
URLValuesSliceKeySuffixArray = "[]"
|
||||||
|
URLValuesSliceKeySuffixIndex = "[i]"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetURLValuesSliceKeySuffix sets the character that is used to
|
||||||
|
// specify a suffic for slices parsed by URLValues.
|
||||||
|
// If the suffix is set to "[i]", then the index of the slice
|
||||||
|
// is used in place of i
|
||||||
|
// Ex: Suffix "[]" would have the form a[]=b&a[]=c
|
||||||
|
// OR Suffix "[i]" would have the form a[0]=b&a[1]=c
|
||||||
|
// OR Suffix "" would have the form a=b&a=c
|
||||||
|
func SetURLValuesSliceKeySuffix(s string) error {
|
||||||
|
if s == URLValuesSliceKeySuffixEmpty || s == URLValuesSliceKeySuffixArray || s == URLValuesSliceKeySuffixIndex {
|
||||||
|
urlValuesSliceKeySuffix = s
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("objx: Invalid URLValuesSliceKeySuffix provided.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON converts the contained object to a JSON string
|
||||||
|
// representation
|
||||||
|
func (m Map) JSON() (string, error) {
|
||||||
|
for k, v := range m {
|
||||||
|
m[k] = cleanUp(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := json.Marshal(m)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New("objx: JSON encode failed with: " + err.Error())
|
||||||
|
}
|
||||||
|
return string(result), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanUpInterfaceArray(in []interface{}) []interface{} {
|
||||||
|
result := make([]interface{}, len(in))
|
||||||
|
for i, v := range in {
|
||||||
|
result[i] = cleanUp(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanUpInterfaceMap(in map[interface{}]interface{}) Map {
|
||||||
|
result := Map{}
|
||||||
|
for k, v := range in {
|
||||||
|
result[fmt.Sprintf("%v", k)] = cleanUp(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanUpStringMap(in map[string]interface{}) Map {
|
||||||
|
result := Map{}
|
||||||
|
for k, v := range in {
|
||||||
|
result[k] = cleanUp(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanUpMSIArray(in []map[string]interface{}) []Map {
|
||||||
|
result := make([]Map, len(in))
|
||||||
|
for i, v := range in {
|
||||||
|
result[i] = cleanUpStringMap(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanUpMapArray(in []Map) []Map {
|
||||||
|
result := make([]Map, len(in))
|
||||||
|
for i, v := range in {
|
||||||
|
result[i] = cleanUpStringMap(v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanUp(v interface{}) interface{} {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case []interface{}:
|
||||||
|
return cleanUpInterfaceArray(v)
|
||||||
|
case []map[string]interface{}:
|
||||||
|
return cleanUpMSIArray(v)
|
||||||
|
case map[interface{}]interface{}:
|
||||||
|
return cleanUpInterfaceMap(v)
|
||||||
|
case Map:
|
||||||
|
return cleanUpStringMap(v)
|
||||||
|
case []Map:
|
||||||
|
return cleanUpMapArray(v)
|
||||||
|
default:
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustJSON converts the contained object to a JSON string
|
||||||
|
// representation and panics if there is an error
|
||||||
|
func (m Map) MustJSON() string {
|
||||||
|
result, err := m.JSON()
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base64 converts the contained object to a Base64 string
|
||||||
|
// representation of the JSON string representation
|
||||||
|
func (m Map) Base64() (string, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
jsonData, err := m.JSON()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
|
||||||
|
_, _ = encoder.Write([]byte(jsonData))
|
||||||
|
_ = encoder.Close()
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustBase64 converts the contained object to a Base64 string
|
||||||
|
// representation of the JSON string representation and panics
|
||||||
|
// if there is an error
|
||||||
|
func (m Map) MustBase64() string {
|
||||||
|
result, err := m.Base64()
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignedBase64 converts the contained object to a Base64 string
|
||||||
|
// representation of the JSON string representation and signs it
|
||||||
|
// using the provided key.
|
||||||
|
func (m Map) SignedBase64(key string) (string, error) {
|
||||||
|
base64, err := m.Base64()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
sig := HashWithKey(base64, key)
|
||||||
|
return base64 + SignatureSeparator + sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustSignedBase64 converts the contained object to a Base64 string
|
||||||
|
// representation of the JSON string representation and signs it
|
||||||
|
// using the provided key and panics if there is an error
|
||||||
|
func (m Map) MustSignedBase64(key string) string {
|
||||||
|
result, err := m.SignedBase64(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
URL Query
|
||||||
|
------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// URLValues creates a url.Values object from an Obj. This
|
||||||
|
// function requires that the wrapped object be a map[string]interface{}
|
||||||
|
func (m Map) URLValues() url.Values {
|
||||||
|
vals := make(url.Values)
|
||||||
|
|
||||||
|
m.parseURLValues(m, vals, "")
|
||||||
|
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Map) parseURLValues(queryMap Map, vals url.Values, key string) {
|
||||||
|
useSliceIndex := false
|
||||||
|
if urlValuesSliceKeySuffix == "[i]" {
|
||||||
|
useSliceIndex = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range queryMap {
|
||||||
|
val := &Value{data: v}
|
||||||
|
switch {
|
||||||
|
case val.IsObjxMap():
|
||||||
|
if key == "" {
|
||||||
|
m.parseURLValues(val.ObjxMap(), vals, k)
|
||||||
|
} else {
|
||||||
|
m.parseURLValues(val.ObjxMap(), vals, key+"["+k+"]")
|
||||||
|
}
|
||||||
|
case val.IsObjxMapSlice():
|
||||||
|
sliceKey := k
|
||||||
|
if key != "" {
|
||||||
|
sliceKey = key + "[" + k + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if useSliceIndex {
|
||||||
|
for i, sv := range val.MustObjxMapSlice() {
|
||||||
|
sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
|
||||||
|
m.parseURLValues(sv, vals, sk)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sliceKey = sliceKey + urlValuesSliceKeySuffix
|
||||||
|
for _, sv := range val.MustObjxMapSlice() {
|
||||||
|
m.parseURLValues(sv, vals, sliceKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case val.IsMSISlice():
|
||||||
|
sliceKey := k
|
||||||
|
if key != "" {
|
||||||
|
sliceKey = key + "[" + k + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if useSliceIndex {
|
||||||
|
for i, sv := range val.MustMSISlice() {
|
||||||
|
sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
|
||||||
|
m.parseURLValues(New(sv), vals, sk)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sliceKey = sliceKey + urlValuesSliceKeySuffix
|
||||||
|
for _, sv := range val.MustMSISlice() {
|
||||||
|
m.parseURLValues(New(sv), vals, sliceKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case val.IsStrSlice(), val.IsBoolSlice(),
|
||||||
|
val.IsFloat32Slice(), val.IsFloat64Slice(),
|
||||||
|
val.IsIntSlice(), val.IsInt8Slice(), val.IsInt16Slice(), val.IsInt32Slice(), val.IsInt64Slice(),
|
||||||
|
val.IsUintSlice(), val.IsUint8Slice(), val.IsUint16Slice(), val.IsUint32Slice(), val.IsUint64Slice():
|
||||||
|
|
||||||
|
sliceKey := k
|
||||||
|
if key != "" {
|
||||||
|
sliceKey = key + "[" + k + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if useSliceIndex {
|
||||||
|
for i, sv := range val.StringSlice() {
|
||||||
|
sk := sliceKey + "[" + strconv.FormatInt(int64(i), 10) + "]"
|
||||||
|
vals.Set(sk, sv)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sliceKey = sliceKey + urlValuesSliceKeySuffix
|
||||||
|
vals[sliceKey] = val.StringSlice()
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if key == "" {
|
||||||
|
vals.Set(k, val.String())
|
||||||
|
} else {
|
||||||
|
vals.Set(key+"["+k+"]", val.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLQuery gets an encoded URL query representing the given
|
||||||
|
// Obj. This function requires that the wrapped object be a
|
||||||
|
// map[string]interface{}
|
||||||
|
func (m Map) URLQuery() (string, error) {
|
||||||
|
return m.URLValues().Encode(), nil
|
||||||
|
}
|
||||||
66
vendor/github.com/stretchr/objx/doc.go
generated
vendored
Normal file
66
vendor/github.com/stretchr/objx/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
Objx - Go package for dealing with maps, slices, JSON and other data.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
|
||||||
|
Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes
|
||||||
|
a powerful `Get` method (among others) that allows you to easily and quickly get
|
||||||
|
access to data within the map, without having to worry too much about type assertions,
|
||||||
|
missing data, default values etc.
|
||||||
|
|
||||||
|
Pattern
|
||||||
|
|
||||||
|
Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy.
|
||||||
|
Call one of the `objx.` functions to create your `objx.Map` to get going:
|
||||||
|
|
||||||
|
m, err := objx.FromJSON(json)
|
||||||
|
|
||||||
|
NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong,
|
||||||
|
the rest will be optimistic and try to figure things out without panicking.
|
||||||
|
|
||||||
|
Use `Get` to access the value you're interested in. You can use dot and array
|
||||||
|
notation too:
|
||||||
|
|
||||||
|
m.Get("places[0].latlng")
|
||||||
|
|
||||||
|
Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type.
|
||||||
|
|
||||||
|
if m.Get("code").IsStr() { // Your code... }
|
||||||
|
|
||||||
|
Or you can just assume the type, and use one of the strong type methods to extract the real value:
|
||||||
|
|
||||||
|
m.Get("code").Int()
|
||||||
|
|
||||||
|
If there's no value there (or if it's the wrong type) then a default value will be returned,
|
||||||
|
or you can be explicit about the default value.
|
||||||
|
|
||||||
|
Get("code").Int(-1)
|
||||||
|
|
||||||
|
If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating,
|
||||||
|
manipulating and selecting that data. You can find out more by exploring the index below.
|
||||||
|
|
||||||
|
Reading data
|
||||||
|
|
||||||
|
A simple example of how to use Objx:
|
||||||
|
|
||||||
|
// Use MustFromJSON to make an objx.Map from some JSON
|
||||||
|
m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`)
|
||||||
|
|
||||||
|
// Get the details
|
||||||
|
name := m.Get("name").Str()
|
||||||
|
age := m.Get("age").Int()
|
||||||
|
|
||||||
|
// Get their nickname (or use their name if they don't have one)
|
||||||
|
nickname := m.Get("nickname").Str(name)
|
||||||
|
|
||||||
|
Ranging
|
||||||
|
|
||||||
|
Since `objx.Map` is a `map[string]interface{}` you can treat it as such.
|
||||||
|
For example, to `range` the data, do what you would expect:
|
||||||
|
|
||||||
|
m := objx.MustFromJSON(json)
|
||||||
|
for key, value := range m {
|
||||||
|
// Your code...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
package objx
|
||||||
215
vendor/github.com/stretchr/objx/map.go
generated
vendored
Normal file
215
vendor/github.com/stretchr/objx/map.go
generated
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MSIConvertable is an interface that defines methods for converting your
|
||||||
|
// custom types to a map[string]interface{} representation.
|
||||||
|
type MSIConvertable interface {
|
||||||
|
// MSI gets a map[string]interface{} (msi) representing the
|
||||||
|
// object.
|
||||||
|
MSI() map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map provides extended functionality for working with
|
||||||
|
// untyped data, in particular map[string]interface (msi).
|
||||||
|
type Map map[string]interface{}
|
||||||
|
|
||||||
|
// Value returns the internal value instance
|
||||||
|
func (m Map) Value() *Value {
|
||||||
|
return &Value{data: m}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nil represents a nil Map.
|
||||||
|
var Nil = New(nil)
|
||||||
|
|
||||||
|
// New creates a new Map containing the map[string]interface{} in the data argument.
|
||||||
|
// If the data argument is not a map[string]interface, New attempts to call the
|
||||||
|
// MSI() method on the MSIConvertable interface to create one.
|
||||||
|
func New(data interface{}) Map {
|
||||||
|
if _, ok := data.(map[string]interface{}); !ok {
|
||||||
|
if converter, ok := data.(MSIConvertable); ok {
|
||||||
|
data = converter.MSI()
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Map(data.(map[string]interface{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MSI creates a map[string]interface{} and puts it inside a new Map.
|
||||||
|
//
|
||||||
|
// The arguments follow a key, value pattern.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Returns nil if any key argument is non-string or if there are an odd number of arguments.
|
||||||
|
//
|
||||||
|
// Example
|
||||||
|
//
|
||||||
|
// To easily create Maps:
|
||||||
|
//
|
||||||
|
// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true))
|
||||||
|
//
|
||||||
|
// // creates an Map equivalent to
|
||||||
|
// m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}}
|
||||||
|
func MSI(keyAndValuePairs ...interface{}) Map {
|
||||||
|
newMap := Map{}
|
||||||
|
keyAndValuePairsLen := len(keyAndValuePairs)
|
||||||
|
if keyAndValuePairsLen%2 != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for i := 0; i < keyAndValuePairsLen; i = i + 2 {
|
||||||
|
key := keyAndValuePairs[i]
|
||||||
|
value := keyAndValuePairs[i+1]
|
||||||
|
|
||||||
|
// make sure the key is a string
|
||||||
|
keyString, keyStringOK := key.(string)
|
||||||
|
if !keyStringOK {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
newMap[keyString] = value
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// ****** Conversion Constructors
|
||||||
|
|
||||||
|
// MustFromJSON creates a new Map containing the data specified in the
|
||||||
|
// jsonString.
|
||||||
|
//
|
||||||
|
// Panics if the JSON is invalid.
|
||||||
|
func MustFromJSON(jsonString string) Map {
|
||||||
|
o, err := FromJSON(jsonString)
|
||||||
|
if err != nil {
|
||||||
|
panic("objx: MustFromJSON failed with error: " + err.Error())
|
||||||
|
}
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustFromJSONSlice creates a new slice of Map containing the data specified in the
|
||||||
|
// jsonString. Works with jsons with a top level array
|
||||||
|
//
|
||||||
|
// Panics if the JSON is invalid.
|
||||||
|
func MustFromJSONSlice(jsonString string) []Map {
|
||||||
|
slice, err := FromJSONSlice(jsonString)
|
||||||
|
if err != nil {
|
||||||
|
panic("objx: MustFromJSONSlice failed with error: " + err.Error())
|
||||||
|
}
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON creates a new Map containing the data specified in the
|
||||||
|
// jsonString.
|
||||||
|
//
|
||||||
|
// Returns an error if the JSON is invalid.
|
||||||
|
func FromJSON(jsonString string) (Map, error) {
|
||||||
|
var m Map
|
||||||
|
err := json.Unmarshal([]byte(jsonString), &m)
|
||||||
|
if err != nil {
|
||||||
|
return Nil, err
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSONSlice creates a new slice of Map containing the data specified in the
|
||||||
|
// jsonString. Works with jsons with a top level array
|
||||||
|
//
|
||||||
|
// Returns an error if the JSON is invalid.
|
||||||
|
func FromJSONSlice(jsonString string) ([]Map, error) {
|
||||||
|
var slice []Map
|
||||||
|
err := json.Unmarshal([]byte(jsonString), &slice)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return slice, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromBase64 creates a new Obj containing the data specified
|
||||||
|
// in the Base64 string.
|
||||||
|
//
|
||||||
|
// The string is an encoded JSON string returned by Base64
|
||||||
|
func FromBase64(base64String string) (Map, error) {
|
||||||
|
decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String))
|
||||||
|
decoded, err := ioutil.ReadAll(decoder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return FromJSON(string(decoded))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustFromBase64 creates a new Obj containing the data specified
|
||||||
|
// in the Base64 string and panics if there is an error.
|
||||||
|
//
|
||||||
|
// The string is an encoded JSON string returned by Base64
|
||||||
|
func MustFromBase64(base64String string) Map {
|
||||||
|
result, err := FromBase64(base64String)
|
||||||
|
if err != nil {
|
||||||
|
panic("objx: MustFromBase64 failed with error: " + err.Error())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromSignedBase64 creates a new Obj containing the data specified
|
||||||
|
// in the Base64 string.
|
||||||
|
//
|
||||||
|
// The string is an encoded JSON string returned by SignedBase64
|
||||||
|
func FromSignedBase64(base64String, key string) (Map, error) {
|
||||||
|
parts := strings.Split(base64String, SignatureSeparator)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, errors.New("objx: Signed base64 string is malformed")
|
||||||
|
}
|
||||||
|
|
||||||
|
sig := HashWithKey(parts[0], key)
|
||||||
|
if parts[1] != sig {
|
||||||
|
return nil, errors.New("objx: Signature for base64 data does not match")
|
||||||
|
}
|
||||||
|
return FromBase64(parts[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustFromSignedBase64 creates a new Obj containing the data specified
|
||||||
|
// in the Base64 string and panics if there is an error.
|
||||||
|
//
|
||||||
|
// The string is an encoded JSON string returned by Base64
|
||||||
|
func MustFromSignedBase64(base64String, key string) Map {
|
||||||
|
result, err := FromSignedBase64(base64String, key)
|
||||||
|
if err != nil {
|
||||||
|
panic("objx: MustFromSignedBase64 failed with error: " + err.Error())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromURLQuery generates a new Obj by parsing the specified
|
||||||
|
// query.
|
||||||
|
//
|
||||||
|
// For queries with multiple values, the first value is selected.
|
||||||
|
func FromURLQuery(query string) (Map, error) {
|
||||||
|
vals, err := url.ParseQuery(query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m := Map{}
|
||||||
|
for k, vals := range vals {
|
||||||
|
m[k] = vals[0]
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustFromURLQuery generates a new Obj by parsing the specified
|
||||||
|
// query.
|
||||||
|
//
|
||||||
|
// For queries with multiple values, the first value is selected.
|
||||||
|
//
|
||||||
|
// Panics if it encounters an error
|
||||||
|
func MustFromURLQuery(query string) Map {
|
||||||
|
o, err := FromURLQuery(query)
|
||||||
|
if err != nil {
|
||||||
|
panic("objx: MustFromURLQuery failed with error: " + err.Error())
|
||||||
|
}
|
||||||
|
return o
|
||||||
|
}
|
||||||
77
vendor/github.com/stretchr/objx/mutations.go
generated
vendored
Normal file
77
vendor/github.com/stretchr/objx/mutations.go
generated
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
// Exclude returns a new Map with the keys in the specified []string
|
||||||
|
// excluded.
|
||||||
|
func (m Map) Exclude(exclude []string) Map {
|
||||||
|
excluded := make(Map)
|
||||||
|
for k, v := range m {
|
||||||
|
if !contains(exclude, k) {
|
||||||
|
excluded[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return excluded
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy creates a shallow copy of the Obj.
|
||||||
|
func (m Map) Copy() Map {
|
||||||
|
copied := Map{}
|
||||||
|
for k, v := range m {
|
||||||
|
copied[k] = v
|
||||||
|
}
|
||||||
|
return copied
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge blends the specified map with a copy of this map and returns the result.
|
||||||
|
//
|
||||||
|
// Keys that appear in both will be selected from the specified map.
|
||||||
|
// This method requires that the wrapped object be a map[string]interface{}
|
||||||
|
func (m Map) Merge(merge Map) Map {
|
||||||
|
return m.Copy().MergeHere(merge)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeHere blends the specified map with this map and returns the current map.
|
||||||
|
//
|
||||||
|
// Keys that appear in both will be selected from the specified map. The original map
|
||||||
|
// will be modified. This method requires that
|
||||||
|
// the wrapped object be a map[string]interface{}
|
||||||
|
func (m Map) MergeHere(merge Map) Map {
|
||||||
|
for k, v := range merge {
|
||||||
|
m[k] = v
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform builds a new Obj giving the transformer a chance
|
||||||
|
// to change the keys and values as it goes. This method requires that
|
||||||
|
// the wrapped object be a map[string]interface{}
|
||||||
|
func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map {
|
||||||
|
newMap := Map{}
|
||||||
|
for k, v := range m {
|
||||||
|
modifiedKey, modifiedVal := transformer(k, v)
|
||||||
|
newMap[modifiedKey] = modifiedVal
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransformKeys builds a new map using the specified key mapping.
|
||||||
|
//
|
||||||
|
// Unspecified keys will be unaltered.
|
||||||
|
// This method requires that the wrapped object be a map[string]interface{}
|
||||||
|
func (m Map) TransformKeys(mapping map[string]string) Map {
|
||||||
|
return m.Transform(func(key string, value interface{}) (string, interface{}) {
|
||||||
|
if newKey, ok := mapping[key]; ok {
|
||||||
|
return newKey, value
|
||||||
|
}
|
||||||
|
return key, value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if a string slice contains a string
|
||||||
|
func contains(s []string, e string) bool {
|
||||||
|
for _, a := range s {
|
||||||
|
if a == e {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
12
vendor/github.com/stretchr/objx/security.go
generated
vendored
Normal file
12
vendor/github.com/stretchr/objx/security.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HashWithKey hashes the specified string using the security key
|
||||||
|
func HashWithKey(data, key string) string {
|
||||||
|
d := sha1.Sum([]byte(data + ":" + key))
|
||||||
|
return hex.EncodeToString(d[:])
|
||||||
|
}
|
||||||
17
vendor/github.com/stretchr/objx/tests.go
generated
vendored
Normal file
17
vendor/github.com/stretchr/objx/tests.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
// Has gets whether there is something at the specified selector
|
||||||
|
// or not.
|
||||||
|
//
|
||||||
|
// If m is nil, Has will always return false.
|
||||||
|
func (m Map) Has(selector string) bool {
|
||||||
|
if m == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !m.Get(selector).IsNil()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNil gets whether the data is nil or not.
|
||||||
|
func (v *Value) IsNil() bool {
|
||||||
|
return v == nil || v.data == nil
|
||||||
|
}
|
||||||
346
vendor/github.com/stretchr/objx/type_specific.go
generated
vendored
Normal file
346
vendor/github.com/stretchr/objx/type_specific.go
generated
vendored
Normal file
|
|
@ -0,0 +1,346 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
/*
|
||||||
|
MSI (map[string]interface{} and []map[string]interface{})
|
||||||
|
*/
|
||||||
|
|
||||||
|
// MSI gets the value as a map[string]interface{}, returns the optionalDefault
|
||||||
|
// value or a system default object if the value is the wrong type.
|
||||||
|
func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} {
|
||||||
|
if s, ok := v.data.(map[string]interface{}); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
if s, ok := v.data.(Map); ok {
|
||||||
|
return map[string]interface{}(s)
|
||||||
|
}
|
||||||
|
if len(optionalDefault) == 1 {
|
||||||
|
return optionalDefault[0]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustMSI gets the value as a map[string]interface{}.
|
||||||
|
//
|
||||||
|
// Panics if the object is not a map[string]interface{}.
|
||||||
|
func (v *Value) MustMSI() map[string]interface{} {
|
||||||
|
if s, ok := v.data.(Map); ok {
|
||||||
|
return map[string]interface{}(s)
|
||||||
|
}
|
||||||
|
return v.data.(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault
|
||||||
|
// value or nil if the value is not a []map[string]interface{}.
|
||||||
|
func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} {
|
||||||
|
if s, ok := v.data.([]map[string]interface{}); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
s := v.ObjxMapSlice()
|
||||||
|
if s == nil {
|
||||||
|
if len(optionalDefault) == 1 {
|
||||||
|
return optionalDefault[0]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]map[string]interface{}, len(s))
|
||||||
|
for i := range s {
|
||||||
|
result[i] = s[i].Value().MSI()
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustMSISlice gets the value as a []map[string]interface{}.
|
||||||
|
//
|
||||||
|
// Panics if the object is not a []map[string]interface{}.
|
||||||
|
func (v *Value) MustMSISlice() []map[string]interface{} {
|
||||||
|
if s := v.MSISlice(); s != nil {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.data.([]map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMSI gets whether the object contained is a map[string]interface{} or not.
|
||||||
|
func (v *Value) IsMSI() bool {
|
||||||
|
_, ok := v.data.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
_, ok = v.data.(Map)
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMSISlice gets whether the object contained is a []map[string]interface{} or not.
|
||||||
|
func (v *Value) IsMSISlice() bool {
|
||||||
|
_, ok := v.data.([]map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
_, ok = v.data.([]Map)
|
||||||
|
if !ok {
|
||||||
|
s, ok := v.data.([]interface{})
|
||||||
|
if ok {
|
||||||
|
for i := range s {
|
||||||
|
switch s[i].(type) {
|
||||||
|
case Map:
|
||||||
|
case map[string]interface{}:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// EachMSI calls the specified callback for each object
|
||||||
|
// in the []map[string]interface{}.
|
||||||
|
//
|
||||||
|
// Panics if the object is the wrong type.
|
||||||
|
func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value {
|
||||||
|
for index, val := range v.MustMSISlice() {
|
||||||
|
carryon := callback(index, val)
|
||||||
|
if !carryon {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereMSI uses the specified decider function to select items
|
||||||
|
// from the []map[string]interface{}. The object contained in the result will contain
|
||||||
|
// only the selected items.
|
||||||
|
func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value {
|
||||||
|
var selected []map[string]interface{}
|
||||||
|
v.EachMSI(func(index int, val map[string]interface{}) bool {
|
||||||
|
shouldSelect := decider(index, val)
|
||||||
|
if !shouldSelect {
|
||||||
|
selected = append(selected, val)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: selected}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupMSI uses the specified grouper function to group the items
|
||||||
|
// keyed by the return of the grouper. The object contained in the
|
||||||
|
// result will contain a map[string][]map[string]interface{}.
|
||||||
|
func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value {
|
||||||
|
groups := make(map[string][]map[string]interface{})
|
||||||
|
v.EachMSI(func(index int, val map[string]interface{}) bool {
|
||||||
|
group := grouper(index, val)
|
||||||
|
if _, ok := groups[group]; !ok {
|
||||||
|
groups[group] = make([]map[string]interface{}, 0)
|
||||||
|
}
|
||||||
|
groups[group] = append(groups[group], val)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: groups}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceMSI uses the specified function to replace each map[string]interface{}s
|
||||||
|
// by iterating each item. The data in the returned result will be a
|
||||||
|
// []map[string]interface{} containing the replaced items.
|
||||||
|
func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value {
|
||||||
|
arr := v.MustMSISlice()
|
||||||
|
replaced := make([]map[string]interface{}, len(arr))
|
||||||
|
v.EachMSI(func(index int, val map[string]interface{}) bool {
|
||||||
|
replaced[index] = replacer(index, val)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: replaced}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollectMSI uses the specified collector function to collect a value
|
||||||
|
// for each of the map[string]interface{}s in the slice. The data returned will be a
|
||||||
|
// []interface{}.
|
||||||
|
func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value {
|
||||||
|
arr := v.MustMSISlice()
|
||||||
|
collected := make([]interface{}, len(arr))
|
||||||
|
v.EachMSI(func(index int, val map[string]interface{}) bool {
|
||||||
|
collected[index] = collector(index, val)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: collected}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ObjxMap ((Map) and [](Map))
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ObjxMap gets the value as a (Map), returns the optionalDefault
|
||||||
|
// value or a system default object if the value is the wrong type.
|
||||||
|
func (v *Value) ObjxMap(optionalDefault ...(Map)) Map {
|
||||||
|
if s, ok := v.data.((Map)); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
if s, ok := v.data.(map[string]interface{}); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
if len(optionalDefault) == 1 {
|
||||||
|
return optionalDefault[0]
|
||||||
|
}
|
||||||
|
return New(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustObjxMap gets the value as a (Map).
|
||||||
|
//
|
||||||
|
// Panics if the object is not a (Map).
|
||||||
|
func (v *Value) MustObjxMap() Map {
|
||||||
|
if s, ok := v.data.(map[string]interface{}); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return v.data.((Map))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault
|
||||||
|
// value or nil if the value is not a [](Map).
|
||||||
|
func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) {
|
||||||
|
if s, ok := v.data.([]Map); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := v.data.([]map[string]interface{}); ok {
|
||||||
|
result := make([]Map, len(s))
|
||||||
|
for i := range s {
|
||||||
|
result[i] = s[i]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
s, ok := v.data.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
if len(optionalDefault) == 1 {
|
||||||
|
return optionalDefault[0]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]Map, len(s))
|
||||||
|
for i := range s {
|
||||||
|
switch s[i].(type) {
|
||||||
|
case Map:
|
||||||
|
result[i] = s[i].(Map)
|
||||||
|
case map[string]interface{}:
|
||||||
|
result[i] = New(s[i])
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustObjxMapSlice gets the value as a [](Map).
|
||||||
|
//
|
||||||
|
// Panics if the object is not a [](Map).
|
||||||
|
func (v *Value) MustObjxMapSlice() [](Map) {
|
||||||
|
if s := v.ObjxMapSlice(); s != nil {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return v.data.([](Map))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsObjxMap gets whether the object contained is a (Map) or not.
|
||||||
|
func (v *Value) IsObjxMap() bool {
|
||||||
|
_, ok := v.data.((Map))
|
||||||
|
if !ok {
|
||||||
|
_, ok = v.data.(map[string]interface{})
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsObjxMapSlice gets whether the object contained is a [](Map) or not.
|
||||||
|
func (v *Value) IsObjxMapSlice() bool {
|
||||||
|
_, ok := v.data.([](Map))
|
||||||
|
if !ok {
|
||||||
|
_, ok = v.data.([]map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
s, ok := v.data.([]interface{})
|
||||||
|
if ok {
|
||||||
|
for i := range s {
|
||||||
|
switch s[i].(type) {
|
||||||
|
case Map:
|
||||||
|
case map[string]interface{}:
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// EachObjxMap calls the specified callback for each object
|
||||||
|
// in the [](Map).
|
||||||
|
//
|
||||||
|
// Panics if the object is the wrong type.
|
||||||
|
func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value {
|
||||||
|
for index, val := range v.MustObjxMapSlice() {
|
||||||
|
carryon := callback(index, val)
|
||||||
|
if !carryon {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// WhereObjxMap uses the specified decider function to select items
|
||||||
|
// from the [](Map). The object contained in the result will contain
|
||||||
|
// only the selected items.
|
||||||
|
func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value {
|
||||||
|
var selected [](Map)
|
||||||
|
v.EachObjxMap(func(index int, val Map) bool {
|
||||||
|
shouldSelect := decider(index, val)
|
||||||
|
if !shouldSelect {
|
||||||
|
selected = append(selected, val)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: selected}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupObjxMap uses the specified grouper function to group the items
|
||||||
|
// keyed by the return of the grouper. The object contained in the
|
||||||
|
// result will contain a map[string][](Map).
|
||||||
|
func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value {
|
||||||
|
groups := make(map[string][](Map))
|
||||||
|
v.EachObjxMap(func(index int, val Map) bool {
|
||||||
|
group := grouper(index, val)
|
||||||
|
if _, ok := groups[group]; !ok {
|
||||||
|
groups[group] = make([](Map), 0)
|
||||||
|
}
|
||||||
|
groups[group] = append(groups[group], val)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: groups}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReplaceObjxMap uses the specified function to replace each (Map)s
|
||||||
|
// by iterating each item. The data in the returned result will be a
|
||||||
|
// [](Map) containing the replaced items.
|
||||||
|
func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value {
|
||||||
|
arr := v.MustObjxMapSlice()
|
||||||
|
replaced := make([](Map), len(arr))
|
||||||
|
v.EachObjxMap(func(index int, val Map) bool {
|
||||||
|
replaced[index] = replacer(index, val)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: replaced}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CollectObjxMap uses the specified collector function to collect a value
|
||||||
|
// for each of the (Map)s in the slice. The data returned will be a
|
||||||
|
// []interface{}.
|
||||||
|
func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value {
|
||||||
|
arr := v.MustObjxMapSlice()
|
||||||
|
collected := make([]interface{}, len(arr))
|
||||||
|
v.EachObjxMap(func(index int, val Map) bool {
|
||||||
|
collected[index] = collector(index, val)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return &Value{data: collected}
|
||||||
|
}
|
||||||
2261
vendor/github.com/stretchr/objx/type_specific_codegen.go
generated
vendored
Normal file
2261
vendor/github.com/stretchr/objx/type_specific_codegen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
159
vendor/github.com/stretchr/objx/value.go
generated
vendored
Normal file
159
vendor/github.com/stretchr/objx/value.go
generated
vendored
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
package objx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Value provides methods for extracting interface{} data in various
|
||||||
|
// types.
|
||||||
|
type Value struct {
|
||||||
|
// data contains the raw data being managed by this Value
|
||||||
|
data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data returns the raw data contained by this Value
|
||||||
|
func (v *Value) Data() interface{} {
|
||||||
|
return v.data
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the value always as a string
|
||||||
|
func (v *Value) String() string {
|
||||||
|
switch {
|
||||||
|
case v.IsNil():
|
||||||
|
return ""
|
||||||
|
case v.IsStr():
|
||||||
|
return v.Str()
|
||||||
|
case v.IsBool():
|
||||||
|
return strconv.FormatBool(v.Bool())
|
||||||
|
case v.IsFloat32():
|
||||||
|
return strconv.FormatFloat(float64(v.Float32()), 'f', -1, 32)
|
||||||
|
case v.IsFloat64():
|
||||||
|
return strconv.FormatFloat(v.Float64(), 'f', -1, 64)
|
||||||
|
case v.IsInt():
|
||||||
|
return strconv.FormatInt(int64(v.Int()), 10)
|
||||||
|
case v.IsInt8():
|
||||||
|
return strconv.FormatInt(int64(v.Int8()), 10)
|
||||||
|
case v.IsInt16():
|
||||||
|
return strconv.FormatInt(int64(v.Int16()), 10)
|
||||||
|
case v.IsInt32():
|
||||||
|
return strconv.FormatInt(int64(v.Int32()), 10)
|
||||||
|
case v.IsInt64():
|
||||||
|
return strconv.FormatInt(v.Int64(), 10)
|
||||||
|
case v.IsUint():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint()), 10)
|
||||||
|
case v.IsUint8():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint8()), 10)
|
||||||
|
case v.IsUint16():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint16()), 10)
|
||||||
|
case v.IsUint32():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint32()), 10)
|
||||||
|
case v.IsUint64():
|
||||||
|
return strconv.FormatUint(v.Uint64(), 10)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%#v", v.Data())
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringSlice returns the value always as a []string
|
||||||
|
func (v *Value) StringSlice(optionalDefault ...[]string) []string {
|
||||||
|
switch {
|
||||||
|
case v.IsStrSlice():
|
||||||
|
return v.MustStrSlice()
|
||||||
|
case v.IsBoolSlice():
|
||||||
|
slice := v.MustBoolSlice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatBool(iv)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsFloat32Slice():
|
||||||
|
slice := v.MustFloat32Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatFloat(float64(iv), 'f', -1, 32)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsFloat64Slice():
|
||||||
|
slice := v.MustFloat64Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatFloat(iv, 'f', -1, 64)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsIntSlice():
|
||||||
|
slice := v.MustIntSlice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatInt(int64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsInt8Slice():
|
||||||
|
slice := v.MustInt8Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatInt(int64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsInt16Slice():
|
||||||
|
slice := v.MustInt16Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatInt(int64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsInt32Slice():
|
||||||
|
slice := v.MustInt32Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatInt(int64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsInt64Slice():
|
||||||
|
slice := v.MustInt64Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatInt(iv, 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsUintSlice():
|
||||||
|
slice := v.MustUintSlice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatUint(uint64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsUint8Slice():
|
||||||
|
slice := v.MustUint8Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatUint(uint64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsUint16Slice():
|
||||||
|
slice := v.MustUint16Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatUint(uint64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsUint32Slice():
|
||||||
|
slice := v.MustUint32Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatUint(uint64(iv), 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
case v.IsUint64Slice():
|
||||||
|
slice := v.MustUint64Slice()
|
||||||
|
vals := make([]string, len(slice))
|
||||||
|
for i, iv := range slice {
|
||||||
|
vals[i] = strconv.FormatUint(iv, 10)
|
||||||
|
}
|
||||||
|
return vals
|
||||||
|
}
|
||||||
|
if len(optionalDefault) == 1 {
|
||||||
|
return optionalDefault[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
44
vendor/github.com/stretchr/testify/mock/doc.go
generated
vendored
Normal file
44
vendor/github.com/stretchr/testify/mock/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Package mock provides a system by which it is possible to mock your objects
|
||||||
|
// and verify calls are happening as expected.
|
||||||
|
//
|
||||||
|
// Example Usage
|
||||||
|
//
|
||||||
|
// The mock package provides an object, Mock, that tracks activity on another object. It is usually
|
||||||
|
// embedded into a test object as shown below:
|
||||||
|
//
|
||||||
|
// type MyTestObject struct {
|
||||||
|
// // add a Mock object instance
|
||||||
|
// mock.Mock
|
||||||
|
//
|
||||||
|
// // other fields go here as normal
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// When implementing the methods of an interface, you wire your functions up
|
||||||
|
// to call the Mock.Called(args...) method, and return the appropriate values.
|
||||||
|
//
|
||||||
|
// For example, to mock a method that saves the name and age of a person and returns
|
||||||
|
// the year of their birth or an error, you might write this:
|
||||||
|
//
|
||||||
|
// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) {
|
||||||
|
// args := o.Called(firstname, lastname, age)
|
||||||
|
// return args.Int(0), args.Error(1)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The Int, Error and Bool methods are examples of strongly typed getters that take the argument
|
||||||
|
// index position. Given this argument list:
|
||||||
|
//
|
||||||
|
// (12, true, "Something")
|
||||||
|
//
|
||||||
|
// You could read them out strongly typed like this:
|
||||||
|
//
|
||||||
|
// args.Int(0)
|
||||||
|
// args.Bool(1)
|
||||||
|
// args.String(2)
|
||||||
|
//
|
||||||
|
// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion:
|
||||||
|
//
|
||||||
|
// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine)
|
||||||
|
//
|
||||||
|
// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those
|
||||||
|
// cases you should check for nil first.
|
||||||
|
package mock
|
||||||
1098
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
Normal file
1098
vendor/github.com/stretchr/testify/mock/mock.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
17
vendor/modules.txt
vendored
17
vendor/modules.txt
vendored
|
|
@ -60,6 +60,15 @@ github.com/jinzhu/inflection
|
||||||
# github.com/jinzhu/now v1.1.5
|
# github.com/jinzhu/now v1.1.5
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/jinzhu/now
|
github.com/jinzhu/now
|
||||||
|
# github.com/juju/clock v0.0.0-20220704231616-a2b96c8eeb27
|
||||||
|
## explicit; go 1.17
|
||||||
|
github.com/juju/clock
|
||||||
|
# github.com/juju/errors v0.0.0-20220328032053-6664a20db930
|
||||||
|
## explicit; go 1.17
|
||||||
|
github.com/juju/errors
|
||||||
|
# github.com/juju/retry v0.0.0-20220204093819-62423bf33287
|
||||||
|
## explicit; go 1.17
|
||||||
|
github.com/juju/retry
|
||||||
# github.com/juju/webbrowser v1.0.0
|
# github.com/juju/webbrowser v1.0.0
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
github.com/juju/webbrowser
|
github.com/juju/webbrowser
|
||||||
|
|
@ -150,10 +159,16 @@ github.com/spf13/cobra
|
||||||
# github.com/spf13/pflag v1.0.5
|
# github.com/spf13/pflag v1.0.5
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
|
# github.com/stretchr/objx v0.4.0
|
||||||
|
## explicit; go 1.12
|
||||||
|
github.com/stretchr/objx
|
||||||
# github.com/stretchr/testify v1.8.0
|
# github.com/stretchr/testify v1.8.0
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/stretchr/testify/assert
|
github.com/stretchr/testify/assert
|
||||||
|
github.com/stretchr/testify/mock
|
||||||
github.com/stretchr/testify/require
|
github.com/stretchr/testify/require
|
||||||
|
# github.com/xdg-go/stringprep v1.0.3
|
||||||
|
## explicit; go 1.11
|
||||||
# golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
|
# golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
golang.org/x/crypto/bcrypt
|
golang.org/x/crypto/bcrypt
|
||||||
|
|
@ -237,8 +252,6 @@ google.golang.org/protobuf/reflect/protoregistry
|
||||||
google.golang.org/protobuf/runtime/protoiface
|
google.golang.org/protobuf/runtime/protoiface
|
||||||
google.golang.org/protobuf/runtime/protoimpl
|
google.golang.org/protobuf/runtime/protoimpl
|
||||||
google.golang.org/protobuf/types/descriptorpb
|
google.golang.org/protobuf/types/descriptorpb
|
||||||
# gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
|
|
||||||
## explicit; go 1.11
|
|
||||||
# gopkg.in/errgo.v1 v1.0.1
|
# gopkg.in/errgo.v1 v1.0.1
|
||||||
## explicit
|
## explicit
|
||||||
gopkg.in/errgo.v1
|
gopkg.in/errgo.v1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue