mirror of
https://github.com/safing/portbase
synced 2025-09-01 18:19:57 +00:00
Release to master
This commit is contained in:
commit
c35d42899a
7 changed files with 231 additions and 48 deletions
113
config/basic_config.go
Normal file
113
config/basic_config.go
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/safing/portbase/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Configuration Keys.
|
||||||
|
var (
|
||||||
|
CfgDevModeKey = "core/devMode"
|
||||||
|
defaultDevMode bool
|
||||||
|
|
||||||
|
CfgLogLevel = "core/log/level"
|
||||||
|
defaultLogLevel = log.InfoLevel.String()
|
||||||
|
logLevel StringOption
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.BoolVar(&defaultDevMode, "devmode", false, "enable development mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerBasicOptions() error {
|
||||||
|
// Get the default log level from the log package.
|
||||||
|
defaultLogLevel = log.GetLogLevel().Name()
|
||||||
|
|
||||||
|
// Register logging setting.
|
||||||
|
// The log package cannot do that, as it would trigger and import loop.
|
||||||
|
if err := Register(&Option{
|
||||||
|
Name: "Log Level",
|
||||||
|
Key: CfgLogLevel,
|
||||||
|
Description: "Configure the logging level.",
|
||||||
|
OptType: OptTypeString,
|
||||||
|
ExpertiseLevel: ExpertiseLevelDeveloper,
|
||||||
|
ReleaseLevel: ReleaseLevelStable,
|
||||||
|
DefaultValue: defaultLogLevel,
|
||||||
|
Annotations: Annotations{
|
||||||
|
DisplayOrderAnnotation: 513,
|
||||||
|
DisplayHintAnnotation: DisplayHintOneOf,
|
||||||
|
CategoryAnnotation: "Development",
|
||||||
|
},
|
||||||
|
PossibleValues: []PossibleValue{
|
||||||
|
{
|
||||||
|
Name: "Critical",
|
||||||
|
Value: "critical",
|
||||||
|
Description: "The critical level only logs errors that lead to a partial, but imminent failure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Error",
|
||||||
|
Value: "error",
|
||||||
|
Description: "The error level logs errors that potentially break functionality. Everything logged by the critical level is included here too.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Warning",
|
||||||
|
Value: "warning",
|
||||||
|
Description: "The warning level logs minor errors and worse. Everything logged by the error level is included here too.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Info",
|
||||||
|
Value: "info",
|
||||||
|
Description: "The info level logs the main events that are going on and are interesting to the user. Everything logged by the warning level is included here too.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Debug",
|
||||||
|
Value: "debug",
|
||||||
|
Description: "The debug level logs some additional debugging details. Everything logged by the info level is included here too.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Trace",
|
||||||
|
Value: "trace",
|
||||||
|
Description: "The trace level logs loads of detailed information as well as operation and request traces. Everything logged by the debug level is included here too.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logLevel = GetAsString(CfgLogLevel, defaultLogLevel)
|
||||||
|
|
||||||
|
// Register to hook to update the log level.
|
||||||
|
if err := module.RegisterEventHook(
|
||||||
|
"config",
|
||||||
|
configChangeEvent,
|
||||||
|
"update log level",
|
||||||
|
setLogLevel,
|
||||||
|
); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Register(&Option{
|
||||||
|
Name: "Development Mode",
|
||||||
|
Key: CfgDevModeKey,
|
||||||
|
Description: "In Development Mode, security restrictions are lifted/softened to enable unrestricted access for debugging and testing purposes.",
|
||||||
|
OptType: OptTypeBool,
|
||||||
|
ExpertiseLevel: ExpertiseLevelDeveloper,
|
||||||
|
ReleaseLevel: ReleaseLevelStable,
|
||||||
|
DefaultValue: defaultDevMode,
|
||||||
|
Annotations: Annotations{
|
||||||
|
DisplayOrderAnnotation: 512,
|
||||||
|
CategoryAnnotation: "Development",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadLogLevel() {
|
||||||
|
setDefaultConfigOption(CfgLogLevel, log.GetLogLevel().Name(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setLogLevel(ctx context.Context, data interface{}) error {
|
||||||
|
log.SetLogLevel(log.ParseLevel(logLevel()))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
|
|
||||||
"github.com/safing/portbase/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Configuration Keys.
|
|
||||||
var (
|
|
||||||
CfgDevModeKey = "core/devMode"
|
|
||||||
defaultDevMode bool
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
flag.BoolVar(&defaultDevMode, "devmode", false, "enable development mode")
|
|
||||||
}
|
|
||||||
|
|
||||||
func logDevModeOverride() {
|
|
||||||
if defaultDevMode {
|
|
||||||
log.Warning("config: development mode is enabled by default by the -devmode flag")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerDevModeOption() error {
|
|
||||||
return Register(&Option{
|
|
||||||
Name: "Development Mode",
|
|
||||||
Key: CfgDevModeKey,
|
|
||||||
Description: "In Development Mode, security restrictions are lifted/softened to enable unrestricted access for debugging and testing purposes.",
|
|
||||||
OptType: OptTypeBool,
|
|
||||||
ExpertiseLevel: ExpertiseLevelDeveloper,
|
|
||||||
ReleaseLevel: ReleaseLevelStable,
|
|
||||||
DefaultValue: defaultDevMode,
|
|
||||||
Annotations: Annotations{
|
|
||||||
DisplayOrderAnnotation: 512,
|
|
||||||
CategoryAnnotation: "Development",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -47,18 +47,15 @@ func prep() error {
|
||||||
modules.SetCmdLineOperation(exportConfigCmd)
|
modules.SetCmdLineOperation(exportConfigCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
logDevModeOverride()
|
return registerBasicOptions()
|
||||||
err := registerDevModeOption()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() error {
|
func start() error {
|
||||||
configFilePath = filepath.Join(dataRoot.Path, "config.json")
|
configFilePath = filepath.Join(dataRoot.Path, "config.json")
|
||||||
|
|
||||||
|
// Load log level from log package after it started.
|
||||||
|
loadLogLevel()
|
||||||
|
|
||||||
err := registerAsDatabase()
|
err := registerAsDatabase()
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -192,5 +192,7 @@ func setDefaultConfigOption(key string, value interface{}, push bool) (err error
|
||||||
// finalize change, activate triggers
|
// finalize change, activate triggers
|
||||||
signalChanges()
|
signalChanges()
|
||||||
|
|
||||||
return saveConfig()
|
// Do not save the configuration, as it only saves the active values, not the
|
||||||
|
// active default value.
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ var (
|
||||||
logBuffer chan *logLine
|
logBuffer chan *logLine
|
||||||
forceEmptyingOfBuffer = make(chan struct{})
|
forceEmptyingOfBuffer = make(chan struct{})
|
||||||
|
|
||||||
logLevelInt = uint32(3)
|
logLevelInt = uint32(InfoLevel)
|
||||||
logLevel = &logLevelInt
|
logLevel = &logLevelInt
|
||||||
|
|
||||||
pkgLevelsActive = abool.NewBool(false)
|
pkgLevelsActive = abool.NewBool(false)
|
||||||
|
@ -134,11 +134,36 @@ func UnSetPkgLevels() {
|
||||||
pkgLevelsActive.UnSet()
|
pkgLevelsActive.UnSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLogLevel returns the current log level.
|
||||||
|
func GetLogLevel() Severity {
|
||||||
|
return Severity(atomic.LoadUint32(logLevel))
|
||||||
|
}
|
||||||
|
|
||||||
// SetLogLevel sets a new log level. Only effective after Start().
|
// SetLogLevel sets a new log level. Only effective after Start().
|
||||||
func SetLogLevel(level Severity) {
|
func SetLogLevel(level Severity) {
|
||||||
atomic.StoreUint32(logLevel, uint32(level))
|
atomic.StoreUint32(logLevel, uint32(level))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the log level.
|
||||||
|
func (s Severity) Name() string {
|
||||||
|
switch s {
|
||||||
|
case TraceLevel:
|
||||||
|
return "trace"
|
||||||
|
case DebugLevel:
|
||||||
|
return "debug"
|
||||||
|
case InfoLevel:
|
||||||
|
return "info"
|
||||||
|
case WarningLevel:
|
||||||
|
return "warning"
|
||||||
|
case ErrorLevel:
|
||||||
|
return "error"
|
||||||
|
case CriticalLevel:
|
||||||
|
return "critical"
|
||||||
|
default:
|
||||||
|
return "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ParseLevel returns the level severity of a log level name.
|
// ParseLevel returns the level severity of a log level name.
|
||||||
func ParseLevel(level string) Severity {
|
func ParseLevel(level string) Severity {
|
||||||
switch strings.ToLower(level) {
|
switch strings.ToLower(level) {
|
||||||
|
|
84
utils/broadcastflag.go
Normal file
84
utils/broadcastflag.go
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/tevino/abool"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BroadcastFlag is a simple system to broadcast a flag value.
|
||||||
|
type BroadcastFlag struct {
|
||||||
|
flag *abool.AtomicBool
|
||||||
|
signal chan struct{}
|
||||||
|
lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flag receives changes from its broadcasting flag.
|
||||||
|
// A Flag must only be used in one goroutine and is not concurrency safe,
|
||||||
|
// but fast.
|
||||||
|
type Flag struct {
|
||||||
|
flag *abool.AtomicBool
|
||||||
|
signal chan struct{}
|
||||||
|
broadcaster *BroadcastFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBroadcastFlag returns a new BroadcastFlag.
|
||||||
|
// In the initial state, the flag is not set and the singal does not trigger.
|
||||||
|
func NewBroadcastFlag() *BroadcastFlag {
|
||||||
|
return &BroadcastFlag{
|
||||||
|
flag: abool.New(),
|
||||||
|
signal: make(chan struct{}),
|
||||||
|
lock: sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFlag returns a new Flag that listens to this broadcasting flag.
|
||||||
|
// In the initial state, the flag is set and the singal triggers.
|
||||||
|
// You can call Refresh immediately to get the current state from the
|
||||||
|
// broadcasting flag.
|
||||||
|
func (bf *BroadcastFlag) NewFlag() *Flag {
|
||||||
|
newFlag := &Flag{
|
||||||
|
flag: abool.NewBool(true),
|
||||||
|
signal: make(chan struct{}),
|
||||||
|
broadcaster: bf,
|
||||||
|
}
|
||||||
|
close(newFlag.signal)
|
||||||
|
return newFlag
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyAndReset notifies all flags of this broadcasting flag and resets the
|
||||||
|
// internal broadcast flag state.
|
||||||
|
func (bf *BroadcastFlag) NotifyAndReset() {
|
||||||
|
bf.lock.Lock()
|
||||||
|
defer bf.lock.Unlock()
|
||||||
|
|
||||||
|
// Notify all flags of the change.
|
||||||
|
bf.flag.Set()
|
||||||
|
close(bf.signal)
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
bf.flag = abool.New()
|
||||||
|
bf.signal = make(chan struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal returns a channel that waits for the flag to be set. This does not
|
||||||
|
// reset the Flag itself, you'll need to call Refresh for that.
|
||||||
|
func (f *Flag) Signal() <-chan struct{} {
|
||||||
|
return f.signal
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet returns whether the flag was set since the last Refresh.
|
||||||
|
// This does not reset the Flag itself, you'll need to call Refresh for that.
|
||||||
|
func (f *Flag) IsSet() bool {
|
||||||
|
return f.flag.IsSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh fetches the current state from the broadcasting flag.
|
||||||
|
func (f *Flag) Refresh() {
|
||||||
|
f.broadcaster.lock.Lock()
|
||||||
|
defer f.broadcaster.lock.Unlock()
|
||||||
|
|
||||||
|
// Copy current flag and signal from the broadcasting flag.
|
||||||
|
f.flag = f.broadcaster.flag
|
||||||
|
f.signal = f.broadcaster.signal
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ func RunPowershellCmd(script string) (output string, err error) {
|
||||||
// Create command to execute.
|
// Create command to execute.
|
||||||
cmd := exec.Command(
|
cmd := exec.Command(
|
||||||
"powershell.exe",
|
"powershell.exe",
|
||||||
|
"-ExecutionPolicy", "Bypass",
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-NonInteractive",
|
"-NonInteractive",
|
||||||
"[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n"+script,
|
"[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n"+script,
|
||||||
|
|
Loading…
Add table
Reference in a new issue