Work on deb and rpm packages, both seem to work now, #1476

This commit is contained in:
Torkel Ödegaard
2015-03-03 17:14:58 +01:00
parent 59da4a0b3b
commit 0db55b6194
10 changed files with 201 additions and 120 deletions

View File

@@ -8,7 +8,8 @@ module.exports = function (grunt) {
srcDir: 'src', srcDir: 'src',
destDir: 'dist', destDir: 'dist',
tempDir: 'tmp', tempDir: 'tmp',
docsDir: 'docs/' docsDir: 'docs/',
arch: grunt.option('arch') || 'x86_64',
}; };
// load plugins // load plugins

View File

@@ -73,11 +73,11 @@ func main() {
test("./pkg/...") test("./pkg/...")
case "package": case "package":
clean() //clean()
//verifyGitRepoIsClean() //verifyGitRepoIsClean()
test("./pkg/...") //test("./pkg/...")
build(".", []string{}) //build(".", []string{})
buildFrontend() //buildFrontend()
createRpmAndDeb() createRpmAndDeb()
case "build-ui": case "build-ui":
@@ -121,24 +121,22 @@ func createRpmAndDeb() {
runError("mkdir", "-p", configDir) runError("mkdir", "-p", configDir)
// copy sample ini file to /etc/opt/grafana // copy sample ini file to /etc/opt/grafana
runError("cp", "conf/sample.ini", filepath.Join(configDir, "grafana.ini")) configFile := filepath.Join(configDir, "grafana.ini")
runError("cp", "conf/sample.ini", configFile)
// copy release files // copy release files
runError("cp", "-a", filepath.Join(workingDir, "tmp")+"/.", versionFolder) runError("cp", "-a", filepath.Join(workingDir, "tmp")+"/.", versionFolder)
fmt.Printf("PackageDir: %v\n", versionFolder)
GeneratePostInstallScript(postInstallScriptPath.Name()) GeneratePostInstallScript(postInstallScriptPath.Name())
fmt.Printf("script_path: %v\n", postInstallScriptPath.Name())
args := []string{ args := []string{
"-s", "dir", "-s", "dir",
"-t", "deb",
"--description", "Grafana", "--description", "Grafana",
"-C", packageRoot, "-C", packageRoot,
"--vendor", "Grafana", "--vendor", "Grafana",
"--url", "http://grafana.org", "--url", "http://grafana.org",
"--license", "Apache 2.0", "--license", "Apache 2.0",
"--maintainer", "contact@grafana.org", "--maintainer", "contact@grafana.org",
"--config-files", filepath.Join(configRoot, "grafana.ini"),
"--after-install", postInstallScriptPath.Name(), "--after-install", postInstallScriptPath.Name(),
"--name", "grafana", "--name", "grafana",
"--version", version, "--version", version,
@@ -146,7 +144,11 @@ func createRpmAndDeb() {
".", ".",
} }
runPrint("fpm", args...) fmt.Println("Creating debian package")
runPrint("fpm", append([]string{"-t", "deb"}, args...)...)
fmt.Println("Creating redhat/centos package")
runPrint("fpm", append([]string{"-t", "rpm"}, args...)...)
} }
func GeneratePostInstallScript(path string) { func GeneratePostInstallScript(path string) {

View File

@@ -0,0 +1,6 @@
FROM centos:7
RUN yum install -y initscripts
ADD *.rpm /tmp/

10
docker/rpmtest/build.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
cp Dockerfile ../../dist
cd ../../dist
docker build --tag "grafana/rpmtest" .
rm Dockerfile
docker run -i -t grafana/rpmtest /bin/bash

13
main.go
View File

@@ -2,6 +2,7 @@ package main
import ( import (
"os" "os"
"os/signal"
"runtime" "runtime"
"strconv" "strconv"
@@ -27,6 +28,13 @@ func main() {
setting.BuildCommit = commit setting.BuildCommit = commit
setting.BuildStamp = buildstampInt64 setting.BuildStamp = buildstampInt64
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
os.Exit(0)
}()
app := cli.NewApp() app := cli.NewApp()
app.Name = "Grafana Backend" app.Name = "Grafana Backend"
app.Usage = "grafana web" app.Usage = "grafana web"
@@ -46,7 +54,12 @@ func main() {
Name: "config", Name: "config",
Usage: "path to grafana.ini config file", Usage: "path to grafana.ini config file",
}, },
cli.StringFlag{
Name: "pidfile",
Usage: "path to pidfile",
},
}...) }...)
app.Run(os.Args) app.Run(os.Args)
log.Close() log.Close()

View File

