Commit 2fb45eee by gotjosh Committed by GitHub

Grafana-CLI: Wrapper for `grafana-cli` within RPM/DEB packages and…

Grafana-CLI: Wrapper for `grafana-cli` within RPM/DEB packages and config/homepath are now global flags (#17695)

* Feature: Introduce a grafana-cli wrapper

When our users install the *nix packed version of grafana, tendency is to use the services and scripts installed as part of the package for grafana-server. These leverage the default configuration options by specifying the several default paths.

This introduces a similar approach for the grafana-cli binary. We exposed it through a wrapper to ensure a proper configuration is in place. To enable that, we add the .real suffix to the original binary (grafana-cli.real) and then use a bash script named grafana-cli as the wrapper.

* Make the config and homepath flags global

* Introduce `configOverrides` as a global flag

This flag allows us to pass configuration overrides as a string.

The string follows the convention of configuration arguments separated by a space e.g. "cfg:default.paths.data=/dev/nullX cfg:default.paths.logs=/dev/nullX"

Also, it is backwards compatible with similar the previous configuration method through tailing arguments. Tailing arguments take presedence over the configuration options string.

* Only log configuration information in debug mode

* Move the grafana-cli binary to $GRAFANA_HOME/bin

As part of the package install process, we copy all the release files and
directories into the grafana home directory. This includes the /bin folder
from where we copied the binaries into their respective destinations.
After that, the /bin folder gets deleted as we don't want to keep
duplicates of the binaries around.

As part of this commit, we moved the re-creation of /bin within
grafana-home and the copy of the original binary (again) after the
folder gets deleted.
parent e7e9d361
...@@ -43,7 +43,9 @@ var ( ...@@ -43,7 +43,9 @@ var (
workingDir string workingDir string
includeBuildId bool = true includeBuildId bool = true
buildId string = "0" buildId string = "0"
binaries []string = []string{"grafana-server", "grafana-cli"} serverBinary string = "grafana-server"
cliBinary string = "grafana-cli"
binaries []string = []string{serverBinary, cliBinary}
isDev bool = false isDev bool = false
enterprise bool = false enterprise bool = false
skipRpmGen bool = false skipRpmGen bool = false
...@@ -230,6 +232,7 @@ type linuxPackageOptions struct { ...@@ -230,6 +232,7 @@ type linuxPackageOptions struct {
packageType string packageType string
packageArch string packageArch string
homeDir string homeDir string
homeBinDir string
binPath string binPath string
serverBinPath string serverBinPath string
cliBinPath string cliBinPath string
...@@ -240,10 +243,11 @@ type linuxPackageOptions struct { ...@@ -240,10 +243,11 @@ type linuxPackageOptions struct {
initdScriptFilePath string initdScriptFilePath string
systemdServiceFilePath string systemdServiceFilePath string
postinstSrc string postinstSrc string
initdScriptSrc string initdScriptSrc string
defaultFileSrc string defaultFileSrc string
systemdFileSrc string systemdFileSrc string
cliBinaryWrapperSrc string
depends []string depends []string
} }
...@@ -258,6 +262,7 @@ func createDebPackages() { ...@@ -258,6 +262,7 @@ func createDebPackages() {
packageType: "deb", packageType: "deb",
packageArch: debPkgArch, packageArch: debPkgArch,
homeDir: "/usr/share/grafana", homeDir: "/usr/share/grafana",
homeBinDir: "/usr/share/grafana/bin",
binPath: "/usr/sbin", binPath: "/usr/sbin",
configDir: "/etc/grafana", configDir: "/etc/grafana",
etcDefaultPath: "/etc/default", etcDefaultPath: "/etc/default",
...@@ -265,10 +270,11 @@ func createDebPackages() { ...@@ -265,10 +270,11 @@ func createDebPackages() {
initdScriptFilePath: "/etc/init.d/grafana-server", initdScriptFilePath: "/etc/init.d/grafana-server",
systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service", systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service",
postinstSrc: "packaging/deb/control/postinst", postinstSrc: "packaging/deb/control/postinst",
initdScriptSrc: "packaging/deb/init.d/grafana-server", initdScriptSrc: "packaging/deb/init.d/grafana-server",
defaultFileSrc: "packaging/deb/default/grafana-server", defaultFileSrc: "packaging/deb/default/grafana-server",
systemdFileSrc: "packaging/deb/systemd/grafana-server.service", systemdFileSrc: "packaging/deb/systemd/grafana-server.service",
cliBinaryWrapperSrc: "packaging/wrappers/grafana-cli",
depends: []string{"adduser", "libfontconfig1"}, depends: []string{"adduser", "libfontconfig1"},
}) })
...@@ -286,6 +292,7 @@ func createRpmPackages() { ...@@ -286,6 +292,7 @@ func createRpmPackages() {
packageType: "rpm", packageType: "rpm",
packageArch: rpmPkgArch, packageArch: rpmPkgArch,
homeDir: "/usr/share/grafana", homeDir: "/usr/share/grafana",
homeBinDir: "/usr/share/grafana/bin",
binPath: "/usr/sbin", binPath: "/usr/sbin",
configDir: "/etc/grafana", configDir: "/etc/grafana",
etcDefaultPath: "/etc/sysconfig", etcDefaultPath: "/etc/sysconfig",
...@@ -293,10 +300,11 @@ func createRpmPackages() { ...@@ -293,10 +300,11 @@ func createRpmPackages() {
initdScriptFilePath: "/etc/init.d/grafana-server", initdScriptFilePath: "/etc/init.d/grafana-server",
systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service", systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service",
postinstSrc: "packaging/rpm/control/postinst", postinstSrc: "packaging/rpm/control/postinst",
initdScriptSrc: "packaging/rpm/init.d/grafana-server", initdScriptSrc: "packaging/rpm/init.d/grafana-server",
defaultFileSrc: "packaging/rpm/sysconfig/grafana-server", defaultFileSrc: "packaging/rpm/sysconfig/grafana-server",
systemdFileSrc: "packaging/rpm/systemd/grafana-server.service", systemdFileSrc: "packaging/rpm/systemd/grafana-server.service",
cliBinaryWrapperSrc: "packaging/wrappers/grafana-cli",
depends: []string{"/sbin/service", "fontconfig", "freetype", "urw-fonts"}, depends: []string{"/sbin/service", "fontconfig", "freetype", "urw-fonts"},
}) })
...@@ -323,10 +331,12 @@ func createPackage(options linuxPackageOptions) { ...@@ -323,10 +331,12 @@ func createPackage(options linuxPackageOptions) {
runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/lib/systemd/system")) runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/lib/systemd/system"))
runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/sbin")) runPrint("mkdir", "-p", filepath.Join(packageRoot, "/usr/sbin"))
// copy binary // copy grafana-cli wrapper
for _, binary := range binaries { runPrint("cp", "-p", options.cliBinaryWrapperSrc, filepath.Join(packageRoot, "/usr/sbin/"+cliBinary))
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+binary), filepath.Join(packageRoot, "/usr/sbin/"+binary))
} // copy grafana-server binary
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+serverBinary), filepath.Join(packageRoot, "/usr/sbin/"+serverBinary))
// copy init.d script // copy init.d script
runPrint("cp", "-p", options.initdScriptSrc, filepath.Join(packageRoot, options.initdScriptFilePath)) runPrint("cp", "-p", options.initdScriptSrc, filepath.Join(packageRoot, options.initdScriptFilePath))
// copy environment var file // copy environment var file
...@@ -338,6 +348,13 @@ func createPackage(options linuxPackageOptions) { ...@@ -338,6 +348,13 @@ func createPackage(options linuxPackageOptions) {
// remove bin path // remove bin path
runPrint("rm", "-rf", filepath.Join(packageRoot, options.homeDir, "bin")) runPrint("rm", "-rf", filepath.Join(packageRoot, options.homeDir, "bin"))
// create /bin within home
runPrint("mkdir", "-p", filepath.Join(packageRoot, options.homeBinDir))
// The grafana-cli binary is exposed through a wrapper to ensure a proper
// configuration is in place. To enable that, we need to store the original
// binary in a separate location to avoid conflicts.
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+cliBinary), filepath.Join(packageRoot, options.homeBinDir, cliBinary))
args := []string{ args := []string{
"-s", "dir", "-s", "dir",
"--description", "Grafana", "--description", "Grafana",
...@@ -391,7 +408,7 @@ func createPackage(options linuxPackageOptions) { ...@@ -391,7 +408,7 @@ func createPackage(options linuxPackageOptions) {
args = append(args, "--iteration", linuxPackageIteration) args = append(args, "--iteration", linuxPackageIteration)
} }
// add dependenciesj // add dependencies
for _, dep := range options.depends { for _, dep := range options.depends {
args = append(args, "--depends", dep) args = append(args, "--depends", dep)
} }
......
...@@ -37,7 +37,7 @@ If running the command returns this error: ...@@ -37,7 +37,7 @@ If running the command returns this error:
then there are two flags that can be used to set homepath and the config file path. then there are two flags that can be used to set homepath and the config file path.
`grafana-cli admin reset-admin-password --homepath "/usr/share/grafana" newpass` `grafana-cli --homepath "/usr/share/grafana" admin reset-admin-password newpass`
If you have not lost the admin password then it is better to set in the Grafana UI. If you need to set the password in a script then the [Grafana API](http://docs.grafana.org/http_api/user/#change-password) can be used. Here is an example using curl with basic auth: If you have not lost the admin password then it is better to set in the Grafana UI. If you need to set the password in a script then the [Grafana API](http://docs.grafana.org/http_api/user/#change-password) can be used. Here is an example using curl with basic auth:
......
#! /usr/bin/env bash
# Wrapper for the grafana-cli binary
# This file serves as a wrapper for the grafana-cli binary. It ensures we set
# the system-wide Grafana configuration that was bundled with the package as we
# use the binary.
DEFAULT=/etc/default/grafana
GRAFANA_HOME=/usr/share/grafana
CONF_DIR=/etc/grafana
DATA_DIR=/var/lib/grafana
PLUGINS_DIR=/var/lib/grafana/plugins
LOG_DIR=/var/log/grafana
CONF_FILE=$CONF_DIR/grafana.ini
PROVISIONING_CFG_DIR=$CONF_DIR/provisioning
EXECUTABLE=$GRAFANA_HOME/bin/grafana-cli
if [ ! -x $EXECUTABLE ]; then
echo "Program not installed or not executable"
exit 5
fi
# overwrite settings from default file
if [ -f "$DEFAULT" ]; then
. "$DEFAULT"
fi
OPTS="--homepath=${GRAFANA_HOME} \
--config=${CONF_FILE} \
--pluginsDir=${PLUGINS_DIR} \
--configOverrides='cfg:default.paths.provisioning=$PROVISIONING_CFG_DIR \
cfg:default.paths.data=${DATA_DIR} \
cfg:default.paths.logs=${LOG_DIR} \
cfg:default.paths.plugins=${PLUGINS_DIR}'"
eval $EXECUTABLE "$OPTS" "$@"
...@@ -2,6 +2,7 @@ package commands ...@@ -2,6 +2,7 @@ package commands
import ( import (
"os" "os"
"strings"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/fatih/color" "github.com/fatih/color"
...@@ -16,16 +17,20 @@ import ( ...@@ -16,16 +17,20 @@ import (
func runDbCommand(command func(commandLine utils.CommandLine, sqlStore *sqlstore.SqlStore) error) func(context *cli.Context) { func runDbCommand(command func(commandLine utils.CommandLine, sqlStore *sqlstore.SqlStore) error) func(context *cli.Context) {
return func(context *cli.Context) { return func(context *cli.Context) {
cmd := &utils.ContextCommandLine{Context: context} cmd := &utils.ContextCommandLine{Context: context}
debug := cmd.GlobalBool("debug")
cfg := setting.NewCfg() cfg := setting.NewCfg()
configOptions := strings.Split(cmd.GlobalString("configOverrides"), " ")
cfg.Load(&setting.CommandLineArgs{ cfg.Load(&setting.CommandLineArgs{
Config: cmd.String("config"), Config: cmd.ConfigFile(),
HomePath: cmd.String("homepath"), HomePath: cmd.HomePath(),
Args: context.Args(), Args: append(configOptions, cmd.Args()...), // tailing arguments have precedence over the options string
}) })
cfg.LogConfigSources() if debug {
cfg.LogConfigSources()
}
engine := &sqlstore.SqlStore{} engine := &sqlstore.SqlStore{}
engine.Cfg = cfg engine.Cfg = cfg
...@@ -95,23 +100,11 @@ var pluginCommands = []cli.Command{ ...@@ -95,23 +100,11 @@ var pluginCommands = []cli.Command{
}, },
} }
var dbCommandFlags = []cli.Flag{
cli.StringFlag{
Name: "homepath",
Usage: "path to grafana install/home path, defaults to working directory",
},
cli.StringFlag{
Name: "config",
Usage: "path to config file",
},
}
var adminCommands = []cli.Command{ var adminCommands = []cli.Command{
{ {
Name: "reset-admin-password", Name: "reset-admin-password",
Usage: "reset-admin-password <new password>", Usage: "reset-admin-password <new password>",
Action: runDbCommand(resetPasswordCommand), Action: runDbCommand(resetPasswordCommand),
Flags: dbCommandFlags,
}, },
{ {
Name: "data-migration", Name: "data-migration",
...@@ -121,7 +114,6 @@ var adminCommands = []cli.Command{ ...@@ -121,7 +114,6 @@ var adminCommands = []cli.Command{
Name: "encrypt-datasource-passwords", Name: "encrypt-datasource-passwords",
Usage: "Migrates passwords from unsecured fields to secure_json_data field. Return ok unless there is an error. Safe to execute multiple times.", Usage: "Migrates passwords from unsecured fields to secure_json_data field. Return ok unless there is an error. Safe to execute multiple times.",
Action: runDbCommand(datamigrations.EncryptDatasourcePaswords), Action: runDbCommand(datamigrations.EncryptDatasourcePaswords),
Flags: dbCommandFlags,
}, },
}, },
}, },
......
...@@ -51,6 +51,18 @@ func main() { ...@@ -51,6 +51,18 @@ func main() {
Name: "debug, d", Name: "debug, d",
Usage: "enable debug logging", Usage: "enable debug logging",
}, },
cli.StringFlag{
Name: "configOverrides",
Usage: "configuration options to override defaults as a string. e.g. cfg:default.paths.log=/dev/null",
},
cli.StringFlag{
Name: "homepath",
Usage: "path to grafana install/home path, defaults to working directory",
},
cli.StringFlag{
Name: "config",
Usage: "path to config file",
},
} }
app.Before = func(c *cli.Context) error { app.Before = func(c *cli.Context) error {
......
...@@ -38,6 +38,10 @@ func (c *ContextCommandLine) Application() *cli.App { ...@@ -38,6 +38,10 @@ func (c *ContextCommandLine) Application() *cli.App {
return c.App return c.App
} }
func (c *ContextCommandLine) HomePath() string { return c.GlobalString("homepath") }
func (c *ContextCommandLine) ConfigFile() string { return c.GlobalString("config") }
func (c *ContextCommandLine) PluginDirectory() string { func (c *ContextCommandLine) PluginDirectory() string {
return c.GlobalString("pluginsDir") return c.GlobalString("pluginsDir")
} }
...@@ -49,3 +53,7 @@ func (c *ContextCommandLine) RepoDirectory() string { ...@@ -49,3 +53,7 @@ func (c *ContextCommandLine) RepoDirectory() string {
func (c *ContextCommandLine) PluginURL() string { func (c *ContextCommandLine) PluginURL() string {
return c.GlobalString("pluginUrl") return c.GlobalString("pluginUrl")
} }
func (c *ContextCommandLine) OptionsString() string {
return c.GlobalString("configOverrides")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment