Skip to content

Commit

Permalink
Merge pull request #1357 from weaveworks/1312-arg-parsing
Browse files Browse the repository at this point in the history
Move all the flag parsing to main.go; implement `scope help`
  • Loading branch information
paulbellamy committed Apr 20, 2016
2 parents f61e29e + cb0901e commit 3c1b068
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 168 deletions.
70 changes: 9 additions & 61 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,94 +1,42 @@
#!/bin/sh
#!/bin/bash

usage() {
echo "$0 --app.foo bar --probe.foo bar"
exit 1
}

mkdir -p /var/run/weave
APP_ARGS=""
PROBE_ARGS=""

TOKEN_PROVIDED=false

if [ "$1" = version ]; then
/home/weave/scope version
if [ "$1" = "version" -o "$1" = "help" ]; then
exec -a scope /home/weave/scope --mode $1
exit 0
fi

while true; do
case "$1" in
--app.*)
if echo "$1" | grep "=" 1>/dev/null; then
ARG_NAME=$(echo "$1" | sed 's/\-\-app\.\([^=]*\)=\(.*\)/\1/')
ARG_VALUE=$(echo "$1" | sed 's/\-\-app\.\([^=]*\)=\(.*\)/\2/')
else
[ $# -gt 1 ] || usage
ARG_NAME=$(echo "$1" | sed 's/\-\-app\.//')
ARG_VALUE="$2"
shift
fi
APP_ARGS="$APP_ARGS -$ARG_NAME=$ARG_VALUE"
;;
--debug)
APP_ARGS="$APP_ARGS -log.level=debug"
PROBE_ARGS="$PROBE_ARGS -log.level=debug"
;;
for arg in $@; do
case "$arg" in
--no-app|--probe-only)
touch /etc/service/app/down
;;
--no-probe|--app-only)
touch /etc/service/probe/down
;;
--weave.hostname*)
if echo "$1" | grep "=" 1>/dev/null; then
ARG_VALUE=$(echo "$1" | sed 's/\-\-weave.hostname=\(.*\)/\1/')
else
[ $# -gt 1 ] || usage
ARG_VALUE="$2"
shift
fi
PROBE_ARGS="$PROBE_ARGS -weave.hostname=$ARG_VALUE"
APP_ARGS="$APP_ARGS -weave.hostname=$ARG_VALUE"
;;
--probe.*)
if echo "$1" | grep "=" 1>/dev/null; then
ARG_NAME=$(echo "$1" | sed 's/\-\-probe\.\([^=]*\)=\(.*\)/\1/')
ARG_VALUE=$(echo "$1" | sed 's/\-\-probe\.\([^=]*\)=\(.*\)/\2/')
else
[ $# -gt 1 ] || usage
ARG_NAME=$(echo "$1" | sed 's/\-\-probe\.//')
ARG_VALUE="$2"
shift
fi
PROBE_ARGS="$PROBE_ARGS -$ARG_NAME=$ARG_VALUE"
;;
--service-token*)
if echo "$1" | grep "=" 1>/dev/null; then
ARG_VALUE=$(echo "$1" | sed 's/\-\-service-token=\(.*\)/\1/')
else
[ $# -gt 1 ] || usage
ARG_VALUE="$2"
shift
fi
PROBE_ARGS="$PROBE_ARGS -token=$ARG_VALUE"
TOKEN_PROVIDED=true
touch /etc/service/app/down
;;
*)
break
;;
esac
shift
done

echo "$APP_ARGS" >/var/run/weave/scope-app.args
echo "$PROBE_ARGS" >/var/run/weave/scope-probe.args
echo "$@" >/var/run/weave/scope-app.args
echo "$@" >/var/run/weave/scope-probe.args

# End of the command line can optionally be some
# addresses of apps to connect to, for people not
# using Weave DNS. We stick these in /var/run/weave/apps
# for the run-probe script to pick up.
MANUAL_APPS=$@
MANUAL_APPS=""

# Implicitly target the Scope Service if a service token was provided with
# no explicit manual app.
Expand Down
2 changes: 1 addition & 1 deletion docker/run-app
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash

