Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57a57932af | |||
| 62a226b1c3 | |||
| a38dcc3ac7 | |||
| c39b0e246b | |||
| f8f1f506ed | |||
| 9d57a1f192 | |||
| ba4a870632 | |||
| ef9ec32c32 | |||
| 17235e4bd1 | |||
| eb82b77782 | |||
| 3af8aa5c4f | |||
| 5b588af73c | |||
| 5ec6eccfac | |||
| 237e0e8631 | |||
| 7a165febf3 | |||
| fd7c38c62f | |||
| 00519f1105 |
+28
-1
@@ -101,7 +101,7 @@ jobs:
|
||||
end-to-end-test-release:
|
||||
docker:
|
||||
- image: circleci/node:10-browsers
|
||||
- image: grafana/grafana:$CIRCLE_TAG
|
||||
- image: grafana/grafana-dev:$CIRCLE_TAG
|
||||
steps:
|
||||
- run: dockerize -wait tcp://127.0.0.1:3000 -timeout 120s
|
||||
- checkout
|
||||
@@ -155,6 +155,15 @@ jobs:
|
||||
name: Lint Go
|
||||
command: 'make lint-go'
|
||||
|
||||
shellcheck:
|
||||
machine: true
|
||||
working_directory: ~/go/src/github.com/grafana/grafana
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: ShellCheck
|
||||
command: 'make shellcheck'
|
||||
|
||||
test-frontend:
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
@@ -663,6 +672,8 @@ workflows:
|
||||
filters: *filter-only-master
|
||||
- lint-go:
|
||||
filters: *filter-only-master
|
||||
- shellcheck:
|
||||
filters: *filter-only-master
|
||||
- test-frontend:
|
||||
filters: *filter-only-master
|
||||
- test-backend:
|
||||
@@ -678,6 +689,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
- build-oss-msi
|
||||
@@ -690,6 +702,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
filters: *filter-only-master
|
||||
@@ -700,6 +713,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
- build-all-enterprise
|
||||
@@ -711,6 +725,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
filters: *filter-only-master
|
||||
@@ -732,6 +747,8 @@ workflows:
|
||||
filters: *filter-only-release
|
||||
- lint-go:
|
||||
filters: *filter-only-release
|
||||
- shellcheck:
|
||||
filters: *filter-only-release
|
||||
- test-frontend:
|
||||
filters: *filter-only-release
|
||||
- test-backend:
|
||||
@@ -747,6 +764,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
- build-oss-msi
|
||||
@@ -759,6 +777,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
filters: *filter-only-release
|
||||
@@ -770,6 +789,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
filters: *filter-only-release
|
||||
@@ -780,6 +800,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
filters: *filter-only-release
|
||||
@@ -803,6 +824,10 @@ workflows:
|
||||
filters: *filter-not-release-or-master
|
||||
- lint-go:
|
||||
filters: *filter-not-release-or-master
|
||||
- lint-go:
|
||||
filters: *filter-not-release-or-master
|
||||
- shellcheck:
|
||||
filters: *filter-not-release-or-master
|
||||
- test-frontend:
|
||||
filters: *filter-not-release-or-master
|
||||
- test-backend:
|
||||
@@ -820,6 +845,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
- cache-server-test
|
||||
@@ -831,6 +857,7 @@ workflows:
|
||||
- test-frontend
|
||||
- codespell
|
||||
- lint-go
|
||||
- shellcheck
|
||||
- mysql-integration-test
|
||||
- postgres-integration-test
|
||||
- cache-server-test
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-dev build-docker-full lint-go gosec revive golangci-lint go-vet test-go test-js test run clean devenv devenv-down revive-alerting
|
||||
|
||||
GO := GO111MODULE=on go
|
||||
GO_FILES := ./pkg/...
|
||||
GO = GO111MODULE=on go
|
||||
GO_FILES ?= ./pkg/...
|
||||
SH_FILES ?= $(shell find ./scripts -name *.sh)
|
||||
|
||||
all: deps build
|
||||
|
||||
@@ -111,6 +112,11 @@ go-vet:
|
||||
|
||||
lint-go: go-vet golangci-lint revive revive-alerting gosec
|
||||
|
||||
# with disabled SC1071 we are ignored some TCL,Expect `/usr/bin/env expect` scripts
|
||||
shellcheck: $(SH_FILES)
|
||||
@docker run --rm -v "$$PWD:/mnt" koalaman/shellcheck:stable \
|
||||
$(SH_FILES) -e SC1071
|
||||
|
||||
run: scripts/go/bin/bra
|
||||
@scripts/go/bin/bra run
|
||||
|
||||
|
||||
@@ -37,15 +37,11 @@ export class ConfigCtrl {
|
||||
|
||||
postUpdate() {
|
||||
if (!this.appModel.enabled) {
|
||||
return this.$q.resolve();
|
||||
return;
|
||||
}
|
||||
return this.appEditCtrl.importDashboards().then(() => {
|
||||
this.enabled = true;
|
||||
return {
|
||||
url: "plugins/raintank-kubernetes-app/page/clusters",
|
||||
message: "Kubernetes App enabled!"
|
||||
};
|
||||
});
|
||||
|
||||
// TODO, whatever you want
|
||||
console.log('Post Update:', this);
|
||||
}
|
||||
}
|
||||
ConfigCtrl.templateUrl = 'components/config/config.html';
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
"company": "Grafana Labs"
|
||||
},
|
||||
"name": "grafana",
|
||||
"version": "6.3.0-beta2",
|
||||
"version": "6.3.0-beta4",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/grafana/grafana.git"
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
export const deprecationWarning = (file: string, oldName: string, newName: string) => {
|
||||
const message = `[Deprecation warning] ${file}: ${oldName} is deprecated. Use ${newName} instead`;
|
||||
export const deprecationWarning = (file: string, oldName: string, newName?: string) => {
|
||||
let message = `[Deprecation warning] ${file}: ${oldName} is deprecated`;
|
||||
if (newName) {
|
||||
message += `. Use ${newName} instead`;
|
||||
}
|
||||
console.warn(message);
|
||||
};
|
||||
|
||||
@@ -67,6 +67,8 @@ fi
|
||||
# Tag as 'latest' for official release; otherwise tag as grafana/grafana:master
|
||||
if echo "$_grafana_tag" | grep -q "^v"; then
|
||||
docker_tag_all "${_docker_repo}" "latest"
|
||||
# Create the expected tag for running the end to end tests successfully
|
||||
docker tag "${_docker_repo}:${_grafana_version}" "grafana/grafana-dev:${_grafana_tag}"
|
||||
else
|
||||
docker_tag_all "${_docker_repo}" "master"
|
||||
docker tag "${_docker_repo}:${_grafana_version}" "grafana/grafana-dev:${_grafana_version}"
|
||||
|
||||
@@ -38,8 +38,14 @@ if echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -vq "beta"
|
||||
echo "pushing ${_docker_repo}:latest"
|
||||
docker_push_all "${_docker_repo}" "latest"
|
||||
docker_push_all "${_docker_repo}" "${_grafana_version}"
|
||||
# Push to the grafana-dev repository with the expected tag
|
||||
# for running the end to end tests successfully
|
||||
docker push "grafana/grafana-dev:${_grafana_tag}"
|
||||
elif echo "$_grafana_tag" | grep -q "^v" && echo "$_grafana_tag" | grep -q "beta"; then
|
||||
docker_push_all "${_docker_repo}" "${_grafana_version}"
|
||||
# Push to the grafana-dev repository with the expected tag
|
||||
# for running the end to end tests successfully
|
||||
docker push "grafana/grafana-dev:${_grafana_tag}"
|
||||
elif echo "$_grafana_tag" | grep -q "master"; then
|
||||
docker_push_all "${_docker_repo}" "master"
|
||||
docker push "grafana/grafana-dev:${_grafana_version}"
|
||||
|
||||
+60
-105
@@ -242,93 +242,69 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
|
||||
}
|
||||
}
|
||||
|
||||
if c.IsGrafanaAdmin || c.OrgRole == m.ROLE_ADMIN {
|
||||
cfgNode := &dtos.NavLink{
|
||||
Id: "cfg",
|
||||
Text: "Configuration",
|
||||
SubTitle: "Organization: " + c.OrgName,
|
||||
Icon: "gicon gicon-cog",
|
||||
Url: setting.AppSubUrl + "/datasources",
|
||||
Children: []*dtos.NavLink{
|
||||
{
|
||||
Text: "Data Sources",
|
||||
Icon: "gicon gicon-datasources",
|
||||
Description: "Add and configure data sources",
|
||||
Id: "datasources",
|
||||
Url: setting.AppSubUrl + "/datasources",
|
||||
},
|
||||
{
|
||||
Text: "Users",
|
||||
Id: "users",
|
||||
Description: "Manage org members",
|
||||
Icon: "gicon gicon-user",
|
||||
Url: setting.AppSubUrl + "/org/users",
|
||||
},
|
||||
{
|
||||
Text: "Teams",
|
||||
Id: "teams",
|
||||
Description: "Manage org groups",
|
||||
Icon: "gicon gicon-team",
|
||||
Url: setting.AppSubUrl + "/org/teams",
|
||||
},
|
||||
{
|
||||
Text: "Plugins",
|
||||
Id: "plugins",
|
||||
Description: "View and configure plugins",
|
||||
Icon: "gicon gicon-plugins",
|
||||
Url: setting.AppSubUrl + "/plugins",
|
||||
},
|
||||
{
|
||||
Text: "Preferences",
|
||||
Id: "org-settings",
|
||||
Description: "Organization preferences",
|
||||
Icon: "gicon gicon-preferences",
|
||||
Url: setting.AppSubUrl + "/org",
|
||||
},
|
||||
configNodes := []*dtos.NavLink{}
|
||||
|
||||
{
|
||||
Text: "API Keys",
|
||||
Id: "apikeys",
|
||||
Description: "Create & manage API keys",
|
||||
Icon: "gicon gicon-apikeys",
|
||||
Url: setting.AppSubUrl + "/org/apikeys",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if c.OrgRole != m.ROLE_ADMIN {
|
||||
cfgNode = &dtos.NavLink{
|
||||
Id: "cfg",
|
||||
Text: "Configuration",
|
||||
SubTitle: "Organization: " + c.OrgName,
|
||||
Icon: "gicon gicon-cog",
|
||||
Url: setting.AppSubUrl + "/admin/users",
|
||||
Children: make([]*dtos.NavLink, 0),
|
||||
}
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, cfgNode)
|
||||
} else {
|
||||
cfgNode := &dtos.NavLink{
|
||||
Id: "cfg",
|
||||
Text: "Configuration",
|
||||
SubTitle: "Organization: " + c.OrgName,
|
||||
Icon: "gicon gicon-cog",
|
||||
Url: setting.AppSubUrl + "/plugins",
|
||||
Children: []*dtos.NavLink{
|
||||
{
|
||||
Text: "Plugins",
|
||||
Id: "plugins",
|
||||
Description: "View and configure plugins",
|
||||
Icon: "gicon gicon-plugins",
|
||||
Url: setting.AppSubUrl + "/plugins",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, cfgNode)
|
||||
if c.OrgRole == m.ROLE_ADMIN {
|
||||
configNodes = append(configNodes, &dtos.NavLink{
|
||||
Text: "Data Sources",
|
||||
Icon: "gicon gicon-datasources",
|
||||
Description: "Add and configure data sources",
|
||||
Id: "datasources",
|
||||
Url: setting.AppSubUrl + "/datasources",
|
||||
})
|
||||
configNodes = append(configNodes, &dtos.NavLink{
|
||||
Text: "Users",
|
||||
Id: "users",
|
||||
Description: "Manage org members",
|
||||
Icon: "gicon gicon-user",
|
||||
Url: setting.AppSubUrl + "/org/users",
|
||||
})
|
||||
}
|
||||
|
||||
if c.OrgRole == m.ROLE_ADMIN || hs.Cfg.EditorsCanAdmin {
|
||||
configNodes = append(configNodes, &dtos.NavLink{
|
||||
Text: "Teams",
|
||||
Id: "teams",
|
||||
Description: "Manage org groups",
|
||||
Icon: "gicon gicon-team",
|
||||
Url: setting.AppSubUrl + "/org/teams",
|
||||
})
|
||||
}
|
||||
|
||||
configNodes = append(configNodes, &dtos.NavLink{
|
||||
Text: "Plugins",
|
||||
Id: "plugins",
|
||||
Description: "View and configure plugins",
|
||||
Icon: "gicon gicon-plugins",
|
||||
Url: setting.AppSubUrl + "/plugins",
|
||||
})
|
||||
|
||||
if c.OrgRole == m.ROLE_ADMIN {
|
||||
configNodes = append(configNodes, &dtos.NavLink{
|
||||
Text: "Preferences",
|
||||
Id: "org-settings",
|
||||
Description: "Organization preferences",
|
||||
Icon: "gicon gicon-preferences",
|
||||
Url: setting.AppSubUrl + "/org",
|
||||
})
|
||||
configNodes = append(configNodes, &dtos.NavLink{
|
||||
Text: "API Keys",
|
||||
Id: "apikeys",
|
||||
Description: "Create & manage API keys",
|
||||
Icon: "gicon gicon-apikeys",
|
||||
Url: setting.AppSubUrl + "/org/apikeys",
|
||||
})
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, &dtos.NavLink{
|
||||
Id: "cfg",
|
||||
Text: "Configuration",
|
||||
SubTitle: "Organization: " + c.OrgName,
|
||||
Icon: "gicon gicon-cog",
|
||||
Url: configNodes[0].Url,
|
||||
Children: configNodes,
|
||||
})
|
||||
|
||||
if c.IsGrafanaAdmin {
|
||||
data.NavTree = append(data.NavTree, &dtos.NavLink{
|
||||
Text: "Server Admin",
|
||||
@@ -346,27 +322,6 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
|
||||
})
|
||||
}
|
||||
|
||||
if (c.OrgRole == m.ROLE_EDITOR || c.OrgRole == m.ROLE_VIEWER) && hs.Cfg.EditorsCanAdmin {
|
||||
cfgNode := &dtos.NavLink{
|
||||
Id: "cfg",
|
||||
Text: "Configuration",
|
||||
SubTitle: "Organization: " + c.OrgName,
|
||||
Icon: "gicon gicon-cog",
|
||||
Url: setting.AppSubUrl + "/org/teams",
|
||||
Children: []*dtos.NavLink{
|
||||
{
|
||||
Text: "Teams",
|
||||
Id: "teams",
|
||||
Description: "Manage org groups",
|
||||
Icon: "gicon gicon-team",
|
||||
Url: setting.AppSubUrl + "/org/teams",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, cfgNode)
|
||||
}
|
||||
|
||||
data.NavTree = append(data.NavTree, &dtos.NavLink{
|
||||
Text: "Help",
|
||||
SubTitle: fmt.Sprintf(`%s v%s (%s)`, setting.ApplicationName, setting.BuildVersion, setting.BuildCommit),
|
||||
|
||||
@@ -60,7 +60,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *m.ReqContext) {
|
||||
if code == "" {
|
||||
state := GenStateString()
|
||||
hashedState := hashStatecode(state, setting.OAuthService.OAuthInfos[name].ClientSecret)
|
||||
hs.writeCookie(ctx.Resp, OauthStateCookieName, hashedState, 60)
|
||||
hs.writeCookie(ctx.Resp, OauthStateCookieName, hashedState, 60, http.SameSiteLaxMode)
|
||||
if setting.OAuthService.OAuthInfos[name].HostedDomain == "" {
|
||||
ctx.Redirect(connect.AuthCodeURL(state, oauth2.AccessTypeOnline))
|
||||
} else {
|
||||
@@ -73,7 +73,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *m.ReqContext) {
|
||||
|
||||
// delete cookie
|
||||
ctx.Resp.Header().Del("Set-Cookie")
|
||||
hs.deleteCookie(ctx.Resp, OauthStateCookieName)
|
||||
hs.deleteCookie(ctx.Resp, OauthStateCookieName, http.SameSiteLaxMode)
|
||||
|
||||
if cookieState == "" {
|
||||
ctx.Handle(500, "login.OAuthLogin(missing saved state)", nil)
|
||||
@@ -213,11 +213,11 @@ func (hs *HTTPServer) OAuthLogin(ctx *m.ReqContext) {
|
||||
ctx.Redirect(setting.AppSubUrl + "/")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) deleteCookie(w http.ResponseWriter, name string) {
|
||||
hs.writeCookie(w, name, "", -1)
|
||||
func (hs *HTTPServer) deleteCookie(w http.ResponseWriter, name string, sameSite http.SameSite) {
|
||||
hs.writeCookie(w, name, "", -1, sameSite)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) writeCookie(w http.ResponseWriter, name string, value string, maxAge int) {
|
||||
func (hs *HTTPServer) writeCookie(w http.ResponseWriter, name string, value string, maxAge int, sameSite http.SameSite) {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: name,
|
||||
MaxAge: maxAge,
|
||||
@@ -225,7 +225,7 @@ func (hs *HTTPServer) writeCookie(w http.ResponseWriter, name string, value stri
|
||||
HttpOnly: true,
|
||||
Path: setting.AppSubUrl + "/",
|
||||
Secure: hs.Cfg.CookieSecure,
|
||||
SameSite: hs.Cfg.CookieSameSite,
|
||||
SameSite: sameSite,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -6,37 +6,53 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func GetGrafanaPluginDir(currentOS string) string {
|
||||
if isDevEnvironment() {
|
||||
return "../data/plugins"
|
||||
if rootPath, ok := tryGetRootForDevEnvironment(); ok {
|
||||
return filepath.Join(rootPath, "data/plugins")
|
||||
}
|
||||
|
||||
return returnOsDefault(currentOS)
|
||||
}
|
||||
|
||||
func isDevEnvironment() bool {
|
||||
// if ../conf/defaults.ini exists, grafana is not installed as package
|
||||
// that its in development environment.
|
||||
// getGrafanaRoot tries to get root of directory when developing grafana ie repo root. It is not perfect it just
|
||||
// checks what is the binary path and tries to guess based on that but if it is not running in dev env you get a bogus
|
||||
// path back.
|
||||
func getGrafanaRoot() (string, error) {
|
||||
ex, err := os.Executable()
|
||||
if err != nil {
|
||||
logger.Error("Could not get executable path. Assuming non dev environment.")
|
||||
return false
|
||||
return "", xerrors.New("Failed to get executable path")
|
||||
}
|
||||
exPath := filepath.Dir(ex)
|
||||
_, last := path.Split(exPath)
|
||||
if last == "bin" {
|
||||
// In dev env the executable for current platform is created in 'bin/' dir
|
||||
defaultsPath := filepath.Join(exPath, "../conf/defaults.ini")
|
||||
_, err = os.Stat(defaultsPath)
|
||||
return err == nil
|
||||
return filepath.Join(exPath, ".."), nil
|
||||
}
|
||||
|
||||
// But at the same time there are per platform directories that contain the binaries and can also be used.
|
||||
defaultsPath := filepath.Join(exPath, "../../conf/defaults.ini")
|
||||
_, err = os.Stat(defaultsPath)
|
||||
return err == nil
|
||||
return filepath.Join(exPath, "../.."), nil
|
||||
}
|
||||
|
||||
// tryGetRootForDevEnvironment returns root path if we are in dev environment. It checks if conf/defaults.ini exists
|
||||
// which should only exist in dev. Second param is false if we are not in dev or if it wasn't possible to determine it.
|
||||
func tryGetRootForDevEnvironment() (string, bool) {
|
||||
rootPath, err := getGrafanaRoot()
|
||||
if err != nil {
|
||||
logger.Error("Could not get executable path. Assuming non dev environment.", err)
|
||||
return "", false
|
||||
}
|
||||
|
||||
devenvPath := filepath.Join(rootPath, "devenv")
|
||||
|
||||
_, err = os.Stat(devenvPath)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return rootPath, true
|
||||
}
|
||||
|
||||
func returnOsDefault(currentOs string) string {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package authproxy
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/mail"
|
||||
@@ -32,6 +33,9 @@ var isLDAPEnabled = ldap.IsEnabled
|
||||
// newLDAP creates multiple LDAP instance
|
||||
var newLDAP = multildap.New
|
||||
|
||||
// supportedHeaders states the supported headers configuration fields
|
||||
var supportedHeaderFields = []string{"Name", "Email", "Login", "Groups"}
|
||||
|
||||
// AuthProxy struct
|
||||
type AuthProxy struct {
|
||||
store *remotecache.RemoteCache
|
||||
@@ -142,9 +146,18 @@ func (auth *AuthProxy) IsAllowedIP() (bool, *Error) {
|
||||
return false, newError("Proxy authentication required", err)
|
||||
}
|
||||
|
||||
// getKey forms a key for the cache
|
||||
// getKey forms a key for the cache based on the headers received as part of the authentication flow.
|
||||
// Our configuration supports multiple headers. The main header contains the email or username.
|
||||
// And the additional ones that allow us to specify extra attributes: Name, Email or Groups.
|
||||
func (auth *AuthProxy) getKey() string {
|
||||
return fmt.Sprintf(CachePrefix, auth.header)
|
||||
key := strings.TrimSpace(auth.header) // start the key with the main header
|
||||
|
||||
auth.headersIterator(func(_, header string) {
|
||||
key = strings.Join([]string{key, header}, "-") // compose the key with any additional headers
|
||||
})
|
||||
|
||||
hashedKey := base32.StdEncoding.EncodeToString([]byte(key))
|
||||
return fmt.Sprintf(CachePrefix, hashedKey)
|
||||
}
|
||||
|
||||
// Login logs in user id with whatever means possible
|
||||
@@ -232,40 +245,36 @@ func (auth *AuthProxy) LoginViaHeader() (int64, error) {
|
||||
AuthId: auth.header,
|
||||
}
|
||||
|
||||
if auth.headerType == "username" {
|
||||
switch auth.headerType {
|
||||
case "username":
|
||||
extUser.Login = auth.header
|
||||
|
||||
// only set Email if it can be parsed as an email address
|
||||
emailAddr, emailErr := mail.ParseAddress(auth.header)
|
||||
emailAddr, emailErr := mail.ParseAddress(auth.header) // only set Email if it can be parsed as an email address
|
||||
if emailErr == nil {
|
||||
extUser.Email = emailAddr.Address
|
||||
}
|
||||
} else if auth.headerType == "email" {
|
||||
case "email":
|
||||
extUser.Email = auth.header
|
||||
extUser.Login = auth.header
|
||||
} else {
|
||||
default:
|
||||
return 0, newError("Auth proxy header property invalid", nil)
|
||||
|
||||
}
|
||||
|
||||
for _, field := range []string{"Name", "Email", "Login", "Groups"} {
|
||||
if auth.headers[field] == "" {
|
||||
continue
|
||||
auth.headersIterator(func(field string, header string) {
|
||||
if field == "Groups" {
|
||||
extUser.Groups = util.SplitString(header)
|
||||
} else {
|
||||
reflect.ValueOf(extUser).Elem().FieldByName(field).SetString(header)
|
||||
}
|
||||
|
||||
if val := auth.ctx.Req.Header.Get(auth.headers[field]); val != "" {
|
||||
if field == "Groups" {
|
||||
extUser.Groups = util.SplitString(val)
|
||||
} else {
|
||||
reflect.ValueOf(extUser).Elem().FieldByName(field).SetString(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
upsert := &models.UpsertUserCommand{
|
||||
ReqContext: auth.ctx,
|
||||
SignupAllowed: setting.AuthProxyAutoSignUp,
|
||||
ExternalUser: extUser,
|
||||
}
|
||||
|
||||
err := bus.Dispatch(upsert)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -274,6 +283,21 @@ func (auth *AuthProxy) LoginViaHeader() (int64, error) {
|
||||
return upsert.Result.Id, nil
|
||||
}
|
||||
|
||||
// headersIterator iterates over all non-empty supported additional headers
|
||||
func (auth *AuthProxy) headersIterator(fn func(field string, header string)) {
|
||||
for _, field := range supportedHeaderFields {
|
||||
h := auth.headers[field]
|
||||
|
||||
if h == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if value := auth.ctx.Req.Header.Get(h); value != "" {
|
||||
fn(field, strings.TrimSpace(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetSignedUser get full signed user info
|
||||
func (auth *AuthProxy) GetSignedUser(userID int64) (*models.SignedInUser, *Error) {
|
||||
query := &models.GetSignedInUserQuery{
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package authproxy
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/ldap"
|
||||
"github.com/grafana/grafana/pkg/services/multildap"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
type TestMultiLDAP struct {
|
||||
@@ -45,37 +45,70 @@ func (stub *TestMultiLDAP) User(login string) (
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func prepareMiddleware(t *testing.T, req *http.Request, store *remotecache.RemoteCache) *AuthProxy {
|
||||
t.Helper()
|
||||
|
||||
ctx := &models.ReqContext{
|
||||
Context: &macaron.Context{
|
||||
Req: macaron.Request{
|
||||
Request: req,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
auth := New(&Options{
|
||||
Store: store,
|
||||
Ctx: ctx,
|
||||
OrgID: 4,
|
||||
})
|
||||
|
||||
return auth
|
||||
}
|
||||
|
||||
func TestMiddlewareContext(t *testing.T) {
|
||||
Convey("auth_proxy helper", t, func() {
|
||||
req, _ := http.NewRequest("POST", "http://example.com", nil)
|
||||
setting.AuthProxyHeaderName = "X-Killa"
|
||||
name := "markelog"
|
||||
store := remotecache.NewFakeStore(t)
|
||||
|
||||
name := "markelog"
|
||||
req.Header.Add(setting.AuthProxyHeaderName, name)
|
||||
|
||||
ctx := &models.ReqContext{
|
||||
Context: &macaron.Context{
|
||||
Req: macaron.Request{
|
||||
Request: req,
|
||||
},
|
||||
},
|
||||
}
|
||||
Convey("when the cache only contains the main header", func() {
|
||||
|
||||
Convey("logs in user from the cache", func() {
|
||||
store := remotecache.NewFakeStore(t)
|
||||
key := fmt.Sprintf(CachePrefix, name)
|
||||
store.Set(key, int64(33), 0)
|
||||
Convey("with a simple cache key", func() {
|
||||
// Set cache key
|
||||
key := fmt.Sprintf(CachePrefix, base32.StdEncoding.EncodeToString([]byte(name)))
|
||||
store.Set(key, int64(33), 0)
|
||||
|
||||
auth := New(&Options{
|
||||
Store: store,
|
||||
Ctx: ctx,
|
||||
OrgID: 4,
|
||||
// Set up the middleware
|
||||
auth := prepareMiddleware(t, req, store)
|
||||
id, err := auth.Login()
|
||||
|
||||
So(auth.getKey(), ShouldEqual, "auth-proxy-sync-ttl:NVQXE23FNRXWO===")
|
||||
So(err, ShouldBeNil)
|
||||
So(id, ShouldEqual, 33)
|
||||
})
|
||||
|
||||
id, err := auth.Login()
|
||||
Convey("when the cache key contains additional headers", func() {
|
||||
setting.AuthProxyHeaders = map[string]string{"Groups": "X-WEBAUTH-GROUPS"}
|
||||
group := "grafana-core-team"
|
||||
req.Header.Add("X-WEBAUTH-GROUPS", group)
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(id, ShouldEqual, 33)
|
||||
key := fmt.Sprintf(CachePrefix, base32.StdEncoding.EncodeToString([]byte(name+"-"+group)))
|
||||
store.Set(key, int64(33), 0)
|
||||
|
||||
auth := prepareMiddleware(t, req, store)
|
||||
|
||||
id, err := auth.Login()
|
||||
|
||||
So(auth.getKey(), ShouldEqual, "auth-proxy-sync-ttl:NVQXE23FNRXWOLLHOJQWMYLOMEWWG33SMUWXIZLBNU======")
|
||||
So(err, ShouldBeNil)
|
||||
So(id, ShouldEqual, 33)
|
||||
})
|
||||
|
||||
Convey("when the does not exist", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Convey("LDAP", func() {
|
||||
@@ -119,13 +152,9 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
|
||||
store := remotecache.NewFakeStore(t)
|
||||
|
||||
server := New(&Options{
|
||||
Store: store,
|
||||
Ctx: ctx,
|
||||
OrgID: 4,
|
||||
})
|
||||
auth := prepareMiddleware(t, req, store)
|
||||
|
||||
id, err := server.Login()
|
||||
id, err := auth.Login()
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(id, ShouldEqual, 42)
|
||||
@@ -149,11 +178,7 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
|
||||
store := remotecache.NewFakeStore(t)
|
||||
|
||||
auth := New(&Options{
|
||||
Store: store,
|
||||
Ctx: ctx,
|
||||
OrgID: 4,
|
||||
})
|
||||
auth := prepareMiddleware(t, req, store)
|
||||
|
||||
stub := &TestMultiLDAP{
|
||||
ID: 42,
|
||||
@@ -170,7 +195,6 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
So(id, ShouldNotEqual, 42)
|
||||
So(stub.loginCalled, ShouldEqual, false)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,11 +21,19 @@ import (
|
||||
|
||||
var getTime = time.Now
|
||||
|
||||
const (
|
||||
errStringInvalidUsernamePassword = "Invalid username or password"
|
||||
errStringInvalidAPIKey = "Invalid API key"
|
||||
)
|
||||
|
||||
var (
|
||||
ReqGrafanaAdmin = Auth(&AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
|
||||
ReqSignedIn = Auth(&AuthOptions{ReqSignedIn: true})
|
||||
ReqEditorRole = RoleAuth(models.ROLE_EDITOR, models.ROLE_ADMIN)
|
||||
ReqOrgAdmin = RoleAuth(models.ROLE_ADMIN)
|
||||
ReqGrafanaAdmin = Auth(&AuthOptions{
|
||||
ReqSignedIn: true,
|
||||
ReqGrafanaAdmin: true,
|
||||
})
|
||||
ReqSignedIn = Auth(&AuthOptions{ReqSignedIn: true})
|
||||
ReqEditorRole = RoleAuth(models.ROLE_EDITOR, models.ROLE_ADMIN)
|
||||
ReqOrgAdmin = RoleAuth(models.ROLE_ADMIN)
|
||||
)
|
||||
|
||||
func GetContextHandler(
|
||||
@@ -106,14 +114,14 @@ func initContextWithApiKey(ctx *models.ReqContext) bool {
|
||||
// base64 decode key
|
||||
decoded, err := apikeygen.Decode(keyString)
|
||||
if err != nil {
|
||||
ctx.JsonApiErr(401, "Invalid API key", err)
|
||||
ctx.JsonApiErr(401, errStringInvalidAPIKey, err)
|
||||
return true
|
||||
}
|
||||
|
||||
// fetch key
|
||||
keyQuery := models.GetApiKeyByNameQuery{KeyName: decoded.Name, OrgId: decoded.OrgId}
|
||||
if err := bus.Dispatch(&keyQuery); err != nil {
|
||||
ctx.JsonApiErr(401, "Invalid API key", err)
|
||||
ctx.JsonApiErr(401, errStringInvalidAPIKey, err)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -121,7 +129,7 @@ func initContextWithApiKey(ctx *models.ReqContext) bool {
|
||||
|
||||
// validate api key
|
||||
if !apikeygen.IsValid(decoded, apikey.Key) {
|
||||
ctx.JsonApiErr(401, "Invalid API key", err)
|
||||
ctx.JsonApiErr(401, errStringInvalidAPIKey, err)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -140,7 +148,6 @@ func initContextWithApiKey(ctx *models.ReqContext) bool {
|
||||
}
|
||||
|
||||
func initContextWithBasicAuth(ctx *models.ReqContext, orgId int64) bool {
|
||||
|
||||
if !setting.BasicAuthEnabled {
|
||||
return false
|
||||
}
|
||||
@@ -158,21 +165,39 @@ func initContextWithBasicAuth(ctx *models.ReqContext, orgId int64) bool {
|
||||
|
||||
loginQuery := models.GetUserByLoginQuery{LoginOrEmail: username}
|
||||
if err := bus.Dispatch(&loginQuery); err != nil {
|
||||
ctx.JsonApiErr(401, "Basic auth failed", err)
|
||||
ctx.Logger.Debug(
|
||||
"Failed to look up the username",
|
||||
"username", username,
|
||||
)
|
||||
ctx.JsonApiErr(401, errStringInvalidUsernamePassword, err)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
user := loginQuery.Result
|
||||
|
||||
loginUserQuery := models.LoginUserQuery{Username: username, Password: password, User: user}
|
||||
loginUserQuery := models.LoginUserQuery{
|
||||
Username: username,
|
||||
Password: password,
|
||||
User: user,
|
||||
}
|
||||
if err := bus.Dispatch(&loginUserQuery); err != nil {
|
||||
ctx.JsonApiErr(401, "Invalid username or password", err)
|
||||
ctx.Logger.Debug(
|
||||
"Failed to authorize the user",
|
||||
"username", username,
|
||||
)
|
||||
|
||||
ctx.JsonApiErr(401, errStringInvalidUsernamePassword, err)
|
||||
return true
|
||||
}
|
||||
|
||||
query := models.GetSignedInUserQuery{UserId: user.Id, OrgId: orgId}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
ctx.JsonApiErr(401, "Authentication error", err)
|
||||
ctx.Logger.Error(
|
||||
"Failed at user signed in",
|
||||
"id", user.Id,
|
||||
"org", orgId,
|
||||
)
|
||||
ctx.JsonApiErr(401, errStringInvalidUsernamePassword, err)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -193,14 +218,14 @@ func initContextWithToken(authTokenService models.UserTokenService, ctx *models.
|
||||
|
||||
token, err := authTokenService.LookupToken(ctx.Req.Context(), rawToken)
|
||||
if err != nil {
|
||||
ctx.Logger.Error("failed to look up user based on cookie", "error", err)
|
||||
ctx.Logger.Error("Failed to look up user based on cookie", "error", err)
|
||||
WriteSessionCookie(ctx, "", -1)
|
||||
return false
|
||||
}
|
||||
|
||||
query := models.GetSignedInUserQuery{UserId: token.UserId, OrgId: orgID}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
ctx.Logger.Error("failed to get user with id", "userId", token.UserId, "error", err)
|
||||
ctx.Logger.Error("Failed to get user with id", "userId", token.UserId, "error", err)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -210,7 +235,7 @@ func initContextWithToken(authTokenService models.UserTokenService, ctx *models.
|
||||
|
||||
rotated, err := authTokenService.TryRotateToken(ctx.Req.Context(), token, ctx.RemoteAddr(), ctx.Req.UserAgent())
|
||||
if err != nil {
|
||||
ctx.Logger.Error("failed to rotate token", "error", err)
|
||||
ctx.Logger.Error("Failed to rotate token", "error", err)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -223,7 +248,7 @@ func initContextWithToken(authTokenService models.UserTokenService, ctx *models.
|
||||
|
||||
func WriteSessionCookie(ctx *models.ReqContext, value string, maxLifetimeDays int) {
|
||||
if setting.Env == setting.DEV {
|
||||
ctx.Logger.Info("new token", "unhashed token", value)
|
||||
ctx.Logger.Info("New token", "unhashed token", value)
|
||||
}
|
||||
|
||||
var maxAge int
|
||||
|
||||
@@ -2,6 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base32"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
@@ -21,7 +23,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const errorTemplate = "error-template"
|
||||
@@ -377,7 +378,9 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
setting.LDAPEnabled = true
|
||||
setting.AuthProxyHeaderName = "X-WEBAUTH-USER"
|
||||
setting.AuthProxyHeaderProperty = "username"
|
||||
setting.AuthProxyHeaders = map[string]string{"Groups": "X-WEBAUTH-GROUPS"}
|
||||
name := "markelog"
|
||||
group := "grafana-core-team"
|
||||
|
||||
middlewareScenario(t, "should not sync the user if it's in the cache", func(sc *scenarioContext) {
|
||||
bus.AddHandler("test", func(query *models.GetSignedInUserQuery) error {
|
||||
@@ -385,11 +388,12 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
key := fmt.Sprintf(cachePrefix, name)
|
||||
key := fmt.Sprintf(cachePrefix, base32.StdEncoding.EncodeToString([]byte(name+"-"+group)))
|
||||
sc.remoteCacheService.Set(key, int64(33), 0)
|
||||
sc.fakeReq("GET", "/")
|
||||
|
||||
sc.req.Header.Add(setting.AuthProxyHeaderName, name)
|
||||
sc.req.Header.Add("X-WEBAUTH-GROUPS", group)
|
||||
sc.exec()
|
||||
|
||||
Convey("Should init user via cache", func() {
|
||||
|
||||
@@ -160,11 +160,11 @@ export class KeybindingSrv {
|
||||
});
|
||||
|
||||
this.bind('t left', () => {
|
||||
scope.appEvent('shift-time-backward');
|
||||
scope.appEvent('shift-time', -1);
|
||||
});
|
||||
|
||||
this.bind('t right', () => {
|
||||
scope.appEvent('shift-time-forward');
|
||||
scope.appEvent('shift-time', 1);
|
||||
});
|
||||
|
||||
// edit panel
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Libaries
|
||||
import React, { Component } from 'react';
|
||||
import { toUtc, dateMath } from '@grafana/data';
|
||||
import { dateMath } from '@grafana/data';
|
||||
|
||||
// Types
|
||||
import { DashboardModel } from '../../state';
|
||||
@@ -16,7 +16,6 @@ import { TimePicker, RefreshPicker } from '@grafana/ui';
|
||||
// Utils & Services
|
||||
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { defaultSelectOptions } from '@grafana/ui/src/components/TimePicker/TimePicker';
|
||||
import { getShiftedTimeRange } from 'app/core/utils/timePicker';
|
||||
|
||||
export interface Props {
|
||||
$injector: any;
|
||||
@@ -43,18 +42,12 @@ export class DashNavTimeControls extends Component<Props> {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
onMoveTimePicker = (direction: number) => {
|
||||
const range = this.timeSrv.timeRange();
|
||||
const { from, to } = getShiftedTimeRange(direction, range);
|
||||
|
||||
this.timeSrv.setTime({
|
||||
from: toUtc(from),
|
||||
to: toUtc(to),
|
||||
});
|
||||
onMoveBack = () => {
|
||||
this.$rootScope.appEvent('shift-time', -1);
|
||||
};
|
||||
onMoveForward = () => {
|
||||
this.$rootScope.appEvent('shift-time', 1);
|
||||
};
|
||||
|
||||
onMoveForward = () => this.onMoveTimePicker(1);
|
||||
onMoveBack = () => this.onMoveTimePicker(-1);
|
||||
|
||||
onChangeTimePicker = (timeRange: TimeRange) => {
|
||||
const { dashboard } = this.props;
|
||||
|
||||
@@ -83,7 +83,7 @@ export class QueryEditorRow extends PureComponent<Props, State> {
|
||||
this.setState({
|
||||
datasource,
|
||||
loadedDataSourceValue: this.props.dataSourceValue,
|
||||
hasTextEditMode: false,
|
||||
hasTextEditMode: _.has(datasource, 'components.QueryCtrl.prototype.toggleEditorMode'),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -122,14 +122,8 @@ export class QueryEditorRow extends PureComponent<Props, State> {
|
||||
const loader = getAngularLoader();
|
||||
const template = '<plugin-component type="query-ctrl" />';
|
||||
const scopeProps = { ctrl: this.getAngularQueryComponentScope() };
|
||||
|
||||
this.angularQueryEditor = loader.load(this.element, scopeProps, template);
|
||||
this.angularScope = scopeProps.ctrl;
|
||||
|
||||
// give angular time to compile
|
||||
setTimeout(() => {
|
||||
this.setState({ hasTextEditMode: !!this.angularScope.toggleEditorMode });
|
||||
}, 100);
|
||||
}
|
||||
|
||||
onToggleCollapse = () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ITimeoutService, ILocationService } from 'angular';
|
||||
import { ContextSrv } from 'app/core/services/context_srv';
|
||||
import { DashboardModel } from '../state/DashboardModel';
|
||||
import { toUtc, dateTime, isDateTime } from '@grafana/data';
|
||||
import { getZoomedTimeRange } from 'app/core/utils/timePicker';
|
||||
import { getZoomedTimeRange, getShiftedTimeRange } from 'app/core/utils/timePicker';
|
||||
|
||||
export class TimeSrv {
|
||||
time: any;
|
||||
@@ -35,6 +35,7 @@ export class TimeSrv {
|
||||
this.time = { from: '6h', to: 'now' };
|
||||
|
||||
$rootScope.$on('zoom-out', this.zoomOut.bind(this));
|
||||
$rootScope.$on('shift-time', this.shiftTime.bind(this));
|
||||
$rootScope.$on('$routeUpdate', this.routeUpdated.bind(this));
|
||||
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
@@ -243,6 +244,16 @@ export class TimeSrv {
|
||||
|
||||
this.setTime({ from: toUtc(from), to: toUtc(to) });
|
||||
}
|
||||
|
||||
shiftTime(e: any, direction: number) {
|
||||
const range = this.timeRange();
|
||||
const { from, to } = getShiftedTimeRange(direction, range);
|
||||
|
||||
this.setTime({
|
||||
from: toUtc(from),
|
||||
to: toUtc(to),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let singleton: TimeSrv;
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { PureComponent } from 'react';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import extend from 'lodash/extend';
|
||||
|
||||
import { PluginMeta, AppPlugin, Button } from '@grafana/ui';
|
||||
import { PluginMeta, AppPlugin, Button, deprecationWarning } from '@grafana/ui';
|
||||
|
||||
import { AngularComponent, getAngularLoader } from '@grafana/runtime';
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
@@ -124,6 +124,12 @@ export class AppConfigCtrlWrapper extends PureComponent<Props, State> {
|
||||
this.postUpdateHook = callback;
|
||||
};
|
||||
|
||||
// Stub to avoid unknown function in legacy code
|
||||
importDashboards = (): Promise<void> => {
|
||||
deprecationWarning('AppConfig', 'importDashboards()');
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
enable = () => {
|
||||
this.model.enabled = true;
|
||||
this.model.pinned = true;
|
||||
|
||||
@@ -9,10 +9,6 @@ export interface GaugeOptions extends SingleStatBaseOptions {
|
||||
|
||||
export const standardGaugeFieldOptions: FieldDisplayOptions = {
|
||||
...standardFieldDisplayOptions,
|
||||
defaults: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
},
|
||||
};
|
||||
|
||||
export const defaults: GaugeOptions = {
|
||||
|
||||
@@ -13,12 +13,10 @@ export interface SingleStatOptions extends SingleStatBaseOptions {
|
||||
prefixFontSize?: string;
|
||||
valueFontSize?: string;
|
||||
postfixFontSize?: string;
|
||||
|
||||
colorBackground?: boolean;
|
||||
colorValue?: boolean;
|
||||
colorPrefix?: boolean;
|
||||
colorPostfix?: boolean;
|
||||
|
||||
sparkline: SparklineOptions;
|
||||
}
|
||||
|
||||
@@ -32,6 +30,7 @@ export const standardFieldDisplayOptions: FieldDisplayOptions = {
|
||||
{ value: -Infinity, color: 'green' },
|
||||
{ value: 80, color: 'red' }, // 80%
|
||||
],
|
||||
mappings: [],
|
||||
},
|
||||
override: {},
|
||||
};
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
|
||||
#
|
||||
# This script is executed from within the container.
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
EXTRA_OPTS="$@"
|
||||
|
||||
CCARMV6=/opt/rpi-tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
|
||||
@@ -15,9 +18,6 @@ CCOSX64=/tmp/osxcross/target/bin/o64-clang
|
||||
CCWIN64=x86_64-w64-mingw32-gcc
|
||||
CCX64=/tmp/x86_64-centos6-linux-gnu/bin/x86_64-centos6-linux-gnu-gcc
|
||||
|
||||
GOPATH=/go
|
||||
REPO_PATH=$GOPATH/src/github.com/grafana/grafana
|
||||
|
||||
cd /go/src/github.com/grafana/grafana
|
||||
echo "current dir: $(pwd)"
|
||||
|
||||
@@ -63,6 +63,7 @@ mkdir dist
|
||||
go run build.go -gen-version ${OPT} > dist/grafana.version
|
||||
|
||||
# Load ruby, needed for packing with fpm
|
||||
# shellcheck disable=SC1091
|
||||
source /etc/profile.d/rvm.sh
|
||||
|
||||
echo "Packaging"
|
||||
|
||||
+12
-15
@@ -9,10 +9,6 @@ CCARMV6=/opt/rpi-tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g
|
||||
CCARMV7=arm-linux-gnueabihf-gcc
|
||||
CCARM64=aarch64-linux-gnu-gcc
|
||||
CCX64=/tmp/x86_64-centos6-linux-gnu/bin/x86_64-centos6-linux-gnu-gcc
|
||||
##########
|
||||
GOPATH=/go
|
||||
REPO_PATH=$GOPATH/src/github.com/grafana/grafana
|
||||
##########
|
||||
|
||||
BUILD_FAST=0
|
||||
BUILD_BACKEND=1
|
||||
@@ -51,9 +47,9 @@ while [ "$1" != "" ]; do
|
||||
esac
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
EXTRA_OPTS="$@"
|
||||
|
||||
|
||||
cd /go/src/github.com/grafana/grafana
|
||||
echo "current dir: $(pwd)"
|
||||
|
||||
@@ -73,7 +69,7 @@ function build_backend_linux_amd64() {
|
||||
if [ ! -d "dist" ]; then
|
||||
mkdir dist
|
||||
fi
|
||||
CC=${CCX64} go run build.go ${OPT} build
|
||||
CC=${CCX64} go run build.go "${OPT}" build
|
||||
}
|
||||
|
||||
function build_backend() {
|
||||
@@ -81,9 +77,9 @@ function build_backend() {
|
||||
mkdir dist
|
||||
fi
|
||||
|
||||
go run build.go -goarch armv6 -cc ${CCARMV6} ${OPT} build
|
||||
go run build.go -goarch armv7 -cc ${CCARMV7} ${OPT} build
|
||||
go run build.go -goarch arm64 -cc ${CCARM64} ${OPT} build
|
||||
go run build.go -goarch armv6 -cc ${CCARMV6} "${OPT}" build
|
||||
go run build.go -goarch armv7 -cc ${CCARMV7} "${OPT}" build
|
||||
go run build.go -goarch arm64 -cc ${CCARM64} "${OPT}" build
|
||||
build_backend_linux_amd64
|
||||
}
|
||||
|
||||
@@ -93,22 +89,22 @@ function build_frontend() {
|
||||
fi
|
||||
yarn install --pure-lockfile --no-progress
|
||||
echo "Building frontend"
|
||||
go run build.go ${OPT} build-frontend
|
||||
go run build.go "${OPT}" build-frontend
|
||||
echo "FRONTEND: finished"
|
||||
}
|
||||
|
||||
function package_linux_amd64() {
|
||||
echo "Packaging Linux AMD64"
|
||||
go run build.go -goos linux -pkg-arch amd64 ${OPT} package-only
|
||||
go run build.go -goos linux -pkg-arch amd64 "${OPT}" package-only
|
||||
go run build.go latest
|
||||
echo "PACKAGE LINUX AMD64: finished"
|
||||
}
|
||||
|
||||
function package_all() {
|
||||
echo "Packaging ALL"
|
||||
go run build.go -goos linux -pkg-arch armv6 ${OPT} -skipRpm package-only
|
||||
go run build.go -goos linux -pkg-arch armv7 ${OPT} package-only
|
||||
go run build.go -goos linux -pkg-arch arm64 ${OPT} package-only
|
||||
go run build.go -goos linux -pkg-arch armv6 "${OPT}" -skipRpm package-only
|
||||
go run build.go -goos linux -pkg-arch armv7 "${OPT}" package-only
|
||||
go run build.go -goos linux -pkg-arch arm64 "${OPT}" package-only
|
||||
package_linux_amd64
|
||||
echo "PACKAGE ALL: finished"
|
||||
}
|
||||
@@ -119,8 +115,9 @@ function package_setup() {
|
||||
rm -rf dist
|
||||
fi
|
||||
mkdir dist
|
||||
go run build.go -gen-version ${OPT} > dist/grafana.version
|
||||
go run build.go -gen-version "${OPT}" > dist/grafana.version
|
||||
# Load ruby, needed for packing with fpm
|
||||
# shellcheck disable=SC1091
|
||||
source /etc/profile.d/rvm.sh
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd /tmp
|
||||
cd /tmp || exit 1
|
||||
tar xfJ x86_64-centos6-linux-gnu.tar.xz
|
||||
tar xfJ osxcross.tar.xz
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
WORKING_DIRECTORY=`pwd`
|
||||
WORKING_DIRECTORY=$(pwd)
|
||||
# copy zip file to /tmp/dist
|
||||
mkdir -p /tmp/dist
|
||||
cp ./dist/*.zip /tmp/dist
|
||||
@@ -23,12 +23,12 @@ echo "Building MSI"
|
||||
python3 generator/build.py "$@"
|
||||
chmod a+x /tmp/scratch/*.msi
|
||||
echo "MSI: Copy to $WORKING_DIRECTORY/dist"
|
||||
cp /tmp/scratch/*.msi $WORKING_DIRECTORY/dist
|
||||
cp /tmp/scratch/*.msi "$WORKING_DIRECTORY/dist"
|
||||
echo "MSI: Generate SHA256"
|
||||
MSI_FILE=`ls $WORKING_DIRECTORY/dist/*.msi`
|
||||
SHA256SUM=`sha256sum $MSI_FILE | cut -f1 -d' '`
|
||||
echo $SHA256SUM > $MSI_FILE.sha256
|
||||
MSI_FILE=$(ls "$WORKING_DIRECTORY"/dist/*.msi)
|
||||
SHA256SUM=$(sha256sum "$MSI_FILE" | cut -f1 -d' ')
|
||||
echo "$SHA256SUM" > "$MSI_FILE.sha256"
|
||||
echo "MSI: SHA256 file content:"
|
||||
cat $MSI_FILE.sha256
|
||||
cat "$MSI_FILE.sha256"
|
||||
echo "MSI: contents of $WORKING_DIRECTORY/dist"
|
||||
ls -al $WORKING_DIRECTORY/dist
|
||||
ls -al "$WORKING_DIRECTORY/dist"
|
||||
|
||||
@@ -21,7 +21,7 @@ ls -al /home/xclient/wix/light.exe.config
|
||||
cat /home/xclient/wix/light.exe.config
|
||||
cp /master/light.exe.config /home/xclient/wix/light.exe.config
|
||||
cat /home/xclient/wix/light.exe.config
|
||||
cd /master
|
||||
cd /master || exit 1
|
||||
echo "Building MSI"
|
||||
python3 generator/build.py "$@"
|
||||
#
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
cd /oss
|
||||
cd /oss || exit 1
|
||||
make
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
cd ..
|
||||
|
||||
|
||||
if [ -z "$CIRCLE_TAG" ]; then
|
||||
_target="master"
|
||||
else
|
||||
@@ -11,5 +10,5 @@ fi
|
||||
|
||||
git clone -b "$_target" --single-branch git@github.com:grafana/grafana-enterprise.git --depth 1
|
||||
|
||||
cd grafana-enterprise
|
||||
cd grafana-enterprise || exit
|
||||
./build.sh
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
# no relation to publish.go
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
|
||||
EXTRA_OPTS="$@"
|
||||
|
||||
# Right now we hack this in into the publish script.
|
||||
@@ -10,7 +12,7 @@ _releaseNoteUrl="https://community.grafana.com/t/release-notes-v6-3-x/19202"
|
||||
_whatsNewUrl="https://grafana.com/docs/guides/whats-new-in-v6-3/"
|
||||
|
||||
./scripts/build/release_publisher/release_publisher \
|
||||
--wn ${_whatsNewUrl} \
|
||||
--rn ${_releaseNoteUrl} \
|
||||
--version ${CIRCLE_TAG} \
|
||||
--apikey ${GRAFANA_COM_API_KEY} ${EXTRA_OPTS}
|
||||
--wn "${_whatsNewUrl}" \
|
||||
--rn "${_releaseNoteUrl}" \
|
||||
--version "${CIRCLE_TAG}" \
|
||||
--apikey "${GRAFANA_COM_API_KEY}" "${EXTRA_OPTS}"
|
||||
|
||||
@@ -8,5 +8,5 @@ cp ./scripts/build/rpmmacros ~/.rpmmacros
|
||||
|
||||
for package in dist/*.rpm; do
|
||||
[ -e "$package" ] || continue
|
||||
./scripts/build/sign_expect $GPG_KEY_PASSWORD $package
|
||||
./scripts/build/sign_expect "$GPG_KEY_PASSWORD" "$package"
|
||||
done
|
||||
|
||||
@@ -9,7 +9,7 @@ GCP_REPO_BUCKET="${6:-grafana-repo}"
|
||||
|
||||
REPO="grafana"
|
||||
|
||||
if [ -z "$RELEASE_TYPE" -o -z "$GPG_PASS" -o -z "$DIST_PATH" ]; then
|
||||
if [ -z "$RELEASE_TYPE" ] || [ -z "$GPG_PASS" ] || [ -z "$DIST_PATH" ]; then
|
||||
echo "Both RELEASE_TYPE (arg 1), GPG_PASS (arg 2) and DIST_PATH (arg 4) has to be set"
|
||||
exit 1
|
||||
fi
|
||||
@@ -36,7 +36,7 @@ mkdir -p /deb-repo/db \
|
||||
gsutil -m rsync -r -d "gs://$GCP_DB_BUCKET/$RELEASE_TYPE" /deb-repo/db
|
||||
|
||||
# Add the new release to the repo
|
||||
cp $DIST_PATH/*.deb /deb-repo/tmp
|
||||
cp "$DIST_PATH"/*.deb /deb-repo/tmp
|
||||
rm /deb-repo/tmp/grafana_latest*.deb || true
|
||||
aptly repo add "$REPO" /deb-repo/tmp #adds too many packages in enterprise
|
||||
|
||||
@@ -64,5 +64,5 @@ gsutil -m rsync -r /deb-repo/repo/grafana/pool "gs://$GCP_REPO_BUCKET/$RELEASE_T
|
||||
gsutil -m rsync -r -d /deb-repo/repo/grafana "gs://$GCP_REPO_BUCKET/$RELEASE_TYPE/deb"
|
||||
|
||||
# usage:
|
||||
#
|
||||
#
|
||||
# deb https://packages.grafana.com/oss/deb stable main
|
||||
|
||||
@@ -8,7 +8,7 @@ GCP_REPO_BUCKET="${5:-grafana-repo}"
|
||||
|
||||
REPO="rpm"
|
||||
|
||||
if [ -z "$RELEASE_TYPE" -o -z "$GPG_PASS" -o -z "$DIST_PATH" ]; then
|
||||
if [ -z "$RELEASE_TYPE" ] || [ -z "$GPG_PASS" ] || [ -z "$DIST_PATH" ]; then
|
||||
echo "Both RELEASE_TYPE (arg 1), GPG_PASS (arg 2) and DIST_PATH (arg 4) has to be set"
|
||||
exit 1
|
||||
fi
|
||||
@@ -33,7 +33,7 @@ mkdir -p /rpm-repo
|
||||
gsutil -m rsync -r "$BUCKET" /rpm-repo
|
||||
|
||||
# Add the new release to the repo
|
||||
cp $DIST_PATH/*.rpm /rpm-repo # adds to many files for enterprise
|
||||
cp "$DIST_PATH"/*.rpm /rpm-repo # adds to many files for enterprise
|
||||
rm /rpm-repo/grafana-latest-1*.rpm || true
|
||||
createrepo /rpm-repo
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
_files=$*
|
||||
|
||||
ALL_SIGNED=0
|
||||
|
||||
for file in $_files; do
|
||||
rpm -K "$file" | grep "pgp.*OK" -q
|
||||
if [[ $? != 0 ]]; then
|
||||
ALL_SIGNED=1
|
||||
echo $file NOT SIGNED
|
||||
if rpm -K "$file" | grep "pgp.*OK" -q ; then
|
||||
echo "$file" OK
|
||||
else
|
||||
echo $file OK
|
||||
ALL_SIGNED=1
|
||||
echo "$file" NOT SIGNED
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
exit $ALL_SIGNED
|
||||
|
||||
@@ -11,19 +11,19 @@ ERROR_COUNT="$(./node_modules/.bin/tsc --project tsconfig.json --noEmit --noImpl
|
||||
DIRECTIVES="$(grep -r -o directive public/app/**/* | wc -l)"
|
||||
CONTROLLERS="$(grep -r -oP 'class .*Ctrl' public/app/**/* | wc -l)"
|
||||
|
||||
if [ $ERROR_COUNT -gt $ERROR_COUNT_LIMIT ]; then
|
||||
if [ "$ERROR_COUNT" -gt $ERROR_COUNT_LIMIT ]; then
|
||||
echo -e "Typescript errors $ERROR_COUNT exceeded $ERROR_COUNT_LIMIT so failing build"
|
||||
exit -1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $DIRECTIVES -gt $DIRECTIVES_LIMIT ]; then
|
||||
if [ "$DIRECTIVES" -gt $DIRECTIVES_LIMIT ]; then
|
||||
echo -e "Directive count $DIRECTIVES exceeded $DIRECTIVES_LIMIT so failing build"
|
||||
exit -1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $CONTROLLERS -gt $CONTROLLERS_LIMIT ]; then
|
||||
if [ "$CONTROLLERS" -gt $CONTROLLERS_LIMIT ]; then
|
||||
echo -e "Controllers count $CONTROLLERS exceeded $CONTROLLERS_LIMIT so failing build"
|
||||
exit -1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "Typescript errors: $ERROR_COUNT"
|
||||
@@ -32,7 +32,7 @@ echo -e "Controllers: $CONTROLLERS"
|
||||
|
||||
if [ "${CIRCLE_BRANCH}" == "master" ]; then
|
||||
./scripts/ci-metrics-publisher.sh \
|
||||
grafana.ci-code.noImplicitAny=$ERROR_COUNT \
|
||||
grafana.ci-code.directives=$DIRECTIVES \
|
||||
grafana.ci-code.controllers=$CONTROLLERS
|
||||
grafana.ci-code.noImplicitAny="$ERROR_COUNT" \
|
||||
grafana.ci-code.directives="$DIRECTIVES" \
|
||||
grafana.ci-code.controllers="$CONTROLLERS"
|
||||
fi
|
||||
|
||||
@@ -13,6 +13,6 @@ for ((i = 1; i <= $#; i++ )); do
|
||||
data=''$data'{"name": "'${first}'", "value": '${remainder}', "interval": 60, "mtype": "gauge", "time": '$(date +%s)'}'
|
||||
done
|
||||
|
||||
curl https://6371:$GRAFANA_MISC_STATS_API_KEY@graphite-us-central1.grafana.net/metrics \
|
||||
curl "https://6371:$GRAFANA_MISC_STATS_API_KEY@graphite-us-central1.grafana.net/metrics" \
|
||||
-H 'Content-type: application/json' \
|
||||
-d "[$data]"
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
#!/bin/bash
|
||||
function exit_if_fail {
|
||||
command=$@
|
||||
echo "Executing '$command'"
|
||||
eval $command
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "'$command' returned $rc."
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
|
||||
# shellcheck source=./scripts/helpers/exit-if-fail.sh
|
||||
source "$(dirname "$0")/helpers/exit-if-fail.sh"
|
||||
|
||||
echo "building backend with install to cache pkgs"
|
||||
exit_if_fail time go install ./pkg/cmd/grafana-server
|
||||
@@ -16,5 +9,5 @@ exit_if_fail time go install ./pkg/cmd/grafana-server
|
||||
echo "running go test"
|
||||
set -e
|
||||
time for d in $(go list ./pkg/...); do
|
||||
exit_if_fail go test -tags=integration -covermode=atomic $d
|
||||
exit_if_fail go test -tags=integration -covermode=atomic "$d"
|
||||
done
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
#!/bin/bash
|
||||
function exit_if_fail {
|
||||
command=$@
|
||||
echo "Executing '$command'"
|
||||
eval $command
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "'$command' returned $rc."
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
|
||||
# shellcheck source=./scripts/helpers/exit-if-fail.sh
|
||||
source "$(dirname "$0")/helpers/exit-if-fail.sh"
|
||||
|
||||
echo "running redis and memcache tests"
|
||||
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
function exit_if_fail {
|
||||
command=$@
|
||||
echo "Executing '$command'"
|
||||
eval $command
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "'$command' returned $rc."
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
# shellcheck source=./scripts/helpers/exit-if-fail.sh
|
||||
source "$(dirname "$0")/helpers/exit-if-fail.sh"
|
||||
|
||||
start=$(date +%s)
|
||||
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
#!/bin/bash
|
||||
function exit_if_fail {
|
||||
command=$@
|
||||
echo "Executing '$command'"
|
||||
eval $command
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "'$command' returned $rc."
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
|
||||
# shellcheck source=./scripts/helpers/exit-if-fail.sh
|
||||
source "$(dirname "$0")/helpers/exit-if-fail.sh"
|
||||
|
||||
export GRAFANA_TEST_DB=mysql
|
||||
|
||||
time for d in $(go list ./pkg/...); do
|
||||
exit_if_fail go test -tags=integration $d
|
||||
done
|
||||
exit_if_fail go test -tags=integration "$d"
|
||||
done
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
#!/bin/bash
|
||||
function exit_if_fail {
|
||||
command=$@
|
||||
echo "Executing '$command'"
|
||||
eval $command
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "'$command' returned $rc."
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
|
||||
# shellcheck source=./scripts/helpers/exit-if-fail.sh
|
||||
source "$(dirname "$0")/helpers/exit-if-fail.sh"
|
||||
|
||||
export GRAFANA_TEST_DB=postgres
|
||||
|
||||
time for d in $(go list ./pkg/...); do
|
||||
exit_if_fail go test -tags=integration $d
|
||||
done
|
||||
exit_if_fail go test -tags=integration "$d"
|
||||
done
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
function exit_if_fail {
|
||||
# shellcheck disable=SC2124
|
||||
command=$@
|
||||
echo "Executing '$command'"
|
||||
eval "$command"
|
||||
rc=$?
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "'$command' returned $rc."
|
||||
exit $rc
|
||||
fi
|
||||
}
|
||||
@@ -6,12 +6,12 @@ set -e
|
||||
_tag=$1
|
||||
_branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||
|
||||
if [ "${_tag}" == "" ]; then
|
||||
if [ "${_tag}" == "" ]; then
|
||||
echo "Missing version param. ex './scripts/tag_release.sh v5.1.1'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${_branch}" == "master" ]; then
|
||||
if [ "${_branch}" == "master" ]; then
|
||||
echo "you cannot tag releases from the master branch"
|
||||
echo "please checkout the release branch"
|
||||
echo "ex 'git checkout v5.1.x'"
|
||||
@@ -20,9 +20,9 @@ fi
|
||||
|
||||
# always make sure to pull latest changes from origin
|
||||
echo "pulling latest changes from ${_branch}"
|
||||
git pull origin ${_branch}
|
||||
git pull origin "${_branch}"
|
||||
|
||||
# create signed tag for latest commit
|
||||
# create signed tag for latest commit
|
||||
git tag -s "${_tag}" -m "release ${_tag}"
|
||||
|
||||
# verify the signed tag
|
||||
@@ -31,7 +31,7 @@ git tag -v "${_tag}"
|
||||
echo "Make sure the tag is signed as expected"
|
||||
echo "press [y] to push the tags"
|
||||
|
||||
read -n 1 confirm
|
||||
read -n -r 1 confirm
|
||||
|
||||
if [ "${confirm}" == "y" ]; then
|
||||
git push origin "${_branch}" --tags
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
#!/bin/bash
|
||||
|
||||
_circle_token=$1
|
||||
_grafana_version=$2
|
||||
|
||||
trigger_build_url=https://circleci.com/api/v1/project/grafana/grafana-docker/tree/master?circle-token=${_circle_token}
|
||||
trigger_build_url="https://circleci.com/api/v1/project/grafana/grafana-docker/tree/master?circle-token=${_circle_token}"
|
||||
|
||||
post_data=$(cat <<EOF
|
||||
{
|
||||
@@ -14,10 +14,10 @@ post_data=$(cat <<EOF
|
||||
EOF
|
||||
)
|
||||
|
||||
echo ${post_data}
|
||||
echo "${post_data}"
|
||||
|
||||
curl \
|
||||
--header "Accept: application/json" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "${post_data}" \
|
||||
--request POST ${trigger_build_url}
|
||||
--request POST "${trigger_build_url}"
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
_circle_token=$1
|
||||
|
||||
trigger_build_url=https://circleci.com/api/v1/project/grafana/grafana-packer/tree/master?circle-token=${_circle_token}
|
||||
trigger_build_url="https://circleci.com/api/v1/project/grafana/grafana-packer/tree/master?circle-token=${_circle_token}"
|
||||
|
||||
curl \
|
||||
--header "Accept: application/json" \
|
||||
--header "Content-Type: application/json" \
|
||||
--request POST ${trigger_build_url}
|
||||
--request POST "${trigger_build_url}"
|
||||
|
||||
@@ -17,7 +17,7 @@ post_data=$(cat <<EOF
|
||||
EOF
|
||||
)
|
||||
|
||||
echo ${post_data}
|
||||
echo "${post_data}"
|
||||
|
||||
curl \
|
||||
--header "Accept: application/json" \
|
||||
|
||||
@@ -6,49 +6,49 @@ docker_build () {
|
||||
package=$3
|
||||
tag=$4
|
||||
|
||||
docker build -f $dockerfile \
|
||||
docker build -f "$dockerfile" \
|
||||
--build-arg "REPO_CONFIG=$repo_file" \
|
||||
--build-arg "PACKAGE=$package" \
|
||||
--tag $tag \
|
||||
--tag "$tag" \
|
||||
--no-cache \
|
||||
.
|
||||
|
||||
retval=$(docker run --rm $tag cat /usr/share/grafana/VERSION)
|
||||
retval=$(docker run --rm "$tag" cat /usr/share/grafana/VERSION)
|
||||
}
|
||||
|
||||
CHECK_BETA=$1
|
||||
if [[ $CHECK_BETA == "beta" ]]; then
|
||||
# Testing deb repos
|
||||
docker_build "Dockerfile.deb" "deb-oss-beta.list" "grafana" "gf-oss-deb-repo-test"
|
||||
_oss_deb_v=$retval
|
||||
_oss_deb_v="$retval"
|
||||
|
||||
docker_build "Dockerfile.deb" "deb-ee-beta.list" "grafana-enterprise" "gf-ee-deb-repo-test"
|
||||
_ee_deb_v=$retval
|
||||
_ee_deb_v="$retval"
|
||||
|
||||
# Testing rpm repos
|
||||
docker_build "Dockerfile.rpm" "rpm-oss-beta.list" "grafana" "gf-oss-rpm-repo-test"
|
||||
_oss_rpm_v=$retval
|
||||
_oss_rpm_v="$retval"
|
||||
|
||||
docker_build "Dockerfile.rpm" "rpm-ee-beta.list" "grafana-enterprise" "gf-ee-rpm-repo-test"
|
||||
_ee_rpm_v=$retval
|
||||
_ee_rpm_v="$retval"
|
||||
else
|
||||
# Testing deb repos
|
||||
docker_build "Dockerfile.deb" "deb-oss-stable.list" "grafana" "gf-oss-deb-repo-test"
|
||||
_oss_deb_v=$retval
|
||||
_oss_deb_v="$retval"
|
||||
|
||||
docker_build "Dockerfile.deb" "deb-ee-stable.list" "grafana-enterprise" "gf-ee-deb-repo-test"
|
||||
_ee_deb_v=$retval
|
||||
_ee_deb_v="$retval"
|
||||
|
||||
# Testing rpm repos
|
||||
docker_build "Dockerfile.rpm" "rpm-oss-stable.list" "grafana" "gf-oss-rpm-repo-test"
|
||||
_oss_rpm_v=$retval
|
||||
_oss_rpm_v="$retval"
|
||||
|
||||
docker_build "Dockerfile.rpm" "rpm-ee-stable.list" "grafana-enterprise" "gf-ee-rpm-repo-test"
|
||||
_ee_rpm_v=$retval
|
||||
_ee_rpm_v="$retval"
|
||||
fi
|
||||
|
||||
echo Versions:
|
||||
echo OSS deb = ${_oss_deb_v}
|
||||
echo OSS rpm = ${_oss_rpm_v}
|
||||
echo EE deb = ${_ee_deb_v}
|
||||
echo EE rpm = ${_ee_rpm_v}
|
||||
echo OSS deb = "${_oss_deb_v}"
|
||||
echo OSS rpm = "${_oss_rpm_v}"
|
||||
echo EE deb = "${_ee_deb_v}"
|
||||
echo EE rpm = "${_ee_rpm_v}"
|
||||
|
||||
Reference in New Issue
Block a user