@@ -5,8 +5,12 @@ package cmd
import ( import (
"fmt" "fmt"
"io/ioutil"
"net/http" "net/http"
"os"
"path" "path"
"path/filepath"
"strconv"
"github.com/Unknwon/macaron" "github.com/Unknwon/macaron"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
@@ -68,6 +72,7 @@ func mapStatic(m *macaron.Macaron, dir string, prefix string) {
func runWeb(c *cli.Context) { func runWeb(c *cli.Context) {
initRuntime(c) initRuntime(c)
writePIDFile(c)
social.NewOAuthService() social.NewOAuthService()
eventpublisher.Init() eventpublisher.Init()
@@ -92,3 +97,22 @@ func runWeb(c *cli.Context) {
log.Fatal(4, "Fail to start server: %v", err) log.Fatal(4, "Fail to start server: %v", err)
} }
} }
func writePIDFile(c *cli.Context) {
path := c.GlobalString("pidfile")
if path == "" {
return
}
// Ensure the required directory structure exists.
err := os.MkdirAll(filepath.Dir(path), 0700)
if err != nil {
log.Fatal(3, "Failed to verify pid directory", err)
}
// Retrieve the PID and write it.
pid := strconv.Itoa(os.Getpid())
if err := ioutil.WriteFile(path, []byte(pid), 0644); err != nil {
log.Fatal(3, "Failed to write pidfile", err)
}
}

View File

@@ -4,3 +4,5 @@
2015/03/03 10:09:13 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER 2015/03/03 10:09:13 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
2015/03/03 10:09:34 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER 2015/03/03 10:09:34 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
2015/03/03 10:15:20 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER 2015/03/03 10:15:20 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
2015/03/03 12:29:29 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER
2015/03/03 12:33:09 [I] Setting: ENV override found: GF_SECURITY_ADMIN_USER

View File

@@ -1,19 +1,21 @@
#!/bin/sh #! /usr/bin/env bash
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: grafana # Provides: grafana
# Required-Start: $local_fs $remote_fs $network # Required-Start: $all
# Required-Stop: $local_fs $remote_fs $network # Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6
# Short-Description: Starts grafana at startup # Short-Description: Start grafana at boot time
# Description: Starts grafana at startup
### END INIT INFO ### END INIT INFO
# tested on
# 1. New lsb that define start-stop-daemon
# 3. Centos with initscripts package installed
# Documentation available at if [ -r /lib/lsb/init-functions ]; then
# http://refspecs.linuxfoundation.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptfunc.html source /lib/lsb/init-functions
# Debian provides some extra functions though fi
. /lib/lsb/init-functions
DAEMON_NAME="grafana" DAEMON_NAME="grafana"
DAEMON_USER="grafana" DAEMON_USER="grafana"
@@ -24,85 +26,143 @@ DAEMON_PID="/var/run/${DAEMON_NAME}.pid"
DAEMON_NICE=0 DAEMON_NICE=0
DAEMON_LOG='/var/log/grafana/grafana.log' DAEMON_LOG='/var/log/grafana/grafana.log'
[ -r "/etc/default/${DAEMON_NAME}" ] && . "/etc/default/${DAEMON_NAME}" # If the daemon is not there, then exit.
[ -x $DAEMON_PATH ] || exit 5
if [ "x$STDOUT" == "x" ]; then
STDOUT=/tmp/grafana.log
fi
function pidofproc() {
if [ $# -ne 3 ]; then
echo "Expected three arguments, e.g. $0 -p pidfile daemon-name"
fi
pid=`pgrep -f $3`
local pidfile=`cat $2`
if [ "x$pidfile" == "x" ]; then
return 1
fi
if [ "x$pid" != "x" -a "$pidfile" == "$pid" ]; then
return 0
fi
return 1
}
function killproc() {
if [ $# -ne 3 ]; then
echo "Expected three arguments, e.g. $0 -p pidfile signal"
fi
pid=`cat $2`
kill -s $3 $pid
}
function log_failure_msg() {
echo "$@" "[ FAILED ]"
}
function log_success_msg() {
echo "$@" "[ OK ]"
}
do_start() { do_start() {
local result cd $DAEMON_PWD
pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null # Checked the PID file exists and check the actual status of process
if [ $? -eq 0 ]; then if [ -e $DAEMON_PID ]; then
log_warning_msg "${DAEMON_NAME} is already started" pidofproc -p $DAEMON_PID $DAEMON_PATH > /dev/null 2>&1 && status="0" || status="$?"
result=0 # If the status is SUCCESS then don't need to start again.
else if [ "x$status" = "x0" ]; then
log_daemon_msg "Starting ${DAEMON_DESC}" "${DAEMON_NAME}" log_failure_msg "$DAEMON_NAME process is running"
touch "${DAEMON_LOG}" exit 1 # Exit
chown $DAEMON_USER "${DAEMON_LOG}" fi
chmod u+rw "${DAEMON_LOG}" fi
if [ -z "${DAEMON_USER}" ]; then # Start the daemon.
start-stop-daemon --start --quiet --oknodo --background \ log_success_msg "Starting the process" "$DAEMON_NAME"
--nicelevel $DAEMON_NICE \
--chdir "${DAEMON_PWD}" \ # Start the daemon with the help of start-stop-daemon
--pidfile "${DAEMON_PID}" --make-pidfile \ # Log the message appropriately
--exec "${DAEMON_PATH}" -- $DAEMON_OPTS if which start-stop-daemon > /dev/null 2>&1; then
result=$? start-stop-daemon \
else --start --quiet --oknodo --background \
start-stop-daemon --start --quiet --oknodo --background \ --nicelevel $DAEMON_NICE \
--nicelevel $DAEMON_NICE \ --chdir "${DAEMON_PWD}" \
--chdir "${DAEMON_PWD}" \ --pidfile "${DAEMON_PID}" --make-pidfile \
--pidfile "${DAEMON_PID}" --make-pidfile \ --chuid "${DAEMON_USER}" \
--chuid "${DAEMON_USER}" \ --exec "${DAEMON_PATH}" -- $DAEMON_OPTS
--exec "${DAEMON_PATH}" -- $DAEMON_OPTS result=$?
result=$? else
fi touch ${DAEMON_PID}
log_end_msg $result chown $DAEMON_USER "${DAEMON_PID}"
fi #daemon --user $DAEMON_USER --pidfile $DAEMON_PID nohup $DAEMON_PATH $DAEMON_OPTS
return $result su -s /bin/sh -c "nohup ${DAEMON_PATH} --pidfile=${DAEMON_PID} ${DAEMON_OPTS} >> $STDOUT 3>&1 &" $DAEMON_USER
fi
log_success_msg "$DAEMON_NAME process was started"
} }
do_stop() { do_stop() {
local result local result
pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
log_warning_msg "${DAEMON_NAME} is not started" log_failure_msg "${DAEMON_NAME} is not started"
result=0 result=0
else else
log_daemon_msg "Stopping ${DAEMON_DESC}" "${DAEMON_NAME}" log_success_msg "Stopping ${DAEMON_NAME}"
killproc -p "${DAEMON_PID}" "${DAEMON_PATH}" killproc -p "${DAEMON_PID}" SIGTERM
result=$? result=$?
log_end_msg $result if [ $result = 0 ]; then
rm "${DAEMON_PID}" log_success_msg "Stopped ${DAEMON_NAME}"
fi rm "${DAEMON_PID}"
return $result fi
fi
return $result
} }
do_restart() { do_restart() {
local result local result
do_stop do_stop
result=$? result=$?
if [ $result = 0 ]; then sleep 2
do_start if [ $result = 0 ]; then
result=$? do_start
fi result=$?
return $result fi
return $result
} }
do_status() { do_status() {
local result if [ -e $DEAMON_PID ]; then
status_of_proc -p "${DAEMON_PID}" "${DAEMON_PATH}" "${DAEMON_NAME}" pidofproc -p "${DAEMON_PID}" "${DAEMON_PATH}" > /dev/null
result=$? if [ $? -ne 0 ]; then
return $result log_failure_msg "$DAEMON_NAME Process is not running"
exit 1
else
log_success_msg "$DAEMON_NAME Process is running"
exit 0
fi
else
log_failure_msg "$DAEMON_NAME Process is not running"
exit 3
fi
} }
do_usage() { do_usage() {
echo $"Usage: $0 {start | stop | restart | status}" echo $"Usage: $0 {start | stop | restart | status}"
exit 1 exit 1
} }
case "$1" in case "$1" in
start) do_start; exit $? ;; start) do_start; exit $? ;;
stop) do_stop; exit $? ;; stop) do_stop; exit $? ;;
restart) do_restart; exit $? ;; restart) do_restart; exit $? ;;
status) do_status; exit $? ;; status) do_status; exit $? ;;
*) do_usage; exit 1 ;; *) do_usage; exit 1 ;;
esac esac

