mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Enable Grafana extensions at build time. (#11752)
* extensions: import and build * bus: use predefined error * enterprise: build script for enterprise packages * poc: auto registering services and dependency injection (cherry picked from commit b5b1ef875f905473af41e49f8071cb9028edc845) * poc: backend services registry progress (cherry picked from commit 97be69725881241bfbf1e7adf0e66801d6b0af3d) * poc: minor update (cherry picked from commit 03d7a6888b81403f458b94305792e075568f0794) * ioc: introduce manuel ioc * enterprise: adds setting for enterprise * build: test and build specific ee commit * cleanup: test testing code * removes example hello service
This commit is contained in:
parent
afce0feb05
commit
28f7b6dad1
@ -93,6 +93,22 @@ jobs:
|
|||||||
- scripts/*.sh
|
- scripts/*.sh
|
||||||
- scripts/publish
|
- scripts/publish
|
||||||
|
|
||||||
|
build-enterprise:
|
||||||
|
docker:
|
||||||
|
- image: grafana/build-container:v0.1
|
||||||
|
working_directory: /go/src/github.com/grafana/grafana
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: build and package grafana
|
||||||
|
command: './scripts/build/build_enterprise.sh'
|
||||||
|
- run:
|
||||||
|
name: sign packages
|
||||||
|
command: './scripts/build/sign_packages.sh'
|
||||||
|
- run:
|
||||||
|
name: sha-sum packages
|
||||||
|
command: 'go run build.go sha-dist'
|
||||||
|
|
||||||
deploy-master:
|
deploy-master:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/python:2.7-stretch
|
- image: circleci/python:2.7-stretch
|
||||||
@ -176,3 +192,7 @@ workflows:
|
|||||||
ignore: /.*/
|
ignore: /.*/
|
||||||
tags:
|
tags:
|
||||||
only: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/
|
only: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/
|
||||||
|
- build-enterprise:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -48,6 +48,7 @@ profile.cov
|
|||||||
/pkg/cmd/grafana-cli/grafana-cli
|
/pkg/cmd/grafana-cli/grafana-cli
|
||||||
/pkg/cmd/grafana-server/grafana-server
|
/pkg/cmd/grafana-server/grafana-server
|
||||||
/pkg/cmd/grafana-server/debug
|
/pkg/cmd/grafana-server/debug
|
||||||
|
/pkg/extensions
|
||||||
debug.test
|
debug.test
|
||||||
/examples/*/dist
|
/examples/*/dist
|
||||||
/packaging/**/*.rpm
|
/packaging/**/*.rpm
|
||||||
|
211
Gopkg.lock
generated
211
Gopkg.lock
generated
@ -27,7 +27,37 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/aws/aws-sdk-go"
|
name = "github.com/aws/aws-sdk-go"
|
||||||
packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/ec2query","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/cloudwatch","service/ec2","service/ec2/ec2iface","service/s3","service/sts"]
|
packages = [
|
||||||
|
"aws",
|
||||||
|
"aws/awserr",
|
||||||
|
"aws/awsutil",
|
||||||
|
"aws/client",
|
||||||
|
"aws/client/metadata",
|
||||||
|
"aws/corehandlers",
|
||||||
|
"aws/credentials",
|
||||||
|
"aws/credentials/ec2rolecreds",
|
||||||
|
"aws/credentials/endpointcreds",
|
||||||
|
"aws/credentials/stscreds",
|
||||||
|
"aws/defaults",
|
||||||
|
"aws/ec2metadata",
|
||||||
|
"aws/endpoints",
|
||||||
|
"aws/request",
|
||||||
|
"aws/session",
|
||||||
|
"aws/signer/v4",
|
||||||
|
"internal/shareddefaults",
|
||||||
|
"private/protocol",
|
||||||
|
"private/protocol/ec2query",
|
||||||
|
"private/protocol/query",
|
||||||
|
"private/protocol/query/queryutil",
|
||||||
|
"private/protocol/rest",
|
||||||
|
"private/protocol/restxml",
|
||||||
|
"private/protocol/xml/xmlutil",
|
||||||
|
"service/cloudwatch",
|
||||||
|
"service/ec2",
|
||||||
|
"service/ec2/ec2iface",
|
||||||
|
"service/s3",
|
||||||
|
"service/sts"
|
||||||
|
]
|
||||||
revision = "decd990ddc5dcdf2f73309cbcab90d06b996ca28"
|
revision = "decd990ddc5dcdf2f73309cbcab90d06b996ca28"
|
||||||
version = "v1.12.67"
|
version = "v1.12.67"
|
||||||
|
|
||||||
@ -75,7 +105,10 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/denisenkom/go-mssqldb"
|
name = "github.com/denisenkom/go-mssqldb"
|
||||||
packages = [".","internal/cp"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"internal/cp"
|
||||||
|
]
|
||||||
revision = "270bc3860bb94dd3a3ffd047377d746c5e276726"
|
revision = "270bc3860bb94dd3a3ffd047377d746c5e276726"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
@ -117,7 +150,12 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/go-macaron/session"
|
name = "github.com/go-macaron/session"
|
||||||
packages = [".","memcache","postgres","redis"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"memcache",
|
||||||
|
"postgres",
|
||||||
|
"redis"
|
||||||
|
]
|
||||||
revision = "b8e286a0dba8f4999042d6b258daf51b31d08938"
|
revision = "b8e286a0dba8f4999042d6b258daf51b31d08938"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
@ -152,7 +190,13 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
packages = ["proto","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp"]
|
packages = [
|
||||||
|
"proto",
|
||||||
|
"ptypes",
|
||||||
|
"ptypes/any",
|
||||||
|
"ptypes/duration",
|
||||||
|
"ptypes/timestamp"
|
||||||
|
]
|
||||||
revision = "c65a0412e71e8b9b3bfd22925720d23c0f054237"
|
revision = "c65a0412e71e8b9b3bfd22925720d23c0f054237"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
@ -221,7 +265,10 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/klauspost/compress"
|
name = "github.com/klauspost/compress"
|
||||||
packages = ["flate","gzip"]
|
packages = [
|
||||||
|
"flate",
|
||||||
|
"gzip"
|
||||||
|
]
|
||||||
revision = "6c8db69c4b49dd4df1fff66996cf556176d0b9bf"
|
revision = "6c8db69c4b49dd4df1fff66996cf556176d0b9bf"
|
||||||
version = "v1.2.1"
|
version = "v1.2.1"
|
||||||
|
|
||||||
@ -252,7 +299,10 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/lib/pq"
|
name = "github.com/lib/pq"
|
||||||
packages = [".","oid"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"oid"
|
||||||
|
]
|
||||||
revision = "61fe37aa2ee24fabcdbe5c4ac1d4ac566f88f345"
|
revision = "61fe37aa2ee24fabcdbe5c4ac1d4ac566f88f345"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
@ -287,7 +337,11 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/opentracing/opentracing-go"
|
name = "github.com/opentracing/opentracing-go"
|
||||||
packages = [".","ext","log"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"ext",
|
||||||
|
"log"
|
||||||
|
]
|
||||||
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
|
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38"
|
||||||
version = "v1.0.2"
|
version = "v1.0.2"
|
||||||
|
|
||||||
@ -297,9 +351,20 @@
|
|||||||
revision = "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0"
|
revision = "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0"
|
||||||
version = "v2.1.0"
|
version = "v2.1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/pkg/errors"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||||
|
version = "v0.8.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
packages = ["api","api/prometheus/v1","prometheus","prometheus/promhttp"]
|
packages = [
|
||||||
|
"api",
|
||||||
|
"api/prometheus/v1",
|
||||||
|
"prometheus",
|
||||||
|
"prometheus/promhttp"
|
||||||
|
]
|
||||||
revision = "967789050ba94deca04a5e84cce8ad472ce313c1"
|
revision = "967789050ba94deca04a5e84cce8ad472ce313c1"
|
||||||
version = "v0.9.0-pre1"
|
version = "v0.9.0-pre1"
|
||||||
|
|
||||||
@ -312,13 +377,22 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/prometheus/common"
|
name = "github.com/prometheus/common"
|
||||||
packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"]
|
packages = [
|
||||||
|
"expfmt",
|
||||||
|
"internal/bitbucket.org/ww/goautoneg",
|
||||||
|
"model"
|
||||||
|
]
|
||||||
revision = "89604d197083d4781071d3c65855d24ecfb0a563"
|
revision = "89604d197083d4781071d3c65855d24ecfb0a563"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/prometheus/procfs"
|
name = "github.com/prometheus/procfs"
|
||||||
packages = [".","internal/util","nfsd","xfs"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"internal/util",
|
||||||
|
"nfsd",
|
||||||
|
"xfs"
|
||||||
|
]
|
||||||
revision = "85fadb6e89903ef7cca6f6a804474cd5ea85b6e1"
|
revision = "85fadb6e89903ef7cca6f6a804474cd5ea85b6e1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
@ -335,13 +409,21 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/smartystreets/assertions"
|
name = "github.com/smartystreets/assertions"
|
||||||
packages = [".","internal/go-render/render","internal/oglematchers"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"internal/go-render/render",
|
||||||
|
"internal/oglematchers"
|
||||||
|
]
|
||||||
revision = "0b37b35ec7434b77e77a4bb29b79677cced992ea"
|
revision = "0b37b35ec7434b77e77a4bb29b79677cced992ea"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/smartystreets/goconvey"
|
name = "github.com/smartystreets/goconvey"
|
||||||
packages = ["convey","convey/gotest","convey/reporting"]
|
packages = [
|
||||||
|
"convey",
|
||||||
|
"convey/gotest",
|
||||||
|
"convey/reporting"
|
||||||
|
]
|
||||||
revision = "9e8dc3f972df6c8fcc0375ef492c24d0bb204857"
|
revision = "9e8dc3f972df6c8fcc0375ef492c24d0bb204857"
|
||||||
version = "1.6.3"
|
version = "1.6.3"
|
||||||
|
|
||||||
@ -353,7 +435,21 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/uber/jaeger-client-go"
|
name = "github.com/uber/jaeger-client-go"
|
||||||
packages = [".","config","internal/baggage","internal/baggage/remote","internal/spanlog","log","rpcmetrics","thrift-gen/agent","thrift-gen/baggage","thrift-gen/jaeger","thrift-gen/sampling","thrift-gen/zipkincore","utils"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"config",
|
||||||
|
"internal/baggage",
|
||||||
|
"internal/baggage/remote",
|
||||||
|
"internal/spanlog",
|
||||||
|
"log",
|
||||||
|
"rpcmetrics",
|
||||||
|
"thrift-gen/agent",
|
||||||
|
"thrift-gen/baggage",
|
||||||
|
"thrift-gen/jaeger",
|
||||||
|
"thrift-gen/sampling",
|
||||||
|
"thrift-gen/zipkincore",
|
||||||
|
"utils"
|
||||||
|
]
|
||||||
revision = "3ac96c6e679cb60a74589b0d0aa7c70a906183f7"
|
revision = "3ac96c6e679cb60a74589b0d0aa7c70a906183f7"
|
||||||
version = "v2.11.2"
|
version = "v2.11.2"
|
||||||
|
|
||||||
@ -365,7 +461,10 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/yudai/gojsondiff"
|
name = "github.com/yudai/gojsondiff"
|
||||||
packages = [".","formatter"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"formatter"
|
||||||
|
]
|
||||||
revision = "7b1b7adf999dab73a6eb02669c3d82dbb27a3dd6"
|
revision = "7b1b7adf999dab73a6eb02669c3d82dbb27a3dd6"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
||||||
@ -378,19 +477,37 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["md4","pbkdf2"]
|
packages = [
|
||||||
|
"md4",
|
||||||
|
"pbkdf2"
|
||||||
|
]
|
||||||
revision = "3d37316aaa6bd9929127ac9a527abf408178ea7b"
|
revision = "3d37316aaa6bd9929127ac9a527abf408178ea7b"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = ["context","context/ctxhttp","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"]
|
packages = [
|
||||||
|
"context",
|
||||||
|
"context/ctxhttp",
|
||||||
|
"http2",
|
||||||
|
"http2/hpack",
|
||||||
|
"idna",
|
||||||
|
"internal/timeseries",
|
||||||
|
"lex/httplex",
|
||||||
|
"trace"
|
||||||
|
]
|
||||||
revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec"
|
revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/oauth2"
|
name = "golang.org/x/oauth2"
|
||||||
packages = [".","google","internal","jws","jwt"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"google",
|
||||||
|
"internal",
|
||||||
|
"jws",
|
||||||
|
"jwt"
|
||||||
|
]
|
||||||
revision = "b28fcf2b08a19742b43084fb40ab78ac6c3d8067"
|
revision = "b28fcf2b08a19742b43084fb40ab78ac6c3d8067"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
@ -408,12 +525,39 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/text"
|
name = "golang.org/x/text"
|
||||||
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
|
packages = [
|
||||||
|
"collate",
|
||||||
|
"collate/build",
|
||||||
|
"internal/colltab",
|
||||||
|
"internal/gen",
|
||||||
|
"internal/tag",
|
||||||
|
"internal/triegen",
|
||||||
|
"internal/ucd",
|
||||||
|
"language",
|
||||||
|
"secure/bidirule",
|
||||||
|
"transform",
|
||||||
|
"unicode/bidi",
|
||||||
|
"unicode/cldr",
|
||||||
|
"unicode/norm",
|
||||||
|
"unicode/rangetable"
|
||||||
|
]
|
||||||
revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3"
|
revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = [".","cloudsql","internal","internal/app_identity","internal/base","internal/datastore","internal/log","internal/modules","internal/remote_api","internal/urlfetch","urlfetch"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"cloudsql",
|
||||||
|
"internal",
|
||||||
|
"internal/app_identity",
|
||||||
|
"internal/base",
|
||||||
|
"internal/datastore",
|
||||||
|
"internal/log",
|
||||||
|
"internal/modules",
|
||||||
|
"internal/remote_api",
|
||||||
|
"internal/urlfetch",
|
||||||
|
"urlfetch"
|
||||||
|
]
|
||||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
@ -425,7 +569,32 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "google.golang.org/grpc"
|
name = "google.golang.org/grpc"
|
||||||
packages = [".","balancer","balancer/base","balancer/roundrobin","codes","connectivity","credentials","encoding","grpclb/grpc_lb_v1/messages","grpclog","health","health/grpc_health_v1","internal","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"]
|
packages = [
|
||||||
|
".",
|
||||||
|
"balancer",
|
||||||
|
"balancer/base",
|
||||||
|
"balancer/roundrobin",
|
||||||
|
"codes",
|
||||||
|
"connectivity",
|
||||||
|
"credentials",
|
||||||
|
"encoding",
|
||||||
|
"grpclb/grpc_lb_v1/messages",
|
||||||
|
"grpclog",
|
||||||
|
"health",
|
||||||
|
"health/grpc_health_v1",
|
||||||
|
"internal",
|
||||||
|
"keepalive",
|
||||||
|
"metadata",
|
||||||
|
"naming",
|
||||||
|
"peer",
|
||||||
|
"resolver",
|
||||||
|
"resolver/dns",
|
||||||
|
"resolver/passthrough",
|
||||||
|
"stats",
|
||||||
|
"status",
|
||||||
|
"tap",
|
||||||
|
"transport"
|
||||||
|
]
|
||||||
revision = "6b51017f791ae1cfbec89c52efdf444b13b550ef"
|
revision = "6b51017f791ae1cfbec89c52efdf444b13b550ef"
|
||||||
version = "v1.9.2"
|
version = "v1.9.2"
|
||||||
|
|
||||||
@ -480,6 +649,6 @@
|
|||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "ad3c71fd3244369c313978e9e7464c7116faee764386439a17de0707a08103aa"
|
inputs-digest = "2bd5b309496d57e2189a1cc28f5c1c41398c19729ba0cf53c8cbb17ea3f706b5"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
23
build.go
23
build.go
@ -41,6 +41,7 @@ var (
|
|||||||
buildNumber int = 0
|
buildNumber int = 0
|
||||||
binaries []string = []string{"grafana-server", "grafana-cli"}
|
binaries []string = []string{"grafana-server", "grafana-cli"}
|
||||||
isDev bool = false
|
isDev bool = false
|
||||||
|
enterprise bool = false
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -58,6 +59,7 @@ func main() {
|
|||||||
flag.StringVar(&phjsToRelease, "phjs", "", "PhantomJS binary")
|
flag.StringVar(&phjsToRelease, "phjs", "", "PhantomJS binary")
|
||||||
flag.BoolVar(&race, "race", race, "Use race detector")
|
flag.BoolVar(&race, "race", race, "Use race detector")
|
||||||
flag.BoolVar(&includeBuildNumber, "includeBuildNumber", includeBuildNumber, "IncludeBuildNumber in package name")
|
flag.BoolVar(&includeBuildNumber, "includeBuildNumber", includeBuildNumber, "IncludeBuildNumber in package name")
|
||||||
|
flag.BoolVar(&enterprise, "enterprise", enterprise, "Build enterprise version of Grafana")
|
||||||
flag.IntVar(&buildNumber, "buildNumber", 0, "Build number from CI system")
|
flag.IntVar(&buildNumber, "buildNumber", 0, "Build number from CI system")
|
||||||
flag.BoolVar(&isDev, "dev", isDev, "optimal for development, skips certain steps")
|
flag.BoolVar(&isDev, "dev", isDev, "optimal for development, skips certain steps")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -283,19 +285,33 @@ func createPackage(options linuxPackageOptions) {
|
|||||||
"-s", "dir",
|
"-s", "dir",
|
||||||
"--description", "Grafana",
|
"--description", "Grafana",
|
||||||
"-C", packageRoot,
|
"-C", packageRoot,
|
||||||
"--vendor", "Grafana",
|
|
||||||
"--url", "https://grafana.com",
|
"--url", "https://grafana.com",
|
||||||
"--license", "\"Apache 2.0\"",
|
|
||||||
"--maintainer", "contact@grafana.com",
|
"--maintainer", "contact@grafana.com",
|
||||||
"--config-files", options.initdScriptFilePath,
|
"--config-files", options.initdScriptFilePath,
|
||||||
"--config-files", options.etcDefaultFilePath,
|
"--config-files", options.etcDefaultFilePath,
|
||||||
"--config-files", options.systemdServiceFilePath,
|
"--config-files", options.systemdServiceFilePath,
|
||||||
"--after-install", options.postinstSrc,
|
"--after-install", options.postinstSrc,
|
||||||
"--name", "grafana",
|
|
||||||
"--version", linuxPackageVersion,
|
"--version", linuxPackageVersion,
|
||||||
"-p", "./dist",
|
"-p", "./dist",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := "grafana"
|
||||||
|
if enterprise {
|
||||||
|
name += "-enterprise"
|
||||||
|
}
|
||||||
|
args = append(args, "--name", name)
|
||||||
|
|
||||||
|
description := "Grafana"
|
||||||
|
if enterprise {
|
||||||
|
description += " Enterprise"
|
||||||
|
}
|
||||||
|
args = append(args, "--vendor", description)
|
||||||
|
|
||||||
|
if !enterprise {
|
||||||
|
args = append(args, "--license", "\"Apache 2.0\"")
|
||||||
|
}
|
||||||
|
|
||||||
if options.packageType == "rpm" {
|
if options.packageType == "rpm" {
|
||||||
args = append(args, "--rpm-posttrans", "packaging/rpm/control/posttrans")
|
args = append(args, "--rpm-posttrans", "packaging/rpm/control/posttrans")
|
||||||
}
|
}
|
||||||
@ -412,6 +428,7 @@ func ldflags() string {
|
|||||||
b.WriteString(fmt.Sprintf(" -X main.version=%s", version))
|
b.WriteString(fmt.Sprintf(" -X main.version=%s", version))
|
||||||
b.WriteString(fmt.Sprintf(" -X main.commit=%s", getGitSha()))
|
b.WriteString(fmt.Sprintf(" -X main.commit=%s", getGitSha()))
|
||||||
b.WriteString(fmt.Sprintf(" -X main.buildstamp=%d", buildStamp()))
|
b.WriteString(fmt.Sprintf(" -X main.buildstamp=%d", buildStamp()))
|
||||||
|
b.WriteString(fmt.Sprintf(" -X main.enterprise=%t", enterprise))
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
// automatically set HEAD for every GET
|
// automatically set HEAD for every GET
|
||||||
macaronR.SetAutoHead(true)
|
macaronR.SetAutoHead(true)
|
||||||
|
|
||||||
r := newRouteRegister(middleware.RequestMetrics, middleware.RequestTracing)
|
r := hs.RouteRegister
|
||||||
|
|
||||||
// not logged in views
|
// not logged in views
|
||||||
r.Get("/", reqSignedIn, Index)
|
r.Get("/", reqSignedIn, Index)
|
||||||
|
@ -35,15 +35,14 @@ type HTTPServer struct {
|
|||||||
context context.Context
|
context context.Context
|
||||||
streamManager *live.StreamManager
|
streamManager *live.StreamManager
|
||||||
cache *gocache.Cache
|
cache *gocache.Cache
|
||||||
|
RouteRegister RouteRegister `inject:""`
|
||||||
|
|
||||||
httpSrv *http.Server
|
httpSrv *http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPServer() *HTTPServer {
|
func (hs *HTTPServer) Init() {
|
||||||
return &HTTPServer{
|
hs.log = log.New("http.server")
|
||||||
log: log.New("http.server"),
|
hs.cache = gocache.New(5*time.Minute, 10*time.Minute)
|
||||||
cache: gocache.New(5*time.Minute, 10*time.Minute),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hs *HTTPServer) Start(ctx context.Context) error {
|
func (hs *HTTPServer) Start(ctx context.Context) error {
|
||||||
|
@ -289,7 +289,7 @@ func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) {
|
|||||||
|
|
||||||
data.NavTree = append(data.NavTree, &dtos.NavLink{
|
data.NavTree = append(data.NavTree, &dtos.NavLink{
|
||||||
Text: "Help",
|
Text: "Help",
|
||||||
SubTitle: fmt.Sprintf(`Grafana v%s (%s)`, setting.BuildVersion, setting.BuildCommit),
|
SubTitle: fmt.Sprintf(`%s v%s (%s)`, setting.ApplicationName, setting.BuildVersion, setting.BuildCommit),
|
||||||
Id: "help",
|
Id: "help",
|
||||||
Url: "#",
|
Url: "#",
|
||||||
Icon: "gicon gicon-question",
|
Icon: "gicon gicon-question",
|
||||||
|
@ -11,6 +11,8 @@ type Router interface {
|
|||||||
Get(pattern string, handlers ...macaron.Handler) *macaron.Route
|
Get(pattern string, handlers ...macaron.Handler) *macaron.Route
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RouteRegister allows you to add routes and macaron.Handlers
|
||||||
|
// that the web server should serve.
|
||||||
type RouteRegister interface {
|
type RouteRegister interface {
|
||||||
Get(string, ...macaron.Handler)
|
Get(string, ...macaron.Handler)
|
||||||
Post(string, ...macaron.Handler)
|
Post(string, ...macaron.Handler)
|
||||||
@ -26,7 +28,8 @@ type RouteRegister interface {
|
|||||||
|
|
||||||
type RegisterNamedMiddleware func(name string) macaron.Handler
|
type RegisterNamedMiddleware func(name string) macaron.Handler
|
||||||
|
|
||||||
func newRouteRegister(namedMiddleware ...RegisterNamedMiddleware) RouteRegister {
|
// NewRouteRegister creates a new RouteRegister with all middlewares sent as params
|
||||||
|
func NewRouteRegister(namedMiddleware ...RegisterNamedMiddleware) RouteRegister {
|
||||||
return &routeRegister{
|
return &routeRegister{
|
||||||
prefix: "",
|
prefix: "",
|
||||||
routes: []route{},
|
routes: []route{},
|
||||||
|
@ -51,7 +51,7 @@ func TestRouteSimpleRegister(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
rr := newRouteRegister(func(name string) macaron.Handler {
|
rr := NewRouteRegister(func(name string) macaron.Handler {
|
||||||
return emptyHandler(name)
|
return emptyHandler(name)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ func TestRouteGroupedRegister(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
rr := newRouteRegister()
|
rr := NewRouteRegister()
|
||||||
|
|
||||||
rr.Delete("/admin", emptyHandler("1"))
|
rr.Delete("/admin", emptyHandler("1"))
|
||||||
rr.Get("/down", emptyHandler("1"), emptyHandler("2"))
|
rr.Get("/down", emptyHandler("1"), emptyHandler("2"))
|
||||||
@ -150,7 +150,7 @@ func TestNamedMiddlewareRouteRegister(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
rr := newRouteRegister(func(name string) macaron.Handler {
|
rr := NewRouteRegister(func(name string) macaron.Handler {
|
||||||
return emptyHandler(name)
|
return emptyHandler(name)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package bus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,6 +10,8 @@ type HandlerFunc interface{}
|
|||||||
type CtxHandlerFunc func()
|
type CtxHandlerFunc func()
|
||||||
type Msg interface{}
|
type Msg interface{}
|
||||||
|
|
||||||
|
var ErrHandlerNotFound = errors.New("handler not found")
|
||||||
|
|
||||||
type Bus interface {
|
type Bus interface {
|
||||||
Dispatch(msg Msg) error
|
Dispatch(msg Msg) error
|
||||||
DispatchCtx(ctx context.Context, msg Msg) error
|
DispatchCtx(ctx context.Context, msg Msg) error
|
||||||
@ -38,12 +40,17 @@ func New() Bus {
|
|||||||
return bus
|
return bus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Want to get rid of global bus
|
||||||
|
func GetBus() Bus {
|
||||||
|
return globalBus
|
||||||
|
}
|
||||||
|
|
||||||
func (b *InProcBus) DispatchCtx(ctx context.Context, msg Msg) error {
|
func (b *InProcBus) DispatchCtx(ctx context.Context, msg Msg) error {
|
||||||
var msgName = reflect.TypeOf(msg).Elem().Name()
|
var msgName = reflect.TypeOf(msg).Elem().Name()
|
||||||
|
|
||||||
var handler = b.handlers[msgName]
|
var handler = b.handlers[msgName]
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
return fmt.Errorf("handler not found for %s", msgName)
|
return ErrHandlerNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = make([]reflect.Value, 2)
|
var params = make([]reflect.Value, 2)
|
||||||
@ -64,7 +71,7 @@ func (b *InProcBus) Dispatch(msg Msg) error {
|
|||||||
|
|
||||||
var handler = b.handlers[msgName]
|
var handler = b.handlers[msgName]
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
return fmt.Errorf("handler not found for %s", msgName)
|
return ErrHandlerNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = make([]reflect.Value, 1)
|
var params = make([]reflect.Value, 1)
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/metrics"
|
"github.com/grafana/grafana/pkg/metrics"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
|
||||||
|
_ "github.com/grafana/grafana/pkg/extensions"
|
||||||
_ "github.com/grafana/grafana/pkg/services/alerting/conditions"
|
_ "github.com/grafana/grafana/pkg/services/alerting/conditions"
|
||||||
_ "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
_ "github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||||
_ "github.com/grafana/grafana/pkg/tsdb/cloudwatch"
|
_ "github.com/grafana/grafana/pkg/tsdb/cloudwatch"
|
||||||
@ -33,6 +34,7 @@ import (
|
|||||||
var version = "5.0.0"
|
var version = "5.0.0"
|
||||||
var commit = "NA"
|
var commit = "NA"
|
||||||
var buildstamp string
|
var buildstamp string
|
||||||
|
var enterprise string
|
||||||
|
|
||||||
var configFile = flag.String("config", "", "path to config file")
|
var configFile = flag.String("config", "", "path to config file")
|
||||||
var homePath = flag.String("homepath", "", "path to grafana install/home path, defaults to working directory")
|
var homePath = flag.String("homepath", "", "path to grafana install/home path, defaults to working directory")
|
||||||
@ -76,6 +78,7 @@ func main() {
|
|||||||
setting.BuildVersion = version
|
setting.BuildVersion = version
|
||||||
setting.BuildCommit = commit
|
setting.BuildCommit = commit
|
||||||
setting.BuildStamp = buildstampInt64
|
setting.BuildStamp = buildstampInt64
|
||||||
|
setting.Enterprise, _ = strconv.ParseBool(enterprise)
|
||||||
|
|
||||||
metrics.M_Grafana_Version.WithLabelValues(version).Set(1)
|
metrics.M_Grafana_Version.WithLabelValues(version).Set(1)
|
||||||
shutdownCompleted := make(chan int)
|
shutdownCompleted := make(chan int)
|
||||||
|
@ -8,9 +8,15 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/facebookgo/inject"
|
||||||
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
|
"github.com/grafana/grafana/pkg/registry"
|
||||||
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
@ -20,15 +26,17 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/login"
|
"github.com/grafana/grafana/pkg/login"
|
||||||
"github.com/grafana/grafana/pkg/metrics"
|
"github.com/grafana/grafana/pkg/metrics"
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/services/alerting"
|
|
||||||
"github.com/grafana/grafana/pkg/services/cleanup"
|
|
||||||
"github.com/grafana/grafana/pkg/services/notifications"
|
"github.com/grafana/grafana/pkg/services/notifications"
|
||||||
"github.com/grafana/grafana/pkg/services/search"
|
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/social"
|
"github.com/grafana/grafana/pkg/social"
|
||||||
"github.com/grafana/grafana/pkg/tracing"
|
"github.com/grafana/grafana/pkg/tracing"
|
||||||
|
|
||||||
|
_ "github.com/grafana/grafana/pkg/extensions"
|
||||||
|
_ "github.com/grafana/grafana/pkg/services/alerting"
|
||||||
|
_ "github.com/grafana/grafana/pkg/services/cleanup"
|
||||||
|
_ "github.com/grafana/grafana/pkg/services/search"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewGrafanaServer() *GrafanaServerImpl {
|
func NewGrafanaServer() *GrafanaServerImpl {
|
||||||
@ -48,18 +56,20 @@ type GrafanaServerImpl struct {
|
|||||||
shutdownFn context.CancelFunc
|
shutdownFn context.CancelFunc
|
||||||
childRoutines *errgroup.Group
|
childRoutines *errgroup.Group
|
||||||
log log.Logger
|
log log.Logger
|
||||||
|
RouteRegister api.RouteRegister `inject:""`
|
||||||
|
|
||||||
httpServer *api.HTTPServer
|
HttpServer *api.HTTPServer `inject:""`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GrafanaServerImpl) Start() error {
|
func (g *GrafanaServerImpl) Start() error {
|
||||||
g.initLogging()
|
g.initLogging()
|
||||||
g.writePIDFile()
|
g.writePIDFile()
|
||||||
|
|
||||||
initSql()
|
// initSql
|
||||||
|
sqlstore.NewEngine() // TODO: this should return an error
|
||||||
|
sqlstore.EnsureAdminUser()
|
||||||
|
|
||||||
metrics.Init(setting.Cfg)
|
metrics.Init(setting.Cfg)
|
||||||
search.Init()
|
|
||||||
login.Init()
|
login.Init()
|
||||||
social.NewOAuthService()
|
social.NewOAuthService()
|
||||||
|
|
||||||
@ -79,30 +89,64 @@ func (g *GrafanaServerImpl) Start() error {
|
|||||||
}
|
}
|
||||||
defer tracingCloser.Close()
|
defer tracingCloser.Close()
|
||||||
|
|
||||||
// init alerting
|
|
||||||
if setting.AlertingEnabled && setting.ExecuteAlerts {
|
|
||||||
engine := alerting.NewEngine()
|
|
||||||
g.childRoutines.Go(func() error { return engine.Run(g.context) })
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup service
|
|
||||||
cleanUpService := cleanup.NewCleanUpService()
|
|
||||||
g.childRoutines.Go(func() error { return cleanUpService.Run(g.context) })
|
|
||||||
|
|
||||||
if err = notifications.Init(); err != nil {
|
if err = notifications.Init(); err != nil {
|
||||||
return fmt.Errorf("Notification service failed to initialize. error: %v", err)
|
return fmt.Errorf("Notification service failed to initialize. error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serviceGraph := inject.Graph{}
|
||||||
|
serviceGraph.Provide(&inject.Object{Value: bus.GetBus()})
|
||||||
|
serviceGraph.Provide(&inject.Object{Value: dashboards.NewProvisioningService()})
|
||||||
|
serviceGraph.Provide(&inject.Object{Value: api.NewRouteRegister(middleware.RequestMetrics, middleware.RequestTracing)})
|
||||||
|
serviceGraph.Provide(&inject.Object{Value: api.HTTPServer{}})
|
||||||
|
services := registry.GetServices()
|
||||||
|
|
||||||
|
// Add all services to dependency graph
|
||||||
|
for _, service := range services {
|
||||||
|
serviceGraph.Provide(&inject.Object{Value: service})
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceGraph.Provide(&inject.Object{Value: g})
|
||||||
|
|
||||||
|
// Inject dependencies to services
|
||||||
|
if err := serviceGraph.Populate(); err != nil {
|
||||||
|
return fmt.Errorf("Failed to populate service dependency: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init & start services
|
||||||
|
for _, service := range services {
|
||||||
|
if registry.IsDisabled(service) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
g.log.Info("Initializing " + reflect.TypeOf(service).Elem().Name())
|
||||||
|
|
||||||
|
if err := service.Init(); err != nil {
|
||||||
|
return fmt.Errorf("Service init failed %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start background services
|
||||||
|
for index := range services {
|
||||||
|
service, ok := services[index].(registry.BackgroundService)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if registry.IsDisabled(services[index]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
g.childRoutines.Go(func() error {
|
||||||
|
err := service.Run(g.context)
|
||||||
|
g.log.Info("Stopped "+reflect.TypeOf(service).Elem().Name(), "reason", err)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
sendSystemdNotification("READY=1")
|
sendSystemdNotification("READY=1")
|
||||||
|
|
||||||
return g.startHttpServer()
|
return g.startHttpServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initSql() {
|
|
||||||
sqlstore.NewEngine()
|
|
||||||
sqlstore.EnsureAdminUser()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GrafanaServerImpl) initLogging() {
|
func (g *GrafanaServerImpl) initLogging() {
|
||||||
err := setting.NewConfigContext(&setting.CommandLineArgs{
|
err := setting.NewConfigContext(&setting.CommandLineArgs{
|
||||||
Config: *configFile,
|
Config: *configFile,
|
||||||
@ -115,14 +159,14 @@ func (g *GrafanaServerImpl) initLogging() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.log.Info("Starting Grafana", "version", version, "commit", commit, "compiled", time.Unix(setting.BuildStamp, 0))
|
g.log.Info("Starting "+setting.ApplicationName, "version", version, "commit", commit, "compiled", time.Unix(setting.BuildStamp, 0))
|
||||||
setting.LogConfigurationInfo()
|
setting.LogConfigurationInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GrafanaServerImpl) startHttpServer() error {
|
func (g *GrafanaServerImpl) startHttpServer() error {
|
||||||
g.httpServer = api.NewHTTPServer()
|
g.HttpServer.Init()
|
||||||
|
|
||||||
err := g.httpServer.Start(g.context)
|
err := g.HttpServer.Start(g.context)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Fail to start server. error: %v", err)
|
return fmt.Errorf("Fail to start server. error: %v", err)
|
||||||
@ -134,7 +178,7 @@ func (g *GrafanaServerImpl) startHttpServer() error {
|
|||||||
func (g *GrafanaServerImpl) Shutdown(code int, reason string) {
|
func (g *GrafanaServerImpl) Shutdown(code int, reason string) {
|
||||||
g.log.Info("Shutdown started", "code", code, "reason", reason)
|
g.log.Info("Shutdown started", "code", code, "reason", reason)
|
||||||
|
|
||||||
err := g.httpServer.Shutdown(g.context)
|
err := g.HttpServer.Shutdown(g.context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
g.log.Error("Failed to shutdown server", "error", err)
|
g.log.Error("Failed to shutdown server", "error", err)
|
||||||
}
|
}
|
||||||
|
3
pkg/extensions/main.go
Normal file
3
pkg/extensions/main.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package extensions
|
||||||
|
|
||||||
|
import _ "github.com/pkg/errors"
|
@ -58,7 +58,7 @@ func (p *PluginManager) Run(ctx context.Context) error {
|
|||||||
p.Kill()
|
p.Kill()
|
||||||
}
|
}
|
||||||
|
|
||||||
p.log.Info("Stopped Plugins", "error", ctx.Err())
|
p.log.Info("Stopped Plugins", "reason", ctx.Err())
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
pkg/registry/registry.go
Normal file
33
pkg/registry/registry.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
var services = []Service{}
|
||||||
|
|
||||||
|
func RegisterService(srv Service) {
|
||||||
|
services = append(services, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetServices() []Service {
|
||||||
|
return services
|
||||||
|
}
|
||||||
|
|
||||||
|
type Service interface {
|
||||||
|
Init() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Useful for alerting service
|
||||||
|
type CanBeDisabled interface {
|
||||||
|
IsDisabled() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type BackgroundService interface {
|
||||||
|
Run(ctx context.Context) error
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDisabled(srv Service) bool {
|
||||||
|
canBeDisabled, ok := srv.(CanBeDisabled)
|
||||||
|
return ok && canBeDisabled.IsDisabled()
|
||||||
|
}
|
@ -11,6 +11,8 @@ import (
|
|||||||
|
|
||||||
"github.com/benbjohnson/clock"
|
"github.com/benbjohnson/clock"
|
||||||
"github.com/grafana/grafana/pkg/log"
|
"github.com/grafana/grafana/pkg/log"
|
||||||
|
"github.com/grafana/grafana/pkg/registry"
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,31 +27,37 @@ type Engine struct {
|
|||||||
resultHandler ResultHandler
|
resultHandler ResultHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEngine() *Engine {
|
func init() {
|
||||||
e := &Engine{
|
registry.RegisterService(&Engine{})
|
||||||
ticker: NewTicker(time.Now(), time.Second*0, clock.New()),
|
}
|
||||||
execQueue: make(chan *Job, 1000),
|
|
||||||
scheduler: NewScheduler(),
|
|
||||||
evalHandler: NewEvalHandler(),
|
|
||||||
ruleReader: NewRuleReader(),
|
|
||||||
log: log.New("alerting.engine"),
|
|
||||||
resultHandler: NewResultHandler(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
func NewEngine() *Engine {
|
||||||
|
e := &Engine{}
|
||||||
|
e.Init()
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Engine) IsDisabled() bool {
|
||||||
|
return !setting.AlertingEnabled || !setting.ExecuteAlerts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Engine) Init() error {
|
||||||
|
e.ticker = NewTicker(time.Now(), time.Second*0, clock.New())
|
||||||
|
e.execQueue = make(chan *Job, 1000)
|
||||||
|
e.scheduler = NewScheduler()
|
||||||
|
e.evalHandler = NewEvalHandler()
|
||||||
|
e.ruleReader = NewRuleReader()
|
||||||
|
e.log = log.New("alerting.engine")
|
||||||
|
e.resultHandler = NewResultHandler()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Engine) Run(ctx context.Context) error {
|
func (e *Engine) Run(ctx context.Context) error {
|
||||||
e.log.Info("Initializing Alerting")
|
|
||||||
|
|
||||||
alertGroup, ctx := errgroup.WithContext(ctx)
|
alertGroup, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
alertGroup.Go(func() error { return e.alertingTicker(ctx) })
|
alertGroup.Go(func() error { return e.alertingTicker(ctx) })
|
||||||
alertGroup.Go(func() error { return e.runJobDispatcher(ctx) })
|
alertGroup.Go(func() error { return e.runJobDispatcher(ctx) })
|
||||||
|
|
||||||
err := alertGroup.Wait()
|
err := alertGroup.Wait()
|
||||||
|
|
||||||
e.log.Info("Stopped Alerting", "reason", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,10 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
"github.com/grafana/grafana/pkg/log"
|
"github.com/grafana/grafana/pkg/log"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/registry"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,24 +18,16 @@ type CleanUpService struct {
|
|||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCleanUpService() *CleanUpService {
|
func init() {
|
||||||
return &CleanUpService{
|
registry.RegisterService(&CleanUpService{})
|
||||||
log: log.New("cleanup"),
|
}
|
||||||
}
|
|
||||||
|
func (service *CleanUpService) Init() error {
|
||||||
|
service.log = log.New("cleanup")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *CleanUpService) Run(ctx context.Context) error {
|
func (service *CleanUpService) Run(ctx context.Context) error {
|
||||||
service.log.Info("Initializing CleanUpService")
|
|
||||||
|
|
||||||
g, _ := errgroup.WithContext(ctx)
|
|
||||||
g.Go(func() error { return service.start(ctx) })
|
|
||||||
|
|
||||||
err := g.Wait()
|
|
||||||
service.log.Info("Stopped CleanUpService", "reason", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (service *CleanUpService) start(ctx context.Context) error {
|
|
||||||
service.cleanUpTmpFiles()
|
service.cleanUpTmpFiles()
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Minute * 10)
|
ticker := time.NewTicker(time.Minute * 10)
|
||||||
|
@ -5,13 +5,23 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
func init() {
|
||||||
bus.AddHandler("search", searchHandler)
|
registry.RegisterService(&SearchService{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchHandler(query *Query) error {
|
type SearchService struct {
|
||||||
|
Bus bus.Bus `inject:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SearchService) Init() error {
|
||||||
|
s.Bus.AddHandler(s.searchHandler)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SearchService) searchHandler(query *Query) error {
|
||||||
dashQuery := FindPersistedDashboardsQuery{
|
dashQuery := FindPersistedDashboardsQuery{
|
||||||
Title: query.Title,
|
Title: query.Title,
|
||||||
SignedInUser: query.SignedInUser,
|
SignedInUser: query.SignedInUser,
|
||||||
|
@ -12,6 +12,7 @@ func TestSearch(t *testing.T) {
|
|||||||
|
|
||||||
Convey("Given search query", t, func() {
|
Convey("Given search query", t, func() {
|
||||||
query := Query{Limit: 2000, SignedInUser: &m.SignedInUser{IsGrafanaAdmin: true}}
|
query := Query{Limit: 2000, SignedInUser: &m.SignedInUser{IsGrafanaAdmin: true}}
|
||||||
|
ss := &SearchService{}
|
||||||
|
|
||||||
bus.AddHandler("test", func(query *FindPersistedDashboardsQuery) error {
|
bus.AddHandler("test", func(query *FindPersistedDashboardsQuery) error {
|
||||||
query.Result = HitList{
|
query.Result = HitList{
|
||||||
@ -35,7 +36,7 @@ func TestSearch(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Convey("That is empty", func() {
|
Convey("That is empty", func() {
|
||||||
err := searchHandler(&query)
|
err := ss.searchHandler(&query)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
Convey("should return sorted results", func() {
|
Convey("should return sorted results", func() {
|
||||||
|
@ -77,7 +77,7 @@ func EnsureAdminUser() {
|
|||||||
log.Info("Created default admin user: %v", setting.AdminUser)
|
log.Info("Created default admin user: %v", setting.AdminUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEngine() {
|
func NewEngine() *xorm.Engine {
|
||||||
x, err := getEngine()
|
x, err := getEngine()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -91,6 +91,8 @@ func NewEngine() {
|
|||||||
sqlog.Error("Fail to initialize orm engine", "error", err)
|
sqlog.Error("Fail to initialize orm engine", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetEngine(engine *xorm.Engine) (err error) {
|
func SetEngine(engine *xorm.Engine) (err error) {
|
||||||
|
@ -45,9 +45,11 @@ var (
|
|||||||
InstanceName string
|
InstanceName string
|
||||||
|
|
||||||
// build
|
// build
|
||||||
BuildVersion string
|
BuildVersion string
|
||||||
BuildCommit string
|
BuildCommit string
|
||||||
BuildStamp int64
|
BuildStamp int64
|
||||||
|
Enterprise bool
|
||||||
|
ApplicationName string
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
LogsPath string
|
LogsPath string
|
||||||
@ -486,6 +488,11 @@ func NewConfigContext(args *CommandLineArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplicationName = "Grafana"
|
||||||
|
if Enterprise {
|
||||||
|
ApplicationName += " Enterprise"
|
||||||
|
}
|
||||||
|
|
||||||
Env = Cfg.Section("").Key("app_mode").MustString("development")
|
Env = Cfg.Section("").Key("app_mode").MustString("development")
|
||||||
InstanceName = Cfg.Section("").Key("instance_name").MustString("unknown_instance_name")
|
InstanceName = Cfg.Section("").Key("instance_name").MustString("unknown_instance_name")
|
||||||
PluginsPath = makeAbsolute(Cfg.Section("paths").Key("plugins").String(), HomePath)
|
PluginsPath = makeAbsolute(Cfg.Section("paths").Key("plugins").String(), HomePath)
|
||||||
|
58
scripts/build/build_enterprise.sh
Executable file
58
scripts/build/build_enterprise.sh
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script is executed from within the container.
|
||||||
|
#
|
||||||
|
|
||||||
|
echo "building enterprise version"
|
||||||
|
|
||||||
|
GOPATH=/go
|
||||||
|
REPO_PATH=$GOPATH/src/github.com/grafana/grafana
|
||||||
|
|
||||||
|
|
||||||
|
cd /go/src/github.com/grafana/grafana
|
||||||
|
echo "current dir: $(pwd)"
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
git clone -b ee_build --single-branch git@github.com:grafana/grafana-enterprise.git --depth 10
|
||||||
|
cd grafana-enterprise
|
||||||
|
git checkout 7fbae9c1be3467c4a39cf6ad85278a6896ceb49f
|
||||||
|
./build.sh
|
||||||
|
|
||||||
|
cd ../grafana
|
||||||
|
|
||||||
|
function exit_if_fail {
|
||||||
|
command=$@
|
||||||
|
echo "Executing '$command'"
|
||||||
|
eval $command
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "'$command' returned $rc."
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_if_fail go test ./pkg/extensions/...
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$CIRCLE_TAG" != "" ]; then
|
||||||
|
echo "Building a release from tag $ls"
|
||||||
|
go run build.go -buildNumber=${CIRCLE_BUILD_NUM} -enterprise=true -includeBuildNumber=false build
|
||||||
|
else
|
||||||
|
echo "Building incremental build for $CIRCLE_BRANCH"
|
||||||
|
go run build.go -buildNumber=${CIRCLE_BUILD_NUM} -enterprise=true build
|
||||||
|
fi
|
||||||
|
|
||||||
|
yarn install --pure-lockfile --no-progress
|
||||||
|
|
||||||
|
source /etc/profile.d/rvm.sh
|
||||||
|
|
||||||
|
echo "current dir: $(pwd)"
|
||||||
|
|
||||||
|
if [ "$CIRCLE_TAG" != "" ]; then
|
||||||
|
echo "Packaging a release from tag $CIRCLE_TAG"
|
||||||
|
go run build.go -buildNumber=${CIRCLE_BUILD_NUM} -enterprise=true -includeBuildNumber=false package latest
|
||||||
|
else
|
||||||
|
echo "Packaging incremental build for $CIRCLE_BRANCH"
|
||||||
|
go run build.go -buildNumber=${CIRCLE_BUILD_NUM} -enterprise=true package latest
|
||||||
|
fi
|
576
vendor/github.com/facebookgo/inject/inject.go
generated
vendored
Normal file
576
vendor/github.com/facebookgo/inject/inject.go
generated
vendored
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
// Package inject provides a reflect based injector. A large application built
|
||||||
|
// with dependency injection in mind will typically involve the boring work of
|
||||||
|
// setting up the object graph. This library attempts to take care of this
|
||||||
|
// boring work by creating and connecting the various objects. Its use involves
|
||||||
|
// you seeding the object graph with some (possibly incomplete) objects, where
|
||||||
|
// the underlying types have been tagged for injection. Given this, the
|
||||||
|
// library will populate the objects creating new ones as necessary. It uses
|
||||||
|
// singletons by default, supports optional private instances as well as named
|
||||||
|
// instances.
|
||||||
|
//
|
||||||
|
// It works using Go's reflection package and is inherently limited in what it
|
||||||
|
// can do as opposed to a code-gen system with respect to private fields.
|
||||||
|
//
|
||||||
|
// The usage pattern for the library involves struct tags. It requires the tag
|
||||||
|
// format used by the various standard libraries, like json, xml etc. It
|
||||||
|
// involves tags in one of the three forms below:
|
||||||
|
//
|
||||||
|
// `inject:""`
|
||||||
|
// `inject:"private"`
|
||||||
|
// `inject:"dev logger"`
|
||||||
|
//
|
||||||
|
// The first no value syntax is for the common case of a singleton dependency
|
||||||
|
// of the associated type. The second triggers creation of a private instance
|
||||||
|
// for the associated type. Finally the last form is asking for a named
|
||||||
|
// dependency called "dev logger".
|
||||||
|
package inject
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/facebookgo/structtag"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logger allows for simple logging as inject traverses and populates the
|
||||||
|
// object graph.
|
||||||
|
type Logger interface {
|
||||||
|
Debugf(format string, v ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate is a short-hand for populating a graph with the given incomplete
|
||||||
|
// object values.
|
||||||
|
func Populate(values ...interface{}) error {
|
||||||
|
var g Graph
|
||||||
|
for _, v := range values {
|
||||||
|
if err := g.Provide(&Object{Value: v}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return g.Populate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Object in the Graph.
|
||||||
|
type Object struct {
|
||||||
|
Value interface{}
|
||||||
|
Name string // Optional
|
||||||
|
Complete bool // If true, the Value will be considered complete
|
||||||
|
Fields map[string]*Object // Populated with the field names that were injected and their corresponding *Object.
|
||||||
|
reflectType reflect.Type
|
||||||
|
reflectValue reflect.Value
|
||||||
|
private bool // If true, the Value will not be used and will only be populated
|
||||||
|
created bool // If true, the Object was created by us
|
||||||
|
embedded bool // If true, the Object is an embedded struct provided internally
|
||||||
|
}
|
||||||
|
|
||||||
|
// String representation suitable for human consumption.
|
||||||
|
func (o *Object) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
fmt.Fprint(&buf, o.reflectType)
|
||||||
|
if o.Name != "" {
|
||||||
|
fmt.Fprintf(&buf, " named %s", o.Name)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Object) addDep(field string, dep *Object) {
|
||||||
|
if o.Fields == nil {
|
||||||
|
o.Fields = make(map[string]*Object)
|
||||||
|
}
|
||||||
|
o.Fields[field] = dep
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Graph of Objects.
|
||||||
|
type Graph struct {
|
||||||
|
Logger Logger // Optional, will trigger debug logging.
|
||||||
|
unnamed []*Object
|
||||||
|
unnamedType map[reflect.Type]bool
|
||||||
|
named map[string]*Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide objects to the Graph. The Object documentation describes
|
||||||
|
// the impact of various fields.
|
||||||
|
func (g *Graph) Provide(objects ...*Object) error {
|
||||||
|
for _, o := range objects {
|
||||||
|
o.reflectType = reflect.TypeOf(o.Value)
|
||||||
|
o.reflectValue = reflect.ValueOf(o.Value)
|
||||||
|
|
||||||
|
if o.Fields != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"fields were specified on object %s when it was provided",
|
||||||
|
o,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Name == "" {
|
||||||
|
if !isStructPtr(o.reflectType) {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"expected unnamed object value to be a pointer to a struct but got type %s "+
|
||||||
|
"with value %v",
|
||||||
|
o.reflectType,
|
||||||
|
o.Value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !o.private {
|
||||||
|
if g.unnamedType == nil {
|
||||||
|
g.unnamedType = make(map[reflect.Type]bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.unnamedType[o.reflectType] {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"provided two unnamed instances of type *%s.%s",
|
||||||
|
o.reflectType.Elem().PkgPath(), o.reflectType.Elem().Name(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
g.unnamedType[o.reflectType] = true
|
||||||
|
}
|
||||||
|
g.unnamed = append(g.unnamed, o)
|
||||||
|
} else {
|
||||||
|
if g.named == nil {
|
||||||
|
g.named = make(map[string]*Object)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.named[o.Name] != nil {
|
||||||
|
return fmt.Errorf("provided two instances named %s", o.Name)
|
||||||
|
}
|
||||||
|
g.named[o.Name] = o
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.Logger != nil {
|
||||||
|
if o.created {
|
||||||
|
g.Logger.Debugf("created %s", o)
|
||||||
|
} else if o.embedded {
|
||||||
|
g.Logger.Debugf("provided embedded %s", o)
|
||||||
|
} else {
|
||||||
|
g.Logger.Debugf("provided %s", o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate the incomplete Objects.
|
||||||
|
func (g *Graph) Populate() error {
|
||||||
|
for _, o := range g.named {
|
||||||
|
if o.Complete {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.populateExplicit(o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We append and modify our slice as we go along, so we don't use a standard
|
||||||
|
// range loop, and do a single pass thru each object in our graph.
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
if i == len(g.unnamed) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
o := g.unnamed[i]
|
||||||
|
i++
|
||||||
|
|
||||||
|
if o.Complete {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.populateExplicit(o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Second pass handles injecting Interface values to ensure we have created
|
||||||
|
// all concrete types first.
|
||||||
|
for _, o := range g.unnamed {
|
||||||
|
if o.Complete {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.populateUnnamedInterface(o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range g.named {
|
||||||
|
if o.Complete {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.populateUnnamedInterface(o); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Graph) populateExplicit(o *Object) error {
|
||||||
|
// Ignore named value types.
|
||||||
|
if o.Name != "" && !isStructPtr(o.reflectType) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
StructLoop:
|
||||||
|
for i := 0; i < o.reflectValue.Elem().NumField(); i++ {
|
||||||
|
field := o.reflectValue.Elem().Field(i)
|
||||||
|
fieldType := field.Type()
|
||||||
|
fieldTag := o.reflectType.Elem().Field(i).Tag
|
||||||
|
fieldName := o.reflectType.Elem().Field(i).Name
|
||||||
|
tag, err := parseTag(string(fieldTag))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unexpected tag format `%s` for field %s in type %s",
|
||||||
|
string(fieldTag),
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip fields without a tag.
|
||||||
|
if tag == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot be used with unexported fields.
|
||||||
|
if !field.CanSet() {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"inject requested on unexported field %s in type %s",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inline tag on anything besides a struct is considered invalid.
|
||||||
|
if tag.Inline && fieldType.Kind() != reflect.Struct {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"inline requested on non inlined field %s in type %s",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't overwrite existing values.
|
||||||
|
if !isNilOrZero(field, fieldType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Named injects must have been explicitly provided.
|
||||||
|
if tag.Name != "" {
|
||||||
|
existing := g.named[tag.Name]
|
||||||
|
if existing == nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"did not find object named %s required by field %s in type %s",
|
||||||
|
tag.Name,
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !existing.reflectType.AssignableTo(fieldType) {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"object named %s of type %s is not assignable to field %s (%s) in type %s",
|
||||||
|
tag.Name,
|
||||||
|
fieldType,
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
existing.reflectType,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
field.Set(reflect.ValueOf(existing.Value))
|
||||||
|
if g.Logger != nil {
|
||||||
|
g.Logger.Debugf(
|
||||||
|
"assigned %s to field %s in %s",
|
||||||
|
existing,
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
o.addDep(fieldName, existing)
|
||||||
|
continue StructLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inline struct values indicate we want to traverse into it, but not
|
||||||
|
// inject itself. We require an explicit "inline" tag for this to work.
|
||||||
|
if fieldType.Kind() == reflect.Struct {
|
||||||
|
if tag.Private {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"cannot use private inject on inline struct on field %s in type %s",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tag.Inline {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"inline struct on field %s in type %s requires an explicit \"inline\" tag",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := g.Provide(&Object{
|
||||||
|
Value: field.Addr().Interface(),
|
||||||
|
private: true,
|
||||||
|
embedded: o.reflectType.Elem().Field(i).Anonymous,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface injection is handled in a second pass.
|
||||||
|
if fieldType.Kind() == reflect.Interface {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maps are created and required to be private.
|
||||||
|
if fieldType.Kind() == reflect.Map {
|
||||||
|
if !tag.Private {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"inject on map field %s in type %s must be named or private",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
field.Set(reflect.MakeMap(fieldType))
|
||||||
|
if g.Logger != nil {
|
||||||
|
g.Logger.Debugf(
|
||||||
|
"made map for field %s in %s",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can only inject Pointers from here on.
|
||||||
|
if !isStructPtr(fieldType) {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"found inject tag on unsupported field %s in type %s",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unless it's a private inject, we'll look for an existing instance of the
|
||||||
|
// same type.
|
||||||
|
if !tag.Private {
|
||||||
|
for _, existing := range g.unnamed {
|
||||||
|
if existing.private {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if existing.reflectType.AssignableTo(fieldType) {
|
||||||
|
field.Set(reflect.ValueOf(existing.Value))
|
||||||
|
if g.Logger != nil {
|
||||||
|
g.Logger.Debugf(
|
||||||
|
"assigned existing %s to field %s in %s",
|
||||||
|
existing,
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
o.addDep(fieldName, existing)
|
||||||
|
continue StructLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newValue := reflect.New(fieldType.Elem())
|
||||||
|
newObject := &Object{
|
||||||
|
Value: newValue.Interface(),
|
||||||
|
private: tag.Private,
|
||||||
|
created: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the newly ceated object to the known set of objects.
|
||||||
|
err = g.Provide(newObject)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally assign the newly created object to our field.
|
||||||
|
field.Set(newValue)
|
||||||
|
if g.Logger != nil {
|
||||||
|
g.Logger.Debugf(
|
||||||
|
"assigned newly created %s to field %s in %s",
|
||||||
|
newObject,
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
o.addDep(fieldName, newObject)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Graph) populateUnnamedInterface(o *Object) error {
|
||||||
|
// Ignore named value types.
|
||||||
|
if o.Name != "" && !isStructPtr(o.reflectType) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < o.reflectValue.Elem().NumField(); i++ {
|
||||||
|
field := o.reflectValue.Elem().Field(i)
|
||||||
|
fieldType := field.Type()
|
||||||
|
fieldTag := o.reflectType.Elem().Field(i).Tag
|
||||||
|
fieldName := o.reflectType.Elem().Field(i).Name
|
||||||
|
tag, err := parseTag(string(fieldTag))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"unexpected tag format `%s` for field %s in type %s",
|
||||||
|
string(fieldTag),
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip fields without a tag.
|
||||||
|
if tag == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only handle interface injection here. Other cases including errors
|
||||||
|
// are handled in the first pass when we inject pointers.
|
||||||
|
if fieldType.Kind() != reflect.Interface {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface injection can't be private because we can't instantiate new
|
||||||
|
// instances of an interface.
|
||||||
|
if tag.Private {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"found private inject tag on interface field %s in type %s",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't overwrite existing values.
|
||||||
|
if !isNilOrZero(field, fieldType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Named injects must have already been handled in populateExplicit.
|
||||||
|
if tag.Name != "" {
|
||||||
|
panic(fmt.Sprintf("unhandled named instance with name %s", tag.Name))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find one, and only one assignable value for the field.
|
||||||
|
var found *Object
|
||||||
|
for _, existing := range g.unnamed {
|
||||||
|
if existing.private {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if existing.reflectType.AssignableTo(fieldType) {
|
||||||
|
if found != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"found two assignable values for field %s in type %s. one type "+
|
||||||
|
"%s with value %v and another type %s with value %v",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
found.reflectType,
|
||||||
|
found.Value,
|
||||||
|
existing.reflectType,
|
||||||
|
existing.reflectValue,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
found = existing
|
||||||
|
field.Set(reflect.ValueOf(existing.Value))
|
||||||
|
if g.Logger != nil {
|
||||||
|
g.Logger.Debugf(
|
||||||
|
"assigned existing %s to interface field %s in %s",
|
||||||
|
existing,
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
o.addDep(fieldName, existing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't find an assignable value, we're missing something.
|
||||||
|
if found == nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"found no assignable value for field %s in type %s",
|
||||||
|
o.reflectType.Elem().Field(i).Name,
|
||||||
|
o.reflectType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Objects returns all known objects, named as well as unnamed. The returned
|
||||||
|
// elements are not in a stable order.
|
||||||
|
func (g *Graph) Objects() []*Object {
|
||||||
|
objects := make([]*Object, 0, len(g.unnamed)+len(g.named))
|
||||||
|
for _, o := range g.unnamed {
|
||||||
|
if !o.embedded {
|
||||||
|
objects = append(objects, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, o := range g.named {
|
||||||
|
if !o.embedded {
|
||||||
|
objects = append(objects, o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// randomize to prevent callers from relying on ordering
|
||||||
|
for i := 0; i < len(objects); i++ {
|
||||||
|
j := rand.Intn(i + 1)
|
||||||
|
objects[i], objects[j] = objects[j], objects[i]
|
||||||
|
}
|
||||||
|
return objects
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
injectOnly = &tag{}
|
||||||
|
injectPrivate = &tag{Private: true}
|
||||||
|
injectInline = &tag{Inline: true}
|
||||||
|
)
|
||||||
|
|
||||||
|
type tag struct {
|
||||||
|
Name string
|
||||||
|
Inline bool
|
||||||
|
Private bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTag(t string) (*tag, error) {
|
||||||
|
found, value, err := structtag.Extract("inject", t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if value == "" {
|
||||||
|
return injectOnly, nil
|
||||||
|
}
|
||||||
|
if value == "inline" {
|
||||||
|
return injectInline, nil
|
||||||
|
}
|
||||||
|
if value == "private" {
|
||||||
|
return injectPrivate, nil
|
||||||
|
}
|
||||||
|
return &tag{Name: value}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isStructPtr(t reflect.Type) bool {
|
||||||
|
return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNilOrZero(v reflect.Value, t reflect.Type) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
default:
|
||||||
|
return reflect.DeepEqual(v.Interface(), reflect.Zero(t).Interface())
|
||||||
|
case reflect.Interface, reflect.Ptr:
|
||||||
|
return v.IsNil()
|
||||||
|
}
|
||||||
|
}
|
30
vendor/github.com/facebookgo/inject/license
generated
vendored
Normal file
30
vendor/github.com/facebookgo/inject/license
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
BSD License
|
||||||
|
|
||||||
|
For inject software
|
||||||
|
|
||||||
|
Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name Facebook nor the names of its contributors may be used to
|
||||||
|
endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
33
vendor/github.com/facebookgo/inject/patents
generated
vendored
Normal file
33
vendor/github.com/facebookgo/inject/patents
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
Additional Grant of Patent Rights Version 2
|
||||||
|
|
||||||
|
"Software" means the inject software distributed by Facebook, Inc.
|
||||||
|
|
||||||
|
Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software
|
||||||
|
("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable
|
||||||
|
(subject to the termination provision below) license under any Necessary
|
||||||
|
Claims, to make, have made, use, sell, offer to sell, import, and otherwise
|
||||||
|
transfer the Software. For avoidance of doubt, no license is granted under
|
||||||
|
Facebook’s rights in any patent claims that are infringed by (i) modifications
|
||||||
|
to the Software made by you or any third party or (ii) the Software in
|
||||||
|
combination with any software or other technology.
|
||||||
|
|
||||||
|
The license granted hereunder will terminate, automatically and without notice,
|
||||||
|
if you (or any of your subsidiaries, corporate affiliates or agents) initiate
|
||||||
|
directly or indirectly, or take a direct financial interest in, any Patent
|
||||||
|
Assertion: (i) against Facebook or any of its subsidiaries or corporate
|
||||||
|
affiliates, (ii) against any party if such Patent Assertion arises in whole or
|
||||||
|
in part from any software, technology, product or service of Facebook or any of
|
||||||
|
its subsidiaries or corporate affiliates, or (iii) against any party relating
|
||||||
|
to the Software. Notwithstanding the foregoing, if Facebook or any of its
|
||||||
|
subsidiaries or corporate affiliates files a lawsuit alleging patent
|
||||||
|
infringement against you in the first instance, and you respond by filing a
|
||||||
|
patent infringement counterclaim in that lawsuit against that party that is
|
||||||
|
unrelated to the Software, the license granted hereunder will not terminate
|
||||||
|
under section (i) of this paragraph due to such counterclaim.
|
||||||
|
|
||||||
|
A "Necessary Claim" is a claim of a patent owned by Facebook that is
|
||||||
|
necessarily infringed by the Software standing alone.
|
||||||
|
|
||||||
|
A "Patent Assertion" is any lawsuit or other action alleging direct, indirect,
|
||||||
|
or contributory infringement or inducement to infringe any patent, including a
|
||||||
|
cross-claim or counterclaim.
|
27
vendor/github.com/facebookgo/structtag/license
generated
vendored
Normal file
27
vendor/github.com/facebookgo/structtag/license
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
61
vendor/github.com/facebookgo/structtag/structtag.go
generated
vendored
Normal file
61
vendor/github.com/facebookgo/structtag/structtag.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Package structtag provides parsing of the defacto struct tag style.
|
||||||
|
package structtag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errInvalidTag = errors.New("invalid tag")
|
||||||
|
|
||||||
|
// Extract the quoted value for the given name returning it if it is found. The
|
||||||
|
// found boolean helps differentiate between the "empty and found" vs "empty
|
||||||
|
// and not found" nature of default empty strings.
|
||||||
|
func Extract(name, tag string) (found bool, value string, err error) {
|
||||||
|
for tag != "" {
|
||||||
|
// skip leading space
|
||||||
|
i := 0
|
||||||
|
for i < len(tag) && tag[i] == ' ' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
tag = tag[i:]
|
||||||
|
if tag == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// scan to colon.
|
||||||
|
// a space or a quote is a syntax error
|
||||||
|
i = 0
|
||||||
|
for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
|
||||||
|
return false, "", errInvalidTag
|
||||||
|
}
|
||||||
|
foundName := string(tag[:i])
|
||||||
|
tag = tag[i+1:]
|
||||||
|
|
||||||
|
// scan quoted string to find value
|
||||||
|
i = 1
|
||||||
|
for i < len(tag) && tag[i] != '"' {
|
||||||
|
if tag[i] == '\\' {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if i >= len(tag) {
|
||||||
|
return false, "", errInvalidTag
|
||||||
|
}
|
||||||
|
qvalue := string(tag[:i+1])
|
||||||
|
tag = tag[i+1:]
|
||||||
|
|
||||||
|
if foundName == name {
|
||||||
|
value, err := strconv.Unquote(qvalue)
|
||||||
|
if err != nil {
|
||||||
|
return false, "", err
|
||||||
|
}
|
||||||
|
return true, value, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, "", nil
|
||||||
|
}
|
23
vendor/github.com/pkg/errors/LICENSE
generated
vendored
Normal file
23
vendor/github.com/pkg/errors/LICENSE
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
269
vendor/github.com/pkg/errors/errors.go
generated
vendored
Normal file
269
vendor/github.com/pkg/errors/errors.go
generated
vendored
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
// Package errors provides simple error handling primitives.
|
||||||
|
//
|
||||||
|
// The traditional error handling idiom in Go is roughly akin to
|
||||||
|
//
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// which applied recursively up the call stack results in error reports
|
||||||
|
// without context or debugging information. The errors package allows
|
||||||
|
// programmers to add context to the failure path in their code in a way
|
||||||
|
// that does not destroy the original value of the error.
|
||||||
|
//
|
||||||
|
// Adding context to an error
|
||||||
|
//
|
||||||
|
// The errors.Wrap function returns a new error that adds context to the
|
||||||
|
// original error by recording a stack trace at the point Wrap is called,
|
||||||
|
// and the supplied message. For example
|
||||||
|
//
|
||||||
|
// _, err := ioutil.ReadAll(r)
|
||||||
|
// if err != nil {
|
||||||
|
// return errors.Wrap(err, "read failed")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// If additional control is required the errors.WithStack and errors.WithMessage
|
||||||
|
// functions destructure errors.Wrap into its component operations of annotating
|
||||||
|
// an error with a stack trace and an a message, respectively.
|
||||||
|
//
|
||||||
|
// Retrieving the cause of an error
|
||||||
|
//
|
||||||
|
// Using errors.Wrap constructs a stack of errors, adding context to the
|
||||||
|
// preceding error. Depending on the nature of the error it may be necessary
|
||||||
|
// to reverse the operation of errors.Wrap to retrieve the original error
|
||||||
|
// for inspection. Any error value which implements this interface
|
||||||
|
//
|
||||||
|
// type causer interface {
|
||||||
|
// Cause() error
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
|
||||||
|
// the topmost error which does not implement causer, which is assumed to be
|
||||||
|
// the original cause. For example:
|
||||||
|
//
|
||||||
|
// switch err := errors.Cause(err).(type) {
|
||||||
|
// case *MyError:
|
||||||
|
// // handle specifically
|
||||||
|
// default:
|
||||||
|
// // unknown error
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// causer interface is not exported by this package, but is considered a part
|
||||||
|
// of stable public API.
|
||||||
|
//
|
||||||
|
// Formatted printing of errors
|
||||||
|
//
|
||||||
|
// All error values returned from this package implement fmt.Formatter and can
|
||||||
|
// be formatted by the fmt package. The following verbs are supported
|
||||||
|
//
|
||||||
|
// %s print the error. If the error has a Cause it will be
|
||||||
|
// printed recursively
|
||||||
|
// %v see %s
|
||||||
|
// %+v extended format. Each Frame of the error's StackTrace will
|
||||||
|
// be printed in detail.
|
||||||
|
//
|
||||||
|
// Retrieving the stack trace of an error or wrapper
|
||||||
|
//
|
||||||
|
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
|
||||||
|
// invoked. This information can be retrieved with the following interface.
|
||||||
|
//
|
||||||
|
// type stackTracer interface {
|
||||||
|
// StackTrace() errors.StackTrace
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Where errors.StackTrace is defined as
|
||||||
|
//
|
||||||
|
// type StackTrace []Frame
|
||||||
|
//
|
||||||
|
// The Frame type represents a call site in the stack trace. Frame supports
|
||||||
|
// the fmt.Formatter interface that can be used for printing information about
|
||||||
|
// the stack trace of this error. For example:
|
||||||
|
//
|
||||||
|
// if err, ok := err.(stackTracer); ok {
|
||||||
|
// for _, f := range err.StackTrace() {
|
||||||
|
// fmt.Printf("%+s:%d", f)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// stackTracer interface is not exported by this package, but is considered a part
|
||||||
|
// of stable public API.
|
||||||
|
//
|
||||||
|
// See the documentation for Frame.Format for more details.
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New returns an error with the supplied message.
|
||||||
|
// New also records the stack trace at the point it was called.
|
||||||
|
func New(message string) error {
|
||||||
|
return &fundamental{
|
||||||
|
msg: message,
|
||||||
|
stack: callers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf formats according to a format specifier and returns the string
|
||||||
|
// as a value that satisfies error.
|
||||||
|
// Errorf also records the stack trace at the point it was called.
|
||||||
|
func Errorf(format string, args ...interface{}) error {
|
||||||
|
return &fundamental{
|
||||||
|
msg: fmt.Sprintf(format, args...),
|
||||||
|
stack: callers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fundamental is an error that has a message and a stack, but no caller.
|
||||||
|
type fundamental struct {
|
||||||
|
msg string
|
||||||
|
*stack
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fundamental) Error() string { return f.msg }
|
||||||
|
|
||||||
|
func (f *fundamental) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
if s.Flag('+') {
|
||||||
|
io.WriteString(s, f.msg)
|
||||||
|
f.stack.Format(s, verb)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case 's':
|
||||||
|
io.WriteString(s, f.msg)
|
||||||
|
case 'q':
|
||||||
|
fmt.Fprintf(s, "%q", f.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithStack annotates err with a stack trace at the point WithStack was called.
|
||||||
|
// If err is nil, WithStack returns nil.
|
||||||
|
func WithStack(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &withStack{
|
||||||
|
err,
|
||||||
|
callers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type withStack struct {
|
||||||
|
error
|
||||||
|
*stack
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *withStack) Cause() error { return w.error }
|
||||||
|
|
||||||
|
func (w *withStack) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
if s.Flag('+') {
|
||||||
|
fmt.Fprintf(s, "%+v", w.Cause())
|
||||||
|
w.stack.Format(s, verb)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case 's':
|
||||||
|
io.WriteString(s, w.Error())
|
||||||
|
case 'q':
|
||||||
|
fmt.Fprintf(s, "%q", w.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap returns an error annotating err with a stack trace
|
||||||
|
// at the point Wrap is called, and the supplied message.
|
||||||
|
// If err is nil, Wrap returns nil.
|
||||||
|
func Wrap(err error, message string) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = &withMessage{
|
||||||
|
cause: err,
|
||||||
|
msg: message,
|
||||||
|
}
|
||||||
|
return &withStack{
|
||||||
|
err,
|
||||||
|
callers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapf returns an error annotating err with a stack trace
|
||||||
|
// at the point Wrapf is call, and the format specifier.
|
||||||
|
// If err is nil, Wrapf returns nil.
|
||||||
|
func Wrapf(err error, format string, args ...interface{}) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = &withMessage{
|
||||||
|
cause: err,
|
||||||
|
msg: fmt.Sprintf(format, args...),
|
||||||
|
}
|
||||||
|
return &withStack{
|
||||||
|
err,
|
||||||
|
callers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMessage annotates err with a new message.
|
||||||
|
// If err is nil, WithMessage returns nil.
|
||||||
|
func WithMessage(err error, message string) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &withMessage{
|
||||||
|
cause: err,
|
||||||
|
msg: message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type withMessage struct {
|
||||||
|
cause error
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
|
||||||
|
func (w *withMessage) Cause() error { return w.cause }
|
||||||
|
|
||||||
|
func (w *withMessage) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
if s.Flag('+') {
|
||||||
|
fmt.Fprintf(s, "%+v\n", w.Cause())
|
||||||
|
io.WriteString(s, w.msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case 's', 'q':
|
||||||
|
io.WriteString(s, w.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cause returns the underlying cause of the error, if possible.
|
||||||
|
// An error value has a cause if it implements the following
|
||||||
|
// interface:
|
||||||
|
//
|
||||||
|
// type causer interface {
|
||||||
|
// Cause() error
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// If the error does not implement Cause, the original error will
|
||||||
|
// be returned. If the error is nil, nil will be returned without further
|
||||||
|
// investigation.
|
||||||
|
func Cause(err error) error {
|
||||||
|
type causer interface {
|
||||||
|
Cause() error
|
||||||
|
}
|
||||||
|
|
||||||
|
for err != nil {
|
||||||
|
cause, ok := err.(causer)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
err = cause.Cause()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
178
vendor/github.com/pkg/errors/stack.go
generated
vendored
Normal file
178
vendor/github.com/pkg/errors/stack.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package errors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Frame represents a program counter inside a stack frame.
|
||||||
|
type Frame uintptr
|
||||||
|
|
||||||
|
// pc returns the program counter for this frame;
|
||||||
|
// multiple frames may have the same PC value.
|
||||||
|
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
|
||||||
|
|
||||||
|
// file returns the full path to the file that contains the
|
||||||
|
// function for this Frame's pc.
|
||||||
|
func (f Frame) file() string {
|
||||||
|
fn := runtime.FuncForPC(f.pc())
|
||||||
|
if fn == nil {
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
file, _ := fn.FileLine(f.pc())
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
// line returns the line number of source code of the
|
||||||
|
// function for this Frame's pc.
|
||||||
|
func (f Frame) line() int {
|
||||||
|
fn := runtime.FuncForPC(f.pc())
|
||||||
|
if fn == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
_, line := fn.FileLine(f.pc())
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format formats the frame according to the fmt.Formatter interface.
|
||||||
|
//
|
||||||
|
// %s source file
|
||||||
|
// %d source line
|
||||||
|
// %n function name
|
||||||
|
// %v equivalent to %s:%d
|
||||||
|
//
|
||||||
|
// Format accepts flags that alter the printing of some verbs, as follows:
|
||||||
|
//
|
||||||
|
// %+s path of source file relative to the compile time GOPATH
|
||||||
|
// %+v equivalent to %+s:%d
|
||||||
|
func (f Frame) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 's':
|
||||||
|
switch {
|
||||||
|
case s.Flag('+'):
|
||||||
|
pc := f.pc()
|
||||||
|
fn := runtime.FuncForPC(pc)
|
||||||
|
if fn == nil {
|
||||||
|
io.WriteString(s, "unknown")
|
||||||
|
} else {
|
||||||
|
file, _ := fn.FileLine(pc)
|
||||||
|
fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
io.WriteString(s, path.Base(f.file()))
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
fmt.Fprintf(s, "%d", f.line())
|
||||||
|
case 'n':
|
||||||
|
name := runtime.FuncForPC(f.pc()).Name()
|
||||||
|
io.WriteString(s, funcname(name))
|
||||||
|
case 'v':
|
||||||
|
f.Format(s, 's')
|
||||||
|
io.WriteString(s, ":")
|
||||||
|
f.Format(s, 'd')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
||||||
|
type StackTrace []Frame
|
||||||
|
|
||||||
|
func (st StackTrace) Format(s fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
switch {
|
||||||
|
case s.Flag('+'):
|
||||||
|
for _, f := range st {
|
||||||
|
fmt.Fprintf(s, "\n%+v", f)
|
||||||
|
}
|
||||||
|
case s.Flag('#'):
|
||||||
|
fmt.Fprintf(s, "%#v", []Frame(st))
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(s, "%v", []Frame(st))
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
fmt.Fprintf(s, "%s", []Frame(st))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stack represents a stack of program counters.
|
||||||
|
type stack []uintptr
|
||||||
|
|
||||||
|
func (s *stack) Format(st fmt.State, verb rune) {
|
||||||
|
switch verb {
|
||||||
|
case 'v':
|
||||||
|
switch {
|
||||||
|
case st.Flag('+'):
|
||||||
|
for _, pc := range *s {
|
||||||
|
f := Frame(pc)
|
||||||
|
fmt.Fprintf(st, "\n%+v", f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stack) StackTrace() StackTrace {
|
||||||
|
f := make([]Frame, len(*s))
|
||||||
|
for i := 0; i < len(f); i++ {
|
||||||
|
f[i] = Frame((*s)[i])
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func callers() *stack {
|
||||||
|
const depth = 32
|
||||||
|
var pcs [depth]uintptr
|
||||||
|
n := runtime.Callers(3, pcs[:])
|
||||||
|
var st stack = pcs[0:n]
|
||||||
|
return &st
|
||||||
|
}
|
||||||
|
|
||||||
|
// funcname removes the path prefix component of a function's name reported by func.Name().
|
||||||
|
func funcname(name string) string {
|
||||||
|
i := strings.LastIndex(name, "/")
|
||||||
|
name = name[i+1:]
|
||||||
|
i = strings.Index(name, ".")
|
||||||
|
return name[i+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimGOPATH(name, file string) string {
|
||||||
|
// Here we want to get the source file path relative to the compile time
|
||||||
|
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
|
||||||
|
// GOPATH at runtime, but we can infer the number of path segments in the
|
||||||
|
// GOPATH. We note that fn.Name() returns the function name qualified by
|
||||||
|
// the import path, which does not include the GOPATH. Thus we can trim
|
||||||
|
// segments from the beginning of the file path until the number of path
|
||||||
|
// separators remaining is one more than the number of path separators in
|
||||||
|
// the function name. For example, given:
|
||||||
|
//
|
||||||
|
// GOPATH /home/user
|
||||||
|
// file /home/user/src/pkg/sub/file.go
|
||||||
|
// fn.Name() pkg/sub.Type.Method
|
||||||
|
//
|
||||||
|
// We want to produce:
|
||||||
|
//
|
||||||
|
// pkg/sub/file.go
|
||||||
|
//
|
||||||
|
// From this we can easily see that fn.Name() has one less path separator
|
||||||
|
// than our desired output. We count separators from the end of the file
|
||||||
|
// path until it finds two more than in the function name and then move
|
||||||
|
// one character forward to preserve the initial path segment without a
|
||||||
|
// leading separator.
|
||||||
|
const sep = "/"
|
||||||
|
goal := strings.Count(name, sep) + 2
|
||||||
|
i := len(file)
|
||||||
|
for n := 0; n < goal; n++ {
|
||||||
|
i = strings.LastIndex(file[:i], sep)
|
||||||
|
if i == -1 {
|
||||||
|
// not enough separators found, set i so that the slice expression
|
||||||
|
// below leaves file unmodified
|
||||||
|
i = -len(sep)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get back to 0 or trim the leading separator
|
||||||
|
file = file[i+len(sep):]
|
||||||
|
return file
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user