Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bool flag config representation #695

Merged
merged 5 commits into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 4 additions & 18 deletions pkg/visor/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,17 +323,10 @@ func (v *Visor) SetAppKillswitch(appName string, killswitch bool) error {
v.log.Infof("Setting %s killswitch to %q", appName, killswitch)

const (
killSwitchArg = "-killswitch"
killSwitchArg = "--killswitch"
)

var value string
if killswitch {
value = "true"
} else {
value = "false"
}

if err := v.conf.UpdateAppArg(v.appL, appName, killSwitchArg, value); err != nil {
if err := v.conf.UpdateAppArg(v.appL, appName, killSwitchArg, killswitch); err != nil {
return err
}

Expand All @@ -351,17 +344,10 @@ func (v *Visor) SetAppSecure(appName string, isSecure bool) error {
v.log.Infof("Setting %s secure to %q", appName, isSecure)

const (
secureArgName = "-secure"
secureArgName = "--secure"
)

var value string
if isSecure {
value = "true"
} else {
value = "false"
}

if err := v.conf.UpdateAppArg(v.appL, appName, secureArgName, value); err != nil {
if err := v.conf.UpdateAppArg(v.appL, appName, secureArgName, isSecure); err != nil {
return err
}

Expand Down
125 changes: 105 additions & 20 deletions pkg/visor/visorconfig/v1.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package visorconfig

import (
"fmt"
"strings"
"sync"

"github.com/skycoin/dmsg/cipher"
Expand Down Expand Up @@ -128,15 +130,22 @@ func (v1 *V1) UpdateAppAutostart(launch *launcher.Launcher, appName string, auto
}

// UpdateAppArg updates the cli flag of the specified app config and also within the launcher.
// It removes argName from app args if value is an empty string.
// The updated config gets flushed to file if there are any changes.
func (v1 *V1) UpdateAppArg(launch *launcher.Launcher, appName, argName, value string) error {
func (v1 *V1) UpdateAppArg(launch *launcher.Launcher, appName, argName string, value interface{}) error {
v1.mu.Lock()
defer v1.mu.Unlock()

conf := v1.Launcher

configChanged := updateArg(conf, appName, argName, value)
var configChanged bool
switch val := value.(type) {
case string:
configChanged = updateStringArg(conf, appName, argName, val)
case bool:
configChanged = updateBoolArg(conf, appName, argName, val)
default:
return fmt.Errorf("invalid arg type %T", value)
}

if !configChanged {
return nil
Expand All @@ -151,32 +160,108 @@ func (v1 *V1) UpdateAppArg(launch *launcher.Launcher, appName, argName, value st
return v1.flush(v1)
}

func updateArg(conf *V1Launcher, appName, argName, value string) bool {
// updateStringArg updates the cli non-boolean flag of the specified app config and also within the launcher.
// It removes argName from app args if value is an empty string.
// The updated config gets flushed to file if there are any changes.
func updateStringArg(conf *V1Launcher, appName, argName, value string) bool {
configChanged := false

for i := range conf.Apps {
if conf.Apps[i].Name == appName {
configChanged = true

argChanged := false
l := len(conf.Apps[i].Args)
for j := 0; j < l; j++ {
if conf.Apps[i].Args[j] == argName && j+1 < len(conf.Apps[i].Args) {
if value == "" {
conf.Apps[i].Args = append(conf.Apps[i].Args[:j], conf.Apps[i].Args[j+2:]...)
j--
if conf.Apps[i].Name != appName {
continue
}

configChanged = true

argChanged := false
l := len(conf.Apps[i].Args)
for j := 0; j < l; j++ {
equalArgName := conf.Apps[i].Args[j] == argName && j+1 < len(conf.Apps[i].Args)
if !equalArgName {
continue
}

if value == "" {
conf.Apps[i].Args = append(conf.Apps[i].Args[:j], conf.Apps[i].Args[j+2:]...)
j-- //nolint:ineffassign
} else {
conf.Apps[i].Args[j+1] = value
}

argChanged = true
break
}

if !argChanged {
conf.Apps[i].Args = append(conf.Apps[i].Args, argName, value)
}

break
}

return configChanged
}

// updateBoolArg updates the cli boolean flag of the specified app config and also within the launcher.
// All flag names and values are formatted as "name=value" to allow arbitrary values with respect to different
// possible default values.
// The updated config gets flushed to file if there are any changes.
func updateBoolArg(conf *V1Launcher, appName, argName string, value bool) bool {
const argFmt = "%s=%v"

configChanged := false

for i := range conf.Apps {
if conf.Apps[i].Name != appName {
continue
}

// we format it to have two dashes, just to unify representation
fmtedArgName := argName
Darkren marked this conversation as resolved.
Show resolved Hide resolved
if argName[1] != '-' {
fmtedArgName = "-" + argName
}

arg := fmt.Sprintf(argFmt, fmtedArgName, value)

configChanged = true

argChanged := false
for j := 0; j < len(conf.Apps[i].Args); j++ {
equalArgName := conf.Apps[i].Args[j][1] == '-' && strings.HasPrefix(conf.Apps[i].Args[j], fmtedArgName)
if conf.Apps[i].Args[j][1] != '-' {
equalArgName = strings.HasPrefix("-"+conf.Apps[i].Args[j], fmtedArgName)
}

if !equalArgName {
continue
}

// check next value. currently we store value along with the flag name in a single string,
// but there're may be some broken configs because of the previous functionality, so we
// make our best effort to fix this on the go
if (j + 1) < len(conf.Apps[i].Args) {
// bool value shouldn't be present there, so we remove it, if it is
if conf.Apps[i].Args[j+1] == "true" || conf.Apps[i].Args[j+1] == "false" {
if (j + 2) < len(conf.Apps[i].Args) {
conf.Apps[i].Args = append(conf.Apps[i].Args[:j+1], conf.Apps[i].Args[j+2:]...)
} else {
conf.Apps[i].Args[j+1] = value
conf.Apps[i].Args = conf.Apps[i].Args[:j+1]
}
argChanged = true
break
}
}

if !argChanged {
conf.Apps[i].Args = append(conf.Apps[i].Args, argName, value)
}
conf.Apps[i].Args[j] = arg
argChanged = true

break
}

if !argChanged {
conf.Apps[i].Args = append(conf.Apps[i].Args, arg)
}

break
}

return configChanged
Expand Down
Loading