View File

@@ -5,7 +5,6 @@ module.exports = function(grunt) {
grunt.registerTask('release', [ grunt.registerTask('release', [
'build', 'build',
'build-post-process', 'build-post-process',
'compress:zip_release',
'compress:tgz_release', 'compress:tgz_release',
]); ]);

View File

@@ -1,23 +1,5 @@
module.exports = function(config) { module.exports = function(config) {
return { return {
zip: {
options: {
archive: '<%= destDir %>/<%= pkg.name %>-latest.zip'
},
files : [
{
expand: true,
cwd: '<%= tempDir %>',
src: ['**/*'],
dest: '<%= pkg.name %>/',
},
{
expand: true,
dest: '<%= pkg.name %>/',
src: ['LICENSE.md', 'README.md', 'NOTICE.md'],
}
]
},
tgz: { tgz: {
options: { options: {
archive: '<%= destDir %>/<%= pkg.name %>-latest.tar.gz' archive: '<%= destDir %>/<%= pkg.name %>-latest.tar.gz'
@@ -36,27 +18,9 @@ module.exports = function(config) {
} }
] ]
}, },
zip_release: {
options: {
archive: '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.zip'
},
files : [
{
expand: true,
cwd: '<%= tempDir %>',
src: ['**/*'],
dest: '<%= pkg.name %>-<%= pkg.version %>/',
},
{
expand: true,
src: ['LICENSE.md', 'README.md', 'NOTICE.md'],
dest: '<%= pkg.name %>-<%= pkg.version %>/',
}
]
},
tgz_release: { tgz_release: {
options: { options: {
archive: '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.tar.gz' archive: '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.<%= arch %>.tar.gz'
}, },
files : [ files : [
{ {