exec -a scope-app /home/weave/scope app $(cat /var/run/weave/scope-app.args)
exec -a scope-app /home/weave/scope --mode app $(cat /var/run/weave/scope-app.args)
2 changes: 1 addition & 1 deletion docker/run-probe
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash

exec -a scope-probe /home/weave/scope probe $(cat /var/run/weave/scope-probe.args) $(cat /var/run/weave/apps)
exec -a scope-probe /home/weave/scope --mode probe $(cat /var/run/weave/scope-probe.args) $(cat /var/run/weave/apps)
52 changes: 14 additions & 38 deletions prog/app.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"flag"
"fmt"
"math/rand"
"net/http"
Expand All @@ -25,7 +24,6 @@ import (
"github.com/weaveworks/scope/common/middleware"
"github.com/weaveworks/scope/common/network"
"github.com/weaveworks/scope/common/weave"
"github.com/weaveworks/scope/common/xfer"
"github.com/weaveworks/scope/probe/docker"
)

Expand Down Expand Up @@ -142,50 +140,28 @@ func pipeRouterFactory(userIDer multitenant.UserIDer, pipeRouterURL, consulInf s
}

// Main runs the app
func appMain() {
var (
window = flag.Duration("window", 15*time.Second, "window")
listen = flag.String("http.address", ":"+strconv.Itoa(xfer.AppPort), "webserver listen address")
logLevel = flag.String("log.level", "info", "logging threshold level: debug|info|warn|error|fatal|panic")
logPrefix = flag.String("log.prefix", "<app>", "prefix for each log line")
logHTTP = flag.Bool("log.http", false, "Log individual HTTP requests")

weaveAddr = flag.String("weave.addr", app.DefaultWeaveURL, "Address on which to contact WeaveDNS")
weaveHostname = flag.String("weave.hostname", app.DefaultHostname, "Hostname to advertise in WeaveDNS")
containerName = flag.String("container.name", app.DefaultContainerName, "Name of this container (to lookup container ID)")
dockerEndpoint = flag.String("docker", app.DefaultDockerEndpoint, "Location of docker endpoint (to lookup container ID)")

collectorURL = flag.String("collector", "local", "Collector to use (local of dynamodb)")
controlRouterURL = flag.String("control.router", "local", "Control router to use (local or sqs)")
pipeRouterURL = flag.String("pipe.router", "local", "Pipe router to use (local)")
userIDHeader = flag.String("userid.header", "", "HTTP header to use as userid")

awsCreateTables = flag.Bool("aws.create.tables", false, "Create the tables in DynamoDB")
consulInf = flag.String("consul.inf", "", "The interface who's address I should advertise myself under in consul")
)
flag.Parse()

setLogLevel(*logLevel)
setLogFormatter(*logPrefix)
func appMain(flags appFlags) {
setLogLevel(flags.logLevel)
setLogFormatter(flags.logPrefix)

userIDer := multitenant.NoopUserIDer
if *userIDHeader != "" {
userIDer = multitenant.UserIDHeader(*userIDHeader)
if flags.userIDHeader != "" {
userIDer = multitenant.UserIDHeader(flags.userIDHeader)
}

collector, err := collectorFactory(userIDer, *collectorURL, *window, *awsCreateTables)
collector, err := collectorFactory(userIDer, flags.collectorURL, flags.window, flags.awsCreateTables)
if err != nil {
log.Fatalf("Error creating collector: %v", err)
return
}

controlRouter, err := controlRouterFactory(userIDer, *controlRouterURL)
controlRouter, err := controlRouterFactory(userIDer, flags.controlRouterURL)
if err != nil {
log.Fatalf("Error creating control router: %v", err)
return
}

pipeRouter, err := pipeRouterFactory(userIDer, *pipeRouterURL, *consulInf)
pipeRouter, err := pipeRouterFactory(userIDer, flags.pipeRouterURL, flags.consulInf)
if err != nil {
log.Fatalf("Error creating pipe router: %v", err)
return
Expand Down Expand Up @@ -213,10 +189,10 @@ func appMain() {

// If user supplied a weave router address, periodically try and register
// out IP address in WeaveDNS.
if *weaveAddr != "" {
if flags.weaveAddr != "" {
weave, err := newWeavePublisher(
*dockerEndpoint, *weaveAddr,
*weaveHostname, *containerName)
flags.dockerEndpoint, flags.weaveAddr,
flags.weaveHostname, flags.containerName)
if err != nil {
log.Println("Failed to start weave integration:", err)
} else {
Expand All @@ -225,12 +201,12 @@ func appMain() {
}

handler := router(collector, controlRouter, pipeRouter)
if *logHTTP {
if flags.logHTTP {
handler = middleware.Logging.Wrap(handler)
}
go func() {
log.Infof("listening on %s", *listen)
log.Info(http.ListenAndServe(*listen, handler))
log.Infof("listening on %s", flags.listen)
log.Info(http.ListenAndServe(flags.listen, handler))
}()

common.SignalHandlerLoop()
Expand Down
144 changes: 132 additions & 12 deletions prog/main.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package main

import (
"flag"
"fmt"
"os"
"strconv"
"strings"
"time"

log "github.com/Sirupsen/logrus"

"github.com/weaveworks/scope/app"
"github.com/weaveworks/scope/common/xfer"
"github.com/weaveworks/weave/common"
)

Expand Down Expand Up @@ -45,27 +50,142 @@ func setLogLevel(levelname string) {
log.SetLevel(level)
}

func usage() {
fmt.Fprintf(os.Stderr, "usage: %s (app|probe|version) args...\n", os.Args[0])
os.Exit(1)
type flags struct {
probe probeFlags
app appFlags
}

type probeFlags struct {
token string
httpListen string
publishInterval time.Duration
spyInterval time.Duration
spyProcs bool
procRoot string
pluginsRoot string
useConntrack bool
insecure bool
logPrefix string
logLevel string

dockerEnabled bool
dockerInterval time.Duration
dockerBridge string

kubernetesEnabled bool
kubernetesAPI string
kubernetesInterval time.Duration

weaveAddr string
weaveHostname string
}

type appFlags struct {
window time.Duration
listen string
logLevel string
logPrefix string
logHTTP bool

weaveAddr string
weaveHostname string
containerName string
dockerEndpoint string

collectorURL string
controlRouterURL string
pipeRouterURL string
userIDHeader string

awsCreateTables bool
consulInf string
}

func main() {
if len(os.Args) < 2 {
usage()
}
var (
flags = flags{}
mode string
debug bool
weaveHostname string
)

module := os.Args[1]
os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
// Flags that apply to both probe and app
flag.StringVar(&mode, "mode", "help", "For internal use.")
flag.BoolVar(&debug, "debug", false, "Force debug logging.")
flag.StringVar(&weaveHostname, "weave.hostname", "", "Hostname to advertise/lookup in WeaveDNS")

// We can ignore these - we need to know how to parse them, but they are interpreted by the entrypoint script.
// They are also here so they are included in usage.
flag.Bool("no-app", false, "Don't run the app.")
flag.Bool("probe-only", false, "Only run the probe.")
flag.Bool("no-probe", false, "Don't run the probe.")
flag.Bool("app-only", false, "Only run the app")
flag.String("service-token", "", "Token to use to authenticate with scope.weave.works")

// Probe flags
flag.StringVar(&flags.probe.token, "probe.token", "default-token", "Token to use to authenticate with scope.weave.works")
flag.StringVar(&flags.probe.httpListen, "probe.http.listen", "", "listen address for HTTP profiling and instrumentation server")
flag.DurationVar(&flags.probe.publishInterval, "probe.publish.interval", 3*time.Second, "publish (output) interval")
flag.DurationVar(&flags.probe.spyInterval, "probe.spy.interval", time.Second, "spy (scan) interval")
flag.BoolVar(&flags.probe.spyProcs, "probe.processes", true, "report processes (needs root)")
flag.StringVar(&flags.probe.procRoot, "probe.proc.root", "/proc", "location of the proc filesystem")
flag.StringVar(&flags.probe.pluginsRoot, "probe.plugins.root", "/var/run/scope/plugins", "Root directory to search for plugins")
flag.BoolVar(&flags.probe.useConntrack, "probe.conntrack", true, "also use conntrack to track connections")
flag.BoolVar(&flags.probe.insecure, "probe.insecure", false, "(SSL) explicitly allow \"insecure\" SSL connections and transfers")
flag.StringVar(&flags.probe.logPrefix, "probe.log.prefix", "<probe>", "prefix for each log line")
flag.StringVar(&flags.probe.logLevel, "probe.log.level", "info", "logging threshold level: debug|info|warn|error|fatal|panic")
flag.BoolVar(&flags.probe.dockerEnabled, "probe.docker", false, "collect Docker-related attributes for processes")
flag.DurationVar(&flags.probe.dockerInterval, "probe.docker.interval", 10*time.Second, "how often to update Docker attributes")
flag.StringVar(&flags.probe.dockerBridge, "probe.docker.bridge", "docker0", "the docker bridge name")
flag.BoolVar(&flags.probe.kubernetesEnabled, "probe.kubernetes", false, "collect kubernetes-related attributes for containers, should only be enabled on the master node")
flag.StringVar(&flags.probe.kubernetesAPI, "probe.kubernetes.api", "", "Address of kubernetes master api")
flag.DurationVar(&flags.probe.kubernetesInterval, "probe.kubernetes.interval", 10*time.Second, "how often to do a full resync of the kubernetes data")
flag.StringVar(&flags.probe.weaveAddr, "probe.weave.addr", "127.0.0.1:6784", "IP address & port of the Weave router")
flag.StringVar(&flags.probe.weaveHostname, "probe.weave.hostname", app.DefaultHostname, "Hostname to lookup in WeaveDNS")

// App flags
flag.DurationVar(&flags.app.window, "app.window", 15*time.Second, "window")
flag.StringVar(&flags.app.listen, "app.http.address", ":"+strconv.Itoa(xfer.AppPort), "webserver listen address")
flag.StringVar(&flags.app.logLevel, "app.log.level", "info", "logging threshold level: debug|info|warn|error|fatal|panic")
flag.StringVar(&flags.app.logPrefix, "app.log.prefix", "<app>", "prefix for each log line")
flag.BoolVar(&flags.app.logHTTP, "app.log.http", false, "Log individual HTTP requests")

flag.StringVar(&flags.app.weaveAddr, "app.weave.addr", app.DefaultWeaveURL, "Address on which to contact WeaveDNS")
flag.StringVar(&flags.app.weaveHostname, "app.weave.hostname", app.DefaultHostname, "Hostname to advertise in WeaveDNS")
flag.StringVar(&flags.app.containerName, "app.container.name", app.DefaultContainerName, "Name of this container (to lookup container ID)")
flag.StringVar(&flags.app.dockerEndpoint, "app.docker", app.DefaultDockerEndpoint, "Location of docker endpoint (to lookup container ID)")

flag.StringVar(&flags.app.collectorURL, "app.collector", "local", "Collector to use (local of dynamodb)")
flag.StringVar(&flags.app.controlRouterURL, "app.control.router", "local", "Control router to use (local or sqs)")
flag.StringVar(&flags.app.pipeRouterURL, "app.pipe.router", "local", "Pipe router to use (local)")
flag.StringVar(&flags.app.userIDHeader, "app.userid.header", "", "HTTP header to use as userid")

flag.BoolVar(&flags.app.awsCreateTables, "app.aws.create.tables", false, "Create the tables in DynamoDB")
flag.StringVar(&flags.app.consulInf, "app.consul.inf", "", "The interface who's address I should advertise myself under in consul")

flag.Parse()

// Deal with common args
if debug {
flags.probe.logLevel = "debug"
flags.app.logLevel = "debug"
}
if weaveHostname != "" {
flags.probe.weaveHostname = weaveHostname
flags.app.weaveHostname = weaveHostname
}

switch module {
switch mode {
case "app":
appMain()
appMain(flags.app)
case "probe":
probeMain()
probeMain(flags.probe)
case "version":
fmt.Println("Weave Scope version", version)
case "help":
flag.PrintDefaults()
default:
usage()
fmt.Printf("command '%s' not recognices", mode)
os.Exit(1)
}
}
Loading

0 comments on commit 3c1b068

Please sign in to comment.