Skip to content

Commit

Permalink
Grafana-CLI: Wrapper for grafana-cli within RPM/DEB packages and co…
Browse files Browse the repository at this point in the history
…nfig/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.
  • Loading branch information
gotjosh committed Jun 24, 2019
1 parent e7e9d36 commit 2fb45ee
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 36 deletions.
53 changes: 35 additions & 18 deletions build.go
Expand Up @@ -43,7 +43,9 @@ var (
workingDir string
includeBuildId bool = true
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
enterprise bool = false
skipRpmGen bool = false
Expand Down Expand Up @@ -230,6 +232,7 @@ type linuxPackageOptions struct {
packageType string
packageArch string
homeDir string
homeBinDir string
binPath string
serverBinPath string
cliBinPath string
Expand All @@ -240,10 +243,11 @@ type linuxPackageOptions struct {
initdScriptFilePath string
systemdServiceFilePath string

postinstSrc string
initdScriptSrc string
defaultFileSrc string
systemdFileSrc string
postinstSrc string
initdScriptSrc string
defaultFileSrc string
systemdFileSrc string
cliBinaryWrapperSrc string

depends []string
}
Expand All @@ -258,17 +262,19 @@ func createDebPackages() {
packageType: "deb",
packageArch: debPkgArch,
homeDir: "/usr/share/grafana",
homeBinDir: "/usr/share/grafana/bin",
binPath: "/usr/sbin",
configDir: "/etc/grafana",
etcDefaultPath: "/etc/default",
etcDefaultFilePath: "/etc/default/grafana-server",
initdScriptFilePath: "/etc/init.d/grafana-server",
systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service",

postinstSrc: "packaging/deb/control/postinst",
initdScriptSrc: "packaging/deb/init.d/grafana-server",
defaultFileSrc: "packaging/deb/default/grafana-server",
systemdFileSrc: "packaging/deb/systemd/grafana-server.service",
postinstSrc: "packaging/deb/control/postinst",
initdScriptSrc: "packaging/deb/init.d/grafana-server",
defaultFileSrc: "packaging/deb/default/grafana-server",
systemdFileSrc: "packaging/deb/systemd/grafana-server.service",
cliBinaryWrapperSrc: "packaging/wrappers/grafana-cli",

depends: []string{"adduser", "libfontconfig1"},
})
Expand All @@ -286,17 +292,19 @@ func createRpmPackages() {
packageType: "rpm",
packageArch: rpmPkgArch,
homeDir: "/usr/share/grafana",
homeBinDir: "/usr/share/grafana/bin",
binPath: "/usr/sbin",
configDir: "/etc/grafana",
etcDefaultPath: "/etc/sysconfig",
etcDefaultFilePath: "/etc/sysconfig/grafana-server",
initdScriptFilePath: "/etc/init.d/grafana-server",
systemdServiceFilePath: "/usr/lib/systemd/system/grafana-server.service",

postinstSrc: "packaging/rpm/control/postinst",
initdScriptSrc: "packaging/rpm/init.d/grafana-server",
defaultFileSrc: "packaging/rpm/sysconfig/grafana-server",
systemdFileSrc: "packaging/rpm/systemd/grafana-server.service",
postinstSrc: "packaging/rpm/control/postinst",
initdScriptSrc: "packaging/rpm/init.d/grafana-server",
defaultFileSrc: "packaging/rpm/sysconfig/grafana-server",
systemdFileSrc: "packaging/rpm/systemd/grafana-server.service",
cliBinaryWrapperSrc: "packaging/wrappers/grafana-cli",

depends: []string{"/sbin/service", "fontconfig", "freetype", "urw-fonts"},
})
Expand All @@ -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/sbin"))

// copy binary
for _, binary := range binaries {
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+binary), filepath.Join(packageRoot, "/usr/sbin/"+binary))
}
// copy grafana-cli wrapper
runPrint("cp", "-p", options.cliBinaryWrapperSrc, filepath.Join(packageRoot, "/usr/sbin/"+cliBinary))

// copy grafana-server binary
runPrint("cp", "-p", filepath.Join(workingDir, "tmp/bin/"+serverBinary), filepath.Join(packageRoot, "/usr/sbin/"+serverBinary))

// copy init.d script
runPrint("cp", "-p", options.initdScriptSrc, filepath.Join(packageRoot, options.initdScriptFilePath))
// copy environment var file
Expand All @@ -338,6 +348,13 @@ func createPackage(options linuxPackageOptions) {
// remove bin path
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{
"-s", "dir",
"--description", "Grafana",
Expand Down Expand Up @@ -391,7 +408,7 @@ func createPackage(options linuxPackageOptions) {
args = append(args, "--iteration", linuxPackageIteration)
}

// add dependenciesj
// add dependencies
for _, dep := range options.depends {
args = append(args, "--depends", dep)
}
Expand Down
2 changes: 1 addition & 1 deletion docs/sources/administration/cli.md
Expand Up @@ -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.

`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:

Expand Down
39 changes: 39 additions & 0 deletions packaging/wrappers/grafana-cli
@@ -0,0 +1,39 @@
#! /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" "$@"
26 changes: 9 additions & 17 deletions pkg/cmd/grafana-cli/commands/commands.go
Expand Up @@ -2,6 +2,7 @@ package commands

import (
"os"
"strings"

"github.com/codegangsta/cli"
"github.com/fatih/color"
Expand All @@ -16,16 +17,20 @@ import (
func runDbCommand(command func(commandLine utils.CommandLine, sqlStore *sqlstore.SqlStore) error) func(context *cli.Context) {
return func(context *cli.Context) {
cmd := &utils.ContextCommandLine{Context: context}
debug := cmd.GlobalBool("debug")

cfg := setting.NewCfg()

configOptions := strings.Split(cmd.GlobalString("configOverrides"), " ")
cfg.Load(&setting.CommandLineArgs{
Config: cmd.String("config"),
HomePath: cmd.String("homepath"),
Args: context.Args(),
Config: cmd.ConfigFile(),
HomePath: cmd.HomePath(),
Args: append(configOptions, cmd.Args()...), // tailing arguments have precedence over the options string
})

cfg.LogConfigSources()
if debug {
cfg.LogConfigSources()
}

engine := &sqlstore.SqlStore{}
engine.Cfg = cfg
Expand Down Expand Up @@ -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{
{
Name: "reset-admin-password",
Usage: "reset-admin-password <new password>",
Action: runDbCommand(resetPasswordCommand),
Flags: dbCommandFlags,
},
{
Name: "data-migration",
Expand All @@ -121,7 +114,6 @@ var adminCommands = []cli.Command{
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.",
Action: runDbCommand(datamigrations.EncryptDatasourcePaswords),
Flags: dbCommandFlags,
},
},
},
Expand Down
12 changes: 12 additions & 0 deletions pkg/cmd/grafana-cli/main.go
Expand Up @@ -51,6 +51,18 @@ func main() {
Name: "debug, d",
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 {
Expand Down
8 changes: 8 additions & 0 deletions pkg/cmd/grafana-cli/utils/command_line.go
Expand Up @@ -38,6 +38,10 @@ func (c *ContextCommandLine) Application() *cli.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 {
return c.GlobalString("pluginsDir")
}
Expand All @@ -49,3 +53,7 @@ func (c *ContextCommandLine) RepoDirectory() string {
func (c *ContextCommandLine) PluginURL() string {
return c.GlobalString("pluginUrl")
}

func (c *ContextCommandLine) OptionsString() string {
return c.GlobalString("configOverrides")
}

0 comments on commit 2fb45ee

Please sign in to comment.