Skip to content

Commit

Permalink
lib: Usage sample for lib/env programs
Browse files Browse the repository at this point in the history
  • Loading branch information
oncilla committed Oct 12, 2018
1 parent 2c450e4 commit 8a281f5
Show file tree
Hide file tree
Showing 7 changed files with 396 additions and 14 deletions.
74 changes: 74 additions & 0 deletions go/lib/env/sample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2018 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package env contains common command line and initialization code for SCION services.
// If something is specific to one app, it should go into that app's code and not here.
//
// During initialization, SIGHUPs are masked. To call a function on each
// SIGHUP, pass the function when calling Init.
package env

import (
"flag"
"fmt"
"io/ioutil"
"os"
)

// ConfigFlag adds a config flag.
func ConfigFlag() *string {
return flag.String("config", "", "Service TOML config file (required)")
}

// SampleFlag adds a sample flag.
func SampleFlag() *string {
return flag.String("sample", "",
"Filename for creating a sample config. If set, the service is not started.")
}

// Usage returns a usage function based on the sample config.
func Usage(sampleConfig string) func() {
return func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nSample config file:\n%s", sampleConfig)
}
}

// CheckFlags checks whether the config flag has been provided. In case it
// is not provided and the sample flag is not set, the usage message is printed.
// If the sample flag is set, a sample config is written to the specified file.
// The first return value is the return code of the program. The second value
// indicates whether the program can continue with its execution or should exit.
func CheckFlags(flagConfig, flagSample, sampleConfig string) (int, bool) {
if flagConfig == "" {
if flagSample != "" {
return writeSample(flagSample, sampleConfig), false
}
fmt.Fprintln(os.Stderr, "Missing config file")
flag.Usage()
return 1, false
}
return 0, true
}

func writeSample(flagSample, sampleConfig string) int {
if err := ioutil.WriteFile(flagSample, []byte(sampleConfig), 0666); err != nil {
fmt.Fprintln(os.Stderr, "Unable to write sample: "+err.Error())
flag.Usage()
return 1
}
fmt.Fprintln(os.Stdout, "Sample file written to: "+flagSample)
return 0
}
80 changes: 80 additions & 0 deletions go/path_srv/internal/psconfig/sample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2018 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package psconfig

const Sample = `[general]
# The ID of the service. This is used to choose the relevant portion of the
# topology file for some services.
ID = "ps1-ff00_0_110-1"
# Directory for loading AS information, certs, keys, path policy, topology.
ConfigDir = "gen/ISD1/ASff00_0_110/ps1-ff00_0_110-1"
# Topology file. If not specified, topology.json is loaded from the config
# directory.
# Topology = "gen/ISD1/ASff00_0_110/ps1-ff00_0_110-1/topology.json"
# ReconnectToDispatcher can be set to true to enable the snetproxy reconnecter.
# ReconnectToDispatcher = true
[logging]
[logging.file]
# Location of the logging file.
Path = "logs/ps1-ff00_0_110-1.log"
# File logging level (trace|debug|info|warn|error|crit) (default debug)
Level = "debug"
# Max size of log file in MiB (default 50)
# Size = 50
# Max age of log file in days (default 7)
# MaxAge = 7
# How frequently to flush to the log file, in seconds. If 0, all messages
# are immediately flushed. If negative, messages are never flushed
# automatically. (default 5)
FlushInterval = 10
[logging.console]
# Console logging level (trace|debug|info|warn|error|crit) (default crit)
Level = "warn"
[metrics]
# The address to export prometheus metrics on. If not set, metrics are not
# exported.
# Prometheus = "127.0.0.1:8000"
[infra]
# Node type.
Type = "PS"
[trust]
# Database for trust information. If a file already exists, it is treated as
# initial trust information. If a file does not exist, it is created from the
# initial information found under ConfigDir/certs.
TrustDB = "gen-cache/ps1-ff00_0_110-1.trust.db"
[ps]
# Path to the path database
PathDB = "gen-cache/ps1-ff00_0_110-1.path.db"
# Enable the "old" replication of down segments between cores using SegSync
# messages (default false)
SegSync = false
# The time after which segments for a destination are refetched. (default 5m)
QueryInterval = "5m"
`
63 changes: 63 additions & 0 deletions go/path_srv/internal/psconfig/sample_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2018 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package psconfig

import (
"testing"
"time"

"github.com/BurntSushi/toml"
. "github.com/smartystreets/goconvey/convey"

"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/env"
)

type TestConfig struct {
General env.General
Logging env.Logging
Metrics env.Metrics
Infra env.Infra
Trust env.Trust
PS Config
}

func TestSampleCorrect(t *testing.T) {
Convey("Load", t, func() {
var cfg TestConfig
// Make sure SegSync is set.
cfg.PS.SegSync = true
_, err := toml.Decode(Sample, &cfg)
SoMsg("err", err, ShouldBeNil)

// Non-psconfig specific
SoMsg("ID correct", cfg.General.ID, ShouldEqual, "ps1-ff00_0_110-1")
SoMsg("ConfigDir correct", cfg.General.ConfigDir, ShouldEqual,
"gen/ISD1/ASff00_0_110/ps1-ff00_0_110-1")
SoMsg("LogFile correct", cfg.Logging.File.Path, ShouldEqual, "logs/ps1-ff00_0_110-1.log")
SoMsg("LogFile correct", cfg.Logging.File.Path, ShouldEqual, "logs/ps1-ff00_0_110-1.log")
SoMsg("LogLvl correct", cfg.Logging.File.Level, ShouldEqual, "debug")
SoMsg("LogFlush correct", *cfg.Logging.File.FlushInterval, ShouldEqual, 10)
SoMsg("LogConsoleLvl correct", cfg.Logging.Console.Level, ShouldEqual, "warn")
SoMsg("Infra correct", cfg.Infra.Type, ShouldEqual, common.PS)
SoMsg("TrustDB correct", cfg.Trust.TrustDB, ShouldEqual,
"gen-cache/ps1-ff00_0_110-1.trust.db")

// psconfig specific
SoMsg("PathDB correct", cfg.PS.PathDB, ShouldEqual, "gen-cache/ps1-ff00_0_110-1.path.db")
SoMsg("SegSync set", cfg.PS.SegSync, ShouldBeFalse)
SoMsg("QueryInterval correct", cfg.PS.QueryInterval.Duration, ShouldEqual, 5*time.Minute)
})
}
14 changes: 9 additions & 5 deletions go/path_srv/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,26 @@ type Config struct {
}

var (
flagConfig = env.ConfigFlag()
flagSample = env.SampleFlag()

config Config
environment *env.Env
flagConfig = flag.String("config", "", "Service TOML config file (required)")
)

func init() {
flag.Usage = env.Usage(psconfig.Sample)
}

// main initializes the path server and starts the dispatcher.
func main() {
os.Exit(realMain())
}

func realMain() int {
flag.Parse()
if *flagConfig == "" {
fmt.Fprintln(os.Stderr, "Missing config file")
flag.Usage()
return 1
if v, ok := env.CheckFlags(*flagConfig, *flagSample, psconfig.Sample); !ok {
return v
}
if err := setup(*flagConfig); err != nil {
fmt.Fprintln(os.Stderr, err)
Expand Down
94 changes: 94 additions & 0 deletions go/sciond/internal/sdconfig/sample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2018 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sdconfig

const Sample = `[general]
# The ID of the service.
ID = "sd1-ff00_0_110"
# Directory for loading AS information, certs, keys, path policy, topology.
ConfigDir = "gen/ISD1/ASff00_0_110/endhost"
# Topology file. If not specified, topology.json is loaded from the config
# directory.
# Topology = "gen/ISD1/ASff00_0_110/endhost/topology.json"
# ReconnectToDispatcher can be set to true to enable the snetproxy reconnecter.
# ReconnectToDispatcher = true
[logging]
[logging.file]
# Location of the logging file.
Path = "logs/sd1-ff00_0_110.log"
# File logging level (trace|debug|info|warn|error|crit) (default debug)
Level = "debug"
# Max size of log file in MiB (default 50)
# Size = 50
# Max age of log file in days (default 7)
# MaxAge = 7
# How frequently to flush to the log file, in seconds. If 0, all messages
# are immediately flushed. If negative, messages are never flushed
# automatically. (default 5)
FlushInterval = 10
[logging.console]
# Console logging level (trace|debug|info|warn|error|crit) (default crit)
Level = "warn"
[metrics]
# The address to export prometheus metrics on. If not set, metrics are not
# exported.
# Prometheus = "127.0.0.1:8000"
[infra]
# Node type.
Type = "SD"
[trust]
# Database for trust information. If a file already exists, it is treated as
# initial trust information. If a file does not exist, it is created from the
# initial information found under ConfigDir/certs.
TrustDB = "gen-cache/sd1-ff00_0_110.trust.db"
[sd]
# Path to the path database.
PathDB = "gen-cache/sd1-ff00_0_110.path.db"
# Address to listen on via the reliable socket protocol. If empty,
# a reliable socket server on the default socket is started.
Reliable = "/run/shm/sciond/default.sock"
# Address to listen on for normal unixgram messages. If empty, a
# unixgram server on the default socket is started.
Unix = "/run/shm/sciond/default-unix.sock"
# If set to True, the socket is removed before being created. (default false)
DeleteSocket = false
# Local address to listen on for SCION messages (if Bind is not set),
# and to send out messages to other nodes.
Public = "1-ff00:0:110,[127.0.0.1]:0"
# If set, Bind is the preferred local address to listen on for SCION
# messages.
# Bind = "1-ff00:0:110,[127.0.0.1]:0"
# The time after which segments for a destination are refetched. (default 5m)
QueryInterval = "5m"
`
Loading

0 comments on commit 8a281f5

Please sign in to comment.